2016-10-19 30 views
5

denetlemek için: amaçlanmaktadırYazma özel tiftik uyarı Ben şu ek açıklama yazdım özel açıklama

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 { 

} 

dikkatsizce denilen sorunlara neden olabilir yöntemlerini açıklama için. Projeme bir ek açıklama işlemci ekledim, ancak bu yalnızca javac komutunun günlük çıktısında uyarı veriyor. Bu uyarının çağrıldığı bir yöntemle, Android Studio'da bu uyarıyı diğer tiftik uyarılarıyla birlikte görünmesini istiyorum. Bu yüzden özel bir tiftik kuralı yazmaya çalışıyorum. Ben tiftik kuralının temel iskelete sahip:

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); 
    } 

} 

Ama buradan devam etmek nasıl bilmiyorum. Bir yöntemde bir açıklama bulunup bulunmadığını nasıl kontrol edebilirim ve Android Studio'da görünecek şekilde bir uyarı yükseltebilir miyim? İşte

herkes için benim Dedektör sınıfı aynı şeyi arıyor

GÜNCELLEME:

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 denetimler ile özel tiftik kontrol entegre edebilirsiniz projenizin kökünde bir lint.xml dosyası oluşturarak ve bunun gibi size özel tiftik kuralı ekleyerek:

<?xml version="1.0" encoding="UTF-8"?> 
<lint> 
    <issue id="Warning" severity="warning"/> 
</lint> 

Sorun etiketinin kimliği, CaimitoDetector sınıfındaki Issue.create() yönteminin ilk bağımsız değişkeninde sağlanan kimliktir. Ayrıca, çalışmasını sağlamak için tiftik kuralınızı /home/{user}/.android/lint klasörünüze oluşturarak çıkarılan jar dosyasını da kopyalamanız gerekecektir. Bunun için özel bir taslak görevi yazdım. İşte benim tiftik kuralın build.gradle dosyasıdır

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) 

Ayrıca güncelleme olarak aynı etkiyi elde etmek için diğer projeler üzerinde bir bağımlılık olarak Java tiftik proje ekleyebilir 3

GÜNCELLEME 2.

enter image description here

GÜNCELLEME 4

Bu konuya bir blog yazısı ekledim https://medium.com/@mosesJay/writing-custom-lint-rules-and-integrating-them-with-android-studio-inspections-or-carefulnow-c54d72f00d30#.3hm576b4f.

cevap

2

Ama senin Detector ilk için bir test yazmak için önermek

buradan devam etmek nasıl bilmiyorum. İşte, Detector testlerinin nasıl yazılacağını gösteren bir örnek projedir [1]. Böylece Detector’unuzu istediğiniz gibi ayarlayabilir ve ayarlayabilirsiniz.

Nasıl bir annoation bir yöntem

üzerinde varsa ben de Android'in varsayılan dedektörleri [2] bir göz öneririm kontrol edebilirsiniz. Orada muhtemelen başlamak için iyi bir nokta bulacaksınız. Örneğin. AnnotationDetector.

ve Android Studio'da görünecek şekilde bir uyarı yükseltmek?

Özel kurallarınızı projenize doğru şekilde entegre ederseniz, Lint sizin için uyarıyı yükseltir. Projenizdeki özel kuralların nasıl entegre edileceğine dair farklı seçenekler için lütfen buraya [3] bakın. Not: Özel kuralların AFAIK uyarıları, yalnızca ilgili Gradle görevini çalıştırırken raporlanır. Android Studio'nun "otomatik vurgulaması" özel kurallarla çalışmaz.

  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

mu daha iyi, ikinci bağlantının kaynak kodunda ne olup bittiğini anlamak için başvurabilir herhangi bir belgeniz var lombok.ast kütüphane? – Moses

+0

Bu https://jar-download.com/java-documentation-javadoc.php?a=lombok-ast&g=com.android.tools.external.lombok&v=0.2.3 adresini buldum, ancak çoğunlukla boşlar çok bilgi. – Moses

+0

Korkarım ki alabileceğin her şey bu. Lombok kullanan ve ek açıklamaları arayabilen daha fazla Android dedektörü vardır (ör. CallSuperDetector). Bunun sofistike olmadığını biliyorum, ancak mevcut çözümleri ele alıp, onların nasıl çalıştığını ve adapte olduklarını anlamak belki de sahip olduğumuz her şeydir. Daha fazla bilgi ederseniz, lütfen bana bildirin :-) – a11n