天天看點

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)