├── quality ├── checkstyle │ ├── suppressions.xml │ └── checkstyle.xml ├── findbugs │ └── findbugs-filter.xml ├── pmd │ └── pmd-ruleset.xml └── lint │ └── lint.xml ├── .gitignore ├── LICENSE ├── jacoco.gradle ├── README.md └── quality.gradle /quality/checkstyle/suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE config 2 | .idea/ 3 | 4 | # Built application files 5 | *.apk 6 | *.ap_ 7 | 8 | # Files for the Dalvik VM 9 | *.dex 10 | 11 | # Java class files 12 | *.class 13 | 14 | # Generated files 15 | bin/ 16 | gen/ 17 | 18 | # Gradle files 19 | .gradle/ 20 | build/ 21 | /*/build/ 22 | 23 | # Local configuration file (sdk path, etc) 24 | local.properties 25 | 26 | # Proguard folder generated by Eclipse 27 | proguard/ 28 | 29 | # Log Files 30 | *.log 31 | -------------------------------------------------------------------------------- /quality/findbugs/findbugs-filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Piasy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /jacoco.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Apply additional build steps to sub-projects*/ 3 | def jacocoToolVersion = rootProject.ext.has('jacocoVersion') ? rootProject.ext.jacocoVersion : '0.7.7.201606060606' 4 | def moduleExcludes = rootProject.ext.has('moduleExcludes') ? rootProject.ext.moduleExcludes : [:] 5 | def ignoredByJacoco = rootProject.ext.has('ignoredByJacoco') ? rootProject.ext.ignoredByJacoco : [] 6 | 7 | if (shouldApplyJacoco(project, ignoredByJacoco)) { 8 | apply plugin: 'jacoco' 9 | 10 | jacoco { 11 | version jacocoToolVersion 12 | } 13 | 14 | task jacocoReport(type: JacocoReport, dependsOn: 'test') { 15 | group = 'Reporting' 16 | description = 'Generate Jacoco coverage reports after running tests.' 17 | 18 | reports { 19 | html { 20 | enabled true 21 | destination file('build/reports/jacoco/full') 22 | } 23 | xml { 24 | enabled true 25 | destination file('build/reports/jacoco/full/jacocoFullReport.xml') 26 | } 27 | } 28 | 29 | sourceDirectories = project.files('src/main/java') 30 | classDirectories = project.fileTree(dir: 'build/intermediates/classes/debug', 31 | excludes: moduleExcludes[project.name] ?: []) 32 | 33 | executionData = project.files('build/jacoco/testDebugUnitTest.exec') 34 | 35 | doFirst { 36 | renameClasses(project.name + '/build/intermediates/classes/debug') 37 | } 38 | } 39 | } 40 | 41 | List listDirRecursive(File rootPath) { 42 | List result = new ArrayList<>() 43 | List children = rootPath.listFiles() 44 | children.each { file -> 45 | if (file.isFile()) { 46 | result.add(file) 47 | } else if (file.isDirectory()) { 48 | result.addAll(listDirRecursive(file)) 49 | } 50 | } 51 | return result 52 | } 53 | 54 | void renameClasses(String rootPath) { 55 | List classes = listDirRecursive(file(rootPath)) 56 | classes.each { file -> 57 | if (file.name.contains('$$')) { 58 | file.renameTo(file.path.replace('$$', '$')) 59 | } 60 | } 61 | } 62 | 63 | boolean shouldApplyJacoco(Project project, List ignoredByJacoco) { 64 | def ignored = ignoredByJacoco.contains(project.name) 65 | def isJava = project.plugins.hasPlugin("java") 66 | def isAndroid = project.plugins.hasPlugin("com.android.library") || plugins.hasPlugin( 67 | "com.android.application") 68 | return !ignored && (isJava || isAndroid) 69 | } 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AndroidCodeQualityConfig 2 | 3 | Code quality config for android project, including lint, pmd, findbugs, checkstyle, jacoco code coverage. Serve as a submodule for repo: https://github.com/Piasy/AndroidTDDBootStrap 4 | 5 | + Usage 6 | + step 1. fork me 7 | + step 2. import the forked repo as git submodule, or just put the folder under your project root. 8 | + step 3. `apply from: '../AndroidCodeQualityConfig/quality.gradle'` for android module then run `gradle check` 9 | + step 4. no more step 4 :). 10 | 11 | If you have many modules, you have another option: 12 | 13 | + step 3. add below code into your root project's `build.gradle`: 14 | 15 | ``` gradle 16 | subprojects { 17 | apply from: "$rootProject.projectDir/AndroidCodeQualityConfig/quality.gradle" 18 | 19 | afterEvaluate { 20 | check.dependsOn 'checkstyle', 'findbugs', 'pmd', 'lint' 21 | } 22 | } 23 | ``` 24 | 25 | + step 4. remove `check.dependsOn 'checkstyle', 'findbugs', 'pmd', 'lint'` in quality.gradle. 26 | + step 5. change the last paragraph of quality.gradle into this: 27 | 28 | ``` gradle 29 | afterEvaluate { 30 | android { 31 | lintOptions { 32 | abortOnError true 33 | xmlReport true 34 | htmlReport true 35 | lintConfig file("${project.rootDir}/AndroidCodeQualityConfig/quality/lint/lint.xml") 36 | } 37 | } 38 | } 39 | ``` 40 | 41 | ## CheckStyle 42 | + [CheckStyle](https://github.com/checkstyle/checkstyle) 43 | + [CheckStyle-IDEA plugin](https://github.com/jshiell/checkstyle-idea) 44 | 45 | ## FindBugs 46 | + [Findbugs](https://github.com/findbugsproject/findbugs) 47 | 48 | ## PMD 49 | + [PMD](https://github.com/pmd/pmd) 50 | 51 | ## Lint 52 | + [Android Lint](http://tools.android.com/tips/lint) 53 | 54 | ## Jacoco 55 | 56 | In your root project `build.gradle`: 57 | 58 | ``` gradle 59 | apply from: 'AndroidCodeQualityConfig/jacoco.gradle' 60 | ``` 61 | 62 | then define `ignoredByJacoco` array in your root project ext part to define ignoring module, and `moduleExcludes` for each not ignoring module. 63 | 64 | ## License 65 | 66 | The MIT License (MIT) 67 | 68 | Copyright (c) 2015 Piasy 69 | 70 | Permission is hereby granted, free of charge, to any person obtaining a copy 71 | of this software and associated documentation files (the "Software"), to deal 72 | in the Software without restriction, including without limitation the rights 73 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 74 | copies of the Software, and to permit persons to whom the Software is 75 | furnished to do so, subject to the following conditions: 76 | 77 | The above copyright notice and this permission notice shall be included in all 78 | copies or substantial portions of the Software. 79 | 80 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 81 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 82 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 83 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 84 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 85 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 86 | SOFTWARE. 87 | -------------------------------------------------------------------------------- /quality/pmd/pmd-ruleset.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | Custom ruleset for Android application 8 | 9 | .*/R.java 10 | .*/gen/.* 11 | .*/test/.* 12 | .*/androidTest/.* 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /quality.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'checkstyle' 2 | apply plugin: 'findbugs' 3 | apply plugin: 'pmd' 4 | 5 | def isJava = plugins.hasPlugin('java') 6 | // Add checkstyle, findbugs, pmd and lint to the check task. 7 | // Comment it if already set in root project's build.gradle. 8 | check.dependsOn 'checkstyle', 'findbugs', 'pmd' 9 | if (!isJava) { 10 | check.dependsOn 'lint' 11 | } 12 | 13 | checkstyle { 14 | toolVersion '7.4' 15 | 16 | configFile file("${project.rootDir}/AndroidCodeQualityConfig/quality/checkstyle/checkstyle.xml") 17 | configProperties.checkstyleSuppressionFilterPath = file( 18 | "${project.rootDir}/AndroidCodeQualityConfig/quality/checkstyle/suppressions.xml") 19 | .absolutePath 20 | } 21 | 22 | task checkstyle(type: Checkstyle, group: 'verification') { 23 | source 'src' 24 | include '**/*.java' 25 | exclude '**/gen/**' 26 | exclude '**/test/**' 27 | exclude '**/androidTest/**' 28 | exclude '**/R.java' 29 | exclude '**/BuildConfig.java' 30 | classpath = files() 31 | } 32 | 33 | 34 | findbugs { 35 | toolVersion = "3.0.1" 36 | ignoreFailures = false 37 | effort = "max" 38 | reportLevel = "high" 39 | excludeFilter = new File("${project.rootDir}/AndroidCodeQualityConfig/quality/findbugs/findbugs-filter.xml") 40 | } 41 | 42 | task findbugs(type: FindBugs, dependsOn: "assemble", group: 'verification') { 43 | if (isJava) { 44 | classes = files("$projectDir.absolutePath/build/classes") 45 | } else { 46 | classes = files("$projectDir.absolutePath/build/intermediates/classes") 47 | } 48 | source 'src' 49 | include '**/*.java' 50 | exclude '**/gen/**' 51 | 52 | reports { 53 | // FindBugs tasks can only have one report enabled 54 | xml.enabled = false 55 | html.enabled = !xml.enabled 56 | xml { 57 | destination file("$projectDir.absolutePath/build/reports/findbugs/findbugs.xml") 58 | } 59 | html { 60 | destination file("$projectDir.absolutePath/build/reports/findbugs/findbugs.html") 61 | } 62 | } 63 | 64 | classpath = files() 65 | } 66 | 67 | 68 | pmd { 69 | toolVersion = '5.5.2' 70 | ignoreFailures = false 71 | ruleSetFiles = files("${project.rootDir}/AndroidCodeQualityConfig/quality/pmd/pmd-ruleset.xml") 72 | ruleSets = [] 73 | } 74 | 75 | task pmd(type: Pmd, group: 'verification') { 76 | source 'src' 77 | include '**/*.java' 78 | exclude('**/gen/**', '**/debug/**') 79 | 80 | reports { 81 | xml.enabled = true 82 | html.enabled = true 83 | xml { 84 | destination file("$projectDir.absolutePath/build/reports/pmd/pmd.xml") 85 | } 86 | html { 87 | destination file("$projectDir.absolutePath/build/reports/pmd/pmd.html") 88 | } 89 | } 90 | } 91 | 92 | if (!isJava) { 93 | android { 94 | lintOptions { 95 | disable 'NewApi' // gradle build will compile code use `Objects.requireNonNull()` for lambda 96 | abortOnError true 97 | xmlReport true 98 | xmlOutput project.file('build/reports/lint/lint-report.xml') 99 | htmlReport true 100 | htmlOutput project.file('build/reports/lint/lint-report.html') 101 | lintConfig file("${project.rootDir}/AndroidCodeQualityConfig/quality/lint/lint.xml") 102 | } 103 | 104 | testOptions.unitTests.all { 105 | testLogging { 106 | events 'passed', 'skipped', 'failed', 'standardOut', 'standardError' 107 | outputs.upToDateWhen { false } 108 | showStandardStreams = true 109 | } 110 | jvmArgs '-noverify' 111 | } 112 | } 113 | } 114 | 115 | apply from: rootProject.file('AndroidCodeQualityConfig/jacoco.gradle') 116 | -------------------------------------------------------------------------------- /quality/lint/lint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /quality/checkstyle/checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 367 | 368 | 369 | 370 | 371 | 372 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | --------------------------------------------------------------------------------