I wrote the following annotation:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.SOURCE) @Target({ElementType.METHOD}) public @interface Warning { }
Designed to annotate methods that can cause problems if they are called carelessly. I added an annotation handler to my project, but this is only a warning in the javac output log file. I want this warning to appear in Android Studio along with other lint warnings wherever a method with this annotation is called. This is why I am trying to write a custom lint rule. I have a basic skeleton of the lint rule:
import com.android.tools.lint.detector.api.Category; import com.android.tools.lint.detector.api.Detector; import com.android.tools.lint.detector.api.Implementation; import com.android.tools.lint.detector.api.Issue; import com.android.tools.lint.detector.api.Scope; import com.android.tools.lint.detector.api.Severity; public class CaimitoDetector extends Detector implements Detector.JavaScanner { public static final Issue ISSUE = Issue.create( "WarningAnnotation", "This method has been annotated with @Warning", "This method has special conditions surrounding it use, be careful when using it and refer to its documentation.", Category.USABILITY, 7, Severity.WARNING, new Implementation(CaimitoDetector.class, Scope.JAVA_FILE_SCOPE)); @Override public void visitMethod(JavaContext context, AstVisitor visitor, MethodInvocation node) { } }
import com.android.tools.lint.client.api.IssueRegistry; import com.android.tools.lint.detector.api.Issue; import java.util.Collections; import java.util.List; public class CaimitoIssueRegistry extends IssueRegistry { @Override public List<Issue> getIssues() { return Collections.singletonList(CaimitoDetector.ISSUE); } }
But I do not know how to proceed from here. How to check if an annotation exists for a method and trigger a warning that will be visible in Android Studio?
UPDATE
Here is my Detector class for those who want to do the same:
import com.android.annotations.NonNull; import com.android.tools.lint.client.api.JavaParser.ResolvedAnnotation; import com.android.tools.lint.client.api.JavaParser.ResolvedMethod; import com.android.tools.lint.client.api.JavaParser.ResolvedNode; import com.android.tools.lint.detector.api.Category; import com.android.tools.lint.detector.api.Context; import com.android.tools.lint.detector.api.Detector; import com.android.tools.lint.detector.api.Implementation; import com.android.tools.lint.detector.api.Issue; import com.android.tools.lint.detector.api.JavaContext; import com.android.tools.lint.detector.api.Scope; import com.android.tools.lint.detector.api.Severity; import com.android.tools.lint.detector.api.Speed; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import lombok.ast.AstVisitor; import lombok.ast.ConstructorInvocation; import lombok.ast.ForwardingAstVisitor; import lombok.ast.MethodInvocation; import lombok.ast.Node; public class CaimitoAnnotationDetector extends Detector implements Detector.JavaScanner { private static final String WARNING_ANNOTATION = "com.treemetrics.caimito.annotations.Warning"; public static final Issue ISSUE = Issue.create( "Waqrning.", "Be careful when using this method.", "This method has special conditions surrounding it use," + " be careful when calling it and refer to its documentation.", Category.USABILITY, 7, Severity.WARNING, new Implementation( CaimitoAnnotationDetector.class, Scope.JAVA_FILE_SCOPE)); @Override public boolean appliesTo(@NonNull Context context, @NonNull File file) { return true; } @NonNull @Override public Speed getSpeed() { return Speed.FAST; } private static void checkMethodAnnotation(@NonNull JavaContext context, @NonNull ResolvedMethod method, @NonNull Node node, @NonNull ResolvedAnnotation annotation) { String signature = annotation.getSignature(); if(WARNING_ANNOTATION.equals(signature) || signature.endsWith(".Warning")) { checkWarning(context, node, annotation); } } private static void checkWarning(@NonNull JavaContext context, @NonNull Node node, @NonNull ResolvedAnnotation annotation) { context.report(ISSUE, node, context.getLocation(node), "Warning"); }
UPDATE 2
You can integrate your regular validation using Android Studio validation by creating a lint.xml file in the root directory of your project and adding a custom lint rule:
<?xml version="1.0" encoding="UTF-8"?> <lint> <issue id="Warning" severity="warning"/> </lint>
Note that the problem tag identifier is the identifier provided in the first argument of the Issue.create () method in the CaimitoDetector class. You will also have to copy the jar file created when you created the lint rule to the / home / {user} /. Android / lint folder for it to work. For this, I wrote a custom gradle task. Here is my lint rule build.gradle file rule
apply plugin: 'java' targetCompatibility = '1.7' sourceCompatibility = '1.7' repositories { jcenter() } dependencies { compile 'com.android.tools.lint:lint-api:24.2.1' compile 'com.android.tools.lint:lint-checks:24.2.1' } jar { manifest { attributes 'Manifest-Version': 1.0 attributes 'Lint-Registry': 'com.treemetrics.caimito.lint.CaimitoIssueRegistry' } } defaultTasks 'assemble' task copyLintJar(type: Copy) { description = 'Copies the caimito-lint jar file into the {user.home}/.android/lint folder.' from('build/libs/') into(System.getProperty("user.home") + '/.android/lint') include("*.jar") }
UPDATE 3
You can also add a Java lint project as a dependency on other projects to get the same effect as Update 2.

UPDATE 4
Since then I wrote a blog post on this subject https://medium.com/@mosesJay/writing-custom-lint-rules-and-integrating-them-with-android-studio-inspections-or-carefulnow-c54d72f00d30# .3hm576b4f .