をチェックするために、カスタムのlint警告を書き込み、私は以下の注釈書かれています:うっかり呼び出された場合の問題を引き起こす可能性がありますメソッドに注釈を付けるためのものであるカスタム注釈
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 {
}
を。私はプロジェクトに注釈プロセッサを追加しましたが、これはjavacコマンドのログ出力に警告を出すだけです。私はこの警告をAndroidスタジオに表示し、このアノテーションを持つメソッドが呼び出されると、他のlint警告とともに表示させます。これが私がカスタムlintルールを書くことを試みている理由です。私は、糸くずのルールの基本骨格を持っている:
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's 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);
}
}
しかし、私は、ここから続行するのか分かりません。メソッドにアノテーションが存在するかどうかを確認し、それがAndroid Studioに表示されるような警告を表示するにはどうすればよいですか?ここで
UPDATE
は同じことを行うために探している人のための私のディテクタクラスです:
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's 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");
}
// ---- Implements JavaScanner ----
@Override
public List<Class<? extends Node>> getApplicableNodeTypes() {
return Arrays.asList(
MethodInvocation.class,
ConstructorInvocation.class);
}
@Override
public AstVisitor createJavaVisitor(@NonNull JavaContext context) {
return new CallChecker(context);
}
private static class CallChecker extends ForwardingAstVisitor {
private final JavaContext mContext;
public CallChecker(JavaContext context) {
mContext = context;
}
@Override
public boolean visitMethodInvocation(@NonNull MethodInvocation call) {
ResolvedNode resolved = mContext.resolve(call);
if(resolved instanceof ResolvedMethod) {
ResolvedMethod method = (ResolvedMethod) resolved;
checkCall(call, method);
}
return false;
}
@Override
public boolean visitConstructorInvocation(@NonNull ConstructorInvocation call) {
ResolvedNode resolved = mContext.resolve(call);
if(resolved instanceof ResolvedMethod) {
ResolvedMethod method = (ResolvedMethod) resolved;
checkCall(call, method);
}
return false;
}
private void checkCall(@NonNull Node call, ResolvedMethod method) {
Iterable<ResolvedAnnotation> annotations = method.getAnnotations();
annotations = filterRelevantAnnotations(annotations);
for(ResolvedAnnotation annotation : annotations) {
checkMethodAnnotation(mContext, method, call, annotation);
}
}
private Iterable<ResolvedAnnotation> filterRelevantAnnotations(Iterable<ResolvedAnnotation> resolvedAnnotationsIn) {
List<ResolvedAnnotation> resolvedAnnotationsOut = new ArrayList<>();
for(ResolvedAnnotation resolvedAnnotation : resolvedAnnotationsIn) {
if(resolvedAnnotation.matches(WARNING_ANNOTATION)) {
resolvedAnnotationsOut.add(resolvedAnnotation);
}
}
return resolvedAnnotationsOut;
}
}
}
UPDATE 2
あなたは、Android Studioの検査でカスタムリントチェックを統合することができますプロジェクトのルートにlint.xmlファイルを作成し、カスタムリントルールを追加します。
問題タグのidは、CaimitoDetectorクラスのIssue.create()メソッドの最初の引数で指定されたIDです。また、lintルールを/home/{user}/.android/lintフォルダに作成して出力されたjarファイルをコピーして、動作させる必要があります。私はこのためにカスタムのgradleタスクを書いた。ここに私の糸くずルールのbuild.gradleファイルです
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")
}
// Runs the copyLintJar task after build has completed.
build.finalizedBy(copyLintJar)
ます。また、アップデートと同じ効果を得るために、他のプロジェクトへの依存性としてあなたのJava糸くずのプロジェクトを追加することができます3
UPDATE 2.
UPDATE 4
私は以来このトピックに関するブログ投稿を書いていますhttps://medium.com/@mosesJay/writing-custom-lint-rules-and-integrating-them-with-android-studio-inspections-or-carefulnow-c54d72f00d30#.3hm576b4f。
lombok.astライブラリを、私はより良い第2のリンクのソースコードで何が起こっているか理解するために参照することができます任意のドキュメントがありますか? – Moses
私はこのhttps://jar-download.com/java-documentation-javadoc.php?a=lombok-ast&g=com.android.tools.external.lombok&v=0.2.3を見つけましたが、ほとんど空です。多くの情報。 – Moses
これはあなたが手に入れてくれるのではないかと心配しています。ロンボクを使用して注釈を検索するAndroid検出器がさらにあります(例:CallSuperDetector)。私はこれが洗練されていないことを知っていますが、既存のソリューションを取って、彼らがどのように働いて、彼らのアプローチに適応するかを理解することは、もっと知りたい場合は、私に教えてください: – a11n