Search code examples
androidkotlinandroid-studioandroid-lint

How to Use Custom Lint in Android Studio


I have some custom lint for my android project. Initially I wrote this code in new project and it was working there, I can see my new lint in Android Studio Ispection tab in Setting. But When I pasted the exat same code for my other project it doenst worked. My project is getting compiled corectly, but I cant see my lint in action nor my custom lint in Android studio inspection serction. Here I pasted my some code for the reference.

I have created java/kotlin module for it.

What I am doing wrong?. I have tried restarting android studio, clear cache and restared, gradle build but nothing worked for my this project Here is the code.

Here AndroidEntryPoint Issue Class

@Suppress("UnstableApiUsage")
object AndroidEntryPointImplementationIssue {
    private const val ID = "AndroidEntryPointImplementationIssue"
    private const val PRIORITY = 7


    private const val DESCRIPTION = "Use @AndroidEntryPoint before running the app"
    private const val EXPLANATION = """
        Class is not contain @AndroidEntryPoint Annotation,
        Use @AndroidEntryPoint before running the app
    """
    private val CATEGORY = Category.CORRECTNESS
    private val SEVERITY = Severity.WARNING

    val ISSUE = Issue.create(
        ID,
        DESCRIPTION,
        EXPLANATION,
        CATEGORY,
        PRIORITY,
        SEVERITY,
        Implementation(
            AndroidEntryPointDetector::class.java,
            Scope.JAVA_FILE_SCOPE
        )
    )

    class AndroidEntryPointDetector : Detector(), XmlScanner {
        override fun getApplicableUastTypes(): List<Class<out UElement>> =
            listOf(UClass::class.java)

        override fun createUastHandler(context: JavaContext): UElementHandler =
            AndroidEntryPointVisitor(context)
    }
}

Here is my Visitor Class

 @Suppress("UnstableApiUsage")
class AndroidEntryPointVisitor(private val context: JavaContext) : UElementHandler() {

    private val superClassQualifiedNameFragment = "in.android.basesession.fragment.BaseFragment"

    override fun visitClass(node: UClass) {
        if ((node.javaPsi.superClass?.qualifiedName == superClassQualifiedNameFragment) &&
            !node.hasAnnotation("dagger.hilt.android.AndroidEntryPoint")
        ) {
            reportIssue(node)
        }
    }

    private fun reportIssue(node: UClass) {
        context.report(
            issue = AndroidEntryPointImplementationIssue.ISSUE,
            scopeClass = node,
            location = context.getNameLocation(node),
            "Use @AndroidEntryPoint before running the app",
            quickfixData = QuickFixes.androidEntryPointQuickFix
        )
    }
}

Here is my Issue Registry class

@Suppress("UnstableApiUsage")
class CustomLintRegistry: IssueRegistry(){
    override val issues =
        listOf(
            AndroidEntryPointImplementationIssue.ISSUE,
        )

    override val api: Int = CURRENT_API

    override val minApi: Int = 6
}

Here I have my issue in my IssueRegistry, And below is my lint module kotlin DSL code

plugins {
    id("java-library")
    id("org.jetbrains.kotlin.jvm")
}

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

repositories{
    mavenLocal()
}

dependencies {
    compileOnly("com.android.tools.lint:lint-api:30.1.0-alpha03")
    testImplementation("com.android.tools.lint:lint-tests:30.1.0-alpha03")
    testImplementation("junit:junit:4.13.2")
}

tasks.jar {
    manifest {
        attributes("Lint-Registry-v3" to "in.lint.CustomLintRegistry")
    }
}

I have also used lintChecks(project(":lint")) in my every module, Where i want it. But Even after trying everything it doesnt worked for this project Whyyyyy???

PS: If you need some extra info pls let me know Guys


Solution

  • So there were a couple of things that I was doing wrong. Let's go one by one. First in AndroidEntryPointImplementationIssue object in class class AndroidEntryPointDetector, I was extending it to Detector(), XmlScanner which is wroing. Because I was trying to write lint for Java/kotlin class not for layout. So I need to replace it with Detector(), Detector.UastScanner. But even after Changing this it was not working for my case. It can work for you. You can try this, but I did extra is I added com.android.tools.lint.client.api.IssueRegistry file resouces/META-INF.services/ directory which contain my MyIssueRegistry` full path. Doing so allow android studio to pick you custom lint.

    I will write a whole Medium article on it. I will update the answer once I done writing.

    enter image description here