package me.ycdev.android.arch.lint.base; 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 java.util.List; import lombok.ast.AstVisitor; import lombok.ast.ClassDeclaration; import lombok.ast.MethodInvocation; public abstract class WrapperDetectorBase extends Detector implements Detector.JavaScanner { protected String mWrapperClassName; protected String[] mTargetClassNames; /** Constructs a new {@link WrapperDetectorBase} check */ public WrapperDetectorBase() { mWrapperClassName = getWrapperClassName(); mTargetClassNames = getTargetClassNames(); } // ---- Implements JavaScanner ---- protected abstract String getWrapperClassName(); protected abstract String[] getTargetClassNames(); protected abstract void reportViolation(JavaContext context, MethodInvocation node); @Override public abstract List<String> getApplicableMethodNames(); @Override public void visitMethod(JavaContext context, AstVisitor visitor, MethodInvocation node) { if (isInvokedInWrapperClass(context, node)) { return; } if (checkRuleViolation(context, node)) { reportViolation(context, node); } } private boolean isInvokedInWrapperClass(JavaContext context, MethodInvocation node) { ClassDeclaration surroundingClassDecl = JavaContext.findSurroundingClass(node); JavaParser.ResolvedClass surroundingClass = (JavaParser.ResolvedClass) context.resolve(surroundingClassDecl); String surroundingClassName = surroundingClass.getName(); return mWrapperClassName.equals(surroundingClassName); } private boolean checkRuleViolation(JavaContext context, MethodInvocation node) { JavaParser.ResolvedMethod method = (JavaParser.ResolvedMethod) context.resolve(node); JavaParser.ResolvedClass containingClass = method.getContainingClass(); String containingClassName = containingClass.getName(); if (mWrapperClassName.equals(containingClassName)) { return false; } for (String targetClassName : mTargetClassNames) { if (targetClassName.equals(containingClassName)) { return true; } if (containingClass.isSubclassOf(targetClassName, false)) { return true; } } return false; } }