Android Studio 中自己定义Lint(二)

2018-11-06  本文已影响0人  百花鱼藤

一、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;        }

上一篇 下一篇

猜你喜欢

热点阅读