[CHERRY PICKED FROM IJ] Fix KotlinFacetSettings serialization issues for compiler arguments

GitOrigin-RevId: 29d3bab972fc797fab7244c16df21763055db0c4
Original commit: https://github.com/JetBrains/intellij-community/commit/4e9f0bfaef343536930276ba27f582a95613d121
This commit is contained in:
Yaroslav.Chernyshev
2021-10-29 12:33:49 +03:00
committed by Nikita Bobko
parent 5f41e3044b
commit 93d569d090
4 changed files with 66 additions and 30 deletions
@@ -24,10 +24,10 @@ object CompilerArgumentsContentProspector {
mutableMapOf() mutableMapOf()
private fun getCompilerArguments(kClass: KClass<out CommonToolArguments>) = argumentPropertiesCache.getOrPut(kClass) { private fun getCompilerArguments(kClass: KClass<out CommonToolArguments>) = argumentPropertiesCache.getOrPut(kClass) {
kClass.memberProperties.filter { prop -> prop.annotations.singleOrNull { it is Argument } != null } kClass.memberProperties.filter { prop -> prop.annotations.any { it is Argument } }
} }
private inline fun <reified R : Any> List<KProperty1<out CommonToolArguments, *>>.filterByReturnType(predicate: (KType?) -> Boolean) = private inline fun <reified R : Any?> List<KProperty1<out CommonToolArguments, *>>.filterByReturnType(predicate: (KType?) -> Boolean) =
filter { predicate(it.returnType) }.mapNotNull { it.safeAs<KProperty1<CommonToolArguments, R>>() } filter { predicate(it.returnType) }.mapNotNull { it.safeAs<KProperty1<CommonToolArguments, R>>() }
fun getFlagCompilerArgumentProperties(kClass: KClass<out CommonToolArguments>): List<KProperty1<out CommonToolArguments, Boolean>> = fun getFlagCompilerArgumentProperties(kClass: KClass<out CommonToolArguments>): List<KProperty1<out CommonToolArguments, Boolean>> =
@@ -37,7 +37,7 @@ object CompilerArgumentsContentProspector {
stringArgumentPropertiesCache.getOrPut(kClass) { getCompilerArguments(kClass).filterByReturnType { it?.classifier == String::class } } stringArgumentPropertiesCache.getOrPut(kClass) { getCompilerArguments(kClass).filterByReturnType { it?.classifier == String::class } }
fun <T : CommonToolArguments> getArrayCompilerArgumentProperties(kClass: KClass<T>): List<KProperty1<out CommonToolArguments, Array<String>?>> = fun <T : CommonToolArguments> getArrayCompilerArgumentProperties(kClass: KClass<T>): List<KProperty1<out CommonToolArguments, Array<String>?>> =
arrayArgumentPropertiesCache.getOrPut(kClass) { getCompilerArguments(kClass).filterByReturnType { it?.classifier?.javaClass?.isArray == true } } arrayArgumentPropertiesCache.getOrPut(kClass) { getCompilerArguments(kClass).filterByReturnType { (it?.classifier as? KClass<*>)?.java?.isArray == true } }
val freeArgsProperty: KProperty1<in CommonToolArguments, List<String>> val freeArgsProperty: KProperty1<in CommonToolArguments, List<String>>
get() = CommonToolArguments::freeArgs get() = CommonToolArguments::freeArgs
@@ -41,8 +41,7 @@ class CompilerArgumentsSerializerV5<T : CommonToolArguments>(override val argume
?.takeIf { it.get(arguments)?.contentEquals(it.get(newInstance)) != true } ?.takeIf { it.get(arguments)?.contentEquals(it.get(newInstance)) != true }
?.get(arguments) ?.get(arguments)
?.let { prop.name to it } ?.let { prop.name to it }
}.filterNot { it.second.isEmpty() } }.toMap()
.toMap()
saveArrayArguments(this, arrayArgumentsByName) saveArrayArguments(this, arrayArgumentsByName)
val freeArgs = CompilerArgumentsContentProspector.freeArgsProperty.get(arguments) val freeArgs = CompilerArgumentsContentProspector.freeArgsProperty.get(arguments)
saveElementsList(this, FREE_ARGS_ROOT_ELEMENTS_NAME, FREE_ARGS_ELEMENT_NAME, freeArgs) saveElementsList(this, FREE_ARGS_ROOT_ELEMENTS_NAME, FREE_ARGS_ELEMENT_NAME, freeArgs)
@@ -3,6 +3,8 @@ package org.jetbrains.kotlin.arguments
import org.jetbrains.kotlin.cli.common.arguments.* import org.jetbrains.kotlin.cli.common.arguments.*
import org.junit.Test import org.junit.Test
import org.junit.Assert.*
import kotlin.reflect.KProperty
class CompilerArgumentsContentProspectorTest { class CompilerArgumentsContentProspectorTest {
@@ -13,9 +15,9 @@ class CompilerArgumentsContentProspectorTest {
val stringProperties = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(K2JVMCompilerArguments::class) val stringProperties = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(K2JVMCompilerArguments::class)
val arrayProperties = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(K2JVMCompilerArguments::class) val arrayProperties = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(K2JVMCompilerArguments::class)
assertContentEquals(flagProperties, k2JVMCompilerArgumentsFlagProperties) { sortedBy { it.name } } assertContentEquals(flagProperties, k2JVMCompilerArgumentsFlagProperties)
assertContentEquals(stringProperties, k2JVMCompilerArgumentsStringProperties) { sortedBy { it.name } } assertContentEquals(stringProperties, k2JVMCompilerArgumentsStringProperties)
assertContentEquals(arrayProperties, k2JVMCompilerArgumentsArrayArgumentProperties) { sortedBy { it.name } } assertContentEquals(arrayProperties, k2JVMCompilerArgumentsArrayArgumentProperties)
} }
@Test @Test
@@ -24,9 +26,9 @@ class CompilerArgumentsContentProspectorTest {
val stringProperties = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(K2MetadataCompilerArguments::class) val stringProperties = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(K2MetadataCompilerArguments::class)
val arrayProperties = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(K2MetadataCompilerArguments::class) val arrayProperties = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(K2MetadataCompilerArguments::class)
assertContentEquals(flagProperties, k2MetadataCompilerArgumentsFlagProperties) { sortedBy { it.name } } assertContentEquals(flagProperties, k2MetadataCompilerArgumentsFlagProperties)
assertContentEquals(stringProperties, k2MetadataCompilerArgumentsStringProperties) { sortedBy { it.name } } assertContentEquals(stringProperties, k2MetadataCompilerArgumentsStringProperties)
assertContentEquals(arrayProperties, k2MetadataCompilerArgumentsArrayProperties) { sortedBy { it.name } } assertContentEquals(arrayProperties, k2MetadataCompilerArgumentsArrayProperties)
} }
@Test @Test
@@ -35,9 +37,9 @@ class CompilerArgumentsContentProspectorTest {
val stringProperties = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(K2JSCompilerArguments::class) val stringProperties = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(K2JSCompilerArguments::class)
val arrayProperties = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(K2JSCompilerArguments::class) val arrayProperties = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(K2JSCompilerArguments::class)
assertContentEquals(flagProperties, k2JSCompilerArgumentsFlagProperties) { sortedBy { it.name } } assertContentEquals(flagProperties, k2JSCompilerArgumentsFlagProperties)
assertContentEquals(stringProperties, k2JSCompilerArgumentsStringProperties) { sortedBy { it.name } } assertContentEquals(stringProperties, k2JSCompilerArgumentsStringProperties)
assert(arrayProperties.isEmpty()) { "Expected empty arrayProperties, but actual ${arrayProperties.joinToString { it.name }}" } assertContentEquals(arrayProperties, k2JSCompilerArgumentsArrayProperties)
} }
@Test @Test
@@ -46,9 +48,9 @@ class CompilerArgumentsContentProspectorTest {
val stringProperties = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(K2JSDceArguments::class) val stringProperties = CompilerArgumentsContentProspector.getStringCompilerArgumentProperties(K2JSDceArguments::class)
val arrayProperties = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(K2JSDceArguments::class) val arrayProperties = CompilerArgumentsContentProspector.getArrayCompilerArgumentProperties(K2JSDceArguments::class)
assertContentEquals(flagProperties, k2JSDceCompilerArgumentsFlagProperties) { sortedBy { it.name } } assertContentEquals(flagProperties, k2JSDceCompilerArgumentsFlagProperties)
assertContentEquals(stringProperties, k2JSDceCompilerArgumentsStringProperties) { sortedBy { it.name } } assertContentEquals(stringProperties, k2JSDceCompilerArgumentsStringProperties)
assertContentEquals(arrayProperties, k2JSDceCompilerArgumentsArrayProperties) { sortedBy { it.name } } assertContentEquals(arrayProperties, k2JSDceCompilerArgumentsArrayProperties)
} }
companion object { companion object {
@@ -69,7 +71,6 @@ class CompilerArgumentsContentProspectorTest {
CommonCompilerArguments::noInline, CommonCompilerArguments::noInline,
CommonCompilerArguments::skipMetadataVersionCheck, CommonCompilerArguments::skipMetadataVersionCheck,
CommonCompilerArguments::skipPrereleaseCheck, CommonCompilerArguments::skipPrereleaseCheck,
CommonCompilerArguments::allowKotlinPackage,
CommonCompilerArguments::reportOutputFiles, CommonCompilerArguments::reportOutputFiles,
CommonCompilerArguments::multiPlatform, CommonCompilerArguments::multiPlatform,
CommonCompilerArguments::noCheckActual, CommonCompilerArguments::noCheckActual,
@@ -91,19 +92,24 @@ class CompilerArgumentsContentProspectorTest {
CommonCompilerArguments::disableUltraLightClasses, CommonCompilerArguments::disableUltraLightClasses,
CommonCompilerArguments::useMixedNamedArguments, CommonCompilerArguments::useMixedNamedArguments,
CommonCompilerArguments::expectActualLinker, CommonCompilerArguments::expectActualLinker,
CommonCompilerArguments::extendedCompilerChecks,
CommonCompilerArguments::disableDefaultScriptingPlugin, CommonCompilerArguments::disableDefaultScriptingPlugin,
CommonCompilerArguments::inferenceCompatibility CommonCompilerArguments::inferenceCompatibility,
CommonCompilerArguments::suppressVersionWarnings
) )
private val commonCompilerArgumentsStringProperties = listOf( private val commonCompilerArgumentsStringProperties = listOf(
CommonCompilerArguments::languageVersion,
CommonCompilerArguments::apiVersion,
CommonCompilerArguments::intellijPluginRoot, CommonCompilerArguments::intellijPluginRoot,
CommonCompilerArguments::dumpPerf, CommonCompilerArguments::dumpPerf,
CommonCompilerArguments::metadataVersion, CommonCompilerArguments::metadataVersion,
CommonCompilerArguments::dumpDirectory, CommonCompilerArguments::dumpDirectory,
CommonCompilerArguments::dumpOnlyFqName, CommonCompilerArguments::dumpOnlyFqName,
CommonCompilerArguments::explicitApi CommonCompilerArguments::explicitApi,
CommonCompilerArguments::kotlinHome
) )
private val commonCompilerArgumentsArrayArgumentProperties = listOf( private val commonCompilerArgumentsArrayProperties = listOf(
CommonCompilerArguments::pluginOptions, CommonCompilerArguments::pluginOptions,
CommonCompilerArguments::pluginClasspaths, CommonCompilerArguments::pluginClasspaths,
CommonCompilerArguments::experimental, CommonCompilerArguments::experimental,
@@ -147,6 +153,8 @@ class CompilerArgumentsContentProspectorTest {
K2JVMCompilerArguments::noExceptionOnExplicitEqualsForBoxedNull, K2JVMCompilerArguments::noExceptionOnExplicitEqualsForBoxedNull,
K2JVMCompilerArguments::disableStandardScript, K2JVMCompilerArguments::disableStandardScript,
K2JVMCompilerArguments::strictMetadataVersionSemantics, K2JVMCompilerArguments::strictMetadataVersionSemantics,
K2JVMCompilerArguments::suppressDeprecatedJvmTargetWarning,
K2JVMCompilerArguments::typeEnhancementImprovementsInStrictMode,
K2JVMCompilerArguments::sanitizeParentheses, K2JVMCompilerArguments::sanitizeParentheses,
K2JVMCompilerArguments::allowNoSourceFiles, K2JVMCompilerArguments::allowNoSourceFiles,
K2JVMCompilerArguments::emitJvmTypeAnnotations, K2JVMCompilerArguments::emitJvmTypeAnnotations,
@@ -180,10 +188,12 @@ class CompilerArgumentsContentProspectorTest {
K2JVMCompilerArguments::stringConcat, K2JVMCompilerArguments::stringConcat,
K2JVMCompilerArguments::klibLibraries, K2JVMCompilerArguments::klibLibraries,
K2JVMCompilerArguments::profileCompilerCommand, K2JVMCompilerArguments::profileCompilerCommand,
K2JVMCompilerArguments::repeatCompileModules K2JVMCompilerArguments::repeatCompileModules,
K2JVMCompilerArguments::lambdas,
K2JVMCompilerArguments::samConversions
) )
private val k2JVMCompilerArgumentsArrayArgumentProperties = commonCompilerArgumentsArrayArgumentProperties + listOf( private val k2JVMCompilerArgumentsArrayArgumentProperties = commonCompilerArgumentsArrayProperties + listOf(
K2JVMCompilerArguments::scriptTemplates, K2JVMCompilerArguments::scriptTemplates,
K2JVMCompilerArguments::additionalJavaModules, K2JVMCompilerArguments::additionalJavaModules,
K2JVMCompilerArguments::scriptResolverEnvironment, K2JVMCompilerArguments::scriptResolverEnvironment,
@@ -201,7 +211,7 @@ class CompilerArgumentsContentProspectorTest {
K2MetadataCompilerArguments::classpath, K2MetadataCompilerArguments::classpath,
K2MetadataCompilerArguments::moduleName K2MetadataCompilerArguments::moduleName
) )
private val k2MetadataCompilerArgumentsArrayProperties = commonCompilerArgumentsArrayArgumentProperties + listOf( private val k2MetadataCompilerArgumentsArrayProperties = commonCompilerArgumentsArrayProperties + listOf(
K2MetadataCompilerArguments::friendPaths, K2MetadataCompilerArguments::friendPaths,
K2MetadataCompilerArguments::refinesPaths K2MetadataCompilerArguments::refinesPaths
) )
@@ -241,7 +251,10 @@ class CompilerArgumentsContentProspectorTest {
K2JSCompilerArguments::includes, K2JSCompilerArguments::includes,
K2JSCompilerArguments::friendModules, K2JSCompilerArguments::friendModules,
K2JSCompilerArguments::errorTolerancePolicy, K2JSCompilerArguments::errorTolerancePolicy,
K2JSCompilerArguments::irDceRuntimeDiagnostic,
K2JSCompilerArguments::repositries,
) )
private val k2JSCompilerArgumentsArrayProperties = commonCompilerArgumentsArrayProperties
private val k2JSDceCompilerArgumentsFlagProperties = commonToolArgumentsFlagProperties + listOf( private val k2JSDceCompilerArgumentsFlagProperties = commonToolArgumentsFlagProperties + listOf(
K2JSDceArguments::devMode, K2JSDceArguments::devMode,
@@ -255,9 +268,15 @@ class CompilerArgumentsContentProspectorTest {
K2JSDceArguments::declarationsToKeep K2JSDceArguments::declarationsToKeep
) )
private fun <T> assertContentEquals(expect: Iterable<T>, actual: Iterable<T>, preprocessor: Iterable<T>.() -> Iterable<T>) { private fun assertContentEquals(expect: Collection<KProperty<*>>, actual: Collection<KProperty<*>>) {
(expect.count() == actual.count()) && preprocessor(expect).zip(preprocessor(actual)).all { it.first == it.second } //assert(expect.count() == actual.count()) {
// "Expected arguments count \"${expect.count()}\" doesn't match with actual \"${actual.count()}\"!"
//}
val processor: (Collection<KProperty<*>>) -> Collection<String> = { el -> el.map { it.name }.sorted() }
assertEquals(
processor(expect).joinToString("\n"),
processor(actual).joinToString("\n")
)
} }
} }
} }
@@ -6,8 +6,10 @@ import org.jetbrains.kotlin.cli.common.arguments.*
import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.junit.Assert
import org.junit.Test import org.junit.Test
import kotlin.random.Random import kotlin.random.Random
import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty1 import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KProperty1 import kotlin.reflect.KProperty1
import kotlin.reflect.full.memberProperties import kotlin.reflect.full.memberProperties
@@ -120,9 +122,25 @@ class CompilerArgumentsSerializationTest {
val deserializer = CompilerArgumentsDeserializerV5(newInstance) val deserializer = CompilerArgumentsDeserializerV5(newInstance)
deserializer.deserializeFrom(element) deserializer.deserializeFrom(element)
T::class.memberProperties.mapNotNull { it.safeAs<KProperty1<T, *>>() }.forEach { T::class.memberProperties.mapNotNull { it.safeAs<KProperty1<T, *>>() }.forEach {
assert(it.get(oldInstance) == it.get(newInstance)) { val oldValue = it.get(oldInstance)
"Property ${it.name} has different values before (${it.get(oldInstance)}) and after (${it.get(newInstance)}) serialization" val newValue = it.get(newInstance)
} if (oldValue == null && newValue == null) return@forEach
Assert.assertNotNull("Old value of property \"${it.name}\" is null but new is not", oldValue)
Assert.assertNotNull("New value of property \"${it.name}\" is null but old is not", newValue)
if ((it.returnType.classifier as? KClass<*>)?.java?.isArray == true)
Assert.assertArrayEquals(
"Property ${it.name} has different values before (${it.get(oldInstance).toString()}) and after (${
it.get(newInstance).toString()
}) serialization",
oldValue as Array<*>, newValue as Array<*>
)
else
assert(it.get(oldInstance) == it.get(newInstance)) {
"Property ${it.name} has different values before (${it.get(oldInstance).toString()}) and after (${
it.get(newInstance).toString()
}) serialization"
}
} }
} }