DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Custom Lint Rules for Android - Detector, Issue, Naming Checks Complete

Creating custom lint rules in Android enables you to enforce project-specific code standards and patterns. Learn how to implement custom Detectors, define Issues, and perform naming checks.

Setting Up a Custom Lint Detector

Start by creating a custom Detector class that extends Detector from the lint API:

class NamingConventionDetector : Detector() {
    companion object {
        val NAMING_ISSUE = Issue.create(
            id = "NamingConvention",
            briefDescription = "Class name should follow PascalCase",
            explanation = "All public classes must follow PascalCase naming convention",
            category = Category.CORRECTNESS,
            priority = 6,
            severity = Severity.WARNING
        )
    }

    override fun getApplicableUastTypes(): List<Class<out UElement>> {
        return listOf(UClass::class.java)
    }

    override fun createUastHandler(context: UastScannerContext): UElementHandler {
        return object : UElementHandler() {
            override fun visitClass(node: UClass) {
                val className = node.name ?: return
                if (!className[0].isUpperCase()) {
                    context.report(
                        NAMING_ISSUE,
                        node,
                        context.getNameLocation(node),
                        "Class '$className' should start with uppercase letter"
                    )
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Registering the Detector

Create an IssueRegistry to register your detector:

class CustomIssueRegistry : IssueRegistry() {
    override val issues: List<Issue>
        get() = listOf(NamingConventionDetector.NAMING_ISSUE)

    override val vendor: Vendor
        get() = Vendor(
            vendorName = "MyApp",
            feedbackUrl = "https://github.com/myapp/issues"
        )
}
Enter fullscreen mode Exit fullscreen mode

Implementing Complex Naming Rules

For more advanced patterns, check method signatures and variable declarations:

if (node.isPublic && node.name?.matches(Regex("[a-z].*")) == true) {
    context.report(NAMING_ISSUE, node, context.getNameLocation(node),
        "Public class must use PascalCase naming")
}
Enter fullscreen mode Exit fullscreen mode

Custom lint rules improve code consistency and catch architectural violations early. Test your rules thoroughly before deploying to CI/CD pipelines.

8 Android app templates on Gumroad

Top comments (0)