Detector.UastScanner源码:javadoc网址
javadoc只提供到了25.5.0这个版本,更新的版本比如26.2.0需要在代码仓库中引入才能看到SourceCodeScanner。
由于API转变是从JavaScanner转换到JavaPsiScanner再到SourceCodeScanner,想看一下JavaPsiScanner的源码解释,可以回退版本25.3.0。
将lint版本在代码仓库中回退到25.3.0,可以看到JavaPsiScanner源码,然后发现它没有单独的类,它是一个接口类,是和JavaScanner一起在Detector类中。如下:
package com.android.tools.lint.detector.api;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.resources.ResourceFolderType;
import com.android.resources.ResourceType;
import com.android.tools.lint.client.api.JavaParser.ResolvedClass;
import com.android.tools.lint.client.api.JavaParser.ResolvedMethod;
import com.android.tools.lint.client.api.LintDriver;
import com.google.common.annotations.Beta;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiMethodCallexpression;
import com.intellij.psi.PsiNewexpression;
import com.intellij.psi.PsiTypeParameter;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import lombok.ast.AstVisitor;
import lombok.ast.ClassDeclaration;
import lombok.ast.ConstructorInvocation;
import lombok.ast.MethodInvocation;
import lombok.ast.Node;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.w3c.dom.Attr;
import org.w3c.dom.document;
import org.w3c.dom.Element;
@Beta
public abstract class Detector {
@Deprecated @SuppressWarnings("unused") // Still here for third-party rules
public interface JavaScanner {
@Nullable
AstVisitor createJavaVisitor(@NonNull JavaContext context);
@Nullable
List> getApplicableNodeTypes();
@Nullable
List getApplicableMethodNames();
void visitMethod(
@NonNull JavaContext context,
@Nullable AstVisitor visitor,
@NonNull MethodInvocation node);
@Nullable
List getApplicableConstructorTypes();
void visitConstructor(
@NonNull JavaContext context,
@Nullable AstVisitor visitor,
@NonNull ConstructorInvocation node,
@NonNull ResolvedMethod constructor);
boolean appliesToResourceRefs();
void visitResourceReference(
@NonNull JavaContext context,
@Nullable AstVisitor visitor,
@NonNull Node node,
@NonNull String type,
@NonNull String name,
boolean isframework);
@Nullable
List applicableSuperClasses();
// TODO: Change signature to pass in the NormalTypeBody instead of the plain Node?
void checkClass(@NonNull JavaContext context, @Nullable ClassDeclaration declaration,
@NonNull Node node, @NonNull ResolvedClass resolvedClass);
}
public interface JavaPsiScanner {
@Nullable
JavaElementVisitor createPsiVisitor(@NonNull JavaContext context);
@Nullable
List> getApplicablePsiTypes();
@Nullable
List getApplicableMethodNames();
void visitMethod(
@NonNull JavaContext context,
@Nullable JavaElementVisitor visitor,
@NonNull PsiMethodCallexpression call,
@NonNull PsiMethod method);
@Nullable
List getApplicableConstructorTypes();
void visitConstructor(
@NonNull JavaContext context,
@Nullable JavaElementVisitor visitor,
@NonNull PsiNewexpression node,
@NonNull PsiMethod constructor);
@Nullable
List getApplicableReferenceNames();
void visitReference(
@NonNull JavaContext context,
@Nullable JavaElementVisitor visitor,
@NonNull PsiJavaCodeReferenceElement reference,
@NonNull PsiElement referenced);
boolean appliesToResourceRefs();
void visitResourceReference(
@NonNull JavaContext context,
@Nullable JavaElementVisitor visitor,
@NonNull PsiElement node,
@NonNull ResourceType type,
@NonNull String name,
boolean isframework);
@Nullable
List applicableSuperClasses();
void checkClass(@NonNull JavaContext context, @NonNull PsiClass declaration);
}
public interface ClassScanner {
void checkClass(@NonNull ClassContext context, @NonNull ClassNode classNode);
@Nullable
int[] getApplicableAsmNodeTypes();
void checkInstruction(@NonNull ClassContext context, @NonNull ClassNode classNode,
@NonNull MethodNode method, @NonNull AbstractInsnNode instruction);
@Nullable
List getApplicableCallNames();
@Nullable
List getApplicableCallOwners();
void checkCall(@NonNull ClassContext context, @NonNull ClassNode classNode,
@NonNull MethodNode method, @NonNull MethodInsnNode call);
}
public interface BinaryResourceScanner {
void checkBinaryResource(@NonNull ResourceContext context);
boolean appliesTo(@NonNull ResourceFolderType folderType);
}
public interface ResourceFolderScanner {
void checkFolder(@NonNull ResourceContext context, @NonNull String folderName);
boolean appliesTo(@NonNull ResourceFolderType folderType);
}
public interface XmlScanner {
void visitdocument(@NonNull XmlContext context, @NonNull document document);
void visitElement(@NonNull XmlContext context, @NonNull Element element);
void visitElementAfter(@NonNull XmlContext context, @NonNull Element element);
void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute);
@Nullable
Collection getApplicableElements();
@Nullable
Collection getApplicableAttributes();
@NonNull
List ALL = new ArrayList<>(0); // NOT Collections.EMPTY!
// We want to distinguish this from just an *empty* list returned by the caller!
}
public interface GradleScanner {
void visitBuildscript(@NonNull Context context, Map sharedData);
}
public interface OtherFileScanner {
@NonNull
EnumSet getApplicableFiles();
}
public void run(@NonNull Context context) {
}
@Deprecated // Slated for removal in lint 2.0 - this method isn't used
public boolean appliesTo(@NonNull Context context, @NonNull File file) {
return false;
}
public void beforeCheckProject(@NonNull Context context) {
}
public void afterCheckProject(@NonNull Context context) {
}
public void beforeCheckLibraryProject(@NonNull Context context) {
}
public void afterCheckLibraryProject(@NonNull Context context) {
}
public void beforeCheckFile(@NonNull Context context) {
}
public void afterCheckFile(@NonNull Context context) {
}
@NonNull
@Deprecated // Slated for removal in Lint 2.0
public Speed getSpeed() {
return Speed.NORMAL;
}
@NonNull
@Deprecated // Slated for removal in Lint 2.0
public Speed getSpeed(@SuppressWarnings("UnusedParameters") @NonNull Issue issue) {
// If not overridden, this detector does not distinguish speed by issue type
return getSpeed();
}
// ---- Dummy implementations to make implementing XmlScanner easier: ----
@SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public void visitdocument(@NonNull XmlContext context, @NonNull document document) {
// This method must be overridden if your detector does
// not return something from getApplicableElements or
// getApplicableAttributes
assert false;
}
@SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
// This method must be overridden if your detector returns
// tag names from getApplicableElements
assert false;
}
@SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public void visitElementAfter(@NonNull XmlContext context, @NonNull Element element) {
}
@SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute) {
// This method must be overridden if your detector returns
// attribute names from getApplicableAttributes
assert false;
}
@SuppressWarnings("javadoc")
@Nullable
public Collection getApplicableElements() {
return null;
}
@Nullable
@SuppressWarnings("javadoc")
public Collection getApplicableAttributes() {
return null;
}
// ---- Dummy implementations to make implementing JavaScanner easier: ----
@Deprecated @Nullable @SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public AstVisitor createJavaVisitor(@NonNull JavaContext context) {
return null;
}
@Deprecated @Nullable@SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public List> getApplicableNodeTypes() {
return null;
}
@Deprecated @SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public void visitMethod(@NonNull JavaContext context, @Nullable AstVisitor visitor,
@NonNull MethodInvocation node) {
}
@Deprecated @SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public void visitResourceReference(@NonNull JavaContext context, @Nullable AstVisitor visitor,
@NonNull Node node, @NonNull String type, @NonNull String name,
boolean isframework) {
}
@Deprecated @SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public void checkClass(@NonNull JavaContext context, @Nullable ClassDeclaration declaration,
@NonNull Node node, @NonNull ResolvedClass resolvedClass) {
}
@Deprecated @SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public void visitConstructor(
@NonNull JavaContext context,
@Nullable AstVisitor visitor,
@NonNull ConstructorInvocation node,
@NonNull ResolvedMethod constructor) {
}
// ---- Dummy implementations to make implementing a ClassScanner easier: ----
@SuppressWarnings("javadoc")
public void checkClass(@NonNull ClassContext context, @NonNull ClassNode classNode) {
}
@SuppressWarnings("javadoc")
@Nullable
public List getApplicableCallNames() {
return null;
}
@SuppressWarnings("javadoc")
@Nullable
public List getApplicableCallOwners() {
return null;
}
@SuppressWarnings("javadoc")
public void checkCall(@NonNull ClassContext context, @NonNull ClassNode classNode,
@NonNull MethodNode method, @NonNull MethodInsnNode call) {
}
@SuppressWarnings("javadoc")
@Nullable
public int[] getApplicableAsmNodeTypes() {
return null;
}
@SuppressWarnings("javadoc")
public void checkInstruction(@NonNull ClassContext context, @NonNull ClassNode classNode,
@NonNull MethodNode method, @NonNull AbstractInsnNode instruction) {
}
// ---- Dummy implementations to make implementing an OtherFileScanner easier: ----
@NonNull
public EnumSet getApplicableFiles() {
return Scope.OTHER_SCOPE;
}
// ---- Dummy implementations to make implementing an GradleScanner easier: ----
public void visitBuildscript(@NonNull Context context, Map sharedData) {
}
// ---- Dummy implementations to make implementing a resource folder scanner easier: ----
public void checkFolder(@NonNull ResourceContext context, @NonNull String folderName) {
}
// ---- Dummy implementations to make implementing a binary resource scanner easier: ----
public void checkBinaryResource(@NonNull ResourceContext context) {
}
public boolean appliesTo(@NonNull ResourceFolderType folderType) {
return true;
}
// ---- Dummy implementation to make implementing JavaPsiScanner easier: ----
@Nullable
public List getApplicableMethodNames() {
return null;
}
@Nullable @SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public List getApplicableConstructorTypes() {
return null;
}
@SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public boolean appliesToResourceRefs() {
return false;
}
@Nullable @SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public List applicableSuperClasses() {
return null;
}
@SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public void visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor,
@NonNull PsiMethodCallexpression call, @NonNull PsiMethod method) {
}
@SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public void visitConstructor(
@NonNull JavaContext context,
@Nullable JavaElementVisitor visitor,
@NonNull PsiNewexpression node,
@NonNull PsiMethod constructor) {
}
@SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public void visitResourceReference(@NonNull JavaContext context,
@Nullable JavaElementVisitor visitor, @NonNull PsiElement node,
@NonNull ResourceType type, @NonNull String name, boolean isframework) {
}
@SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public void checkClass(@NonNull JavaContext context, @NonNull PsiClass declaration) {
}
@Nullable @SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public JavaElementVisitor createPsiVisitor(@NonNull JavaContext context) {
return null;
}
@Nullable @SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public List> getApplicablePsiTypes() {
return null;
}
@Nullable @SuppressWarnings({"unused", "javadoc"})
public List getApplicableReferenceNames() {
return null;
}
@SuppressWarnings({"UnusedParameters", "unused", "javadoc"})
public void visitReference(
@NonNull JavaContext context,
@Nullable JavaElementVisitor visitor,
@NonNull PsiJavaCodeReferenceElement reference,
@NonNull PsiElement referenced) {
}
}
lint中解析java代码的第一代分析器JavaScanner在25.2.0版本开始标注废弃,但在代码中仍然存在,在com.android.tools.lint.detector.api.Detector那个类文件中。
现在从第一代开始了解基本方法:
JavaScanner是用于扫描Java源文件解析树的检测器的专用接口,它是一个interface。



