We can implement some custom lint for Kotlin code.
So, I put an example the custom lint.
Some helpful links.
- http://tools.android.com/tips/lint-custom-rules
- http://tools.android.com/tips/lint/writing-a-lint-check
You can also find examples in the GitHub repositories. Let’s try to implement custom lint and reduce easy mistake from your projects.
Gradle
dependencies {
compileOnly "com.android.tools.lint:lint-api:26.0.1"
compileOnly "com.android.tools.lint:lint-checks:26.0.1"
}
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
jar {
manifest {
attributes("Lint-Registry-v2": "your.custom.lint.package.LintClassName")
}
}
Detector
class yourCustomLintDetector : Detector(), UastScanner {
companion object {
private val issueId = "yourCustomLint"
private val issueDescription = "Description for yourCustomLint"
private val issueExplanation = "Some more concrete explanation for yourCustomLint"
// https://android.googlesource.com/platform/tools/base/+/master/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Category.java#122
private val issueCategory = Category.CORRECTNESS
private val issuePriority = 10
private val issueSeverity = Severity.FATAL
private val implementation = Implementation(yourCustomLintDetector::class.java, Scope.JAVA_FILE_SCOPE)
internal val issue = Issue.create(issueId, issueDescription, issueExplanation, issueCategory, issuePriority, issueSeverity, implementation)
}
override fun applicableSuperClasses() = listOf("some.super.class.of.yourCustomLint")
// If a target, class which inherits "some.super.class.of.yourCustomLint", has no "yourCustomLintName" method, then the following lines report it user.
override fun visitClass(context: JavaContext, declaration: UClass) {
val isOverridden = declaration.methods
.firstOrNull { method -> method.isOverride && method.name.contains("yourCustomLintName") } != null
if (!isOverridden) {
declaration.uastAnchor?.let {
context.report(issue, context.getLocation(it), "$issueDescription \n $issueExplanation")
}
}
}
}
Registry
import your.custom.lint.package
class LintClassName : IssueRegistry() {
override fun getIssues() = listOf(yourCustomLintDetector.issue)
}
check
Add the lines on your gradle dependencies.
dependencies {
lintChecks project(':your-lint-project')
}
Test
You can implement tests for the custom rule.
import com.android.tools.lint.checks.infrastructure.LintDetectorTest
class yourCustomLintDetectorNotOverrideTest : LintDetectorTest() {
fun testBasic() {
lint().files(
LintDetectorTest.java("" +
"package test.pkg;\n" +
"import some.super.class.of.yourCustomLint;\n" +
"public class TestClass1 extends yourCustomLint {\n" +
" @Override public void yourCustomLintName() {}\n" +
"}")) // an example
.allowCompilationErrors()
.run()
.expect("Error message the lint should raise.....\n"
"1 errors, 0 warnings") // an example
}
override fun getDetector() = yourCustomLintDetector()
override fun getIssues() = listOf(yourCustomLintDetector.issue)
}
import com.android.tools.lint.checks.infrastructure.LintDetectorTest
class yourCustomLintDetectorOverrideTest : LintDetectorTest() {
fun testBasic() {
lint().files(
LintDetectorTest.java("" +
"package test.pkg;\n" +
"import some.super.class.of.yourCustomLint;\n" +
"public class TestClass1 extends yourCustomLint {\n" +
" @Override public void yourCustomLintName() {}\n" +
"}")) // an example
.allowCompilationErrors()
.run()
.expectClean()
}
override fun getDetector() = yourCustomLintDetector()
override fun getIssues() = listOf(yourCustomLintDetector.issue)
}
Conclusion
I described an example to implement Custom Lint for Gradle plugin. I believe custom lint help your projects and if you work with some guys, the feature should help you more powerful.
Have a good testing π