美文网首页
Android Lint & Checkstyle

Android Lint & Checkstyle

作者: swust_cp | 来源:发表于2018-06-27 17:50 被阅读70次

Android项目中配置Lint和Checkstyle

了解Android上lint,insepections以及checkstyle:Android静态代码分析

  • Android Lint,它只是检测和Android日常开发中一些问题,比如xml资源中hardcode text。

    在将配置之前,首先需要澄清一点,Android的lint工具是sdk自带的,它在~/Library/Android/sdk/tools/bin目录下,可以通过lint --list查看当前lint版本所支持的所有issue列表,通过lint --show也可以查看当前lint所支持的所有issue详细描述。

    Android Lint总体上还分了以下categories:

    ​ Correctness
    Correctness:Messages
    Correctness:Chrome OS
    Security
    Performance
    Usability:Typography
    Usability:Icons
    Usability
    Accessibility
    Internationalization
    Internationalization:Bidirectional Text

    随意选取其中一个详细信息(另外也可通过lint --show issueId查看具体某个issueId的详细信息):

    image.png

    如上图:

    RtlEnabled:issued id,同时还显示了RtlEnabled的Priority,Severity,Category。

    • 配置lint:
    1. 如果在Android的项目中可以直接运行./gradlew lint或者./gradlew xxxProject:lint即可运行相关的project,运行完成之后也会生成具体的report:

      image.png

这里暂以html打开就能看到一个Overview,显示有哪些错误,其中Security是lint其中一个category,同时lint还默认disable一些checks,如果还需disable更多的话,可以在lintOptions里配置对应的issueId为ignore或者添加lint.xml进行配置:

  1. 有些项目会根据实际情况会对默认lint提供的issues进行一些修改,比如修改它的serverity,disable一些issues,具体怎么配置呢,其实只需要在对应project的build.gradle中添加lintOptions即可:

    lintOptions {
        abortOnError false //当运行./gradlew lint时,出现错误不中断
        check "HardcodedText" //指定要检查的issue列表
        error "HardcodedText" //修改HardcodedText的优先级为error
        //另外也可以结合lint.xml来进行配置,也可以只用lint.xml这个看具体需要
        lintConfig file("../lint.xml") //默认会加载当前路径的lint.xml,如果lint.xml没有放在当前项目目录,则需要通过lintConfig进行指定
    }
    

    lint.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <lint>
        <!--配置severity为ignore相当于关闭此issue-->
        <issue id="RestrictedApi" severity="ignore"/> 
        <issue id="ExportedService" severity="ignore"/>
    </lint>
    

    这样配置之后,在重新执行./gradlew lint,就没有相关的lint提示了,另外也可以但多运行./gradlew lintDebug或者说./gradlew lintRelease,如果只是运行lint的话,它会默认运行所有的buildType。

    总体来说,lint配置还是很简单的。

    useful links:

    Writing custom lint rules

    使用lint改进你的代码

    DSL object for configuration lint options

  • Checkstyle 可以检测项目中的code style,保证团队成员开发的code风格一致,如:line length不能超过100(可设置),方法,变量,类的命名等。

    Checkstyle是一个开源的工具,github地址, 它提供了很多的module来进行配置,类似于Android lint的issues,查看具体的checks

    配置checkstyle

    1. 在build.gradle

      apply plugin: 'checksytle'
      
      task checkstyle(type: Checkstyle) {
          configFile rootProject.file('checkstyle/checkstyle.xml')
          source 'src/main/java'
          exclude '**/gen/**'
          ignoreFailures false
          showViolations true
          include '**/*.java'
      
          reports {
              xml.enabled false
              html.enabled true
              html.stylesheet resources.text.fromFile('../checkstyle/xsl/checkstyle-custom.xsl')
          }
      
          classpath = files()
      }
      

      先看下面的checkstyle-custom.xsl文件,这个xsl文件,可以让checksytle以不同的样式进行展现,常见的样式可以点这里,另外也可以参考这里,看下gradle checkstyle官方的文档。运行./gradlew checkstyle生成report,下面是我用上面的样式生成的report:

      image.png
  1. 接着看checkstyle/checkstyle.xml的配置文件,下面是它的内容

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE module PUBLIC
        "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
        "http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd">
    
    <module name="Checker">
        <module name="SuppressionFilter">
            <property name="file" value="checkstyle/checkstyle-suppressions.xml"/>
            <property name="optional" value="false"/>
        </module>
        <!--module name="NewlineAtEndOfFile"/-->
        <module name="FileLength"/>
        <module name="FileTabCharacter"/>
    
        <!-- Trailing spaces -->
        <module name="RegexpSingleline">
            <property name="format" value="\s+$"/>
            <property name="message" value="Line has trailing spaces."/>
        </module>
    
        <!-- Space after 'for' and 'if' -->
        <module name="RegexpSingleline">
            <property name="format" value="^\s*(for|if)[^ ]\("/>
            <property name="message" value="Space needed before opening parenthesis."/>
        </module>
    
        <!-- For each spacing -->
        <module name="RegexpSingleline">
            <property name="format" value="^\s*for \(.*?([^ ]:|:[^ ])"/>
            <property name="message" value="Space needed around ':' character."/>
        </module>
    
        <module name="TreeWalker">
            <!--<property name="cacheFile" value="${checkstyle.cache.file}"/>-->
    
            <!-- Checks for Javadoc comments.                     -->
            <!-- See http://checkstyle.sf.net/config_javadoc.html -->
            <!--module name="JavadocMethod"/-->
            <!--module name="JavadocType"/-->
            <!--module name="JavadocVariable"/-->
            <!--module name="JavadocStyle"/-->
    
    
            <!-- Checks for Naming Conventions.                  -->
            <!-- See http://checkstyle.sf.net/config_naming.html -->
            <!--<module name="ConstantName"/>-->
            <module name="LocalFinalVariableName"/>
            <module name="LocalVariableName"/>
            <module name="MemberName"/>
            <module name="MethodName">
                <property name="format" value="^[a-z][a-zA-Z0-9_]*$"/>
            </module>
            <module name="PackageName"/>
            <module name="ParameterName"/>
            <module name="StaticVariableName"/>
            <module name="TypeName"/>
    
    
            <!-- Checks for imports                              -->
            <!-- See http://checkstyle.sf.net/config_import.html -->
            <module name="AvoidStarImport"/>
            <module name="IllegalImport"/>
            <module name="RedundantImport"/>
            <module name="UnusedImports">
                <property name="processJavadoc" value="true"/>
            </module>
    
    
            <!-- Checks for Size Violations.                    -->
            <!-- See http://checkstyle.sf.net/config_sizes.html -->
            <module name="LineLength">
                <property name="max" value="120"/>
            </module>
            <module name="MethodLength">
                <property name="max" value="200"/>
            </module>
            <!--module name="ParameterNumber"/-->
    
    
            <!-- Checks for whitespace                               -->
            <!-- See http://checkstyle.sf.net/config_whitespace.html -->
            <module name="GenericWhitespace"/>
            <module name="EmptyForIteratorPad"/>
            <module name="MethodParamPad"/>
            <!--<module name="NoWhitespaceAfter"/>-->
            <module name="NoWhitespaceBefore"/>
            <module name="OperatorWrap">
                <property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
                        LT, MINUS, MOD, NOT_EQUAL, QUESTION, SL, SR, STAR"/>
                <property name="option" value="nl"/>
            </module>
            <module name="ParenPad"/>
            <module name="TypecastParenPad"/>
            <module name="WhitespaceAfter"/>
            <module name="WhitespaceAround"/>
    
    
            <!-- Modifier Checks                                    -->
            <!-- See http://checkstyle.sf.net/config_modifiers.html -->
            <module name="ModifierOrder"/>
            <module name="RedundantModifier"/>
    
    
            <!-- Checks for blocks. You know, those {}'s         -->
            <!-- See http://checkstyle.sf.net/config_blocks.html -->
            <!--module name="AvoidNestedBlocks"/-->
            <!--module name="EmptyBlock"/-->
            <module name="LeftCurly"/>
            <!--module name="NeedBraces"/-->
            <module name="RightCurly"/>
    
    
            <!-- Checks for common coding problems               -->
            <!-- See http://checkstyle.sf.net/config_coding.html -->
            <!--module name="AvoidInlineConditionals"/-->
            <module name="CovariantEquals"/>
            <module name="EmptyStatement"/>
            <!--<module name="EqualsAvoidNull"/>-->
            <module name="EqualsHashCode"/>
            <!--module name="HiddenField"/-->
            <module name="IllegalInstantiation"/>
            <!--<module name="InnerAssignment"/>-->
            <!--module name="MagicNumber"/-->
            <module name="MissingSwitchDefault"/>
            <!--<module name="RedundantThrows"/>-->
            <module name="SimplifyBooleanExpression"/>
            <module name="SimplifyBooleanReturn"/>
    
            <!-- Checks for class design                         -->
            <!-- See http://checkstyle.sf.net/config_design.html -->
            <!--module name="DesignForExtension"/-->
            <!--module name="FinalClass"/-->
            <!--module name="HideUtilityClassConstructor"/-->
            <!--module name="InterfaceIsType"/-->
            <!--module name="VisibilityModifier"/-->
    
    
            <!-- Miscellaneous other checks.                   -->
            <!-- See http://checkstyle.sf.net/config_misc.html -->
            <!--module name="ArrayTypeStyle"/-->
            <!--module name="FinalParameters"/-->
            <!--module name="TodoComment"/-->
            <module name="UpperEll"/>
        </module>
    </module>
    

    可以看到它配置了不同的module来对我们的项目进行检测。那么如果要对某些文件的某些module进行过滤,怎么办呢?其实这上面的xml配置中已经写出来了,配置一个SuppressionFilter即可

    <module name="SuppressionFilter">
            <property name="file" value="checkstyle/checkstyle-suppressions.xml"/>
            <property name="optional" value="false"/>
        </module>
    
  2. 那我们 来看看checkstyle-suppressions.xml这个文件到底是怎么配置的呢?

    <?xml version="1.0"?>
    
    <!DOCTYPE suppressions PUBLIC
        "-//Puppy Crawl//DTD Suppressions 1.2//EN"
        "http://checkstyle.sourceforge.net/dtds/suppressions_1_2.dtd">
    
    <suppressions>
        <!--<suppress checks="LineLength" files="**/eventbus/events/*.java"/>-->
    
        <suppress checks="AvoidStarImport|LineLength|WhitespaceAround|MethodName|RedundantImport|LeftCurlyCheck|ParameterNameCheck"
                  files=".*/eventbus/events/.*.java"/>
        <suppress checks="RegexpSingleline|LineLength|LocalFinalVariableName"
                  files=".*/utils/extend/.*.java"/>
    </suppressions>
    

    可以看到checks属性对应的就是module的名字,files就是需要过滤的文件,这样在重新运行./gradlew checkstyle。这些文件对应的modules就不会进行检测。
    如果想将让checkstyle加入到git-hooks,戳这里在Git hook上配置Android Lint和Checkstyle

相关文章

网友评论

      本文标题:Android Lint & Checkstyle

      本文链接:https://www.haomeiwen.com/subject/gpriyftx.html