379 lines
12 KiB
Groovy
379 lines
12 KiB
Groovy
apply plugin: 'checkstyle'
|
|
apply plugin: 'cpd'
|
|
apply plugin: 'pmd'
|
|
apply plugin: 'io.gitlab.arturbosch.detekt'
|
|
|
|
def getCpdTask
|
|
def getPmdTask
|
|
def getCheckstyleTask
|
|
def getLintTask
|
|
def getKotlinDetektTask
|
|
|
|
def appendError
|
|
def appendCpdErrors
|
|
def appendKotlinErrors
|
|
def appendCheckstyleErrors
|
|
def appendPmdErrors
|
|
def appendLintErrors
|
|
|
|
repositories {
|
|
maven { url "http://dl.bintray.com/touchin/touchin-tools" }
|
|
}
|
|
|
|
configurations {
|
|
pngtastic
|
|
}
|
|
|
|
cpd {
|
|
skipLexicalErrors = true
|
|
}
|
|
|
|
detekt {
|
|
input = files("${rootDir}")
|
|
config = files("$buildScriptsDir/kotlin/detekt-config.yml")
|
|
|
|
// TODO add excludes from rootProject.extensions.findByName("staticAnalysisExcludes")
|
|
filters = ".*src/test.*,.*/resources/.*,.*/tmp/.*,.*/build/.*"
|
|
|
|
reports {
|
|
html {
|
|
enabled = true
|
|
destination = file("${project.buildDir}/reports/kotlin-detekt.html")
|
|
}
|
|
xml {
|
|
enabled = true
|
|
destination = file("${project.buildDir}/reports/kotlin-detekt.xml")
|
|
}
|
|
}
|
|
}
|
|
|
|
import org.apache.tools.ant.taskdefs.condition.Os
|
|
|
|
ext.getIdeaFormatTask = { isAndroidProject, sources ->
|
|
def ideaPath = System.getenv("IDEA_HOME")
|
|
if (ideaPath == null) {
|
|
return tasks.create((isAndroidProject ? "android" : "server") + "donothing")
|
|
}
|
|
return tasks.create((isAndroidProject ? "android" : "server") + "IdeaFormat_$project.name", Exec) {
|
|
def inspectionPath
|
|
def params = ["-r", "-mask", "*.java,*.kt,*.xml"]
|
|
for (String source : sources) {
|
|
params.add(source)
|
|
}
|
|
|
|
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
|
inspectionPath = ['cmd', '/c', "\"${ideaPath}\\bin\\format.bat\" ${params.join(" ")}"]
|
|
} else {
|
|
inspectionPath = ["$ideaPath/bin/format.sh"]
|
|
}
|
|
commandLine inspectionPath
|
|
if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
|
|
args = params
|
|
}
|
|
}
|
|
}
|
|
|
|
ext.getStaticAnalysisTaskNames = { isAndroidProject, sources, buildVariant, checkstyleEnabled, pmdEnabled ->
|
|
def tasksNames = new ArrayList<String>()
|
|
try {
|
|
tasksNames.add(getCpdTask(isAndroidProject, sources))
|
|
tasksNames.add(getKotlinDetektTask())
|
|
if (isAndroidProject) {
|
|
if (checkstyleEnabled) {
|
|
tasksNames.add(getCheckstyleTask(sources))
|
|
}
|
|
if (pmdEnabled) {
|
|
tasksNames.add(getPmdTask(sources))
|
|
}
|
|
tasksNames.add(getLintTask(buildVariant))
|
|
}
|
|
} catch (Exception exception) {
|
|
println(exception.toString())
|
|
}
|
|
return tasksNames
|
|
}
|
|
|
|
ext.generateReport = { isAndroidProject ->
|
|
StringBuilder consoleReport = new StringBuilder()
|
|
consoleReport.append("STATIC ANALYSIS RESULTS:")
|
|
def count = 0
|
|
|
|
def previousCount = count
|
|
count = appendCpdErrors(count, new File("${project.buildDir}/reports/cpd.xml"))
|
|
if (count - previousCount > 0) {
|
|
consoleReport.append("\nCPD: FAILED (" + (count - previousCount) + " errors)")
|
|
} else {
|
|
consoleReport.append("\nCPD: PASSED")
|
|
}
|
|
|
|
previousCount = count
|
|
count = appendKotlinErrors(count, new File("${project.buildDir}/reports/kotlin-detekt.xml"))
|
|
if (count - previousCount > 0) {
|
|
consoleReport.append("\nKotlin-detekt: FAILED (" + (count - previousCount) + " errors)")
|
|
} else {
|
|
consoleReport.append("\nKotlin-detekt: PASSED")
|
|
}
|
|
|
|
if (isAndroidProject) {
|
|
def checkstyleFile = new File("${project.buildDir}/reports/checkstyle.xml")
|
|
if (checkstyleFile.exists()) {
|
|
previousCount = count
|
|
count = appendCheckstyleErrors(count, checkstyleFile)
|
|
if (count - previousCount > 0) {
|
|
consoleReport.append("\nCheckstyle: FAILED (" + (count - previousCount) + " errors)")
|
|
} else {
|
|
consoleReport.append("\nCheckstyle: PASSED")
|
|
}
|
|
}
|
|
|
|
def pmdFile = new File("${project.buildDir}/reports/pmd.xml")
|
|
if (pmdFile.exists()) {
|
|
previousCount = count
|
|
count = appendPmdErrors(count, pmdFile)
|
|
if (count - previousCount > 0) {
|
|
consoleReport.append("\nPMD: FAILED (" + (count - previousCount) + " errors)")
|
|
} else {
|
|
consoleReport.append("\nPMD: PASSED")
|
|
}
|
|
}
|
|
|
|
previousCount = count
|
|
count = appendLintErrors(count, new File("${project.buildDir}/reports/lint_report.xml"))
|
|
if (count - previousCount > 0) {
|
|
consoleReport.append("\nLint: FAILED (" + (count - previousCount) + " errors)")
|
|
} else {
|
|
consoleReport.append("\nLint: PASSED")
|
|
}
|
|
}
|
|
|
|
if (count > 0) {
|
|
consoleReport.append("\nOverall: FAILED (" + count + " errors)")
|
|
throw new Exception(consoleReport.toString())
|
|
} else {
|
|
consoleReport.append("\nOverall: PASSED")
|
|
println(consoleReport.toString())
|
|
}
|
|
}
|
|
|
|
appendError = { number, analyzer, file, line, errorId, errorLink, description ->
|
|
println("$number. $analyzer : $description ($errorId)\n\tat $file: $line")
|
|
}
|
|
|
|
appendKotlinErrors = { count, checkstyleFile ->
|
|
def rootNode = new XmlParser().parse(checkstyleFile)
|
|
for (def fileNode : rootNode.children()) {
|
|
if (!fileNode.name().equals("file")) {
|
|
continue
|
|
}
|
|
|
|
for (def errorNode : fileNode.children()) {
|
|
if (!errorNode.name().equals("error")) {
|
|
continue
|
|
}
|
|
count++
|
|
|
|
appendError(count, "Detekt", fileNode.attribute("name"), errorNode.attribute("line"), errorNode.attribute("source"), "", errorNode.attribute("message"))
|
|
}
|
|
}
|
|
return count
|
|
}
|
|
|
|
appendCpdErrors = { count, cpdFile ->
|
|
def rootNode = new XmlParser().parse(cpdFile)
|
|
for (def duplicationNode : rootNode.children()) {
|
|
if (!duplicationNode.name().equals("duplication")) {
|
|
continue
|
|
}
|
|
count++
|
|
|
|
def duplicationIndex = 0
|
|
|
|
String duplicationPoints = ""
|
|
for (def filePointNode : duplicationNode.children()) {
|
|
if (filePointNode.name().equals("file")) {
|
|
def file = filePointNode.attribute("path")
|
|
def line = filePointNode.attribute("line")
|
|
duplicationPoints += "\n " + file + ":" + line
|
|
duplicationIndex++
|
|
}
|
|
}
|
|
println("$count CPD: code duplication $duplicationPoints")
|
|
}
|
|
return count
|
|
}
|
|
|
|
appendCheckstyleErrors = { count, checkstyleFile ->
|
|
def rootNode = new XmlParser().parse(checkstyleFile)
|
|
for (def fileNode : rootNode.children()) {
|
|
if (!fileNode.name().equals("file")) {
|
|
continue
|
|
}
|
|
|
|
for (def errorNode : fileNode.children()) {
|
|
if (!errorNode.name().equals("error")) {
|
|
continue
|
|
}
|
|
count++
|
|
|
|
def error = errorNode.attribute("source")
|
|
def link = "http://checkstyle.sourceforge.net/apidocs/" + error.replace('.', '/') + ".html"
|
|
appendError(count, "Checkstyle", fileNode.attribute("name"), errorNode.attribute("line"), error, link, errorNode.attribute("message"))
|
|
}
|
|
}
|
|
return count
|
|
}
|
|
|
|
appendPmdErrors = { count, pmdFile ->
|
|
def rootNode = new XmlParser().parse(pmdFile)
|
|
for (def fileNode : rootNode.children()) {
|
|
if (!fileNode.name().equals("file")) {
|
|
continue
|
|
}
|
|
|
|
for (def errorNode : fileNode.children()) {
|
|
if (!errorNode.name().equals("violation")) {
|
|
continue
|
|
}
|
|
count++
|
|
|
|
appendError(count, "PMD", fileNode.attribute("name"), errorNode.attribute("beginline"),
|
|
errorNode.attribute("rule").trim(), errorNode.attribute("externalInfoUrl").trim(), errorNode.text().trim())
|
|
}
|
|
}
|
|
return count
|
|
}
|
|
|
|
appendLintErrors = { count, lintFile ->
|
|
def rootNode = new XmlParser().parse(lintFile)
|
|
for (def issueNode : rootNode.children()) {
|
|
if (!issueNode.name().equals("issue")
|
|
|| !issueNode.attribute("severity").equals("Error")) {
|
|
continue
|
|
}
|
|
for (def locationNode : issueNode.children()) {
|
|
if (!locationNode.name().equals("location")) {
|
|
continue
|
|
}
|
|
count++
|
|
appendError(count, "Lint", locationNode.attribute("file"), locationNode.attribute("line"),
|
|
issueNode.attribute("id"), issueNode.attribute("explanation"), issueNode.attribute("message"))
|
|
}
|
|
}
|
|
return count
|
|
}
|
|
|
|
getCpdTask = { isAndroidProject, sources ->
|
|
def taskName = (isAndroidProject ? "android" : "server") + "cpd_${project.name}"
|
|
def task = tasks.findByName(taskName)
|
|
if (task == null) {
|
|
task = tasks.create(taskName, tasks.findByName('cpdCheck').getClass().getSuperclass()) {
|
|
minimumTokenCount = 60
|
|
source = files(sources)
|
|
ignoreFailures = true
|
|
reports {
|
|
xml {
|
|
enabled = true
|
|
destination = file("${project.buildDir}/reports/cpd.xml")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return task.name
|
|
}
|
|
|
|
getPmdTask = { sources ->
|
|
def taskName = "pmd_${project.name}"
|
|
def task = tasks.findByName(taskName)
|
|
if (task == null) {
|
|
task = tasks.create(taskName, Pmd) {
|
|
pmdClasspath = configurations.pmd.asFileTree
|
|
ruleSetFiles = files "$buildScriptsDir/pmd/rulesets/java/android.xml"
|
|
ruleSets = []
|
|
source files(sources)
|
|
ignoreFailures = true
|
|
reports {
|
|
html {
|
|
enabled = true
|
|
destination file("${project.buildDir}/reports/pmd.html")
|
|
}
|
|
xml {
|
|
enabled = true
|
|
destination file("${project.buildDir}/reports/pmd.xml")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return task.name
|
|
}
|
|
|
|
getLintTask = { buildVariant ->
|
|
def lintTaskName
|
|
if (buildVariant != null) {
|
|
lintTaskName = "lint${buildVariant.name.capitalize()}"
|
|
} else {
|
|
def lintDebugTask = tasks.matching { it.getName().contains("lint") && it.getName().contains("Debug") }.first()
|
|
lintTaskName = lintDebugTask.getName()
|
|
}
|
|
android.lintOptions.abortOnError = false
|
|
android.lintOptions.checkAllWarnings = true
|
|
android.lintOptions.warningsAsErrors = false
|
|
android.lintOptions.xmlReport = true
|
|
android.lintOptions.xmlOutput = file "$project.buildDir/reports/lint_report.xml"
|
|
android.lintOptions.htmlReport = false
|
|
android.lintOptions.lintConfig = file "$buildScriptsDir/lint/lint.xml"
|
|
return lintTaskName
|
|
}
|
|
|
|
getCheckstyleTask = { sources ->
|
|
def taskName = "checkstyle_$project.name"
|
|
def task = tasks.findByName(taskName)
|
|
if (task == null) {
|
|
def compileReleaseTask = tasks.matching {
|
|
it.getName().contains("compile") && it.getName().contains("Release") && it.getName().contains("Java") && !it.getName().contains("UnitTest")
|
|
}.last()
|
|
task = tasks.create(taskName, Checkstyle) {
|
|
ignoreFailures = true
|
|
showViolations = false
|
|
source files(sources)
|
|
configFile file("$buildScriptsDir/checkstyle/configuration/touchin_checkstyle.xml")
|
|
checkstyleClasspath = configurations.checkstyle.asFileTree
|
|
classpath = files(System.getenv("ANDROID_HOME") + "/platforms/" + android.compileSdkVersion + "/android.jar") +
|
|
files(System.properties.'java.home' + "/lib/rt.jar") +
|
|
compileReleaseTask.classpath
|
|
reports {
|
|
xml {
|
|
enabled = true
|
|
destination file("${project.buildDir}/reports/checkstyle.xml")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return task.name
|
|
}
|
|
|
|
getKotlinDetektTask = { "detekt" }
|
|
|
|
task optimizePng {
|
|
doFirst {
|
|
def jarArgs = new ArrayList<String>()
|
|
jarArgs.add(configurations.pngtastic.asPath)
|
|
def relatedPathIndex = "${rootDir}".length() + 1
|
|
for (def file : fileTree(dir: "${rootDir}", include: '**/src/**/res/drawable**/*.png')) {
|
|
jarArgs.add(file.absolutePath.substring(relatedPathIndex))
|
|
}
|
|
for (def file : fileTree(dir: "${rootDir}", include: '**/src/**/res/mipmap**/*.png')) {
|
|
jarArgs.add(file.absolutePath.substring(relatedPathIndex))
|
|
}
|
|
javaexec { main = "-jar"; args = jarArgs; workingDir = file("${rootDir}") }
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
pmd 'net.sourceforge.pmd:pmd-core:5.5.3'
|
|
pmd 'net.sourceforge.pmd:pmd-java:5.5.3'
|
|
|
|
checkstyle 'ru.touchin:checkstyle:7.6.2-fork'
|
|
|
|
pngtastic 'com.github.depsypher:pngtastic:1.2'
|
|
}
|