2017-12-07 7 views
1

Androidコードでコンストラクタに注入された数をチェックするリントルールを作成しようとしています。たとえば、ビューモデルに対して特定の数値を超えた場合、私は糸くずの警告を発生させます。コンストラクタ内の注入回数のリントルール

私は糸くず検出器にUastScannerを実装する必要があることを知っていますが、良い文書が見つからないために迷子になっています。他の誰かがこれまで何かしたことはありますか?それとも良い文書化を見つけることができますか?

ありがとうございます!

+0

私は糸くずのルールは、Androidの中で最も文書化されていないものの1つだと考えています。私は[既存のものを見る]ことをお勧めします(https://android.googlesource.com/platform/tools/base/+/master/lint/libs/lint-checks/src/main/java/com /アンドロイド/ツール/ lint /チェック)とそこから行く。 –

答えて

0

だから私はJavaScannerを使用して解決策を見つけることができたが、私は(私たちはあまりにもKotlinクラスを持っているので、それは、私が使用したいものである)UastScannerを使用して、まだ何も見つかっていない。

public class NumberOfDependenciesInjectedDetector extends Detector implements Detector.JavaScanner { 

    private static final int NUMBER_OF_INJECTIONS_ALLOWED = 5; 
    private static final Class<? extends Detector> DETECTOR = NumberOfDependenciesInjectedDetector.class; 
    private static final EnumSet<Scope> SCOPE = Scope.JAVA_FILE_SCOPE; 
    private static final Implementation IMPLEMENTATION = new Implementation(DETECTOR, SCOPE); 

    public static final Issue ISSUE = Issue.create(
      "NumberOfDependenciesInjected", 
      "Limit number of injections in a class via constructor", 
      "A longer description here", 
      Category.CORRECTNESS, 
      10, 
      Severity.ERROR, 
      IMPLEMENTATION 
    ); 

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

    @Override 
    public Speed getSpeed(Issue issue) { 
     return Speed.FAST; 
    } 

    @Override 
    public List<Class<? extends Node>> getApplicableNodeTypes() { 
     return Collections.<Class<? extends Node>>singletonList(ConstructorDeclaration.class); 
    } 

    @Override 
    public AstVisitor createJavaVisitor(JavaContext context) { 
     return new ConstructorVisitor(context); 
    } 

    private static class ConstructorVisitor extends ForwardingAstVisitor { 

     private JavaContext javaContext; 

     private ConstructorVisitor(JavaContext javaContext) { 
      this.javaContext = javaContext; 
     } 

     @Override 
     public boolean visitConstructorDeclaration(ConstructorDeclaration node) { 
      if (node.astParameters().size() > NUMBER_OF_INJECTIONS_ALLOWED) { 
       javaContext.report(ISSUE, node, javaContext.getLocation(node), "My message goes here"); 
       return true; 
      } 
      return false; 
     } 
    } 
} 
0

*注 - 編集されたソリューションの回答全体をお読みください。 *

私はそうのようなUAST変換を書くことができました:

public class NumberOfDependenciesInjectedDetector extends Detector implements Detector.UastScanner { 

    private static final int NUMBER_OF_INJECTIONS_ALLOWED = 5; 
    private static final Class<? extends Detector> DETECTOR = NumberOfDependenciesInjectedDetector.class; 
    private static final EnumSet<Scope> SCOPE = Scope.JAVA_FILE_SCOPE; 
    private static final Implementation IMPLEMENTATION = new Implementation(DETECTOR, SCOPE); 

    public static final Issue ISSUE = Issue.create(
      "NumberOfDependenciesInjected", 
      "Limit number of injections in a class via constructor", 
      "A longer description here", 
      Category.CORRECTNESS, 
      10, 
      Severity.ERROR, 
      IMPLEMENTATION 
    ); 

    @Override 
    public List<Class<? extends UElement>> getApplicableUastTypes() { 
     return Collections.<Class<? extends UElement>>singletonList(UClass.class); 
    } 

    @Override 
    public UElementHandler createUastHandler(JavaContext context) { 
     return new ConstructorVisitor(context); 
    } 

    private static class ConstructorVisitor extends UElementHandler { 

     private JavaContext javaContext; 

     private ConstructorVisitor(JavaContext javaContext) { 
      this.javaContext = javaContext; 
     } 

     @Override 
     public void visitClass(UClass clazz){ 
      UMethod[] methods = clazz.getMethods(); 

      for(UMethod method : methods){ 
       if(!method.isConstructor()) continue; 

       if (method.getParameterList().getParametersCount() > NUMBER_OF_INJECTIONS_ALLOWED) { 
        javaContext.report(ISSUE, method, javaContext.getLocation(method), "Injections exceed allowed value of " + NUMBER_OF_INJECTIONS_ALLOWED); 
       } 
      } 
     } 
    } 
} 

しかし、まだ非常に混乱... Kotlinのソースファイルをピックアップしていないようです。

EDIT:12/19/17 - FIXED

問題は2倍であった:

1)作業のチェックをブロックされたサイ方法の隠された使用方法は確かにありました。 visitClassメソッドはgetParameterList()ではなくgetUastParameters()を使用します。して上にvisitclassを交換してください:

糸くず-devのグループに直接のTor Norbyeと話した後、彼は、Android Studioの3.0が実際に糸くずがkotlinで外部から動作しませんので、動作するように期待されていなかったことを指摘し
@Override 
public void visitClass(UClass clazz){ 
    UMethod[] methods = clazz.getMethods(); 

    for(UMethod method : methods){ 
     if(!method.isConstructor()) continue; 

     if (method.getUastParameters().size() > NUMBER_OF_INJECTIONS_ALLOWED) { 
      javaContext.report(ISSUE, clazz, javaContext.getLocation(method), "Injections exceed allowed value of " + NUMBER_OF_INJECTIONS_ALLOWED); 
     } 
    } 
} 

2)ここで説明するように。 Android Studio 3.1 Canaryにアップグレードして、linterを実行すると、期待されるレポートが作成されました。

+0

問題がScope.JAVA_FILE_SCOPEにあると思われます。しかし、Scope.ALLを含む他のスコープのどれも動作していないようです。JAVA_FILE_SCOPEを除いて、リンターは問題のファイルを報告しません。 –

+0

私が考えることができるのは、このスニペットにいくつかの偶発的なPSIの使用があることだけですが、どこが見えないのでしょうか。その結果、javaファイルだけが動作します。 –

関連する問題