Android Studio 中自己定义Lint(二)

一、Android lint uast介绍

UastScanner包含13个回调方法,下面介绍常用的几个:

1.getApplicableUastTypes

此方法返回需要检查的AST节点的类型,类型匹配的UElement将会被createUastHandler(createJavaVisitor)创建的UElementHandler(Visitor)检查。

2.createUastHandler

创建一个UastHandler来检查需要检查的UElement,对应于getApplicableUastTypes

3.getApplicableMethodNames

返回你所需要检查的方法名称列表,或者返回null,相匹配的方法将通过visitMethod方法被检查

4.visitMethod

检查与getApplicableMethodNames相匹配的方法

5.getApplicableConstructorTypes

返回需要检查的构造函数类型列表,类型匹配的方法将通过visitConstructor被检查

6.visitConstructor

检查与getApplicableConstructorTypes相匹配的构造方法

7.getApplicableReferenceNames

返回需要检查的引用路径名,匹配的引用将通过visitReference被检查

8.visitReference

检查与getApplicableReferenceNames匹配的引用

9.appliesToResourceRefs

返回需要检查的资源引用,匹配的引用将通过visitResourceReference被检查

10.visitResourceReference

检查与appliesToResourceRefs匹配的资源引用

11.applicableSuperClasses

返回需要检查的父类名列表,此处需要类的全路径名

11.visitClass

检查applicableSuperClasses返回的类

二、uast和psi对比



建议:

UastContext context = UastUtils.getUastContext(element); UExpression body = context.getMethodBody(method);

UastContext context = UastUtils.getUastContext(element); UExpression initializer = context.getInitializerBody(field);

Call names

In PSI, a call was represented by a PsiCallExpression, and to get to things like the method called or to the operand/qualifier, you'd first need to get the "method expression". In UAST there is no method expression and this information is available directly on the UCallExpression element. Therefore, here's how you'd change the code:

<    call.getMethodExpression().getReferenceName(); --- >    call.getMethodName()

Call qualifiers

Similarly,

<    call.getMethodExpression().getQualifierExpression(); --- >    call.getReceiver()

Call arguments

PSI had a separate PsiArgumentList element you had to look up before you could get to the actual arguments, as an array. In UAST these are available directly on the call, and are represented as a list instead of an array.

<    PsiExpression[] args = call.getArgumentList().getExpressions(); --- >    List args = call.getValueArguments();

Typically you also need to go through your code and replace array access, arg[i], with list access, arg.get(i). Or in Kotlin, just arg[i]...

Instanceof

You may have code which does something like "parent instanceof PsiAssignmentExpression" to see if something is an assignment. Instead, use one of the many utilities in UastExpressionUtils - such as UastExpressionUtils.isAssignment(UElement). Take a look at all the methods there now - there are methods for checking whether a call is a constructor, whether an expression is an array initializer, etc etc.

Android Resources

Don't do your own AST lookup to figure out if something is a reference to an Android resource (e.g. see if the class refers to an inner class of a class named "R" etc.) There is now a new utility class which handles this: ResourceReference. Here's an example of code which has a UExpression and wants to know it's referencing a R.styleable resource:

ResourceReference reference = ResourceReference.get(expression);        if (reference == null || reference.getType() != ResourceType.STYLEABLE) {            return;        }

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容