Android-代码规范自动检测之CheckStyle

概述

Checkstyle是一个开发工具,用于帮助程序员编写符合编码标准的Java代码。它使检查Java代码的过程自动化,从而使人们不必承担这项乏味(但重要)的任务。这对于想要执行编码标准的项目来说是非常理想的。

Checkstyle是高度可配置的,可以支持几乎任何编码标准。提供了一个示例配置文件,该文件支持Sun代码约定、谷歌Java风格。

集成方式

可以通过gradle插件和gradle脚本两种方式来实现。下面列一下两种方式的有点:

  • gradle插件:可以把扫描结果输出到.html和.xml文件中。

  • gradle脚本:可以直接点击问题跳转到源码处,方便快速查看。

Gradle脚本

首先在工程根目录(其它位置也可以)下创建配置文件夹codestyles/checkstyle。然后在创建checkstyle.xml文件用于存放代码规范配置,创建checkstyle.gradle用于配置插件和脚本。文件目录如下图:
配置目录结构
checkstyle.gradle文件内容


allprojects { org.gradle.api.Project project ->
    apply plugin: 'checkstyle'
 
    checkstyle {
        configFile rootProject.file('codestyles/checkstyle/checkrlues.xml')
        toolVersion '8.23'
        ignoreFailures false
        showViolations true
    }
    task('checkstyle', type: Checkstyle) {
        source 'src/main/java'
        include '**/*.java'
        exclude '**/R.java', '**/BuildConfig.java'
        classpath = files()
    }
        project.afterEvaluate {
        }
    }

checkstyle.xml配置文件

<?xml version="1.0"?><!DOCTYPE module PUBLIC
    "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
    "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<module name="Checker">
    <module name="TreeWalker">
 
        <!-- Annotations-->
        <!-- 注解位置-->
        <module name="AnnotationLocation">
            <property name="allowSamelineMultipleAnnotations" value="false" />
            <property name="allowSamelineSingleParameterlessAnnotation" value="false" />
            <property name="allowSamelineParameterizedAnnotation" value="false" />
        </module>
 
 
        <!-- Block-->
        <!--检查空代码块-->
        <module name="EmptyBlock" />
 
        <!--定义左大括号位置-->
        <module name="LeftCurly">
            <property name="option" value="eol" />
            <property name="tokens" value="CLASS_DEF,INTERFACE_DEF,METHOD_DEF,CTOR_DEF" />
        </module>
 
        <module name="RightCurly">
            <property name="id" value="RightCurlySame" />
            <property name="tokens" value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
                    LITERAL_DO" />
        </module>
        <module name="RightCurly">
            <property name="id" value="RightCurlyAlone" />
            <property name="option" value="alone" />
            <property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
                    INSTANCE_INIT" />
        </module>
 
        <!--检查空Catch块-->
        <module name="EmptyCatchBlock">
            <property name="exceptionVariableName" value="expected|ignore" />
        </module>
 
        <!--缺少括号-->
        <module name="NeedBraces">
            <property name="allowSingleLineStatement" value="true" />
            <property name="tokens" value=" LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_IF, LITERAL_WHILE, LAMBDA" />
        </module>
 
 
        <!-- Javadoc-->
        <!--<module name="JavadocType">-->
        <!--    <property name="authorFormat" value="\S" />-->
        <!--    <property name="tokens" value="CLASS_DEF,INTERFACE_DEF" />-->
        <!--</module>-->
 
 
        <!--  Naming -->
        <!--常量命名-->
        <module name="ConstantName" />
        <module name="ClassTypeParameterName">
            <message key="name.invalidPattern"
                value="Class type name ''{0}'' must match pattern ''{1}''." />
            <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)" />
        </module>
        <!--lambda 参数命名-->
        <module name="LambdaParameterName" />
        <!--接口注解命名-->
        <module name="InterfaceTypeParameterName" />
        <module name="MethodTypeParameterName" />
        <module name="MethodName" />
        <module name="ParameterName" />
        <module name="PackageName">
            <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$" />
        </module>
        <module name="TypeName">
            <message key="name.invalidPattern"
                value="Type name ''{0}'' must match pattern ''{1}''." />
        </module>
 
        <!-- Imports-->
        <module name="RedundantImport" />
        <module name="UnusedImports" />
 
 
        <!--Modifiers-->
 
 
        <!--Coding -->
        <module name="CovariantEquals" />
        <module name="EmptyStatement" />
        <module name="EqualsAvoidNull" />
        <module name="EqualsHashCode" />
        <module name="NestedTryDepth">
            <property name="max" value="3" />
        </module>
        <module name="SimplifyBooleanExpression" />
        <module name="SimplifyBooleanReturn" />
        <module name="StringLiteralEquality" />
        <module name="EqualsAvoidNull" />
        <module name="ExplicitInitialization">
            <property name="onlyObjectReferences" value="true" />
        </module>
        <!--switch 缺少break return语句-->
        <module name="FallThrough" />
        <module name="OneStatementPerLine" />
        <module name="RequireThis" />
        <module name="UnnecessaryParentheses" />
        <module name="UnnecessarySemicolonInEnumeration" />
        <module name="UnnecessarySemicolonInTryWithResources" />
        <module name="DefaultComesLast" />
        <module name="HiddenField" >
            <property name="ignoreConstructorParameter" value="true"/>
            <property name="ignoreSetter" value="true"/>
        </module>
        <module name="IllegalInstantiation" />
 
        <!--for嵌套层次-->
        <module name="NestedForDepth">
            <property name="max" value="3" />
        </module>
        <!--if 嵌套层数-->
        <module name="NestedIfDepth">
            <property name="max" value="4" />
        </module>
        <!--try catch嵌套层数-->
        <module name="NestedTryDepth">
            <property name="max" value="3" />
        </module>
        <!--非法字符-->
        <module name="IllegalTokenText">
            <property name="tokens" value="STRING_LITERAL, CHAR_LITERAL" />
            <property name="format"
                value="\\u00(08|09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)" />
            <property name="message" value="Avoid using corresponding octal or Unicode escape." />
        </module>
 
 
        <!--Class Design-->
        <!--class 名称需和文件名一致-->
        <module name="OneTopLevelClass" />
        <module name="NoFinalizer" />
 
 
        <!--Miscellaneous-->
        <module name="ArrayTypeStyle" />
        <module name="UpperEll" />
        <module name="OuterTypeFilename" />
 
 
        <!--Regexp-->
        <module name="RegexpSinglelineJava">
            <!-- . matches any character, so we need to
                 escape it and use \. to match dots. -->
            <property name="format" value="System\.out\.println" />
            <property name="ignoreComments" value="true" />
        </module>
 
 
        <!--Size Violations-->
        <module name="LineLength">
            <property name="max" value="120" />
            <property name="ignorePattern"
                value="^package.*|^import.*|a href|href|http://|https://|ftp://|^\s*//.*" />
 
        </module>
 
        <!--<module name="ParameterNumber" />-->
 
 
        <!--Whitespace-->
        <module name="EmptyLineSeparator">
            <property name="allowNoEmptyLineBetweenFields" value="true" />
        </module>
        <module name="MethodParamPad" />
        <module name="NoWhitespaceBefore">
            <property name="tokens"
                value="COMMA, SEMI, POST_INC, POST_DEC, DOT, ELLIPSIS, METHOD_REF" />
            <property name="allowLineBreaks" value="true" />
        </module>
        <module name="ParenPad" />
        <module name="SeparatorWrap">
            <property name="id" value="SeparatorWrapDot" />
            <property name="tokens" value="DOT" />
            <property name="option" value="nl" />
        </module>
        <module name="SeparatorWrap">
            <property name="id" value="SeparatorWrapComma" />
            <property name="tokens" value="COMMA" />
            <property name="option" value="EOL" />
        </module>
        <module name="SeparatorWrap">
            <property name="id" value="SeparatorWrapMethodRef" />
            <property name="tokens" value="METHOD_REF" />
            <property name="option" value="nl" />
        </module>
    </module>
 
    <property name="fileExtensions" value="java, properties, xml, vm, g, g4, dtd, kt" />
    <property name="charset" value="UTF-8" />
    <property name="severity" value="error" />
</module>

在project的build.gradle中引入checkstyle.gradle。

//引用checkstyle.gradle
apply from:'codestyles/checkstyle/checkstyle.gradle'
buildscript {
    ext.kotlin_version = '1.3.61'
    repositories {
        google()
        jcenter()
         
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
 
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
 
allprojects {
    repositories {
        google()
        jcenter()
         
    }
}
 
task clean(type: Delete) {
    delete rootProject.buildDir
}

执行代码规范检测:在右边栏点击Gradle,在Tasks组别中找到other组,然后找到checkstyle任务,点击执行。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
生成的report报告位置module/build/reports
在这里插入图片描述

Gradle插件

插件搜索下载,下载成功之后需要重启IDE。
在这里插入图片描述
重新启动IDE之后会在底部栏新增一个CheckStyle,在Rules:下拉选框中默认会有两个已经配置好的代码规范,Sun Checks和GoogleChecks,可以先勾选Google Checks如下图所示:
在这里插入图片描述
然后点击左侧按钮进行检测,检测范围可以是整个项目,改动的项目等。检测结果如下图:
在这里插入图片描述
同时在AS设置Preferences->Other Settings->Check Style,也可以进行设置。
在这里插入图片描述

发布了11 篇原创文章 · 获赞 3 · 访问量 2741

猜你喜欢

转载自blog.csdn.net/KyungLip/article/details/103908329
今日推荐