【发布时间】:2026-01-05 04:00:02
【问题描述】:
我正在关注 this tutorial 和 this Custom Detector Example 以实施自定义 Lint 规则。基本上我所做的是:
- 在 Android Studio 中创建一个新的 Android 项目;
- 为步骤 1 中创建的项目创建 java 模块;
- 在模块的
build.gradle上,导入 Lint API 依赖项; - 创建一个
Issue&IssueRegistry&CustomDetector; - 在模块的
build.gradle上引用IssueRegistry; - 创建单元测试;
我的问题是,在我的 JUnit 执行期间,我总是收到“无警告”。当我调试测试时,我可以看到我的自定义检测器没有被调用,我做错了什么?
Strings.java
public class Strings {
public static final String STR_ISSUE_001_ID = "VarsMustHaveMoreThanOneCharacter";
public static final String STR_ISSUE_001_DESCRIPTION = "Avoid naming variables with only one character";
public static final String STR_ISSUE_001_EXPLANATION = "Variables named with only one character do not pass any meaning to the reader. " +
"Variables name should clear indicate the meaning of the value it is holding";
}
问题.java
public class Issues {
public static final
Issue ISSUE_001 = Issue.create(
STR_ISSUE_001_ID,
STR_ISSUE_001_DESCRIPTION,
STR_ISSUE_001_EXPLANATION,
SECURITY,
// Priority ranging from 0 to 10 in severeness
6,
WARNING,
new Implementation(VariableNameDetector.class, ALL_RESOURCES_SCOPE)
);
}
IssuesRegistry.java
public class IssueRegistry extends com.android.tools.lint.client.api.IssueRegistry {
@Override
public List<Issue> getIssues() {
List<Issue> issues = new ArrayList<>();
issues.add(ISSUE_001);
return issues;
}
}
VariableNameDetector.java
public class VariableNameDetector extends Detector implements Detector.JavaScanner {
public VariableNameDetector() {
}
@Override
public boolean appliesToResourceRefs() {
return false;
}
@Override
public boolean appliesTo(Context context, File file) {
return true;
}
@Override
@Nullable
public AstVisitor createJavaVisitor(JavaContext context) {
return new NamingConventionVisitor(context);
}
@Override
public List<String> getApplicableMethodNames() {
return null;
}
@Override
public List<Class<? extends Node>> getApplicableNodeTypes() {
List<Class<? extends Node>> types = new ArrayList<>(1);
types.add(lombok.ast.VariableDeclaration.class);
return types;
}
@Override
public void visitMethod(
JavaContext context,
AstVisitor visitor,
MethodInvocation methodInvocation
) {
}
@Override
public void visitResourceReference(
JavaContext context,
AstVisitor visitor,
Node node,
String type,
String name,
boolean isFramework
) {
}
private class NamingConventionVisitor extends ForwardingAstVisitor {
private final JavaContext context;
NamingConventionVisitor(JavaContext context) {
this.context = context;
}
@Override
public boolean visitVariableDeclaration(VariableDeclaration node) {
StrictListAccessor<VariableDefinitionEntry, VariableDeclaration> varDefinitions =
node.getVariableDefinitionEntries();
for (VariableDefinitionEntry varDefinition : varDefinitions) {
String name = varDefinition.astName().astValue();
if (name.length() == 1) {
context.report(
ISSUE_001,
context.getLocation(node),
STR_ISSUE_001_DESCRIPTION
);
return true;
}
}
return false;
}
}
}
build.gradle
apply plugin: 'java'
configurations {
lintChecks
}
ext {
VERSION_LINT_API = '24.3.1'
VERSION_LINT_API_TESTS = '24.3.1'
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "com.android.tools.lint:lint-api:$VERSION_LINT_API"
implementation "com.android.tools.lint:lint-checks:$VERSION_LINT_API"
testImplementation "com.android.tools.lint:lint-tests:$VERSION_LINT_API_TESTS"
}
jar {
manifest {
attributes('Lint-Registry': 'br.com.edsilfer.lint_rules.resources.IssueRegistry')
}
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
TestVariableNameDetector.java
private static final String ARG_DEFAULT_LINT_SUCCESS_LOG = "No warnings.";
@Override
protected Detector getDetector() {
return new VariableNameDetector();
}
@Override
protected List<Issue> getIssues() {
return Collections.singletonList(Issues.ISSUE_001);
}
public void test_file_with_no_variables_with_length_equals_01() throws Exception {
assertEquals(
ARG_DEFAULT_LINT_SUCCESS_LOG,
lintProject(java("assets/Test.java", "public class Test {public String sampleVariable;}"))
);
}
public void test_file_with_variables_with_length_equals_01() throws Exception {
assertEquals(
ARG_DEFAULT_LINT_SUCCESS_LOG,
lintProject(java("assets/Test3.java", "public class Test {public String a;bnvhgvhj}"))
);
}
}
PS:在 Java 模块上,我无权访问 assets 或 res 文件夹,这就是我创建 String.java 并在我的单元中使用 java(to, source) 的原因测试 - 我假设这个 java 方法与我在这个问题顶部引用的教程链接中的 xml 相同。
【问题讨论】:
标签: android lint android-lint