Kotlin Facet: Reuse configuration serialization in JPS (previous implementation is not usable after configuration refactoring)

Original commit: 278cc71c4a
This commit is contained in:
Alexey Sedunov
2017-03-07 20:50:28 +03:00
parent fac356c690
commit e24fd4e986
2 changed files with 134 additions and 4 deletions
@@ -0,0 +1,130 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.config
import com.intellij.util.xmlb.SkipDefaultsSerializationFilter
import com.intellij.util.xmlb.XmlSerializer
import org.jdom.DataConversionException
import org.jdom.Element
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
private fun Element.getOption(name: String) = getChildren("option").firstOrNull { it.getAttribute("name").value == name }
private fun Element.getOptionValue(name: String) = getOption(name)?.getAttribute("value")?.value
private fun Element.getOptionBody(name: String) = getOption(name)?.children?.firstOrNull()
private fun readV1Config(element: Element): KotlinFacetSettings {
return KotlinFacetSettings().apply {
val useProjectSettings = element.getOptionValue("useProjectSettings")?.toBoolean()
val targetPlatformName = element.getOptionBody("versionInfo")?.getOptionValue("targetPlatformName")
val targetPlatform = TargetPlatformKind.ALL_PLATFORMS.firstOrNull { it.description == targetPlatformName }
?: TargetPlatformKind.Jvm[JvmTarget.DEFAULT]
val compilerInfoElement = element.getOptionBody("compilerInfo")
val compilerSettings = CompilerSettings().apply {
compilerInfoElement?.getOptionBody("compilerSettings")?.let { compilerSettingsElement ->
XmlSerializer.deserializeInto(this, compilerSettingsElement)
}
}
val commonArgumentsElement = compilerInfoElement?.getOptionBody("_commonCompilerArguments")
val jvmArgumentsElement = compilerInfoElement?.getOptionBody("k2jvmCompilerArguments")
val jsArgumentsElement = compilerInfoElement?.getOptionBody("k2jsCompilerArguments")
val compilerArguments = targetPlatform.createCompilerArguments()
commonArgumentsElement?.let { XmlSerializer.deserializeInto(compilerArguments, it) }
when (compilerArguments) {
is K2JVMCompilerArguments -> jvmArgumentsElement?.let { XmlSerializer.deserializeInto(compilerArguments, it) }
is K2JSCompilerArguments -> jsArgumentsElement?.let { XmlSerializer.deserializeInto(compilerArguments, it) }
}
if (useProjectSettings != null) {
this.useProjectSettings = useProjectSettings
}
else {
// Migration problem workaround for pre-1.1-beta releases (mainly 1.0.6) -> 1.1-rc+
// Problematic cases: 1.1-beta/1.1-beta2 -> 1.1-rc+ (useProjectSettings gets reset to false)
// This heuristic detects old enough configurations:
if (jvmArgumentsElement == null) {
this.useProjectSettings = false
}
}
this.compilerSettings = compilerSettings
this.compilerArguments = compilerArguments
}
}
private fun readV2Config(element: Element): KotlinFacetSettings {
return KotlinFacetSettings().apply {
element.getAttributeValue("useProjectSettings")?.let { useProjectSettings = it.toBoolean() }
val platformName = element.getAttributeValue("platform")
val platformKind = TargetPlatformKind.ALL_PLATFORMS.firstOrNull { it.description == platformName } ?: TargetPlatformKind.DEFAULT_PLATFORM
element.getChild("compilerSettings")?.let {
compilerSettings = CompilerSettings()
XmlSerializer.deserializeInto(compilerSettings!!, it)
}
element.getChild("compilerArguments")?.let {
compilerArguments = platformKind.createCompilerArguments()
XmlSerializer.deserializeInto(compilerArguments!!, it)
}
}
}
fun deserializeFacetSettings(element: Element): KotlinFacetSettings {
val version =
try {
element.getAttribute("version")?.intValue
}
catch(e: DataConversionException) {
null
} ?: KotlinFacetSettings.DEFAULT_VERSION
return when (version) {
1 -> readV1Config(element)
2 -> readV2Config(element)
else -> KotlinFacetSettings() // Reset facet configuration if versions don't match
}
}
fun KotlinFacetSettings.serializeFacetSettings(element: Element) {
val filter = SkipDefaultsSerializationFilter()
element.setAttribute("version", KotlinFacetSettings.CURRENT_VERSION.toString())
targetPlatformKind?.let {
element.setAttribute("platform", it.description)
}
if (!useProjectSettings) {
element.setAttribute("useProjectSettings", useProjectSettings.toString())
}
compilerSettings?.let {
Element("compilerSettings").apply {
XmlSerializer.serializeInto(it, this, filter)
element.addContent(this)
}
}
compilerArguments?.let {
Element("compilerArguments").apply {
XmlSerializer.serializeInto(it, this, filter)
element.addContent(this)
}
}
}
@@ -16,12 +16,12 @@
package org.jetbrains.kotlin.jps.model
import com.intellij.util.xmlb.XmlSerializer
import org.jdom.Element
import org.jetbrains.jps.model.JpsElement
import org.jetbrains.jps.model.module.JpsModule
import org.jetbrains.jps.model.serialization.facet.JpsFacetConfigurationSerializer
import org.jetbrains.kotlin.config.KotlinFacetSettings
import org.jetbrains.kotlin.config.deserializeFacetSettings
import org.jetbrains.kotlin.config.serializeFacetSettings
object JpsKotlinFacetConfigurationSerializer : JpsFacetConfigurationSerializer<JpsKotlinFacetModuleExtension>(
JpsKotlinFacetModuleExtension.KIND,
@@ -34,7 +34,7 @@ object JpsKotlinFacetConfigurationSerializer : JpsFacetConfigurationSerializer<J
parent: JpsElement?,
module: JpsModule
): JpsKotlinFacetModuleExtension {
return JpsKotlinFacetModuleExtension(XmlSerializer.deserialize(facetConfigurationElement, KotlinFacetSettings::class.java)!!)
return JpsKotlinFacetModuleExtension(deserializeFacetSettings(facetConfigurationElement))
}
override fun saveExtension(
@@ -42,6 +42,6 @@ object JpsKotlinFacetConfigurationSerializer : JpsFacetConfigurationSerializer<J
facetConfigurationTag: Element,
module: JpsModule
) {
XmlSerializer.serializeInto((extension as JpsKotlinFacetModuleExtension).settings, facetConfigurationTag)
(extension as JpsKotlinFacetModuleExtension).settings.serializeFacetSettings(facetConfigurationTag)
}
}