2016-10-19 13 views
5

をチェックするために、カスタムの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.

enter image description here

UPDATE 4

私は以来このトピックに関するブログ投稿を書いていますhttps://medium.com/@mosesJay/writing-custom-lint-rules-and-integrating-them-with-android-studio-inspections-or-carefulnow-c54d72f00d30#.3hm576b4f

答えて

2

しかし、私はあなたのDetector最初のためのテストを書くことをお勧めし

ここから続行するのか分かりません。ここには、Detectorテスト[1]を書く方法を示すサンプルプロジェクトがあります。あなたが好きなようにあなたのDetectorを試して調整することができますその方法。

にはどうすればannoationはメソッド

上に存在する場合、私はAndroidのデフォルトの検出器[2]を見てすることをお勧め確認することができます。あなたはたぶん始めるのが良い点を見つけるでしょう。例えば。 AnnotationDetector

Android Studioで表示されるような警告を表示しますか?

カスタムルールをプロジェクトに正しく組み込むと、警告が表示されます。プロジェクトでカスタムルールを統合する方法のさまざまなオプションについては、こちら[3]をご覧ください。注意:カスタムルールのAFAIK警告は、対応するGradleタスクの実行時にのみ報告されます。 Android Studioの「自動ハイライト」はカスタムルールでは機能しません。

  1. https://github.com/a11n/CustomLintRules
  2. https://android.googlesource.com/platform/tools/base/+/master/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks
  3. https://github.com/a11n/android-lint/tree/master/6_application
+0

lombok.astライブラリを、私はより良い第2のリンクのソースコードで何が起こっているか理解するために参照することができます任意のドキュメントがありますか? – Moses

+0

私はこのhttps://jar-download.com/java-documentation-javadoc.php?a=lombok-ast&g=com.android.tools.external.lombok&v=0.2.3を見つけましたが、ほとんど空です。多くの情報。 – Moses

+0

これはあなたが手に入れてくれるのではないかと心配しています。ロンボクを使用して注釈を検索するAndroid検出器がさらにあります(例:CallSuperDetector)。私はこれが洗練されていないことを知っていますが、既存のソリューションを取って、彼らがどのように働いて、彼らのアプローチに適応するかを理解することは、もっと知りたい場合は、私に教えてください: – a11n

関連する問題