Custom Lint Rules

15876 단어 Android
이 글은 Android Advent Calendar 2015 22일째 되는 글이다.
2일 지나서 죄송합니다...
전날은 @shiraji씨의 나는 Annotation Processing(app)의 총결산 + Android Annotations(AA)와 AutoValue의 샘플 코드를 써 보았다.입니다.
아주 작은 단락이지만 오리지널 규칙을 확장lint하는 방법을 소개해 드리겠습니다.
평소에 앱을 개발하면 기본적으로 필요하지 않지만 프로그램 라이브러리를 제공할 때 비교적 번거로운 인터페이스라면 표준lint에서 경고를 보내기 때문에 이런 문제들을 해결하는 데 도움이 된다.
또 팀 개발에 정적 점검 프로그램을 추가하려는 경우에도 편리하다.

How to develop


lint의 사용자 정의 규칙을 만들기 위해서는 다음과 같은 3단계를 대체적으로 이행해야 한다.
  • Detector
  • 생성
  • Issue
  • 생성
  • Registry
  • 작성
    우선 프로젝트를 만들자.
    lint를 PC에서 실행하기 위해 안드로이드 프로젝트가 아니라 순수한 자바 프로젝트로 제작되었습니다.
    구축 시스템에서Gradle을 사용할 때 다음은build입니다.gradle에 추가합니다.
    build.gradle
    apply plugin: 'java'
    
    repositories {
        jcenter()
    }
    
    dependencies {
        compile 'com.android.tools.lint:lint-api:24.3.1'
        compile 'com.android.tools.lint:lint-checks:24.3.1'
    }
    
    jar {
        manifest {
            // define your registry
            attributes("Lint-Registry": "com.example.google.lint.MyIssueRegistry")
        }
    }
    
    defaultTasks 'assemble'
    
    dependencies에lint-api와lint-checks 두 가지jar를 추가했습니다.
    jar 작업 내부에 MyIssueRegistry와 같은 종류가 정의되어 있으며, 아래에 설명이 있을 것입니다.

    Detector


    우선, detector 반을 만듭니다.이 반은 실제 보고 issue의 논리를 정의하기 위한 반이다.
    예를 들어, 특정 Custom View를 사용할 때는 attribute를 사용해야 합니다.
    package googleio.demo;
    
    import java.util.Collection;
    import java.util.Collections;
    
    import org.w3c.dom.Element;
    
    import com.android.tools.lint.detector.api.Category;
    import com.android.tools.lint.detector.api.Issue;
    import com.android.tools.lint.detector.api.ResourceXmlDetector;
    import com.android.tools.lint.detector.api.Scope;
    import com.android.tools.lint.detector.api.Severity;
    import com.android.tools.lint.detector.api.XmlContext;
    
    public class MyDetector extends ResourceXmlDetector {
        public static final Issue ISSUE = Issue.create(
                "MyId",
                "My brief summary of the issue",
                "My longer explanation of the issue",
                Category.CORRECTNESS, 6, Severity.WARNING,
                new Implementation(MyDetector.class, Scope.RESOURCE_FILE_SCOPE));
    
        @Override
        public Collection<String> getApplicableElements() {
            return Collections.singletonList(
                    "com.google.io.demo.MyCustomView");
        }
    
        @Override
        public void visitElement(XmlContext context, Element element) {
            if (!element.hasAttributeNS(
                    "http://schemas.android.com/apk/res/com.google.io.demo",
                    "exampleString")) {
                context.report(ISSUE, element, context.getLocation(element),
                        "Missing required attribute 'exampleString'");
            }
        }
    }
    
    우선, 이 등급은 ResourceXmlDetector이라는 등급으로 확장되었다.이 레벨은 레이아웃, String 자원 등 XML 파일을 검사할 때 사용하는 detector입니다.
    detector는 자바의 원본 코드와 바이트 코드를 검사하는 데 사용할 다른 물품도 준비했다.여기.에서 확인할 수 있다.getApplicableElements 이 방법은 이 detector를 검사 대상의 XML 라벨로 반환해야 한다.
    여기에는 MyCustomView의 FQDN이 지정되어 있습니다.이렇게 하면 lint는 MyCustom View 탭이 검출된 후 visitElement 방법을 부른다.visitElement 방법에서 두 번째 파라미터의 요소에 속성이 포함되어 있는지 확인하고 없으면 리포트에 경고가 발생합니다.첫 번째 인자 context에는 다양한 정보가 포함되어 있으며, 프로젝트의 정보 (minSdkVersion과 targetSdkVersion) 와 XML의 path도 얻을 수 있습니다.

    Issue

    context.report 메서드의 첫 번째 매개변수는 Issue입니다.Issue는 detector에서 감지된 경고를 나타내는 클래스입니다.
    public static final Issue ISSUE = Issue.create(
        "MyId",
        "My brief summary of the issue",
        "My longer explanation of the issue",
        Category.CORRECTNESS, 6, Severity.WARNING,
        new Implementation(MyDetector.class, Scope.RESOURCE_FILE_SCOPE));
    
    매개 변수는 대량으로 혼동되기 쉽다. 아래와 같다.
  • ID...이 아이슈를 식별하는 데 쓰인다.간결한 서술성이 필요하다.
  • Summary...한 줄에 포함된 문자 수로 문제의 개요를 기록합니다.IDE의 lint UI는 원칙적으로 이summary를 사용합니다.
  • Explanation...Summary보다 긴 문자 수로 문제가 무엇인지 자세히 설명합니다.이 설명은 lint의 HTML 보고서에서 사용됩니다.
  • Category...Category는 (ex) Usability > Icons) 를 끼워 넣으면 문제의 필터와 정렬에 도움이 됩니다.또한 명령선에서 특정 type의 lint만 실행할 수 있습니다.'correctness'와'performance'등API에 정의된 값을 사용한다.
  • Prority... 1부터 10까지의 정수를 정의할 수 있으며 10은 가장 심각한 레벨을 나타냅니다.issue를 정렬할 때 사용합니다.
  • Severity...기본값인 fatal, error, warning,ignore 네 개를 정의할 수 있습니다.이 값은 사용자 lint입니다.xml로 덮어쓸 수 있습니다.
  • Detector class...방금 설치한 Detector 클래스를 지정합니다.Detector는 모든 lint의run에서 생성되기 때문에 상태의 cleanup 등에 주의할 필요가 없습니다.
  • Scope...이 issue가 적용되는 역할 영역을 지정합니다.여기. 일람표가 있으니 적당한 것을 선택하세요.
  • Registry


    기존 Issue는 BuiltinIssueRegistry 클래스에 집중되어 있으며 사용자 정의 규칙을 정의할 경우 Registry 클래스를 독자적으로 정의해야 한다.
    package googleio.demo;
    
    import java.util.Arrays;
    import java.util.List;
    
    import com.android.tools.lint.client.api.IssueRegistry;
    import com.android.tools.lint.detector.api.Issue;
    
    public class MyIssueRegistry extends IssueRegistry {
    
        public MyIssueRegistry() {
        }
    
        @Override
        public List<Issue> getIssues() {
            return Arrays.asList(
                MyDetector.ISSUE
            );
        }
    }
    
    getIssues 메서드가 생성된 Issue를 반환합니다.Registry는 lint를 실례화할 때 무변수 구조기를 사용하기 때문에 무변수 구조기 정의는 필수적입니다.

    Run lint


    위에서 말한 바와 같이 맞춤형 규칙의 제작은 끝났지만 실제로 실행하기에는 시간이 좀 걸린다.
    상기 프로젝트에서 생성된jar를 .android/lint/에 설치해야 합니다.
    겸사겸사 말씀드리지만, 하나하나cp는 매우 번거롭습니다.build.gradle에서 다음과 같은 작업을 미리 정의하는 것이 좋을 것 같습니다.
    task install(type: Copy, dependsOn: build) {
        from configurations.lintChecks
        into System.getProperty('user.home') + '/.android/lint/'
    }
    
    lint는 다음 순서대로 합니다.android 폴더를 검색합니다.
  • ANDROID_SDK_HOME (system prop or environment variable)
  • user.home (system prop)
  • HOME (environment variable)
  • 따라서 ANDROIDSDK_홈에서.android가 존재하면user.홈을 검색하지 않도록 주의하세요.
    설치가 완료되면 lint 명령을 통해 실행할 수 있습니다.
    $ lint --show MyId
    MyId
    ----
    Summary: My summary of the issue
    
    Priority: 6 / 10
    Severity: Warning
    Category: Correctness
    
    My longer explanation of the issue
    
    $ lint --check MyId /demo/workspace/Demo
    
    Scanning Demo: ...............
    res/layout/sample_my_custom_view.xml:20: Warning: Missing required attribute 'exampleString' [MyId]
        <com.google.io.demo.MyCustomView
        ^
    0 errors, 1 warnings
    

    젠킨스 쓸 때...


    Android Lint Plugin 사용 시 $ANDROIDLINT_JARS라는 환경 변수로jar을 지정하면 된다고 합니다.

    좀 더 복잡한 룰을 만들고 싶은데...


    읽다기존 소스공부하세요.

    Link

  • lint
  • Writing Custom Lint Rules
  • Writing a Lint Check
  • googlesamples/android-custom-lint-rules
  • Help developers with custom Lint rules
  • Writing Custom Lint Checks with Gradle
  • 좋은 웹페이지 즐겨찾기