[CHERRY PICKED FROM IJ] [Import] Introduce new version of KotlinFacetSettings, improve serialization of compiler arguments
^KTIJ-13451 Fixed GitOrigin-RevId: 17ff1ea6c947b7582b445004959c42e54819d31a Original commit: https://github.com/JetBrains/intellij-community/commit/14bd2509ad37f0c818f6753b097d4c138fba5d89
This commit is contained in:
committed by
Nikita Bobko
parent
1c634ee6e2
commit
f6d9e53b66
+46
@@ -0,0 +1,46 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.kotlin.arguments
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.arguments.Argument
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.InternalArgument
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.full.memberProperties
|
||||
|
||||
object CompilerArgumentsContentProspector {
|
||||
private val argumentPropertiesCache: MutableMap<KClass<out CommonToolArguments>, List<KProperty1<out CommonToolArguments, *>>> =
|
||||
mutableMapOf()
|
||||
|
||||
private val flagArgumentPropertiesCache: MutableMap<KClass<out CommonToolArguments>, List<KProperty1<out CommonToolArguments, Boolean>>> =
|
||||
mutableMapOf()
|
||||
|
||||
private val stringArgumentPropertiesCache: MutableMap<KClass<out CommonToolArguments>, List<KProperty1<out CommonToolArguments, String?>>> =
|
||||
mutableMapOf()
|
||||
|
||||
private val arrayArgumentPropertiesCache: MutableMap<KClass<out CommonToolArguments>, List<KProperty1<out CommonToolArguments, Array<String>?>>> =
|
||||
mutableMapOf()
|
||||
|
||||
private fun getCompilerArguments(kClass: KClass<out CommonToolArguments>) = argumentPropertiesCache.getOrPut(kClass) {
|
||||
kClass.memberProperties.filter { prop -> prop.annotations.singleOrNull { it is Argument } != null }
|
||||
}
|
||||
|
||||
private inline fun <reified R : Any> List<KProperty1<out CommonToolArguments, *>>.filterByReturnType(predicate: (KType?) -> Boolean) =
|
||||
filter { predicate(it.returnType) }.mapNotNull { it.safeAs<KProperty1<CommonToolArguments, R>>() }
|
||||
|
||||
fun getFlagCompilerArgumentProperties(kClass: KClass<out CommonToolArguments>): List<KProperty1<out CommonToolArguments, Boolean>> =
|
||||
flagArgumentPropertiesCache.getOrPut(kClass) { getCompilerArguments(kClass).filterByReturnType { it?.classifier == Boolean::class } }
|
||||
|
||||
fun <T : CommonToolArguments> getStringCompilerArgumentProperties(kClass: KClass<T>): List<KProperty1<out CommonToolArguments, String?>> =
|
||||
stringArgumentPropertiesCache.getOrPut(kClass) { getCompilerArguments(kClass).filterByReturnType { it?.classifier == String::class } }
|
||||
|
||||
fun <T : CommonToolArguments> getArrayCompilerArgumentProperties(kClass: KClass<T>): List<KProperty1<out CommonToolArguments, Array<String>?>> =
|
||||
arrayArgumentPropertiesCache.getOrPut(kClass) { getCompilerArguments(kClass).filterByReturnType { it?.classifier?.javaClass?.isArray == true } }
|
||||
|
||||
val freeArgsProperty: KProperty1<in CommonToolArguments, List<String>>
|
||||
get() = CommonToolArguments::freeArgs
|
||||
val internalArgumentsProperty: KProperty1<in CommonToolArguments, List<InternalArgument>>
|
||||
get() = CommonToolArguments::internalArguments
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.kotlin.arguments
|
||||
|
||||
import org.jdom.Element
|
||||
import org.jdom.Text
|
||||
import org.jetbrains.kotlin.cli.common.arguments.ArgumentParseErrors
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.InternalArgument
|
||||
import org.jetbrains.kotlin.cli.common.arguments.LanguageSettingsParser
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.io.File
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
|
||||
interface CompilerArgumentsDeserializer<T : CommonToolArguments> {
|
||||
val compilerArguments: T
|
||||
fun deserializeFrom(element: Element)
|
||||
}
|
||||
|
||||
class CompilerArgumentsDeserializerV5<T : CommonToolArguments>(override val compilerArguments: T) : CompilerArgumentsDeserializer<T> {
|
||||
override fun deserializeFrom(element: Element) {
|
||||
val flagArgumentsByName = readFlagArguments(element)
|
||||
val flagArgumentsPropertiesMap = CompilerArgumentsContentProspector.getFlagCompilerArgumentProperties(compilerArguments::class)
|
||||
.associateBy { it.name }
|
||||
flagArgumentsByName.forEach { (name, value) ->
|
||||
val mutableProp = flagArgumentsPropertiesMap[name].safeAs<KMutableProperty1<T, Boolean>>() ?: return@forEach
|
||||
mutableProp.set(compilerArguments, value)
|
||||
}
|
||||
|
||||
val stringArgumentsByName = readStringArguments(element)
|
||||
val stringArgumentPropertiesMap = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(compilerArguments::class)
|
||||
.associateBy { it.name }
|
||||
stringArgumentsByName.forEach { (name, arg) ->
|
||||
val mutableProp = stringArgumentPropertiesMap[name].safeAs<KMutableProperty1<T, String?>>() ?: return@forEach
|
||||
mutableProp.set(compilerArguments, arg)
|
||||
}
|
||||
val arrayArgumentsByName = readArrayArguments(element)
|
||||
val arrayArgumentPropertiesMap = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(compilerArguments::class)
|
||||
.associateBy { it.name }
|
||||
arrayArgumentsByName.forEach { (name, arr) ->
|
||||
val mutableProp = arrayArgumentPropertiesMap[name].safeAs<KMutableProperty1<T, Array<String>?>>() ?: return@forEach
|
||||
mutableProp.set(compilerArguments, arr)
|
||||
}
|
||||
val freeArgs = readElementsList(element, FREE_ARGS_ROOT_ELEMENTS_NAME, FREE_ARGS_ELEMENT_NAME)
|
||||
CompilerArgumentsContentProspector.freeArgsProperty.also {
|
||||
val mutableProp = it.safeAs<KMutableProperty1<T, List<String>>>() ?: return@also
|
||||
mutableProp.set(compilerArguments, freeArgs)
|
||||
}
|
||||
|
||||
val internalArguments = readElementsList(element, INTERNAL_ARGS_ROOT_ELEMENTS_NAME, INTERNAL_ARGS_ELEMENT_NAME)
|
||||
.mapNotNull { parseInternalArgument(it) }
|
||||
CompilerArgumentsContentProspector.internalArgumentsProperty.safeAs<KMutableProperty1<T, List<InternalArgument>>>()
|
||||
?.set(compilerArguments, internalArguments)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun readElementConfigurable(element: Element, rootElementName: String, configurable: Element.() -> Unit) {
|
||||
element.getChild(rootElementName)?.apply { configurable(this) }
|
||||
}
|
||||
|
||||
private fun readStringArguments(element: Element): Map<String, String> = mutableMapOf<String, String>().also {
|
||||
readElementConfigurable(element, STRING_ROOT_ELEMENTS_NAME) {
|
||||
getChildren(STRING_ELEMENT_NAME).forEach { child ->
|
||||
val name = child.getAttribute(NAME_ATTR_NAME)?.value ?: return@forEach
|
||||
val arg = if (name == "classpath")
|
||||
readElementsList(child, ARGS_ATTR_NAME, ARG_ATTR_NAME).joinToString(File.pathSeparator)
|
||||
else child.getAttribute(ARG_ATTR_NAME)?.value ?: return@forEach
|
||||
it += name to arg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun readFlagArguments(element: Element): Map<String, Boolean> = mutableMapOf<String, Boolean>().also {
|
||||
readElementConfigurable(element, FLAG_ROOT_ELEMENTS_NAME) {
|
||||
getChildren(FLAG_ELEMENT_NAME).forEach { child ->
|
||||
val name = child.getAttribute(NAME_ATTR_NAME)?.value ?: return@forEach
|
||||
val arg = child.getAttribute(ARG_ATTR_NAME)?.booleanValue ?: return@forEach
|
||||
it += name to arg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun readElementsList(element: Element, rootElementName: String, elementName: String): List<String> =
|
||||
mutableListOf<String>().also { list ->
|
||||
readElementConfigurable(element, rootElementName) {
|
||||
val items = getChildren(elementName)
|
||||
if (items.isNotEmpty()) {
|
||||
items.mapNotNullTo(list) { (it.content.firstOrNull() as? Text)?.textTrim }
|
||||
} else {
|
||||
list += listOfNotNull((content.firstOrNull() as? Text)?.textTrim)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun readArrayArguments(element: Element): Map<String, Array<String>> = mutableMapOf<String, Array<String>>().apply {
|
||||
readElementConfigurable(element, ARRAY_ROOT_ELEMENTS_NAME) {
|
||||
getChildren(ARRAY_ELEMENT_NAME).forEach { child ->
|
||||
val name = child.getAttribute(NAME_ATTR_NAME)?.value ?: return@forEach
|
||||
val array = readElementsList(child, ARGS_ATTR_NAME, ARG_ATTR_NAME).toTypedArray()
|
||||
this@apply += name to array
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseInternalArgument(argument: String): InternalArgument? {
|
||||
val parser = LanguageSettingsParser()
|
||||
return parser.parseInternalArgument(argument, ArgumentParseErrors())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.kotlin.arguments
|
||||
|
||||
import org.jdom.Element
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments
|
||||
import org.jetbrains.kotlin.config.restoreNormalOrdering
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.io.File
|
||||
import kotlin.reflect.KProperty1
|
||||
|
||||
interface CompilerArgumentsSerializer<T : CommonToolArguments> {
|
||||
val arguments: T
|
||||
fun serializeTo(element: Element): Element
|
||||
}
|
||||
|
||||
class CompilerArgumentsSerializerV5<T : CommonToolArguments>(override val arguments: T) : CompilerArgumentsSerializer<T> {
|
||||
|
||||
override fun serializeTo(element: Element): Element = Element(COMPILER_ARGUMENTS_ELEMENT_NAME).apply {
|
||||
val newInstance = arguments::class.java.getConstructor().newInstance()
|
||||
val flagArgumentsByName = CompilerArgumentsContentProspector.getFlagCompilerArgumentProperties(arguments::class)
|
||||
.mapNotNull { prop ->
|
||||
prop.safeAs<KProperty1<T, Boolean>>()
|
||||
?.takeIf { it.get(arguments) != it.get(newInstance) }
|
||||
?.get(arguments)
|
||||
?.let { prop.name to it }
|
||||
}.toMap()
|
||||
saveFlagArguments(this, flagArgumentsByName)
|
||||
|
||||
val stringArgumentsByName = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(arguments::class)
|
||||
.mapNotNull { prop ->
|
||||
prop.safeAs<KProperty1<T, String?>>()
|
||||
?.takeIf { it.get(arguments) != it.get(newInstance) }
|
||||
?.get(arguments)
|
||||
?.let { prop.name to it }
|
||||
}.toMap()
|
||||
saveStringArguments(this, stringArgumentsByName)
|
||||
|
||||
val arrayArgumentsByName = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(arguments::class)
|
||||
.mapNotNull { prop ->
|
||||
prop.safeAs<KProperty1<T, Array<String>?>>()
|
||||
?.takeIf { it.get(arguments)?.contentEquals(it.get(newInstance)) != true }
|
||||
?.get(arguments)
|
||||
?.let { prop.name to it }
|
||||
}.filterNot { it.second.isEmpty() }
|
||||
.toMap()
|
||||
saveArrayArguments(this, arrayArgumentsByName)
|
||||
val freeArgs = CompilerArgumentsContentProspector.freeArgsProperty.get(arguments)
|
||||
saveElementsList(this, FREE_ARGS_ROOT_ELEMENTS_NAME, FREE_ARGS_ELEMENT_NAME, freeArgs)
|
||||
val internalArguments = CompilerArgumentsContentProspector.internalArgumentsProperty.get(arguments).map { it.stringRepresentation }
|
||||
saveElementsList(this, INTERNAL_ARGS_ROOT_ELEMENTS_NAME, INTERNAL_ARGS_ELEMENT_NAME, internalArguments)
|
||||
restoreNormalOrdering(arguments)
|
||||
element.addContent(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun saveElementConfigurable(element: Element, rootElementName: String, configurable: Element.() -> Unit) {
|
||||
element.addContent(Element(rootElementName).apply { configurable(this) })
|
||||
}
|
||||
|
||||
private fun saveStringArguments(element: Element, argumentsByName: Map<String, String>) {
|
||||
if (argumentsByName.isEmpty()) return
|
||||
saveElementConfigurable(element, STRING_ROOT_ELEMENTS_NAME) {
|
||||
argumentsByName.entries.forEach { (name, arg) ->
|
||||
Element(STRING_ELEMENT_NAME).also {
|
||||
it.setAttribute(NAME_ATTR_NAME, name)
|
||||
if (name == "classpath") {
|
||||
saveElementsList(it, ARGS_ATTR_NAME, ARG_ATTR_NAME, arg.split(File.pathSeparator))
|
||||
} else {
|
||||
it.setAttribute(ARG_ATTR_NAME, arg)
|
||||
}
|
||||
addContent(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveFlagArguments(element: Element, argumentsByName: Map<String, Boolean>) {
|
||||
if (argumentsByName.isEmpty()) return
|
||||
saveElementConfigurable(element, FLAG_ROOT_ELEMENTS_NAME) {
|
||||
argumentsByName.entries.forEach { (name, arg) ->
|
||||
Element(FLAG_ELEMENT_NAME).also {
|
||||
it.setAttribute(NAME_ATTR_NAME, name)
|
||||
it.setAttribute(ARG_ATTR_NAME, arg.toString())
|
||||
addContent(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveElementsList(element: Element, rootElementName: String, elementName: String, elementList: List<String>) {
|
||||
if (elementList.isEmpty()) return
|
||||
saveElementConfigurable(element, rootElementName) {
|
||||
val singleModule = elementList.singleOrNull()
|
||||
if (singleModule != null) {
|
||||
addContent(singleModule)
|
||||
} else {
|
||||
elementList.forEach { elementValue -> addContent(Element(elementName).also { it.addContent(elementValue) }) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveArrayArguments(element: Element, arrayArgumentsByName: Map<String, Array<String>>) {
|
||||
if (arrayArgumentsByName.isEmpty()) return
|
||||
saveElementConfigurable(element, ARRAY_ROOT_ELEMENTS_NAME) {
|
||||
arrayArgumentsByName.entries.forEach { (name, arg) ->
|
||||
Element(ARRAY_ELEMENT_NAME).also {
|
||||
it.setAttribute(NAME_ATTR_NAME, name)
|
||||
saveElementsList(it, ARGS_ATTR_NAME, ARG_ATTR_NAME, arg.toList())
|
||||
addContent(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.kotlin.arguments
|
||||
|
||||
internal const val COMPILER_ARGUMENTS_ELEMENT_NAME = "compilerArguments"
|
||||
internal const val FLAG_ROOT_ELEMENTS_NAME = "flagArguments"
|
||||
internal const val FLAG_ELEMENT_NAME = "flagArg"
|
||||
internal const val STRING_ROOT_ELEMENTS_NAME = "stringArguments"
|
||||
internal const val STRING_ELEMENT_NAME = "stringArg"
|
||||
internal const val ARRAY_ROOT_ELEMENTS_NAME = "arrayArguments"
|
||||
internal const val ARRAY_ELEMENT_NAME = "arrayArg"
|
||||
internal const val FREE_ARGS_ROOT_ELEMENTS_NAME = "freeArgs"
|
||||
internal const val FREE_ARGS_ELEMENT_NAME = "freeArg"
|
||||
internal const val INTERNAL_ARGS_ROOT_ELEMENTS_NAME = "internalArgs"
|
||||
internal const val INTERNAL_ARGS_ELEMENT_NAME = "internalArg"
|
||||
|
||||
internal const val NAME_ATTR_NAME = "name"
|
||||
internal const val ARG_ATTR_NAME = "arg"
|
||||
internal const val ARGS_ATTR_NAME = "args"
|
||||
@@ -159,7 +159,7 @@ data class ExternalSystemNativeMainRunTask(
|
||||
class KotlinFacetSettings {
|
||||
companion object {
|
||||
// Increment this when making serialization-incompatible changes to configuration data
|
||||
val CURRENT_VERSION = 4
|
||||
val CURRENT_VERSION = 5
|
||||
val DEFAULT_VERSION = 0
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@ import com.intellij.util.xmlb.XmlSerializer
|
||||
import org.jdom.DataConversionException
|
||||
import org.jdom.Element
|
||||
import org.jdom.Text
|
||||
import org.jetbrains.kotlin.arguments.COMPILER_ARGUMENTS_ELEMENT_NAME
|
||||
import org.jetbrains.kotlin.arguments.CompilerArgumentsDeserializerV5
|
||||
import org.jetbrains.kotlin.arguments.CompilerArgumentsSerializerV5
|
||||
import org.jetbrains.kotlin.cli.common.arguments.*
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.platform.*
|
||||
@@ -25,7 +28,7 @@ import java.lang.reflect.Modifier
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.full.superclasses
|
||||
|
||||
fun Element.getOption(name: String) = getChildren("option").firstOrNull { it.getAttribute("name").value == name }
|
||||
fun Element.getOption(name: String) = getChildren("option").firstOrNull { name == it?.getAttribute("name")?.value }
|
||||
|
||||
private fun Element.getOptionValue(name: String) = getOption(name)?.getAttribute("value")?.value
|
||||
|
||||
@@ -124,7 +127,10 @@ fun Element.getFacetPlatformByConfigurationElement(): TargetPlatform {
|
||||
}.orDefault() // finally, fallback to the default platform
|
||||
}
|
||||
|
||||
private fun readV2AndLaterConfig(element: Element): KotlinFacetSettings {
|
||||
private fun readV2AndLaterConfig(
|
||||
element: Element,
|
||||
argumentReader: (Element, CommonToolArguments) -> Unit = { el, arg -> XmlSerializer.deserializeInto(arg, el) }
|
||||
): KotlinFacetSettings {
|
||||
return KotlinFacetSettings().apply {
|
||||
element.getAttributeValue("useProjectSettings")?.let { useProjectSettings = it.toBoolean() }
|
||||
val targetPlatform = element.getFacetPlatformByConfigurationElement()
|
||||
@@ -164,12 +170,12 @@ private fun readV2AndLaterConfig(element: Element): KotlinFacetSettings {
|
||||
compilerSettings = CompilerSettings()
|
||||
XmlSerializer.deserializeInto(compilerSettings!!, it)
|
||||
}
|
||||
element.getChild("compilerArguments")?.let {
|
||||
element.getChild(COMPILER_ARGUMENTS_ELEMENT_NAME)?.let {
|
||||
compilerArguments = targetPlatform.createArguments {
|
||||
freeArgs = mutableListOf()
|
||||
internalArguments = mutableListOf()
|
||||
}
|
||||
XmlSerializer.deserializeInto(compilerArguments!!, it)
|
||||
argumentReader(it, compilerArguments!!)
|
||||
compilerArguments!!.detectVersionAutoAdvance()
|
||||
}
|
||||
productionOutputPath = element.getChild("productionOutputPath")?.let {
|
||||
@@ -193,16 +199,12 @@ private fun readElementsList(element: Element, rootElementName: String, elementN
|
||||
return null
|
||||
}
|
||||
|
||||
private fun readV3Config(element: Element): KotlinFacetSettings {
|
||||
return readV2AndLaterConfig(element)
|
||||
}
|
||||
|
||||
private fun readV2Config(element: Element): KotlinFacetSettings {
|
||||
return readV2AndLaterConfig(element)
|
||||
}
|
||||
|
||||
private fun readLatestConfig(element: Element): KotlinFacetSettings {
|
||||
return readV2AndLaterConfig(element)
|
||||
return readV2AndLaterConfig(element) { el, bean -> CompilerArgumentsDeserializerV5(bean).deserializeFrom(el) }
|
||||
}
|
||||
|
||||
fun deserializeFacetSettings(element: Element): KotlinFacetSettings {
|
||||
@@ -213,8 +215,7 @@ fun deserializeFacetSettings(element: Element): KotlinFacetSettings {
|
||||
} ?: KotlinFacetSettings.DEFAULT_VERSION
|
||||
return when (version) {
|
||||
1 -> readV1Config(element)
|
||||
2 -> readV2Config(element)
|
||||
3 -> readV3Config(element)
|
||||
2, 3, 4 -> readV2Config(element)
|
||||
KotlinFacetSettings.CURRENT_VERSION -> readLatestConfig(element)
|
||||
else -> return KotlinFacetSettings() // Reset facet configuration if versions don't match
|
||||
}.apply { this.version = version }
|
||||
@@ -278,7 +279,7 @@ private val Class<*>.normalOrdering
|
||||
// Replacing fields with delegated properties leads to unexpected reordering of entries in facet configuration XML
|
||||
// It happens due to XmlSerializer using different orderings for field- and method-based accessors
|
||||
// This code restores the original ordering
|
||||
private fun Element.restoreNormalOrdering(bean: Any) {
|
||||
internal fun Element.restoreNormalOrdering(bean: Any) {
|
||||
val normalOrdering = bean.javaClass.normalOrdering
|
||||
val elementsToReorder = this.getContent<Element> { it is Element && it.getAttribute("name")?.value in normalOrdering }
|
||||
elementsToReorder.sortedBy { normalOrdering[it.getAttribute("name")?.value!!] }
|
||||
@@ -293,7 +294,7 @@ private fun buildChildElement(element: Element, tag: String, bean: Any, filter:
|
||||
}
|
||||
}
|
||||
|
||||
private fun KotlinFacetSettings.writeLatestConfig(element: Element) {
|
||||
private fun KotlinFacetSettings.writeConfig(element: Element) {
|
||||
val filter = SkipDefaultsSerializationFilter()
|
||||
|
||||
// TODO: Introduce new version of facet serialization. See https://youtrack.jetbrains.com/issue/KT-38235
|
||||
@@ -362,9 +363,20 @@ private fun KotlinFacetSettings.writeLatestConfig(element: Element) {
|
||||
it.convertPathsToSystemIndependent()
|
||||
buildChildElement(element, "compilerSettings", it, filter)
|
||||
}
|
||||
}
|
||||
|
||||
private fun KotlinFacetSettings.writeV2toV4Config(element: Element) = writeConfig(element).apply {
|
||||
compilerArguments?.let { copyBean(it) }?.let {
|
||||
it.convertPathsToSystemIndependent()
|
||||
val compilerArgumentsXml = buildChildElement(element, "compilerArguments", it, filter)
|
||||
val compilerArgumentsXml = buildChildElement(element, "compilerArguments", it, SkipDefaultsSerializationFilter())
|
||||
compilerArgumentsXml.dropVersionsIfNecessary(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun KotlinFacetSettings.writeLatestConfig(element: Element) = writeConfig(element).apply {
|
||||
compilerArguments?.let { copyBean(it) }?.let {
|
||||
it.convertPathsToSystemIndependent()
|
||||
val compilerArgumentsXml = CompilerArgumentsSerializerV5(it).serializeTo(element)
|
||||
compilerArgumentsXml.dropVersionsIfNecessary(it)
|
||||
}
|
||||
}
|
||||
@@ -400,15 +412,18 @@ fun Element.dropVersionsIfNecessary(settings: CommonCompilerArguments) {
|
||||
}
|
||||
}
|
||||
|
||||
fun KotlinFacetSettings.serializeFacetSettings(element: Element) {
|
||||
val versionToWrite = when (version) {
|
||||
2, 3 -> version
|
||||
else -> KotlinFacetSettings.CURRENT_VERSION
|
||||
fun KotlinFacetSettings.serializeFacetSettings(element: Element) = when (version) {
|
||||
2, 3, 4 -> {
|
||||
element.setAttribute("version", version.toString())
|
||||
writeV2toV4Config(element)
|
||||
}
|
||||
else -> {
|
||||
element.setAttribute("version", KotlinFacetSettings.CURRENT_VERSION.toString())
|
||||
writeLatestConfig(element)
|
||||
}
|
||||
element.setAttribute("version", versionToWrite.toString())
|
||||
writeLatestConfig(element)
|
||||
}
|
||||
|
||||
|
||||
private fun TargetPlatform.serializeComponentPlatforms(): String {
|
||||
val componentPlatforms = componentPlatforms
|
||||
val componentPlatformNames = componentPlatforms.mapTo(ArrayList()) { it.serializeToString() }
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.kotlin.arguments
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.arguments.*
|
||||
import org.junit.Test
|
||||
|
||||
|
||||
class CompilerArgumentsContentProspectorTest {
|
||||
|
||||
@Test
|
||||
fun testJVMArgumentsContent() {
|
||||
val flagProperties = CompilerArgumentsContentProspector.getFlagCompilerArgumentProperties(K2JVMCompilerArguments::class)
|
||||
val stringProperties = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(K2JVMCompilerArguments::class)
|
||||
val arrayProperties = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(K2JVMCompilerArguments::class)
|
||||
|
||||
assertContentEquals(flagProperties, k2JVMCompilerArgumentsFlagProperties) { sortedBy { it.name } }
|
||||
assertContentEquals(stringProperties, k2JVMCompilerArgumentsStringProperties) { sortedBy { it.name } }
|
||||
assertContentEquals(arrayProperties, k2JVMCompilerArgumentsArrayArgumentProperties) { sortedBy { it.name } }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMetadataArgumentsContent() {
|
||||
val flagProperties = CompilerArgumentsContentProspector.getFlagCompilerArgumentProperties(K2MetadataCompilerArguments::class)
|
||||
val stringProperties = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(K2MetadataCompilerArguments::class)
|
||||
val arrayProperties = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(K2MetadataCompilerArguments::class)
|
||||
|
||||
assertContentEquals(flagProperties, k2MetadataCompilerArgumentsFlagProperties) { sortedBy { it.name } }
|
||||
assertContentEquals(stringProperties, k2MetadataCompilerArgumentsStringProperties) { sortedBy { it.name } }
|
||||
assertContentEquals(arrayProperties, k2MetadataCompilerArgumentsArrayProperties) { sortedBy { it.name } }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testJsArgumentsContent() {
|
||||
val flagProperties = CompilerArgumentsContentProspector.getFlagCompilerArgumentProperties(K2JSCompilerArguments::class)
|
||||
val stringProperties = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(K2JSCompilerArguments::class)
|
||||
val arrayProperties = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(K2JSCompilerArguments::class)
|
||||
|
||||
assertContentEquals(flagProperties, k2JSCompilerArgumentsFlagProperties) { sortedBy { it.name } }
|
||||
assertContentEquals(stringProperties, k2JSCompilerArgumentsStringProperties) { sortedBy { it.name } }
|
||||
assert(arrayProperties.isEmpty()) { "Expected empty arrayProperties, but actual ${arrayProperties.joinToString { it.name }}" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testJsDceArgumentsContent() {
|
||||
val flagProperties = CompilerArgumentsContentProspector.getFlagCompilerArgumentProperties(K2JSDceArguments::class)
|
||||
val stringProperties = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(K2JSDceArguments::class)
|
||||
val arrayProperties = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(K2JSDceArguments::class)
|
||||
|
||||
assertContentEquals(flagProperties, k2JSDceCompilerArgumentsFlagProperties) { sortedBy { it.name } }
|
||||
assertContentEquals(stringProperties, k2JSDceCompilerArgumentsStringProperties) { sortedBy { it.name } }
|
||||
assertContentEquals(arrayProperties, k2JSDceCompilerArgumentsArrayProperties) { sortedBy { it.name } }
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val commonToolArgumentsFlagProperties = listOf(
|
||||
CommonToolArguments::allWarningsAsErrors,
|
||||
CommonToolArguments::extraHelp,
|
||||
CommonToolArguments::help,
|
||||
CommonToolArguments::suppressWarnings,
|
||||
CommonToolArguments::verbose,
|
||||
CommonToolArguments::version,
|
||||
)
|
||||
|
||||
private val commonCompilerArgumentsFlagProperties = commonToolArgumentsFlagProperties + listOf(
|
||||
CommonCompilerArguments::allowKotlinPackage,
|
||||
CommonCompilerArguments::progressiveMode,
|
||||
CommonCompilerArguments::script,
|
||||
CommonCompilerArguments::noInline,
|
||||
CommonCompilerArguments::skipMetadataVersionCheck,
|
||||
CommonCompilerArguments::skipPrereleaseCheck,
|
||||
CommonCompilerArguments::allowKotlinPackage,
|
||||
CommonCompilerArguments::reportOutputFiles,
|
||||
CommonCompilerArguments::multiPlatform,
|
||||
CommonCompilerArguments::noCheckActual,
|
||||
CommonCompilerArguments::newInference,
|
||||
CommonCompilerArguments::inlineClasses,
|
||||
CommonCompilerArguments::polymorphicSignature,
|
||||
CommonCompilerArguments::legacySmartCastAfterTry,
|
||||
CommonCompilerArguments::effectSystem,
|
||||
CommonCompilerArguments::readDeserializedContracts,
|
||||
CommonCompilerArguments::properIeee754Comparisons,
|
||||
CommonCompilerArguments::reportPerf,
|
||||
CommonCompilerArguments::allowResultReturnType,
|
||||
CommonCompilerArguments::listPhases,
|
||||
CommonCompilerArguments::profilePhases,
|
||||
CommonCompilerArguments::checkPhaseConditions,
|
||||
CommonCompilerArguments::checkStickyPhaseConditions,
|
||||
CommonCompilerArguments::useFir,
|
||||
CommonCompilerArguments::useFirExtendedCheckers,
|
||||
CommonCompilerArguments::disableUltraLightClasses,
|
||||
CommonCompilerArguments::useMixedNamedArguments,
|
||||
CommonCompilerArguments::expectActualLinker,
|
||||
CommonCompilerArguments::disableDefaultScriptingPlugin,
|
||||
CommonCompilerArguments::inferenceCompatibility
|
||||
)
|
||||
|
||||
private val commonCompilerArgumentsStringProperties = listOf(
|
||||
CommonCompilerArguments::intellijPluginRoot,
|
||||
CommonCompilerArguments::dumpPerf,
|
||||
CommonCompilerArguments::metadataVersion,
|
||||
CommonCompilerArguments::dumpDirectory,
|
||||
CommonCompilerArguments::dumpOnlyFqName,
|
||||
CommonCompilerArguments::explicitApi
|
||||
)
|
||||
private val commonCompilerArgumentsArrayArgumentProperties = listOf(
|
||||
CommonCompilerArguments::pluginOptions,
|
||||
CommonCompilerArguments::pluginClasspaths,
|
||||
CommonCompilerArguments::experimental,
|
||||
CommonCompilerArguments::useExperimental,
|
||||
CommonCompilerArguments::optIn,
|
||||
CommonCompilerArguments::commonSources,
|
||||
CommonCompilerArguments::disablePhases,
|
||||
CommonCompilerArguments::verbosePhases,
|
||||
CommonCompilerArguments::phasesToDumpBefore,
|
||||
CommonCompilerArguments::phasesToDumpAfter,
|
||||
CommonCompilerArguments::phasesToDump,
|
||||
CommonCompilerArguments::namesExcludedFromDumping,
|
||||
CommonCompilerArguments::phasesToValidateBefore,
|
||||
CommonCompilerArguments::phasesToValidateAfter,
|
||||
CommonCompilerArguments::phasesToValidate,
|
||||
)
|
||||
|
||||
private val k2JVMCompilerArgumentsFlagProperties = commonCompilerArgumentsFlagProperties + listOf(
|
||||
K2JVMCompilerArguments::includeRuntime,
|
||||
K2JVMCompilerArguments::noJdk,
|
||||
K2JVMCompilerArguments::noStdlib,
|
||||
K2JVMCompilerArguments::noReflect,
|
||||
K2JVMCompilerArguments::javaParameters,
|
||||
K2JVMCompilerArguments::useIR,
|
||||
K2JVMCompilerArguments::useOldBackend,
|
||||
K2JVMCompilerArguments::allowUnstableDependencies,
|
||||
K2JVMCompilerArguments::doNotClearBindingContext,
|
||||
K2JVMCompilerArguments::noCallAssertions,
|
||||
K2JVMCompilerArguments::noReceiverAssertions,
|
||||
K2JVMCompilerArguments::noParamAssertions,
|
||||
K2JVMCompilerArguments::strictJavaNullabilityAssertions,
|
||||
K2JVMCompilerArguments::noOptimize,
|
||||
K2JVMCompilerArguments::inheritMultifileParts,
|
||||
K2JVMCompilerArguments::useTypeTable,
|
||||
K2JVMCompilerArguments::skipRuntimeVersionCheck,
|
||||
K2JVMCompilerArguments::useOldClassFilesReading,
|
||||
K2JVMCompilerArguments::singleModule,
|
||||
K2JVMCompilerArguments::suppressMissingBuiltinsError,
|
||||
K2JVMCompilerArguments::useJavac,
|
||||
K2JVMCompilerArguments::compileJava,
|
||||
K2JVMCompilerArguments::noExceptionOnExplicitEqualsForBoxedNull,
|
||||
K2JVMCompilerArguments::disableStandardScript,
|
||||
K2JVMCompilerArguments::strictMetadataVersionSemantics,
|
||||
K2JVMCompilerArguments::sanitizeParentheses,
|
||||
K2JVMCompilerArguments::allowNoSourceFiles,
|
||||
K2JVMCompilerArguments::emitJvmTypeAnnotations,
|
||||
K2JVMCompilerArguments::noOptimizedCallableReferences,
|
||||
K2JVMCompilerArguments::noKotlinNothingValueException,
|
||||
K2JVMCompilerArguments::noResetJarTimestamps,
|
||||
K2JVMCompilerArguments::noUnifiedNullChecks,
|
||||
K2JVMCompilerArguments::useOldSpilledVarTypeAnalysis,
|
||||
K2JVMCompilerArguments::useOldInlineClassesManglingScheme,
|
||||
K2JVMCompilerArguments::enableJvmPreview,
|
||||
)
|
||||
|
||||
private val k2JVMCompilerArgumentsStringProperties = commonCompilerArgumentsStringProperties + listOf(
|
||||
K2JVMCompilerArguments::destination,
|
||||
K2JVMCompilerArguments::classpath,
|
||||
K2JVMCompilerArguments::jdkHome,
|
||||
K2JVMCompilerArguments::expression,
|
||||
K2JVMCompilerArguments::moduleName,
|
||||
K2JVMCompilerArguments::jvmTarget,
|
||||
K2JVMCompilerArguments::abiStability,
|
||||
K2JVMCompilerArguments::javaModulePath,
|
||||
K2JVMCompilerArguments::constructorCallNormalizationMode,
|
||||
K2JVMCompilerArguments::assertionsMode,
|
||||
K2JVMCompilerArguments::buildFile,
|
||||
K2JVMCompilerArguments::declarationsOutputPath,
|
||||
K2JVMCompilerArguments::javaPackagePrefix,
|
||||
K2JVMCompilerArguments::supportCompatqualCheckerFrameworkAnnotations,
|
||||
K2JVMCompilerArguments::jspecifyAnnotations,
|
||||
K2JVMCompilerArguments::jvmDefault,
|
||||
K2JVMCompilerArguments::defaultScriptExtension,
|
||||
K2JVMCompilerArguments::stringConcat,
|
||||
K2JVMCompilerArguments::klibLibraries,
|
||||
K2JVMCompilerArguments::profileCompilerCommand,
|
||||
K2JVMCompilerArguments::repeatCompileModules
|
||||
)
|
||||
|
||||
private val k2JVMCompilerArgumentsArrayArgumentProperties = commonCompilerArgumentsArrayArgumentProperties + listOf(
|
||||
K2JVMCompilerArguments::scriptTemplates,
|
||||
K2JVMCompilerArguments::additionalJavaModules,
|
||||
K2JVMCompilerArguments::scriptResolverEnvironment,
|
||||
K2JVMCompilerArguments::javacArguments,
|
||||
K2JVMCompilerArguments::javaSourceRoots,
|
||||
K2JVMCompilerArguments::jsr305,
|
||||
K2JVMCompilerArguments::friendPaths
|
||||
)
|
||||
|
||||
private val k2MetadataCompilerArgumentsFlagProperties = commonCompilerArgumentsFlagProperties + listOf(
|
||||
K2MetadataCompilerArguments::enabledInJps
|
||||
)
|
||||
private val k2MetadataCompilerArgumentsStringProperties = commonCompilerArgumentsStringProperties + listOf(
|
||||
K2MetadataCompilerArguments::destination,
|
||||
K2MetadataCompilerArguments::classpath,
|
||||
K2MetadataCompilerArguments::moduleName
|
||||
)
|
||||
private val k2MetadataCompilerArgumentsArrayProperties = commonCompilerArgumentsArrayArgumentProperties + listOf(
|
||||
K2MetadataCompilerArguments::friendPaths,
|
||||
K2MetadataCompilerArguments::refinesPaths
|
||||
)
|
||||
private val k2JSCompilerArgumentsFlagProperties = commonCompilerArgumentsFlagProperties + listOf(
|
||||
K2JSCompilerArguments::noStdlib,
|
||||
K2JSCompilerArguments::sourceMap,
|
||||
K2JSCompilerArguments::metaInfo,
|
||||
K2JSCompilerArguments::irProduceKlibDir,
|
||||
K2JSCompilerArguments::irProduceKlibFile,
|
||||
K2JSCompilerArguments::irProduceJs,
|
||||
K2JSCompilerArguments::irDce,
|
||||
K2JSCompilerArguments::irDceDriven,
|
||||
K2JSCompilerArguments::irDcePrintReachabilityInfo,
|
||||
K2JSCompilerArguments::irPropertyLazyInitialization,
|
||||
K2JSCompilerArguments::irOnly,
|
||||
K2JSCompilerArguments::irPerModule,
|
||||
K2JSCompilerArguments::generateDts,
|
||||
K2JSCompilerArguments::typedArrays,
|
||||
K2JSCompilerArguments::friendModulesDisabled,
|
||||
K2JSCompilerArguments::metadataOnly,
|
||||
K2JSCompilerArguments::enableJsScripting,
|
||||
K2JSCompilerArguments::fakeOverrideValidator,
|
||||
K2JSCompilerArguments::wasm
|
||||
)
|
||||
private val k2JSCompilerArgumentsStringProperties = commonCompilerArgumentsStringProperties + listOf(
|
||||
K2JSCompilerArguments::outputFile,
|
||||
K2JSCompilerArguments::libraries,
|
||||
K2JSCompilerArguments::sourceMapPrefix,
|
||||
K2JSCompilerArguments::sourceMapBaseDirs,
|
||||
K2JSCompilerArguments::sourceMapEmbedSources,
|
||||
K2JSCompilerArguments::target,
|
||||
K2JSCompilerArguments::moduleKind,
|
||||
K2JSCompilerArguments::main,
|
||||
K2JSCompilerArguments::outputPrefix,
|
||||
K2JSCompilerArguments::outputPostfix,
|
||||
K2JSCompilerArguments::irModuleName,
|
||||
K2JSCompilerArguments::includes,
|
||||
K2JSCompilerArguments::friendModules,
|
||||
K2JSCompilerArguments::errorTolerancePolicy,
|
||||
)
|
||||
|
||||
private val k2JSDceCompilerArgumentsFlagProperties = commonToolArgumentsFlagProperties + listOf(
|
||||
K2JSDceArguments::devMode,
|
||||
K2JSDceArguments::printReachabilityInfo,
|
||||
)
|
||||
private val k2JSDceCompilerArgumentsStringProperties = listOf(
|
||||
K2JSDceArguments::outputDirectory,
|
||||
K2JSDceArguments::devModeOverwritingStrategy,
|
||||
)
|
||||
private val k2JSDceCompilerArgumentsArrayProperties = listOf(
|
||||
K2JSDceArguments::declarationsToKeep
|
||||
)
|
||||
|
||||
private fun <T> assertContentEquals(expect: Iterable<T>, actual: Iterable<T>, preprocessor: Iterable<T>.() -> Iterable<T>) {
|
||||
(expect.count() == actual.count()) && preprocessor(expect).zip(preprocessor(actual)).all { it.first == it.second }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.kotlin.arguments
|
||||
|
||||
import org.jdom.Element
|
||||
import org.jetbrains.kotlin.cli.common.arguments.*
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.junit.Test
|
||||
import kotlin.random.Random
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.full.memberProperties
|
||||
|
||||
class CompilerArgumentsSerializationTest {
|
||||
|
||||
@Test
|
||||
fun testDummyJVM() {
|
||||
doSerializeDeserializeAndCompareTest<K2JVMCompilerArguments>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRandomFlagArgumentsJVM() {
|
||||
doRandomFlagArgumentsTest<K2JVMCompilerArguments>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRandomStringArgumentsJVM() {
|
||||
doRandomStringArgumentsTest<K2JVMCompilerArguments>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLongClasspathArgumentJVM() {
|
||||
doSerializeDeserializeAndCompareTest<K2JVMCompilerArguments> {
|
||||
classpath = generateSequence { generateRandomString(50) }.take(10).toList().joinToString(File.pathSeparator)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun testRandomArrayArgumentsJVM() {
|
||||
doRandomArrayArgumentsTest<K2JVMCompilerArguments>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDummyJs() {
|
||||
doSerializeDeserializeAndCompareTest<K2JSCompilerArguments>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRandomFlagArgumentsJS() {
|
||||
doRandomFlagArgumentsTest<K2JSCompilerArguments>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRandomStringArgumentsJS() {
|
||||
doRandomStringArgumentsTest<K2JSCompilerArguments>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRandomArrayArgumentsJS() {
|
||||
doRandomArrayArgumentsTest<K2JSCompilerArguments>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDummyMetadata() {
|
||||
doSerializeDeserializeAndCompareTest<K2MetadataCompilerArguments>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRandomFlagArgumentsMetadata() {
|
||||
doRandomFlagArgumentsTest<K2MetadataCompilerArguments>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRandomStringArgumentsMetadata() {
|
||||
doRandomStringArgumentsTest<K2MetadataCompilerArguments>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLongClasspathArgumentMetadata() {
|
||||
doSerializeDeserializeAndCompareTest<K2MetadataCompilerArguments> {
|
||||
classpath = generateSequence { generateRandomString(50) }.take(10).toList().joinToString(File.pathSeparator)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRandomArrayArgumentsMetadata() {
|
||||
doRandomArrayArgumentsTest<K2MetadataCompilerArguments>()
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun testDummyJsDce() {
|
||||
doSerializeDeserializeAndCompareTest<K2JSDceArguments>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRandomFlagArgumentsJSDce() {
|
||||
doRandomFlagArgumentsTest<K2JSDceArguments>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRandomStringArgumentsJSDce() {
|
||||
doRandomStringArgumentsTest<K2JSDceArguments>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRandomArrayArgumentsJSDce() {
|
||||
doRandomArrayArgumentsTest<K2JSDceArguments>()
|
||||
}
|
||||
|
||||
|
||||
private inline fun <reified T : CommonToolArguments> doSerializeDeserializeAndCompareTest(configure: T.() -> Unit = {}) {
|
||||
val oldInstance = T::class.java.getConstructor().newInstance().apply(configure)
|
||||
val serializer = CompilerArgumentsSerializerV5<T>(oldInstance)
|
||||
val mockFacetElement = Element("ROOT")
|
||||
val element = serializer.serializeTo(mockFacetElement)
|
||||
val newInstance = T::class.java.getConstructor().newInstance()
|
||||
val deserializer = CompilerArgumentsDeserializerV5(newInstance)
|
||||
deserializer.deserializeFrom(element)
|
||||
T::class.memberProperties.mapNotNull { it.safeAs<KProperty1<T, *>>() }.forEach {
|
||||
assert(it.get(oldInstance) == it.get(newInstance)) {
|
||||
"Property ${it.name} has different values before (${it.get(oldInstance)}) and after (${it.get(newInstance)}) serialization"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T : CommonToolArguments> doRandomFlagArgumentsTest() {
|
||||
val flagProperties = CompilerArgumentsContentProspector.getFlagCompilerArgumentProperties(T::class)
|
||||
val randomFlags = generateSequence { Random.nextBoolean() }.take(flagProperties.size).toList()
|
||||
doSerializeDeserializeAndCompareTest<T> {
|
||||
flagProperties.zip(randomFlags).forEach {
|
||||
it.first.cast<KMutableProperty1<T, Boolean>>().set(this, it.second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T : CommonToolArguments> doRandomStringArgumentsTest() {
|
||||
val stringProperties = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(T::class)
|
||||
val randomStrings = generateSequence { generateRandomString(Random.nextInt(20)) }.take(stringProperties.size).toList()
|
||||
doSerializeDeserializeAndCompareTest<T> {
|
||||
stringProperties.zip(randomStrings).forEach {
|
||||
it.first.cast<KMutableProperty1<T, String?>>().set(this, it.second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T : CommonToolArguments> doRandomArrayArgumentsTest() {
|
||||
val arrayProperties = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(T::class)
|
||||
val randomArrays = generateSequence {
|
||||
generateSequence { generateRandomString(Random.nextInt(20)) }.take(Random.nextInt(10)).toList().toTypedArray()
|
||||
}.take(arrayProperties.size).toList()
|
||||
doSerializeDeserializeAndCompareTest<T> {
|
||||
arrayProperties.zip(randomArrays).forEach {
|
||||
it.first.cast<KMutableProperty1<T, Array<String>?>>().set(this, it.second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
|
||||
|
||||
private fun generateRandomString(length: Int) = generateSequence { Random.nextInt(0, charPool.size) }
|
||||
.take(length)
|
||||
.map(charPool::get)
|
||||
.joinToString("")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user