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;? ? ? ? }

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi閱讀 7,424評論 0 10
  • include<stdio.h> define PI 3.14 double calculateArea (int...
    齾爩麤閱讀 236評論 0 0
  • 食物|情懷是一種追隨 俗話說,一場秋雨一場寒。初秋時節,冰涼的空氣肆意的穿梭,被雨水澆灌后的街道,稀少的行人,幾片...
    貓小北閱讀 1,726評論 0 8
  • 原文鏈接:http://www.jetbrains.org/intellij/sdk/docs/basics/ty...
    pr488閱讀 1,148評論 0 0