apply plugin: 'cpd' apply plugin: 'io.gitlab.arturbosch.detekt' def getCpdTask def getLintTask def getKotlinDetektTasks def appendError def appendCpdErrors def appendKotlinErrors def appendLintErrors repositories { maven { url "http://dl.bintray.com/touchin/touchin-tools" } } configurations { pngtastic } cpd { skipLexicalErrors = true } 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 -> def tasksNames = new ArrayList() try { tasksNames.add(getCpdTask(isAndroidProject, sources)) tasksNames.addAll(getKotlinDetektTasks()) if (isAndroidProject) { 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 subprojects.forEach { subproject -> def reportFile = new File("${rootProject.buildDir}/reports/kotlin-detekt-${subproject.name}.xml") if (reportFile.exists()) { count = appendKotlinErrors(count, reportFile).toInteger() } } if (count - previousCount > 0) { consoleReport.append("\nKotlin-detekt: FAILED (" + (count - previousCount) + " errors)") } else { consoleReport.append("\nKotlin-detekt: PASSED") } if (isAndroidProject) { previousCount = count count = appendLintErrors(count, new File("${rootProject.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 } 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_${rootProject.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("${rootProject.buildDir}/reports/cpd.xml") } } } } return task.path } getLintTask = { buildVariant -> def appProject = subprojects.find { it.plugins.hasPlugin("com.android.application") } def lintTaskPath if (buildVariant != null) { lintTaskPath = ":${appProject.name}:lint${buildVariant.name.capitalize()}" } else { def lintDebugTasks = appProject.tasks.matching { it.getName().contains("lint") && it.getName().contains("Debug") } lintTaskPath = lintDebugTasks.first().path } if (lintTaskPath == null) { throw IllegalStateException("Unable to find lint debug task for build variant: ${buildVariant}") } return lintTaskPath } getKotlinDetektTasks = { subprojects .findResults { it.tasks.findByName("detekt")?.path } .findAll { !it.contains(":libs") } } task optimizePng { doFirst { def jarArgs = new ArrayList() 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 { pngtastic 'com.github.depsypher:pngtastic:1.2' }