Пользовательский детектор аннотации Lint не сработал - PullRequest
0 голосов
/ 24 марта 2020

Я пытаюсь написать свое первое правило Lint. На данный момент я просто хочу обнаружить использование аннотации @AnyThread.

. Я создал модуль для реализации моего пользовательского правила. Файл Gradle для этого модуля (я использую плагин Gradle версии 3.6.1):

targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_1_8

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    compileOnly 'com.android.tools.lint:lint-api:26.6.1'
    compileOnly 'com.android.tools.lint:lint-checks:26.6.1'

    testImplementation "com.android.tools.lint:lint:26.6.1"
    testImplementation "com.android.tools.lint:lint-tests:26.6.1"
    testImplementation "com.android.tools:testutils:26.6.1"

    testImplementation "junit:junit:4.12"
}

jar {
    manifest {
        attributes("Lint-Registry-v2": "com.test.lint.MyIssueRegistry")
    }
}

Мой детектор:

package com.test.lint
//...
class AnyThreadAnnotationDetector: AbstractAnnotationDetector(), Detector.UastScanner {

    companion object {
        private const val AnyThreadId = "AnyThreadId"
        const val AnyThreadDescription = "This is an attempt to find AnyThread annotation in code"
        const val AnyThreadExplanation = "AnyThread annotation found!"

        val ANYTHREAD_ANNOTATION_ISSUE = Issue.create(
            id = AnyThreadId,
            briefDescription = AnyThreadDescription,
            explanation = AnyThreadExplanation,
            category = Category.CORRECTNESS,
            priority = 4,
            severity = Severity.INFORMATIONAL,
            implementation = Implementation(
                AnyThreadAnnotationDetector::class.java,
                Scope.JAVA_FILE_SCOPE
            )
        )
    }

    override fun applicableAnnotations(): List<String>? = listOf("androidx.annotation.AnyThread")

    override fun visitAnnotationUsage(
        context: JavaContext,
        usage: UElement,
        type: AnnotationUsageType,
        annotation: UAnnotation,
        qualifiedName: String,
        method: PsiMethod?,
        annotations: List<UAnnotation>,
        allMemberAnnotations: List<UAnnotation>,
        allClassAnnotations: List<UAnnotation>,
        allPackageAnnotations: List<UAnnotation>
    ) {

      context.report(
          issue = ANYTHREAD_ANNOTATION_ISSUE,
          scope = usage,
          location = context.getNameLocation(usage),
          message = "A message"
      )
  }
}

My IssueRegistry is:

class MyIssueRegistry : IssueRegistry() {
    override val issues: List<Issue>
        get() = listOf(
            AnyThreadAnnotationDetector.ANYTHREAD_ANNOTATION_ISSUE)

    override val api: Int = CURRENT_API
}

Я написал несколько тестов:


class AnyThreadAnnotationDetectorTest  {

      @Test
      fun noAnnotatedFileKotlin() {
          TestLintTask.lint()
              .files(
                  LintDetectorTest.kotlin(
                      """
          |package foo;
          |
          |class XmlHttpRequest {
          |}""".trimMargin()
                  )
              )
              .allowMissingSdk()
              .issues(AnyThreadAnnotationDetector.ANYTHREAD_ANNOTATION_ISSUE)
              .run()
              .expectClean()
      }

      @Test
      fun annotatedKotlinMethod() {
          TestLintTask.lint()
              .files(
                  LintDetectorTest.kotlin(
                      """
          |package foo;
          |
          |import androidx.annotation.AnyThread
          |
          |class XmlHttpRequest {
          |@AnyThread
          |fun test(){}
          |}""".trimMargin()
                  )
              )
              .allowMissingSdk()
              .issues(AnyThreadAnnotationDetector.ANYTHREAD_ANNOTATION_ISSUE)
              .run()
              .expect(
                  """
                          Just a test to find annotations
                          0 errors, 0 warnings
                          """.trimIndent()
              )
      }


      @Test
      fun testNoisyDetector() {
          TestLintTask.lint().files(Stubs.ANYTHREAD_EXPERIMENT)
              .allowMissingSdk()
              .issues(AnyThreadAnnotationDetector.ANYTHREAD_ANNOTATION_ISSUE)
              .run()
              .expect(
                  """
                          Just a test to find annotations
                          0 errors, 0 warnings
                          """.trimIndent()
              )
      }
    }

Где Stubs.ANYTHREAD_EXPERIMENT:

object Stubs {
    val ANYTHREAD_EXPERIMENT = kotlin(
        "com/test/applicationlintdemoapp/AnythreadAnnotationStubs.kt",
        """
                package com.test.applicationlintdemoapp

                import androidx.annotation.AnyThread

                class AnythreadClassExperiment {
                    @AnyThread
                    fun setTimeToNow() {
                        TimeTravelProvider().setTime(System.currentTimeMillis())
                    }

                    @AnyThread
                    fun setTimeToEpoch() {
                        TimeTravelProvider().setTime(0)
                    }

                    fun violateTimeTravelAccords() {
                        TimeTravelProvider().setTime(-1)
                    }
                }
            """
    ).indented().within("src")
}

Все мои тесты не пройдены (кроме noAnnotatedFileKotlin), на самом деле, если я поставьте точку останова на вызов context.report, тест, выполненный в режиме отладки, никогда не приостанавливается, это означает, что аннотация androidx.annotation.AnyThread никогда не обнаруживается.

Что может go не так? что я пропустил?

Я видел и читал несколько документов:

И я контролировал конфигурацию, применяя NoisyDetector, приведенный в докладе Кодирование в стиле: Stati c Анализ с использованием пользовательских правил Lint , результат теста хорошо.

...