2016-10-19 6 views
5

를 확인합니다 : 것입니다작성 사용자 정의 보풀 경고가 나는 다음과 같은 주석을 작성한 사용자 정의 주석

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 명령의 로그 출력에만 경고를 제공합니다. 나는이 경고가있는 메소드가 호출되는 곳이면 어디서나 다른 lint 경고와 함께이 경고를 Android Studio에 표시하려고합니다. 이것이 내가 맞춤 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

을 당신은 안드로이드 스튜디오 검사와 사용자 정의 보풀 검사를 통합 할 수 있습니다 프로젝트의 루트에 lint.xml 파일을 만들고 여기에 사용자 정의 lint 규칙을 추가하면 다음과 같습니다.

문제 태그의 ID는 CaimitoDetector 클래스의 Issue.create() 메서드의 첫 번째 인수에서 제공된 ID입니다. 또한 lint 규칙을 빌드하여 출력 된 jar 파일을 /home/{user}/.android/lint 폴더에 복사해야 작동합니다. 나는 이것을 위해 custom 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) 

또한 업데이트와 같은 효과를 얻기 위해 다른 프로젝트에 대한 종속성으로 자바 보풀이 프로젝트를 추가 할 수 있습니다 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이 방법

에 있는지 나는 안드로이드의 기본 탐지기 [2]를 살펴 가지고하는 것이 좋습니다 확인할 수 있습니다. 아마 당신은 시작하기 좋은 지점을 발견 할 것입니다. 예 : AnnotationDetector.

경고가 발생하여 Android Studio에 표시됩니다.

사용자 정의 규칙을 프로젝트에 올바르게 통합하면 Lint에서 경고를 표시합니다. 프로젝트에 사용자 지정 규칙을 통합하는 방법에 대한 다양한 옵션을 보려면 여기 [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 도서관은? – 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

나는 이것이 모두 당신이 얻게 될까 봐 걱정됩니다. lombok을 사용하고 특수 효과를 검색하는 Android 탐지기가 더 많이 있습니다 (예 : CallSuperDetector). 나는 이것이 정교하지 않다는 것을 안다. 그러나 기존의 해결책을 취하고 그들이 어떻게 일하고 그들의 접근 방식을 적응 시키는가는 아마 우리가 가진 전부 일 것이다. 자세한 내용을 알고 싶다면 – a11n