针对构造函数中注入次数的Lint规则

我试图在我的Android代码中创建一个Lint规则,检查构造函数中是否注入数字,所以如果我为视图模型超过了某个数字,例如,我将引发一个lint警告。

我知道我必须在我的Lint探测器中实施一个UastScanner,但是我迷路了,因为我找不到好的文档。 还有别人做过这样的事吗? 或者我可以在哪里find好的文档?

谢谢!

所以我能够使用JavaScannerfind一个解决方案,但是我还没有发现任何使用UastScanner的东西(这正是我想使用的,因为我们也有Kotlin类):

public class NumberOfDependenciesInjectedDetector extends Detector implements Detector.JavaScanner { private static final int NUMBER_OF_INJECTIONS_ALLOWED = 5; private static final Class DETECTOR = NumberOfDependenciesInjectedDetector.class; private static final EnumSet SCOPE = Scope.JAVA_FILE_SCOPE; private static final Implementation IMPLEMENTATION = new Implementation(DETECTOR, SCOPE); public static final Issue ISSUE = Issue.create( "NumberOfDependenciesInjected", "Limit number of injections in a class via constructor", "A longer description here", Category.CORRECTNESS, 10, Severity.ERROR, IMPLEMENTATION ); @Override public boolean appliesTo(Context context, File file) { return true; } @Override public Speed getSpeed(Issue issue) { return Speed.FAST; } @Override public List> getApplicableNodeTypes() { return Collections.>singletonList(ConstructorDeclaration.class); } @Override public AstVisitor createJavaVisitor(JavaContext context) { return new ConstructorVisitor(context); } private static class ConstructorVisitor extends ForwardingAstVisitor { private JavaContext javaContext; private ConstructorVisitor(JavaContext javaContext) { this.javaContext = javaContext; } @Override public boolean visitConstructorDeclaration(ConstructorDeclaration node) { if (node.astParameters().size() > NUMBER_OF_INJECTIONS_ALLOWED) { javaContext.report(ISSUE, node, javaContext.getLocation(node), "My message goes here"); return true; } return false; } } } 

*注 – 阅读编辑解决方案的完整答案。 *

我能够像这样写出UAST转换:

 public class NumberOfDependenciesInjectedDetector extends Detector implements Detector.UastScanner { private static final int NUMBER_OF_INJECTIONS_ALLOWED = 5; private static final Class DETECTOR = NumberOfDependenciesInjectedDetector.class; private static final EnumSet SCOPE = Scope.JAVA_FILE_SCOPE; private static final Implementation IMPLEMENTATION = new Implementation(DETECTOR, SCOPE); public static final Issue ISSUE = Issue.create( "NumberOfDependenciesInjected", "Limit number of injections in a class via constructor", "A longer description here", Category.CORRECTNESS, 10, Severity.ERROR, IMPLEMENTATION ); @Override public List> getApplicableUastTypes() { return Collections.>singletonList(UClass.class); } @Override public UElementHandler createUastHandler(JavaContext context) { return new ConstructorVisitor(context); } private static class ConstructorVisitor extends UElementHandler { private JavaContext javaContext; private ConstructorVisitor(JavaContext javaContext) { this.javaContext = javaContext; } @Override public void visitClass(UClass clazz){ UMethod[] methods = clazz.getMethods(); for(UMethod method : methods){ if(!method.isConstructor()) continue; if (method.getParameterList().getParametersCount() > NUMBER_OF_INJECTIONS_ALLOWED) { javaContext.report(ISSUE, method, javaContext.getLocation(method), "Injections exceed allowed value of " + NUMBER_OF_INJECTIONS_ALLOWED); } } } } } 

不过,这似乎还没有拿起Kotlin的源文件…非常混乱。

编辑:12/19/17 – 固定

问题有两方面:

1)确实有一个隐藏的Psi方法的使用,阻止检查工作。 visitClass方法不应该使用getParameterList(),而应该使用getUastParameters()。 将上面的visitclass替换为:

 @Override public void visitClass(UClass clazz){ UMethod[] methods = clazz.getMethods(); for(UMethod method : methods){ if(!method.isConstructor()) continue; if (method.getUastParameters().size() > NUMBER_OF_INJECTIONS_ALLOWED) { javaContext.report(ISSUE, clazz, javaContext.getLocation(method), "Injections exceed allowed value of " + NUMBER_OF_INJECTIONS_ALLOWED); } } } 

2)在与Tor Norbye直接在lint-dev组谈话之后,他指出Android Studio 3.0的lint实际上并不与kotlin一起工作,因此不会像这里描述的那样工作。 升级到Android Studio 3.1 Canary并运行linter产生了预期的报告。