[KPM] Implement KotlinExternalModelContainer
KT-51262 KT-51220
This commit is contained in:
committed by
Space
parent
55448943af
commit
f1655e5f4e
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.kpm
|
||||
|
||||
import org.jetbrains.kotlin.gradle.kpm.idea.InternalKotlinGradlePluginApi
|
||||
import java.io.Serializable
|
||||
|
||||
interface KotlinHasExternalModel {
|
||||
val external: KotlinExternalModelContainer
|
||||
}
|
||||
|
||||
abstract class KotlinExternalModelContainer internal constructor() : Serializable {
|
||||
abstract operator fun <T : Any> contains(key: KotlinExternalModelKey<T>): Boolean
|
||||
abstract operator fun <T : Any> get(key: KotlinExternalModelKey<T>): T?
|
||||
fun <T : Any> getOrThrow(key: KotlinExternalModelKey<T>): T = get(key)
|
||||
?: throw NoSuchElementException("Missing external model for ${key.id}")
|
||||
|
||||
@InternalKotlinGradlePluginApi
|
||||
companion object {
|
||||
fun mutable(): KotlinMutableExternalModelContainer = KotlinMutableExternalModelContainerImpl()
|
||||
}
|
||||
|
||||
object Empty : KotlinExternalModelContainer() {
|
||||
override fun <T : Any> contains(key: KotlinExternalModelKey<T>): Boolean = false
|
||||
override fun <T : Any> get(key: KotlinExternalModelKey<T>): T? = null
|
||||
}
|
||||
}
|
||||
|
||||
abstract class KotlinMutableExternalModelContainer internal constructor() : KotlinExternalModelContainer() {
|
||||
abstract operator fun <T : Any> set(key: KotlinExternalModelKey<T>, value: T)
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.kpm
|
||||
|
||||
import org.jetbrains.kotlin.gradle.kpm.idea.InternalKotlinGradlePluginApi
|
||||
import java.io.Serializable
|
||||
|
||||
internal class KotlinMutableExternalModelContainerImpl : KotlinMutableExternalModelContainer(), Serializable {
|
||||
private val values = mutableMapOf<KotlinExternalModelKey<*>, Any>()
|
||||
|
||||
@Synchronized
|
||||
override fun <T : Any> set(key: KotlinExternalModelKey<T>, value: T) {
|
||||
values[key] = value
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun <T : Any> contains(key: KotlinExternalModelKey<T>): Boolean {
|
||||
return key in values
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
@Suppress("unchecked_cast")
|
||||
override fun <T : Any> get(key: KotlinExternalModelKey<T>): T? {
|
||||
return values[key]?.let { it as T }
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun writeReplace(): Any {
|
||||
val serializedValues = values.filterKeys { it.serializer != null }
|
||||
.mapValues { (key, value) ->
|
||||
@Suppress("unchecked_cast")
|
||||
val serializer = checkNotNull(key.serializer) as KotlinExternalModelSerializer<Any>
|
||||
serializer.serialize(value)
|
||||
}.mapKeys { (key, _) -> key.id }
|
||||
.toMutableMap()
|
||||
|
||||
return SerializedKotlinExternalModelContainer(serializedValues)
|
||||
}
|
||||
}
|
||||
|
||||
private class SerializedKotlinExternalModelContainer(
|
||||
private val serializedValues: MutableMap<KotlinExternalModelId<*>, ByteArray>
|
||||
) : KotlinExternalModelContainer(), Serializable {
|
||||
|
||||
private val deserializedValues = mutableMapOf<KotlinExternalModelId<*>, Any>()
|
||||
|
||||
@Synchronized
|
||||
override fun <T : Any> contains(key: KotlinExternalModelKey<T>): Boolean {
|
||||
return key.id in deserializedValues || key.id in serializedValues
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
@Suppress("unchecked_cast")
|
||||
override fun <T : Any> get(key: KotlinExternalModelKey<T>): T? {
|
||||
deserializedValues[key.id]?.let { return it as T }
|
||||
val serializedValue = serializedValues.remove(key.id) ?: return null
|
||||
val deserializedValue = key.serializer?.deserialize(serializedValue) ?: return null
|
||||
deserializedValues[key.id] = deserializedValue
|
||||
return deserializedValue
|
||||
}
|
||||
|
||||
@InternalKotlinGradlePluginApi
|
||||
companion object {
|
||||
private const val serialVersionUID = 0L
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("FunctionName")
|
||||
|
||||
package org.jetbrains.kotlin.gradle.kpm
|
||||
|
||||
import org.jetbrains.kotlin.gradle.kpm.idea.InternalKotlinGradlePluginApi
|
||||
import java.io.Serializable
|
||||
|
||||
inline fun <reified T : Any> KotlinExternalModelId(disambiguationName: String? = null): KotlinExternalModelId<T> {
|
||||
return KotlinExternalModelId(KotlinExternalModelType(), disambiguationName)
|
||||
}
|
||||
|
||||
class KotlinExternalModelId<T : Any> @PublishedApi internal constructor(
|
||||
internal val type: KotlinExternalModelType<T>,
|
||||
private val disambiguationName: String? = null
|
||||
) : Serializable {
|
||||
override fun toString(): String {
|
||||
return if (disambiguationName == null) type.toString()
|
||||
else "$disambiguationName:$type"
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
other as KotlinExternalModelId<*>
|
||||
if (type != other.type) return false
|
||||
if (disambiguationName != other.disambiguationName) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = type.hashCode()
|
||||
result = 31 * result + (disambiguationName?.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
|
||||
@InternalKotlinGradlePluginApi
|
||||
companion object {
|
||||
private const val serialVersionUID = 0L
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("FunctionName")
|
||||
|
||||
package org.jetbrains.kotlin.gradle.kpm
|
||||
|
||||
inline fun <reified T : Any> KotlinExternalModelKey(
|
||||
disambiguationName: String? = null, serializer: KotlinExternalModelSerializer<T>? = null
|
||||
): KotlinExternalModelKey<T> = KotlinExternalModelKey(KotlinExternalModelId(disambiguationName), serializer)
|
||||
|
||||
inline fun <reified T : Any> KotlinExternalModelKey(serializer: KotlinExternalModelSerializer<T>): KotlinExternalModelKey<T> =
|
||||
KotlinExternalModelKey(KotlinExternalModelId(), serializer)
|
||||
|
||||
class KotlinExternalModelKey<T : Any> @PublishedApi internal constructor(
|
||||
internal val id: KotlinExternalModelId<T>,
|
||||
internal val serializer: KotlinExternalModelSerializer<T>? = null,
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as KotlinExternalModelKey<*>
|
||||
|
||||
if (id != other.id) return false
|
||||
if (serializer != other.serializer) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = id.hashCode()
|
||||
result = 31 * result + (serializer?.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.kpm
|
||||
|
||||
import org.jetbrains.kotlin.gradle.kpm.idea.InternalKotlinGradlePluginApi
|
||||
import java.io.*
|
||||
|
||||
interface KotlinExternalModelSerializer<T : Any> {
|
||||
fun serialize(value: T): ByteArray
|
||||
fun deserialize(data: ByteArray): T
|
||||
|
||||
@InternalKotlinGradlePluginApi
|
||||
companion object {
|
||||
inline fun <reified T : Serializable> serializable(): KotlinExternalModelSerializer<T> =
|
||||
KotlinSerializableExternalModelSerializer(T::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal class KotlinSerializableExternalModelSerializer<T : Serializable>(
|
||||
private val clazz: Class<T>
|
||||
) : KotlinExternalModelSerializer<T> {
|
||||
override fun serialize(value: T): ByteArray {
|
||||
return ByteArrayOutputStream().run {
|
||||
ObjectOutputStream(this).use { stream -> stream.writeObject(value) }
|
||||
toByteArray()
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserialize(data: ByteArray): T {
|
||||
return ObjectInputStream(ByteArrayInputStream(data)).use { stream ->
|
||||
clazz.cast(stream.readObject())
|
||||
}
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.kpm
|
||||
|
||||
import org.jetbrains.kotlin.gradle.kpm.idea.InternalKotlinGradlePluginApi
|
||||
import java.io.Serializable
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
@Suppress("FunctionName")
|
||||
inline fun <reified T : Any> KotlinExternalModelType(): KotlinExternalModelType<T> {
|
||||
return KotlinExternalModelType(externalModelTypeSignature(typeOf<T>()))
|
||||
}
|
||||
|
||||
class KotlinExternalModelType</* Used as phantom type */ @Suppress("unused") T: Any>
|
||||
@PublishedApi internal constructor(private val signature: String) : Serializable {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is KotlinExternalModelType<*>) return false
|
||||
if (other.signature != this.signature) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = 31 * signature.hashCode()
|
||||
override fun toString(): String = "ExternalModelType($signature)"
|
||||
|
||||
@InternalKotlinGradlePluginApi
|
||||
companion object {
|
||||
private const val serialVersionUID = 0L
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun externalModelTypeSignature(type: KType): String {
|
||||
require(!type.isMarkedNullable) { "Unexpected nullable type. Found $type" }
|
||||
require(type.arguments.isEmpty()) { "Parameterized types are not supported. Found $type" }
|
||||
val classifier = requireNotNull(type.classifier) { "Expected classifier. Found $type" }
|
||||
val clazz = (classifier as? KClass<*>) ?: throw IllegalArgumentException("Expected KClass classifier. Found $classifier")
|
||||
return clazz.qualifiedName ?: throw IllegalArgumentException("Missing qualifiedName in $type")
|
||||
}
|
||||
+4
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.kpm.idea
|
||||
|
||||
import org.jetbrains.kotlin.gradle.kpm.KotlinExternalModelContainer
|
||||
import java.io.Serializable
|
||||
|
||||
interface IdeaKotlinFragment : Serializable {
|
||||
@@ -14,6 +15,7 @@ interface IdeaKotlinFragment : Serializable {
|
||||
val directRefinesDependencies: Collection<IdeaKotlinFragment>
|
||||
val sourceDirectories: Collection<IdeaKotlinSourceDirectory>
|
||||
val resourceDirectories: Collection<IdeaKotlinResourceDirectory>
|
||||
val external: KotlinExternalModelContainer
|
||||
}
|
||||
|
||||
@InternalKotlinGradlePluginApi
|
||||
@@ -23,7 +25,8 @@ data class IdeaKotlinFragmentImpl(
|
||||
override val dependencies: Collection<IdeaKotlinFragmentDependency>,
|
||||
override val directRefinesDependencies: Collection<IdeaKotlinFragment>,
|
||||
override val sourceDirectories: Collection<IdeaKotlinSourceDirectory>,
|
||||
override val resourceDirectories: Collection<IdeaKotlinResourceDirectory>
|
||||
override val resourceDirectories: Collection<IdeaKotlinResourceDirectory>,
|
||||
override val external: KotlinExternalModelContainer
|
||||
) : IdeaKotlinFragment {
|
||||
|
||||
@InternalKotlinGradlePluginApi
|
||||
|
||||
Reference in New Issue
Block a user