package me.ycdev.android.arch.lint.base; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.tools.lint.client.api.JavaParser; import com.android.tools.lint.detector.api.Detector; import com.android.tools.lint.detector.api.JavaContext; import com.android.tools.lint.detector.api.Speed; import java.util.HashSet; import java.util.List; import lombok.ast.ClassDeclaration; import lombok.ast.Node; public abstract class InheritDetectorBase extends Detector implements Detector.JavaScanner { protected HashSet<String> mWrapperClasses; protected HashSet<String> mTargetClasses; /** Constructs a new {@link InheritDetectorBase} check */ public InheritDetectorBase() { mWrapperClasses = getWrapperClasses(); mTargetClasses = new HashSet<>(applicableSuperClasses()); } protected abstract HashSet<String> getWrapperClasses(); @Override public abstract List<String> applicableSuperClasses(); protected abstract void reportViolation(JavaContext context, Node node); @Override public void checkClass(@NonNull JavaContext context, @Nullable ClassDeclaration declaration, @NonNull Node node, @NonNull JavaParser.ResolvedClass resolvedClass) { String className = resolvedClass.getName(); if (mWrapperClasses.contains(className)) { return; // ignore the wrapper classes } JavaParser.ResolvedClass superClass = resolvedClass.getSuperClass(); String superClassName = superClass.getName(); while (!mWrapperClasses.contains(superClassName)) { if (mTargetClasses.contains(superClassName)) { Node locationNode = node instanceof ClassDeclaration ? ((ClassDeclaration) node).astName() : node; reportViolation(context, locationNode); break; } superClass = superClass.getSuperClass(); superClassName = superClass.getName(); } } @Override public Speed getSpeed() { return Speed.FAST; } }