2016-12-19 5 views
11

私は楽しいためにカスタムリントディテクタを作成しています。私はcustom lint rule in Android(Javaの場合と同じにする必要があります)を作成するには、大ぞうきょう牧場の授業を行っていますJava/Android用のカスタムリントインターフェイスを実装せずにクラス呼び出しを見つけた場合のレポート

私は欲しいオカレンスを検出できます。クラスコンストラクターが呼び出されたことを示します。しかし、私たちはAbstract Syntax Tree 経由でトラバースしているため、コールバックの実装を検出できません。私はJavaにファイルをチェックするように指示する方法が不明で、オカレンスが見つからない場合にのみ報告します。この場合、インタフェースの実装。私は一度に1枚の葉しか見ることができません。

どのように2回発生するのか、発生した場所を格納し、それに応じてロジックとレポートを実行するにはどうすればよいですか?

package com.bignerdranch.linette.detectors; 

import com.android.annotations.NonNull; 
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.Location; 
import com.android.tools.lint.detector.api.Scope; 
import com.android.tools.lint.detector.api.Severity; 
import com.android.tools.lint.detector.api.TextFormat; 

import java.io.File; 
import java.util.EnumSet; 
import java.util.List; 

import lombok.ast.AstVisitor; 
import lombok.ast.Node; 

/** 
* Lint check for the usage of to-do statements 
*/ 
public class CallBackDetector extends Detector implements Detector.JavaScanner { 

    private static final String FRAGMENT_MATCHER_STRING = "NoInternetDialogFragment()"; 
    private static final String INTERFACE_MATCHER_STRING = 
      "NoInternetDialogFragment.NoInternetCallbackInterface"; 

    private static final Class<? extends Detector> DETECTOR_CLASS = CallBackDetector.class; 
    private static final EnumSet<Scope> DETECTOR_SCOPE = Scope.JAVA_FILE_SCOPE; 

    private static final Implementation IMPLEMENTATION = new Implementation(
      DETECTOR_CLASS, 
      DETECTOR_SCOPE 
    ); 

    private static final String ISSUE_ID = "NoInternetDialogFragment"; 
    private static final String ISSUE_DESCRIPTION = 
      "NoInternetDialogFragment Callback not detected"; 
    private static final String ISSUE_EXPLANATION = 
      "When using NoInternetDialogFragment you must implement its' callback -- " 
        + "NoInternetCallbackInterface"; 
    private static final Category ISSUE_CATEGORY = Category.CORRECTNESS; 
    private static final int ISSUE_PRIORITY = 10; 
    private static final Severity ISSUE_SEVERITY = Severity.ERROR; 

    public static final Issue ISSUE = Issue.create(
      ISSUE_ID, 
      ISSUE_DESCRIPTION, 
      ISSUE_EXPLANATION, 
      ISSUE_CATEGORY, 
      ISSUE_PRIORITY, 
      ISSUE_SEVERITY, 
      IMPLEMENTATION 
    ); 

    /** 
    * Constructs a new {@link CallBackDetector} check 
    */ 
    public CallBackDetector() { 
    } 

    @Override 
    public boolean appliesTo(@NonNull Context context, @NonNull File file) { 
     return true; 
    } 

    @Override 
    public List<Class<? extends Node>> getApplicableNodeTypes() { 
     return null; 
    } 

    @Override 
    public AstVisitor createJavaVisitor(@NonNull JavaContext context) { 
     String source = context.getContents(); 

     // Check validity of source 
     if (source == null) { 
      return null; 
     } 

     if(source.indexOf(INTERFACE_MATCHER_STRING) >=0){ 
      return null; 
     } 
     int index = source.indexOf(FRAGMENT_MATCHER_STRING); 

     for (int i = index; i >= 0; i = source.indexOf(FRAGMENT_MATCHER_STRING, i + 1)) { 
      Location location = Location.create(context.file, source, i, 
        i + FRAGMENT_MATCHER_STRING.length()); 
      context.report(ISSUE, location, ISSUE.getBriefDescription(TextFormat.TEXT)); 
     } 
     return null; 
    } 

} 
+0

クラスコンストラクタをいくつかのファクトリメソッドにラップする場合はどうなりますか? –

答えて

1

あなたはフィールドとして検索し、すべての構文トラバーサルの最後にそれらを報告の参照を格納している場合、それは可能です:あなたが今持っているようcreateJavaVisitorインサイド

は、コンストラクタを使用するためのチェックを行います。この時点で問題を報告する代わりに、CallBackDetectorにコンストラクタの使用に関する参照を保持するコレクションフィールドを作成します。その後、すべてのコンストラクター使用のリストが表示されます。

ここでもまた、createJavaVisitorあなたが探しているインターフェイスを実装しているクラスをチェックし、これを別のフィールドコレクションに追加します。

DetectorのメソッドafterCheckProjectapi here)をオーバーライドして、いつ完了したかを知ることができます。このメソッドでは、2つのコレクションを繰り返し処理し、一致するペア(コンストラクターと実装されているインターフェイス)である両方のコレクションからアイテムをすべて削除します。いずれのコレクションにも残っているものは、Lintのエラーです。この時点で問題として追加できます。

関連する問題