Mak*_*iev 10 java android lint kotlin
我想确保在我的 Android 应用程序(Java 和 Kotlin 代码中)中不会调用特定类的特定方法。假设,我有一个使用Bar以下两种方法调用的类:allowed()和disallowed()。这是代码:
package com;
public class Bar {
public void disallowed() {
}
public void allowed() {
}
}
Run Code Online (Sandbox Code Playgroud)
并假设客户端代码可以调用allowed()并且不应该调用disallowed(). 我发现Google的内置AddJavascriptInterfaceDetector的源代码与我的情况类似。
这是我的 lint 规则的代码:
样本代码检测器
package com.sample.mobile.lint
import com.android.tools.lint.detector.api.Category
import com.android.tools.lint.detector.api.Detector
import com.android.tools.lint.detector.api.Implementation
import com.android.tools.lint.detector.api.Issue
import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
import com.intellij.psi.PsiMethod
import org.jetbrains.uast.UCallExpression
class SampleCodeDetector : Detector(), SourceCodeScanner {
companion object {
@JvmField
val ISSUE = Issue.create(
// ID: used in @SuppressLint warnings etc
"Usage of Bar#disallowed()",
// Title -- shown in the IDE's preference dialog, as category headers in the
// Analysis results window, etc
"Usage of Bar#disallowed() - Summary",
// Full explanation of the issue; you can use some markdown markup such as
// `monospace`, *italic*, and **bold**.
"This check highlights the usage of Bar#disallowed()",
Category.CORRECTNESS,
8,
Severity.ERROR,
Implementation(
SampleCodeDetector::class.java,
Scope.JAVA_FILE_SCOPE
)
)
const val FULLY_QUALIFIED_CLASS_NAME = "com.Bar"
const val METHOD_NAME = "disallowed"
}
override fun getApplicableMethodNames() = listOf(METHOD_NAME)
override fun visitMethod(context: JavaContext, node: UCallExpression, method: PsiMethod) {
val evaluator = context.evaluator
if (!evaluator.methodMatches(method, FULLY_QUALIFIED_CLASS_NAME, true)) {
return
}
val message = "`Bar.disallowed()` should not be called"
context.report(ISSUE, node, context.getNameLocation(node), message)
}
}
Run Code Online (Sandbox Code Playgroud)
样本问题注册表
package com.sample.mobile.lint
import com.android.tools.lint.client.api.IssueRegistry
import com.android.tools.lint.detector.api.Issue
class SampleIssueRegistry : IssueRegistry() {
override val issues: List<Issue> get() = listOf(SampleCodeDetector.ISSUE)
}
Run Code Online (Sandbox Code Playgroud)
构建.gradle
apply plugin: 'java-library'
dependencies {
String lintVersion = "26.1.1"
compileOnly "com.android.tools.lint:lint-api:$lintVersion"
compileOnly "com.android.tools.lint:lint-checks:$lintVersion"
compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.60"
testImplementation "com.android.tools.lint:lint:$lintVersion"
testImplementation "com.android.tools.lint:lint-tests:$lintVersion"
}
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
jar {
manifest {
// Only use the "-v2" key here if your checks have been updated to the
// new 3.0 APIs (including UAST)
attributes("Lint-Registry-v2": "com.sample.mobile.lint.SampleIssueRegistry")
}
}
Run Code Online (Sandbox Code Playgroud)
样本代码检测器测试
package com.sample.mobile.lint
import com.android.tools.lint.checks.infrastructure.LintDetectorTest
import com.android.tools.lint.detector.api.Detector
class SampleCodeDetectorTest : LintDetectorTest() {
private val javaFile = "package com.sample.mobile.app;\n" +
"\n" +
"import android.util.Log;\n" +
"\n" +
"import com.Bar;\n" +
"\n" +
"public class Foo {\n" +
"\n" +
" public void calLLog() {\n" +
" int a = 2;\n" +
" int b = 8;\n" +
" Log.d(\"Tag\", \"a+b=\" + (a + b));\n" +
" \n" +
" Bar bar = new Bar();\n" +
" bar.allowed();\n" +
" bar.disallowed();\n" +
" }\n" +
"}\n"
fun testJava() {
lint().files(LintDetectorTest.java(javaFile))
.run()
.expect("")
}
override fun getDetector(): Detector? {
return SampleCodeDetector()
}
override fun getIssues() = listOf(SampleCodeDetector.ISSUE)
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,测试失败了:
org.junit.ComparisonFailure:
Expected :
Actual :No warnings.
Run Code Online (Sandbox Code Playgroud)
当然,预期的结果不是空字符串,但无论如何,“没有警告”。不正确,因为有一个调用Bar#disallowed()inclass Foo
您还应该将com.Bar类的源代码包含到测试中:
import com.android.tools.lint.checks.infrastructure.LintDetectorTest
import com.android.tools.lint.detector.api.Detector
class SampleCodeDetectorTest : LintDetectorTest() {
private val javaFile = """
package com.sample.mobile.app;
import android.util.Log;
import com.Bar;
public class Foo {
public void calLLog() {
int a = 2;
int b = 8;
Log.d("Tag", "a+b=" + (a + b));
Bar bar = new Bar();
bar.allowed();
bar.disallowed();
}
}
""".trimIndent()
private val barJavaFile = """
package com;
public class Bar {
public void disallowed() {
}
public void allowed() {
}
}
""".trimIndent()
fun testJava() {
lint().files(java(javaFile), java(barJavaFile))
.run()
.expect("""
src/com/sample/mobile/app/Foo.java:16: Error: Bar.disallowed() should not be called [Usage of Bar#disallowed()]
bar.disallowed();
~~~~~~~~~~
1 errors, 0 warnings
""".trimIndent())
}
override fun getDetector(): Detector? {
return SampleCodeDetector()
}
override fun getIssues() = listOf(SampleCodeDetector.ISSUE)
}
Run Code Online (Sandbox Code Playgroud)
Lint 只是不知道com.Bar是什么并且默默地忽略它。
| 归档时间: |
|
| 查看次数: |
2967 次 |
| 最近记录: |