- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我遵循this tutorial和this Custom Detector Example以实现自定义lint规则。基本上我所做的是:
在android工作室中创建一个新的android项目;
为步骤1中创建的项目创建Java模块;
在模块的build.gralde上,导入lint api依赖项;
创建问题&issueregister&customdetector;
参考模块build.gradle上的IssuereRegister;
创建单元测试;
我的问题是,在我的JUnits执行期间,我总是收到“没有警告”。当我解除测试时,我可以看到我的自定义检测器没有被调用,我做错了什么?
字符串.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";
}
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)
);
}
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;
}
}
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;
}
}
}
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"
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}"))
);
}
}
assets
或
res
文件夹的权限,这就是为什么我创建了一个
String.java
并在单元测试中使用了
java(to, source)
的原因-我假设这个
java
方法与我在本问题顶部引用的教程链接中的
xml
方法相同。
最佳答案
结果在我的案例中,问题出在junit本身。我认为我试图模拟文件的方式是错误的。下面的文本是我创建的README.md of a sample project的一部分,目的是记录我从这个api中学到的知识,并回答标题中的问题:
创建
创建一个新的android项目;
创建一个新的Java库模块-自定义lint规则一旦准备好就打包到.jar库中,因此使用它们实现它们的最简单方法是在Java模块库中;
在模块的build.gradle
上:
在Java1.7中添加目标和源兼容性;
为lint api、lint检查和测试依赖项添加依赖项;
添加包含两个属性的jar packing task:Manifest-Version
和Lint-Registry
,将第一个属性设置为1.0,将第二个属性设置为类的完整路径,该类稍后将包含问题的目录;
添加默认taslassemble
;
[可选]:添加将生成的.jar复制到~/.android/lint
中的任务;
检查ref001并选择最适合您需要的检测器,根据它创建并实现一个类来完成检测器的角色;
仍然基于ref0001选择的文件,创建并实现一个checker类,稍后在detector的createJavaVisitor()
方法中引用它;
为了srp,不要将checker放在同一个检测器类的文件中;
将生成的.jar文件从build/lib
复制到~/.android/lint
-如果在build.gradle
上添加了一个任务,则可以跳过此步骤;
重新启动计算机-一旦创建并移到~/.android/lint
中,lint应在下次程序启动时读取自定义规则。为了在android studio中设置警报框,使缓存失效并重新启动ide就足够了,但是,要在lint report上捕获您的自定义规则,可能需要重新启动计算机;
测试探测器和检查器
测试自定义规则不是一件容易的事情-主要是由于缺少官方api的文档。本节将介绍处理此问题的两种方法。此项目的主要目标是创建将针对真实文件运行的自定义规则,因此,测试文件对于测试它们是必要的。它们可以放在lint java库模块的./gradlew check
文件夹中;
方法01:LintDetectorTest
确保已添加所有测试依赖项-签出sample project'ssrc/test/resources
;
将build.gradle
和EnhancedLintDetectorTest.java
复制到项目的测试目录中;
android studio存在一个已知的缺陷,它无法看到FileUtils.java
文件夹中的文件,这些文件是解决这个问题的一个办法;src/test/resources
应返回将要进行测试的所有问题。一个很好的方法是从问题注册中心获取它们;
创建一个扩展自EnhancedLintDetectorTest.java
的测试类;
实现返回待测检测器实例的方法;
使用EnhancedLintDetectorTest.java
执行自定义规则的检查,并使用其result对象断言测试;
注意getDetector()
来自lintFiles("test file path taking resources dir as root")
,因此,您仅限于junit 3。
方法02:lint-junit规则
您可能已经注意到,方法01可能有点过于复杂,尽管您仅限于JUnit3特性。因此,GitHub user a11n创建了一个Lint JUnit Rule允许以更简单的方式测试自定义lint规则,这对junit 4和up特性很重要。有关如何使用此apprach创建测试的详细信息,请参阅他的项目README.md。
当前,Lint JUnit Rule不更正测试文件的根目录,并且您可能无法看到从ide传递的测试-但是,当从命令行运行测试时,它可以工作。创建issue和PR以修复此错误。
关于android - 如何在Android Studio中正确实现和测试“自定义 Lint 规则”?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45846014/
PHPLint、JSLint,我最近在阅读一些IDE. 那么,什么是“linting”? 最佳答案 Linting 是运行程序的过程,该程序将分析代码是否存在潜在错误。 参见lint在维基百科上: l
Elixir是否有 Lint (如Javascript)可以检查每个函数是否具有类型规范? 最佳答案 有一个Erlang编译器开关+warn_missing_spec可以做到这一点,但是目前我无法使其
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 5 年前。 Improve this qu
例如,我让它在 .rb 和 .js 文件上匹配。 例如**/*.{js,rb} 并且还想在 Gemfile 和 Rakefile 上进行匹配。 最佳答案 解决方案是递归地使用 {},例如 "lin
我有一个自述文件,其中包含文件夹的文档、包含的库以及如何使用它们。 自述文件不是任何库的一部分,因此 nx-lint 会引发此错误: NX ERROR The following file(s
我的 React Native 构建突然失败并出现错误,尽管一天前工作得很好,没有任何相关的更改。 FAILURE: Build failed with an exception. * What we
我有一个 lint-gradle-api.jar 错误,我在论坛上查看了其他类似的问题,但我仍然有问题。有人有想法吗? Error running Gradle: Exit code 1 from:
我已经将 Android Studio 更新到 3.2.1,现在停止了这样的问题:找不到 lint-gradle-api.jar (com.android.tools.lint:lint-gradle
我目前正在从 tslint 迁移到 eslint。我在我的 .eslintignore 中配置了几个文件夹,我想从 linting 中完全忽略它们。这确实有效,但现在我收到错误: “无效的 lint
Q (tldr;): 我如何使用 android-lint 中的 JavaScanner 检查特定函数调用是否具有特定作为参数的字符串已被 try/catch block 包围。 详细信息:我已经完成
我有一个在 Cocoapods 上发布的库。 当我运行pod lib lint时从包含 MyProject.podspec 的目录中,命令行挂起 $ pod lib lint -> MyProject
我正在尝试使用 Android lint 来检查有关我的项目的一些事情。它似乎忽略了我提供的 lint.xml 文件,使我无法启用检查。 我在 Ubuntu 14.04 上使用 Android Stu
我正在使用工具栏附带的 CodeMirror 设计一个应用程序。由于性能原因,我没有通过异步或异步模式执行 lint。 我在工具栏中提供了一个图标,单击它我正在解析和构建错误。但是我对如何在编辑器中更
使用 ./gradlew lintDebug 生成 Android lint 报告时,报告中不包括 javac lint 错误,例如弃用或未经检查的转换。 我目前只是在编译时启用这些 javac 选项
默认情况下,在 gradle 中为发布构建启用了 lint。没有 abortOnError false 此选项会中止构建。 我的发布构建成功执行(没有 lint 警告),但是当我通过 gradle 调
我有一个使用 Android 构建工具版本 1.3.1 的 gradle Android 构建,并对我的代码运行 lint 检查。运行 Sonar 任务(由 org.sonarqube gradle
只是想知道是否有人可以帮助我进行 Gulp 设置。目前我正在使用 gulp-sass 和 gulp-scss-lint 进行监视任务。我想要发生的是,当为 linting 任务完全运行保存一个 scs
我正在做一个项目,最近更新到 android Gradle 构建工具 3.0.0 (com.android.tools.build:gradle:3.0.0)。我现在在通过 Android studi
我有一个带有 gradle 的 Android 项目。虽然 gradle 插件是 2.x.x,但运行 ./gradlew lint 的时间大约为 4 分钟。我已经将项目升级到 gradle plugi
事情是这样的。我有一个与 API 15 及更高版本兼容的应用程序,但由于它非常大并且我已经达到 65k 方法限制,我不得不将它设为 MultiDexApplication 类的后代。这会稍微减慢构建时
我是一名优秀的程序员,十分优秀!