[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()
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>>() }
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 } }
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>>
get() = CommonToolArguments::freeArgs
@@ -41,8 +41,7 @@ class CompilerArgumentsSerializerV5<T : CommonToolArguments>(override val argume
?.takeIf { it.get(arguments)?.contentEquals(it.get(newInstance)) != true }
?.get(arguments)
?.let { prop.name to it }
}.filterNot { it.second.isEmpty() }
.toMap()
}.toMap()
saveArrayArguments(this, arrayArgumentsByName)
val freeArgs = CompilerArgumentsContentProspector.freeArgsProperty.get(arguments)
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.junit.Test
import org.junit.Assert.*
import kotlin.reflect.KProperty
class CompilerArgumentsContentProspectorTest {
@@ -13,9 +15,9 @@ class CompilerArgumentsContentProspectorTest {
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 } }
assertContentEquals(flagProperties, k2JVMCompilerArgumentsFlagProperties)
assertContentEquals(stringProperties, k2JVMCompilerArgumentsStringProperties)
assertContentEquals(arrayProperties, k2JVMCompilerArgumentsArrayArgumentProperties)
}
@Test
@@ -24,9 +26,9 @@ class CompilerArgumentsContentProspectorTest {
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 } }
assertContentEquals(flagProperties, k2MetadataCompilerArgumentsFlagProperties)
assertContentEquals(stringProperties, k2MetadataCompilerArgumentsStringProperties)
assertContentEquals(arrayProperties, k2MetadataCompilerArgumentsArrayProperties)
}
@Test
@@ -35,9 +37,9 @@ class CompilerArgumentsContentProspectorTest {
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 }}" }
assertContentEquals(flagProperties, k2JSCompilerArgumentsFlagProperties)
assertContentEquals(stringProperties, k2JSCompilerArgumentsStringProperties)
assertContentEquals(arrayProperties, k2JSCompilerArgumentsArrayProperties)
}
@Test
@@ -46,9 +48,9 @@ class CompilerArgumentsContentProspectorTest {
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 } }
assertContentEquals(flagProperties, k2JSDceCompilerArgumentsFlagProperties)
assertContentEquals(stringProperties, k2JSDceCompilerArgumentsStringProperties)
assertContentEquals(arrayProperties, k2JSDceCompilerArgumentsArrayProperties)
}
companion object {
@@ -69,7 +71,6 @@ class CompilerArgumentsContentProspectorTest {
CommonCompilerArguments::noInline,
CommonCompilerArguments::skipMetadataVersionCheck,
CommonCompilerArguments::skipPrereleaseCheck,
CommonCompilerArguments::allowKotlinPackage,
CommonCompilerArguments::reportOutputFiles,
CommonCompilerArguments::multiPlatform,
CommonCompilerArguments::noCheckActual,
@@ -91,19 +92,24 @@ class CompilerArgumentsContentProspectorTest {
CommonCompilerArguments::disableUltraLightClasses,
CommonCompilerArguments::useMixedNamedArguments,
CommonCompilerArguments::expectActualLinker,
CommonCompilerArguments::extendedCompilerChecks,
CommonCompilerArguments::disableDefaultScriptingPlugin,
CommonCompilerArguments::inferenceCompatibility
CommonCompilerArguments::inferenceCompatibility,
CommonCompilerArguments::suppressVersionWarnings
)
private val commonCompilerArgumentsStringProperties = listOf(
CommonCompilerArguments::languageVersion,
CommonCompilerArguments::apiVersion,
CommonCompilerArguments::intellijPluginRoot,
CommonCompilerArguments::dumpPerf,
CommonCompilerArguments::metadataVersion,
CommonCompilerArguments::dumpDirectory,
CommonCompilerArguments::dumpOnlyFqName,
CommonCompilerArguments::explicitApi
CommonCompilerArguments::explicitApi,
CommonCompilerArguments::kotlinHome
)
private val commonCompilerArgumentsArrayArgumentProperties = listOf(
private val commonCompilerArgumentsArrayProperties = listOf(
CommonCompilerArguments::pluginOptions,
CommonCompilerArguments::pluginClasspaths,
CommonCompilerArguments::experimental,
@@ -147,6 +153,8 @@ class CompilerArgumentsContentProspectorTest {
K2JVMCompilerArguments::noExceptionOnExplicitEqualsForBoxedNull,
K2JVMCompilerArguments::disableStandardScript,
K2JVMCompilerArguments::strictMetadataVersionSemantics,
K2JVMCompilerArguments::suppressDeprecatedJvmTargetWarning,
K2JVMCompilerArguments::typeEnhancementImprovementsInStrictMode,
K2JVMCompilerArguments::sanitizeParentheses,
K2JVMCompilerArguments::allowNoSourceFiles,
K2JVMCompilerArguments::emitJvmTypeAnnotations,
@@ -180,10 +188,12 @@ class CompilerArgumentsContentProspectorTest {
K2JVMCompilerArguments::stringConcat,
K2JVMCompilerArguments::klibLibraries,
K2JVMCompilerArguments::profileCompilerCommand,
K2JVMCompilerArguments::repeatCompileModules
K2JVMCompilerArguments::repeatCompileModules,
K2JVMCompilerArguments::lambdas,
K2JVMCompilerArguments::samConversions
)
private val k2JVMCompilerArgumentsArrayArgumentProperties = commonCompilerArgumentsArrayArgumentProperties + listOf(
private val k2JVMCompilerArgumentsArrayArgumentProperties = commonCompilerArgumentsArrayProperties + listOf(
K2JVMCompilerArguments::scriptTemplates,
K2JVMCompilerArguments::additionalJavaModules,
K2JVMCompilerArguments::scriptResolverEnvironment,
@@ -201,7 +211,7 @@ class CompilerArgumentsContentProspectorTest {
K2MetadataCompilerArguments::classpath,
K2MetadataCompilerArguments::moduleName
)
private val k2MetadataCompilerArgumentsArrayProperties = commonCompilerArgumentsArrayArgumentProperties + listOf(
private val k2MetadataCompilerArgumentsArrayProperties = commonCompilerArgumentsArrayProperties + listOf(
K2MetadataCompilerArguments::friendPaths,
K2MetadataCompilerArguments::refinesPaths
)
@@ -241,7 +251,10 @@ class CompilerArgumentsContentProspectorTest {
K2JSCompilerArguments::includes,
K2JSCompilerArguments::friendModules,
K2JSCompilerArguments::errorTolerancePolicy,
K2JSCompilerArguments::irDceRuntimeDiagnostic,
K2JSCompilerArguments::repositries,
)
private val k2JSCompilerArgumentsArrayProperties = commonCompilerArgumentsArrayProperties
private val k2JSDceCompilerArgumentsFlagProperties = commonToolArgumentsFlagProperties + listOf(
K2JSDceArguments::devMode,
@@ -255,9 +268,15 @@ class CompilerArgumentsContentProspectorTest {
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 }
private fun assertContentEquals(expect: Collection<KProperty<*>>, actual: Collection<KProperty<*>>) {
//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.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.junit.Assert
import org.junit.Test
import kotlin.random.Random
import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KProperty1
import kotlin.reflect.full.memberProperties
@@ -120,9 +122,25 @@ class CompilerArgumentsSerializationTest {
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"
}
val oldValue = it.get(oldInstance)
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"
}
}
}