HMPP: Fix serialization of TargetPlatform in Kotlin facet
This commit is contained in:
@@ -10,20 +10,21 @@ import org.jetbrains.kotlin.platform.SimplePlatform
|
|||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.platform.toTargetPlatform
|
import org.jetbrains.kotlin.platform.toTargetPlatform
|
||||||
|
|
||||||
sealed class NativePlatform : SimplePlatform("Native")
|
sealed class NativePlatform : SimplePlatform("Native") {
|
||||||
|
override val oldFashionedDescription: String
|
||||||
|
get() = toString() + " "
|
||||||
|
}
|
||||||
|
|
||||||
object NativePlatformUnspecifiedTarget : NativePlatform() {
|
object NativePlatformUnspecifiedTarget : NativePlatform() {
|
||||||
override fun toString() = "$platformName (general)"
|
override val targetName: String
|
||||||
|
get() = "general"
|
||||||
override val oldFashionedDescription: String
|
|
||||||
get() = "Native (general) "
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class NativePlatformWithTarget(val target: KonanTarget) : NativePlatform() {
|
data class NativePlatformWithTarget(val target: KonanTarget) : NativePlatform() {
|
||||||
override fun toString() = "$platformName ($target)"
|
override fun toString() = super.toString() // override the method generated for data class
|
||||||
|
|
||||||
override val oldFashionedDescription: String
|
override val targetName: String
|
||||||
get() = "Native ($target) "
|
get() = target.visibleName
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION_ERROR")
|
@Suppress("DEPRECATION_ERROR")
|
||||||
@@ -64,3 +65,6 @@ object NativePlatforms {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun TargetPlatform?.isNative(): Boolean = this?.isNotEmpty() == true && all { it is NativePlatform }
|
fun TargetPlatform?.isNative(): Boolean = this?.isNotEmpty() == true && all { it is NativePlatform }
|
||||||
|
|
||||||
|
private val legacyNativePlatformUnspecifiedTargetSerializedRepresentation = "${NativePlatformUnspecifiedTarget.platformName} []"
|
||||||
|
fun NativePlatformUnspecifiedTarget.legacySerializeToString(): String = legacyNativePlatformUnspecifiedTargetSerializedRepresentation
|
||||||
|
|||||||
@@ -57,7 +57,14 @@ open class TargetPlatform(val componentPlatforms: Set<SimplePlatform>) : Collect
|
|||||||
* Ideally, each specific subtype should be either a data class or singleton.
|
* Ideally, each specific subtype should be either a data class or singleton.
|
||||||
*/
|
*/
|
||||||
abstract class SimplePlatform(val platformName: String) {
|
abstract class SimplePlatform(val platformName: String) {
|
||||||
override fun toString(): String = platformName
|
override fun toString(): String {
|
||||||
|
val targetName = targetName
|
||||||
|
return if (targetName.isNotEmpty()) "$platformName ($targetName)" else platformName
|
||||||
|
}
|
||||||
|
|
||||||
|
// description of TargetPlatformVersion or name of custom platform-specific target; used in serialization
|
||||||
|
open val targetName: String
|
||||||
|
get() = targetPlatformVersion.description
|
||||||
|
|
||||||
/** See KDoc for [TargetPlatform.oldFashionedDescription] */
|
/** See KDoc for [TargetPlatform.oldFashionedDescription] */
|
||||||
abstract val oldFashionedDescription: String
|
abstract val oldFashionedDescription: String
|
||||||
@@ -87,4 +94,4 @@ fun TargetPlatform?.isCommon(): Boolean = this != null && size > 1 && iterator()
|
|||||||
|
|
||||||
fun SimplePlatform.toTargetPlatform(): TargetPlatform = TargetPlatform(setOf(this))
|
fun SimplePlatform.toTargetPlatform(): TargetPlatform = TargetPlatform(setOf(this))
|
||||||
|
|
||||||
fun SimplePlatform.serializeToString() = "${this.platformName} [${this.targetPlatformVersion.description}]"
|
fun SimplePlatform.serializeToString(): String = "$platformName [$targetName]"
|
||||||
|
|||||||
@@ -25,16 +25,16 @@ fun <T> TargetPlatform?.has(klass: Class<T>): Boolean = this != null && subplatf
|
|||||||
* also provides better description for multiplatforms.
|
* also provides better description for multiplatforms.
|
||||||
*/
|
*/
|
||||||
val TargetPlatform.oldFashionedDescription: String
|
val TargetPlatform.oldFashionedDescription: String
|
||||||
// the invocation if isCommon is not preferable as it could be governed by separate flag and may
|
// this method mistakenly detects "common native" platform as "Common (experimental)"
|
||||||
// to appear independently on count of target platforms
|
// though this does not seem to have any significant effect
|
||||||
get() = this.singleOrNull()?.oldFashionedDescription ?: "Common (experimental) "
|
get() = this.singleOrNull()?.oldFashionedDescription ?: "Common (experimental) "
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders multiplatform in form
|
* Renders multiplatform in form
|
||||||
* '$PLATFORM_1 / $PLATFORM_2 / ...'
|
* '$PLATFORM_1/$PLATFORM_2/...'
|
||||||
* e.g.
|
* e.g.
|
||||||
* 'JVM (1.8) / JS / Native'
|
* 'JVM (1.8)/JS/Native (ios_x64)'
|
||||||
*/
|
*/
|
||||||
val TargetPlatform.presentableDescription: String
|
val TargetPlatform.presentableDescription: String
|
||||||
get() = componentPlatforms.joinToString(separator = "/")
|
get() = componentPlatforms.joinToString(separator = "/")
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ import org.jetbrains.kotlin.platform.js.JsPlatform
|
|||||||
import org.jetbrains.kotlin.platform.jvm.JdkPlatform
|
import org.jetbrains.kotlin.platform.jvm.JdkPlatform
|
||||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatform
|
import org.jetbrains.kotlin.platform.jvm.JvmPlatform
|
||||||
import org.jetbrains.kotlin.platform.konan.NativePlatform
|
import org.jetbrains.kotlin.platform.konan.NativePlatform
|
||||||
|
import org.jetbrains.kotlin.platform.konan.NativePlatformUnspecifiedTarget
|
||||||
|
import org.jetbrains.kotlin.platform.konan.NativePlatforms
|
||||||
|
import org.jetbrains.kotlin.platform.konan.legacySerializeToString
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.full.superclasses
|
import kotlin.reflect.full.superclasses
|
||||||
@@ -104,19 +107,40 @@ private fun readV1Config(element: Element): KotlinFacetSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Introduce new version of facet serialization. See https://youtrack.jetbrains.com/issue/KT-38235
|
||||||
|
// This is necessary to avoid having too much custom logic for platform serialization.
|
||||||
fun Element.getFacetPlatformByConfigurationElement(): TargetPlatform {
|
fun Element.getFacetPlatformByConfigurationElement(): TargetPlatform {
|
||||||
val platformNames = getAttributeValue("allPlatforms")?.split('/')?.toSet()
|
val platformNames = getAttributeValue("allPlatforms")?.split('/')?.toSet()
|
||||||
if (platformNames != null) {
|
if (platformNames != null && platformNames.isNotEmpty()) {
|
||||||
return TargetPlatform(CommonPlatforms.allSimplePlatforms
|
val knownSimplePlatforms = HashMap<String, SimplePlatform>() // serialization presentation to simple platform
|
||||||
.flatMap { it.componentPlatforms }
|
|
||||||
.filter { platformNames.contains(it.serializeToString()) }
|
// first, collect serialization presentations for every known simple platform
|
||||||
.toSet())
|
CommonPlatforms.allSimplePlatforms
|
||||||
|
.flatMap { it.componentPlatforms }
|
||||||
|
.forEach { knownSimplePlatforms[it.serializeToString()] = it }
|
||||||
|
|
||||||
|
// next, add legacy aliases for some of the simple platforms; ex: unspecifiedNativePlatform
|
||||||
|
NativePlatformUnspecifiedTarget.let { knownSimplePlatforms[it.legacySerializeToString()] = it }
|
||||||
|
|
||||||
|
val simplePlatforms = platformNames.mapNotNull(knownSimplePlatforms::get)
|
||||||
|
if (simplePlatforms.isNotEmpty()) return TargetPlatform(simplePlatforms.toSet())
|
||||||
|
|
||||||
|
// empty set of simple platforms is not allowed, in such case fallback to legacy algorithm
|
||||||
}
|
}
|
||||||
// failed to read list of all platforms. Fallback to legacy algorythm
|
|
||||||
val platformName = getAttributeValue("platform")
|
// failed to read list of all platforms. Fallback to legacy algorithm
|
||||||
// this code could be simplified using union after fixing the equals method in SimplePlatform
|
val platformName = getAttributeValue("platform") as String
|
||||||
val allPlatforms = ArrayList(CommonPlatforms.allSimplePlatforms).also { it.add(CommonPlatforms.defaultCommonPlatform) }
|
|
||||||
return allPlatforms.firstOrNull { it.oldFashionedDescription == platformName }.orDefault()
|
return CommonPlatforms.allSimplePlatforms.firstOrNull {
|
||||||
|
// first, look for exact match through all simple platforms
|
||||||
|
it.oldFashionedDescription == platformName
|
||||||
|
} ?: CommonPlatforms.defaultCommonPlatform.takeIf {
|
||||||
|
// then, check exact match for the default common platform
|
||||||
|
it.oldFashionedDescription == platformName
|
||||||
|
} ?: NativePlatforms.unspecifiedNativePlatform.takeIf {
|
||||||
|
// if none of the above succeeded, check if it's an old-style record about native platform (without suffix with target name)
|
||||||
|
it.oldFashionedDescription.startsWith(platformName)
|
||||||
|
}.orDefault() // finally, fallback to the default platform
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readV2AndLaterConfig(element: Element): KotlinFacetSettings {
|
private fun readV2AndLaterConfig(element: Element): KotlinFacetSettings {
|
||||||
@@ -298,9 +322,14 @@ private fun buildChildElement(element: Element, tag: String, bean: Any, filter:
|
|||||||
private fun KotlinFacetSettings.writeLatestConfig(element: Element) {
|
private fun KotlinFacetSettings.writeLatestConfig(element: Element) {
|
||||||
val filter = SkipDefaultsSerializationFilter()
|
val filter = SkipDefaultsSerializationFilter()
|
||||||
|
|
||||||
targetPlatform?.let {
|
// TODO: Introduce new version of facet serialization. See https://youtrack.jetbrains.com/issue/KT-38235
|
||||||
element.setAttribute("platform", it.oldFashionedDescription)
|
// This is necessary to avoid having too much custom logic for platform serialization.
|
||||||
element.setAttribute("allPlatforms", it.componentPlatforms.map { it.serializeToString() }.sorted().joinToString(separator = "/"))
|
targetPlatform?.let { targetPlatform ->
|
||||||
|
element.setAttribute("platform", targetPlatform.oldFashionedDescription)
|
||||||
|
element.setAttribute(
|
||||||
|
"allPlatforms",
|
||||||
|
targetPlatform.componentPlatforms.map { it.serializeToString() }.sorted().joinToString(separator = "/")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (!useProjectSettings) {
|
if (!useProjectSettings) {
|
||||||
element.setAttribute("useProjectSettings", useProjectSettings.toString())
|
element.setAttribute("useProjectSettings", useProjectSettings.toString())
|
||||||
|
|||||||
Reference in New Issue
Block a user