Skip to content

Instantly share code, notes, and snippets.

@davidvavra
Created March 22, 2019 17:06
Show Gist options
  • Save davidvavra/4f620ab3c5d3dc605439c3a2e2629e4c to your computer and use it in GitHub Desktop.
Save davidvavra/4f620ab3c5d3dc605439c3a2e2629e4c to your computer and use it in GitHub Desktop.
Lint check for detecting non-null assertion (!!) in your code
import com.android.tools.lint.client.api.UElementHandler
import com.android.tools.lint.detector.api.*
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UPostfixExpression
class NonNullAssertionDetector : Detector(), Detector.UastScanner {
override fun getApplicableUastTypes(): List<Class<out UElement>>? {
return listOf(UPostfixExpression::class.java)
}
override fun createUastHandler(context: JavaContext): UElementHandler? {
return object : UElementHandler() {
override fun visitPostfixExpression(node: UPostfixExpression) {
if (node.asRenderString().contains("!!")) {
context.report(
NON_NULL_ASSERTION_ISSUE,
node,
context.getLocation(node),
"This code includes non-null assertion (!!)"
)
}
}
}
}
}
val NON_NULL_ASSERTION_ISSUE = Issue.create(
"NonNullAssertion",
"Non-null assertion (!!) used",
"Don't use non-null assertions (!!). Design your code better to avoid needing it in the first place. As a last resort, replace it with checkNotNull() function.",
Implementation(NonNullAssertionDetector::class.java, Scope.JAVA_FILE_SCOPE),
"https://android.jlelse.eu/how-to-remove-all-from-your-kotlin-code-87dc2c9767fb",
Category.CORRECTNESS,
5,
Severity.WARNING
)
@bizzguy
Copy link

bizzguy commented Apr 2, 2019

Loved your gist for checking NON_NULL_ASSERTION_ISSUE. Just added it to my project.

My only comment is that you should have a test for it as well! Feel free to use this:

import com.android.tools.lint.checks.infrastructure.LintDetectorTest.kotlin
import com.android.tools.lint.checks.infrastructure.TestLintTask.lint
import org.junit.Test

class NonNullAssertDetectorTest {

    @Test
    fun propertyUsingBangBang() {
        lint()
            .files(kotlin("""
          package foo
          class Something {
            var someProperty : String? = null
            fun someMethod() {
                someProperty!!.length
            }
          }
          """).indented())
            .issues(NON_NULL_ASSERTION_ISSUE)
            .allowCompilationErrors()
            .run()
            .expect("""
            |src/foo/Something.kt:5: Warning: This code includes non-null assertion (!!) [NonNullAssertion]
            |      someProperty!!.length
            |      ~~~~~~~~~~~~~~
            |0 errors, 1 warnings
          """.trimMargin())
    }

    @Test
    fun propertyWithoutBangBang() {
        lint()
            .files(kotlin("""
          package foo
          class Something {
            var someProperty : String? = null
            fun someMethod() {
                someProperty.length
            }
          }
          """).indented())
            .issues(NON_NULL_ASSERTION_ISSUE)
            .allowCompilationErrors()
            .run()
            .expectClean()
    }

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment