diff --git a/project_views/default.bazelproject b/project_views/default.bazelproject index 53da3bcc..fd7885c7 100644 --- a/project_views/default.bazelproject +++ b/project_views/default.bazelproject @@ -6,6 +6,8 @@ directories: -bazel-cache -bazel-testlogs -bazel-genfiles + -.aswb + -.ijwb # Automatically includes all relevant targets under the 'directories' above derive_targets_from_directories: true diff --git a/rules/android/lint/lint_aspect.bzl b/rules/android/lint/lint_aspect.bzl index e39962f0..45f8c719 100644 --- a/rules/android/lint/lint_aspect.bzl +++ b/rules/android/lint/lint_aspect.bzl @@ -186,7 +186,7 @@ def _lint_common_args( args.set_param_file_format("multiline") args.use_param_file("--flagfile=%s", use_always = True) - args.add("--name", ctx.label.name) + args.add("--name", str(ctx.label).lstrip("@")) if android: args.add("--android") if library: diff --git a/tools/lint/src/main/java/com/grab/lint/LintResults.kt b/tools/lint/src/main/java/com/grab/lint/LintResults.kt index 893a0ffd..7ce11f50 100644 --- a/tools/lint/src/main/java/com/grab/lint/LintResults.kt +++ b/tools/lint/src/main/java/com/grab/lint/LintResults.kt @@ -1,5 +1,6 @@ package com.grab.lint +import org.w3c.dom.Document import org.w3c.dom.Element import java.io.File import java.io.FileWriter @@ -9,7 +10,6 @@ import java.util.concurrent.TimeUnit import javax.xml.parsers.DocumentBuilder import javax.xml.parsers.DocumentBuilderFactory import javax.xml.transform.OutputKeys -import javax.xml.transform.Transformer import javax.xml.transform.TransformerFactory import javax.xml.transform.dom.DOMSource import javax.xml.transform.stream.StreamResult @@ -57,62 +57,80 @@ class LintResults( private fun buildJunitReport(documentBuilder: DocumentBuilder, errorIssues: List) { val junitDoc = documentBuilder.newDocument() - val testSuites = junitDoc.createElement("testsuites").also { - it["name"] = name - it["tests"] = errorIssues.size.toString() - it["time"] = TimeUnit.MILLISECONDS.toSeconds(elapsed).toString() - } - junitDoc.appendChild(testSuites) - - errorIssues.groupBy { it["id"] }.forEach { (id, issues) -> - val failures = issues.size.toString() - val testSuite = junitDoc.createElement("testsuite").also { - it["name"] = id - it["tests"] = failures - it["failures"] = failures - } - testSuites.appendChild(testSuite) + val rootTestSuites = junitDoc.createElement("testsuites").also(junitDoc::appendChild) - issues.forEach { issue -> - val message = issue["message"] - val summary = issue["summary"] - val location = issue.getElementsByTagName("location").elements().first() - val file = location["file"].replace("../", "") - val line = location["line"] - val explanation = listOf( - issue["explanation"], - "\nFile: $file:$line", - "Error line:", - issue["errorLine1"], - issue["errorLine2"] - ).joinToString(separator = "\n") - - val testCase = junitDoc.createElement("testcase").also { - it["name"] = message - it["classname"] = summary - it["file"] = file - it["line"] = line - } - val failure = junitDoc.createElement("failure").also { - it["message"] = explanation + when { + errorIssues.isEmpty() -> addSuccessfulTestCase(junitDoc, rootTestSuites) + else -> errorIssues.groupBy { it["id"] }.forEach { (id, issues) -> + val failures = issues.size.toString() + val testSuite = junitDoc.createElement("testsuite").also { + it["name"] = id + it["tests"] = failures + it["failures"] = failures + it["time"] = TimeUnit.MILLISECONDS.toSeconds(elapsed).toString() } - testCase.appendChild(failure) - testSuite.appendChild(testCase) + rootTestSuites.appendChild(testSuite) + issues.forEach { issue -> mapIssueToTestCase(issue, junitDoc, testSuite) } } } try { FileWriter(outputJunitXml).use { fileWriter -> - val transformer: Transformer = TransformerFactory.newInstance().newTransformer() - transformer.setOutputProperty(OutputKeys.INDENT, "yes") - transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2") - transformer.transform(DOMSource(junitDoc), StreamResult(fileWriter)) + with(TransformerFactory.newInstance().newTransformer()) { + setOutputProperty(OutputKeys.INDENT, "yes") + setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2") + transform(DOMSource(junitDoc), StreamResult(fileWriter)) + } } } catch (e: Exception) { throw RuntimeException(e) } } + private fun addSuccessfulTestCase(junitDoc: Document, rootTestSuites: Element) { + val testSuite = junitDoc.createElement("testsuite").also { + it["name"] = name + it["tests"] = "1" + it["time"] = TimeUnit.MILLISECONDS.toSeconds(elapsed).toString() + it.appendChild(junitDoc.createElement("testcase").also { testcase -> + testcase["name"] = "Android lint on $name" + testcase["classname"] = name + }) + } + rootTestSuites.appendChild(testSuite) + } + + private fun mapIssueToTestCase( + issue: Element, + junitDoc: Document, + testSuite: Element + ) { + val message = issue["message"] + val summary = issue["summary"] + val location = issue.getElementsByTagName("location").elements().first() + val file = location["file"].replace("../", "") + val line = location["line"] + val explanation = listOf( + issue["explanation"], + "\nFile: $file:$line", + "Error line:", + issue["errorLine1"], + issue["errorLine2"] + ).joinToString(separator = "\n") + + val testCase = junitDoc.createElement("testcase").also { + it["name"] = message + it["classname"] = summary + it["file"] = file + it["line"] = line + } + val failure = junitDoc.createElement("failure").also { + it["message"] = explanation + } + testCase.appendChild(failure) + testSuite.appendChild(testCase) + } + companion object { /** * Map of Android Lint Issue id to message text that is recognized as success. diff --git a/tools/lint/src/test/java/com/grab/lint/LintResultsTest.kt b/tools/lint/src/test/java/com/grab/lint/LintResultsTest.kt index 1f6540ab..f9abb06d 100644 --- a/tools/lint/src/test/java/com/grab/lint/LintResultsTest.kt +++ b/tools/lint/src/test/java/com/grab/lint/LintResultsTest.kt @@ -144,9 +144,6 @@ class LintResultsTest { DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(outputJunitXml).apply { assertNode( "testsuites", - "name" to "Test", - "tests" to "1", - "time" to "0" ) assertNode( "testsuite",