天天看点

lint/checkstyle/findbugs/pmd使用汇总

前言

在开发应用的过程中,往往更关注功能和用户体验。其实优化代码,可以预防和减少一些可能会报出的问题。首先我们必须承认是人都会犯错,使用一些工具可以检查,然后修改问题。

1.lint

看下官方对lint的定义,如下图

lint/checkstyle/findbugs/pmd使用汇总

lint的原理如下

lint/checkstyle/findbugs/pmd使用汇总

使用lint,可有很多方式,包括下面但不只:

  • 命令行
  • gradle
  • AS的Inspect Code

lint和proguard一样,可以写自定义过滤检查,有如下方式:

  • Android项目根目录下的lint.xml
<?xml version="1.0" encoding="UTF-8"?>
<lint>
    <!-- Disable the given check in this project -->
    <issue id="IconMissingDensityFolder" severity="ignore" />

    <!-- Ignore the ObsoleteLayoutParam issue in the specified files -->
    <issue id="ObsoleteLayoutParam">
        <ignore path="res/layout/activation.xml" />
        <ignore path="res/layout-xlarge/activation.xml" />
    </issue>

    <!-- Ignore the UselessLeaf issue in the specified file -->
    <issue id="UselessLeaf">
        <ignore path="res/layout/main.xml" />
    </issue>

    <!-- Change the severity of hardcoded strings to "error" -->
    <issue id="HardcodedText" severity="error" />
</lint>
           
  • 禁止Java文件检查
@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
           
  • 禁止xml文件检查
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:ignore="UnusedResources" >

    <TextView
        android:text="@string/auto_update_prompt" />
</LinearLayout>
           

更多关于lint可以查阅:write lint

2.checkstyle

checkstyle帮助开发者实现常用JAVA代码规范的自动化检查。它的功能比较丰富,相对配置起来比较复杂,你需要根据自己的需求配置你想检查的东西,比如Annotations,Block Checks,Class Design,Coding,Duplicate Code,Headers,Imports,Javadoc Comments,Metrics,Miscellaneous,Modifiers,Naming Conventions,Regexp,Size Violations,Whitespace。

我参考glide写了下自己的配置文件,在project根目录下的build.gradle

添加如下代码

subprojects { project ->
    apply plugin: 'checkstyle'
    checkstyle {
        toolVersion = '6.12.1'
    }

    checkstyle {
        configFile = rootProject.file('huaweicheckstyle.xml')
        configProperties.checkStyleConfigDir = rootProject.rootDir
    }

    task('checkstyle', type: Checkstyle) {
        source 'src'
        ignoreFailures false
        showViolations true
        include '**/*.java'
        exclude '**/gen/**'

        classpath = files()
    }

    afterEvaluate {
        if(project.tasks.findByName('check')) {
            check.dependsOn('checkstyle')
        }
    }

    gradle.projectsEvaluated {
        tasks.withType(JavaCompile) {
            options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation'
        }
    }
}
           

可以对整个project执行checkstyle

gradlew.bat checkstyle
           

也可以对某个module执行checkstyle,比如app模块

另外可以安装下checkstyle-idea插件,在settings添加自己的checkstyle配置文件。

lint/checkstyle/findbugs/pmd使用汇总

可以在窗口中执行对应的操作

lint/checkstyle/findbugs/pmd使用汇总

当然你可以扫描单个java文件

lint/checkstyle/findbugs/pmd使用汇总

3.FindBugs

findbugs是一个分析bytecode并找出其中可疑部分的一个工具。它给项目字节码做一个全面扫描,通过一些通用规则去判断可能潜在的一些问题,比如性能,多线程安全等等。有些时候它也会给出很详细的说明,为什么这种做法不大好,蛮有意思的。

找到需要集成的android项目,一般是app模块,在其的build.gradle添加如下代码集成:

apply plugin: 'findbugs'
findbugs {
    toolVersion = FINDBUGS_VERSION
}
afterEvaluate{
        task('findbugs', type: FindBugs, dependsOn: assembleDebug) {
        description 'Run Findbugs'
        group 'verification'
        classes = fileTree('build/intermediates/classes/')
        source fileTree('src')
        classpath = project.configurations.compile
        effort 'max'
        excludeFilter file("findbugs-exclude.xml")

        reports {
            xml.enabled = false
            html.enabled = true
        }
    }

    check.dependsOn('findbugs')
}
           

FindBugs也可以自定义过滤检查,在上面代码中,我们已经使用了findbugs-exclude.xml作为自定义过滤检查,简单的配置如下:

<FindBugsFilter>

    <Match>
        <Class name="~.*R\$.*"/>
    </Match>
    <Match>
        <Class name="~.*Manifest\$.*"/>
    </Match>
</FindBugsFilter>
           

关于更详细的文档可以查看:findbugs

经过上面的配置之后,可以在右边的gradle窗口里找到对应的task,如下图

lint/checkstyle/findbugs/pmd使用汇总

点击运行之后,就可以在app/build目录下面找到对应的错误报表

lint/checkstyle/findbugs/pmd使用汇总

打开这个html文件,找到需要修改的问题。

4.pmd

PMD也是一个静态代码分析工具,它主要用来分析一些常见问题。

PMD和Findbugs功能上有很多重叠的地方,二者区别主要体现在分析对象上,Findbugs扫描的是字节码,所以找到问题的级别有可能不一样,它有很多定义好的rule,例如在Android里,目前有三项规则:

  • CallSuperFirst,它会检查在Activity或Service里的子类里,是否在错误位轩调用父类onCreate等应该放在方法前的方法。
  • CallSuperLast,和CallSuperFirst,但它会检查一些应该在方法结束时才调用父类实现的情况。
  • DoNotHardCodeSDCard,这也是一个常见错误,你应该用Environment.getExternalStorageDirectory()

目前为止PMD对于Android的检查项并不多,使用它主要是用来检查一些JAVA中的常见错误。

配置如下:

apply plugin: 'pmd'
pmd {
    toolVersion '5.4.0'
}
afterEvulate {
    task('pmd', type: Pmd) {
        targetJdk TargetJdk.VERSION_1_7
        description 'Run pmd'
        group 'verification'
        ruleSets = []
        ruleSetFiles = files('pmd-ruleset.xml')
        source = fileTree('src')
        reports {
            xml.enabled = false
            html.enabled = true
        }
        check.dependsOn('pmd')
    }
}
           

pmd也可以配置过滤检查文件,如上我们使用了pmd-ruleset.xml

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<ruleset name="PMD.rul" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">

    <description>This ruleset was created from PMD.rul</description>

    <rule ref="rulesets/java/basic.xml">
        <exclude name="AvoidBranchingStatementAsLastInLoop"/>
    </rule>
</ruleset>
           

更多配置可以查阅:pmd

和FindBugs一样,可以在右边的gradle窗口里找到pmd task

lint/checkstyle/findbugs/pmd使用汇总

点击运行之后,可以在app/build目录下面找到对应的报表文件。

lint/checkstyle/findbugs/pmd使用汇总

打开这个pmd.html,针对性修改存在的问题。

总结

有效的使用上面几个工具,可以极大的提高我们的代码质量,也能规避很多不好代码带来的潜在问题。

后续

有时间会整理下覆盖率测试(jacoco)和代码审核工具(Gerrit)