From ad5a42459a6e754fd57bd7e25fb3b7fe198d3297 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Thu, 15 Feb 2018 21:46:07 +0300 Subject: [PATCH] Pill: Apply required changes to the default JUnit configuration on import --- buildSrc/src/main/kotlin/pill/plugin.kt | 80 +++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/buildSrc/src/main/kotlin/pill/plugin.kt b/buildSrc/src/main/kotlin/pill/plugin.kt index 1d547f24bf2..70a3cbded79 100644 --- a/buildSrc/src/main/kotlin/pill/plugin.kt +++ b/buildSrc/src/main/kotlin/pill/plugin.kt @@ -2,7 +2,16 @@ package org.jetbrains.kotlin.pill import org.gradle.api.Plugin import org.gradle.api.Project +import shadow.org.jdom2.input.SAXBuilder +import shadow.org.jdom2.* +import shadow.org.jdom2.output.DOMOutputter +import shadow.org.jdom2.output.Format +import shadow.org.jdom2.output.XMLOutputter +import javax.xml.transform.TransformerFactory +import javax.xml.transform.dom.* import java.io.File +import java.io.FileOutputStream +import javax.xml.transform.stream.StreamResult class JpsCompatiblePlugin : Plugin { override fun apply(project: Project) {} @@ -110,6 +119,7 @@ class JpsCompatibleRootPlugin : Plugin { .forEach { it.delete() } copyRunConfigurations() + setOptionsForDefaultJunitRunConfiguration(project) for (file in files) { val stubFile = file.path @@ -131,6 +141,76 @@ class JpsCompatibleRootPlugin : Plugin { .forEach { File(targetDir, it.first).writeText(it.second) } } + /* + This sets a proper (project root) working directory and a "idea.home.path" property to the default JUnit configuration, + so one does not need to make these changes manually. + */ + private fun setOptionsForDefaultJunitRunConfiguration(project: Project) { + val workspaceFile = File(projectDir, ".idea/workspace.xml") + if (!workspaceFile.exists()) { + project.logger.warn("${workspaceFile.name} does not exist, JUnit default run configuration was not modified") + return + } + + val document = SAXBuilder().build(workspaceFile) + val rootElement = document.rootElement + + fun Element.getOrCreateChild(name: String, vararg attributes: Pair): Element { + for (child in getChildren(name)) { + if (attributes.all { (attribute, value) -> child.getAttributeValue(attribute) == value }) { + return child + } + } + + return Element(name).apply { + for ((attributeName, value) in attributes) { + setAttribute(attributeName, value) + } + + this@getOrCreateChild.addContent(this@apply) + } + } + + val platformDirProjectRelative = "\$PROJECT_DIR\$/" + platformDir.toRelativeString(projectDir) + + val runManagerComponent = rootElement.getOrCreateChild("component", "name" to "RunManager") + val junitConfiguration = runManagerComponent.getOrCreateChild( + "configuration", + "default" to "true", + "type" to "JUnit", + "factoryName" to "JUnit" + ) + + junitConfiguration.apply { + getOrCreateChild("option", "name" to "WORKING_DIRECTORY").setAttribute("value", "file://\$PROJECT_DIR\$") + getOrCreateChild("option", "name" to "VM_PARAMETERS").also { vmParams -> + val ideaHomePathOptionKey = "-Didea.home.path=" + val ideaHomePathOption = ideaHomePathOptionKey + platformDirProjectRelative + val existingOptions = vmParams.getAttributeValue("value", "").split(' ') + if (existingOptions.none { it.startsWith(ideaHomePathOptionKey) }) { + vmParams.setAttribute("value", (vmParams.getAttributeValue("value", "") + " " + ideaHomePathOption).trim()) + } + } + } + + val output = XMLOutputter().also { + it.format = Format.getPrettyFormat().apply { + setEscapeStrategy { Verifier.isHighSurrogate(it) || it == '"' } + setIndent(" ") + setTextMode(Format.TextMode.TRIM) + setOmitEncoding(false) + setOmitDeclaration(false) + } + } + + val postProcessedXml = output.outputString(document) + .replace(""", """) + .replace(" ", " ") + .replace(" ", " ") + + workspaceFile.writeText(postProcessedXml) + } + private fun attachPlatformSources(platformVersion: String) = fun(library: PLibrary): PLibrary { val platformSourcesJar = File(platformDir, "sources/ideaIC-$platformVersion-sources.jar")