diff --git a/libraries/tools/kotlin-gradle-plugin-idea-proto/api/kotlin-gradle-plugin-idea-proto.api b/libraries/tools/kotlin-gradle-plugin-idea-proto/api/kotlin-gradle-plugin-idea-proto.api index bf44fa04660..f22477ee70a 100644 --- a/libraries/tools/kotlin-gradle-plugin-idea-proto/api/kotlin-gradle-plugin-idea-proto.api +++ b/libraries/tools/kotlin-gradle-plugin-idea-proto/api/kotlin-gradle-plugin-idea-proto.api @@ -1,3 +1,8 @@ +public final class org/jetbrains/kotlin/gradle/idea/proto/ExtrasKt { + public static final fun Extras (Lorg/jetbrains/kotlin/gradle/idea/serialize/IdeaKotlinSerializationContext;[B)Lorg/jetbrains/kotlin/tooling/core/MutableExtras; + public static final fun toByteArray (Lorg/jetbrains/kotlin/tooling/core/Extras;Lorg/jetbrains/kotlin/gradle/idea/serialize/IdeaKotlinSerializationContext;)[B +} + public final class org/jetbrains/kotlin/gradle/idea/proto/kpm/KpmIdeaProto { public static final fun IdeaKpmProject (Lorg/jetbrains/kotlin/gradle/idea/serialize/IdeaKotlinSerializationContext;Ljava/io/InputStream;)Lorg/jetbrains/kotlin/gradle/idea/kpm/IdeaKpmProject; public static final fun IdeaKpmProject (Lorg/jetbrains/kotlin/gradle/idea/serialize/IdeaKotlinSerializationContext;Ljava/nio/ByteBuffer;)Lorg/jetbrains/kotlin/gradle/idea/kpm/IdeaKpmProject; diff --git a/libraries/tools/kotlin-gradle-plugin-idea-proto/src/main/kotlin/org/jetbrains/kotlin/gradle/idea/proto/extras.kt b/libraries/tools/kotlin-gradle-plugin-idea-proto/src/main/kotlin/org/jetbrains/kotlin/gradle/idea/proto/extras.kt index c7bef2a7df8..dc31e427b20 100644 --- a/libraries/tools/kotlin-gradle-plugin-idea-proto/src/main/kotlin/org/jetbrains/kotlin/gradle/idea/proto/extras.kt +++ b/libraries/tools/kotlin-gradle-plugin-idea-proto/src/main/kotlin/org/jetbrains/kotlin/gradle/idea/proto/extras.kt @@ -8,12 +8,28 @@ package org.jetbrains.kotlin.gradle.idea.proto import com.google.protobuf.ByteString +import com.google.protobuf.InvalidProtocolBufferException import org.jetbrains.kotlin.gradle.idea.proto.generated.IdeaExtrasProto import org.jetbrains.kotlin.gradle.idea.proto.generated.ideaExtrasProto import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinExtrasSerializer import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinSerializationContext import org.jetbrains.kotlin.tooling.core.* +fun Extras.toByteArray(context: IdeaKotlinSerializationContext): ByteArray { + return context.IdeaExtrasProto(this).toByteArray() +} + +fun IdeaKotlinSerializationContext.Extras(data: ByteArray): MutableExtras? { + return try { + val proto = IdeaExtrasProto.parseFrom(data) + Extras(proto) + + } catch (e: InvalidProtocolBufferException) { + logger.error("Failed to deserialize Extras", e) + null + } +} + @Suppress("unchecked_cast") internal fun IdeaKotlinSerializationContext.IdeaExtrasProto(extras: Extras): IdeaExtrasProto { val context = this diff --git a/libraries/tools/kotlin-gradle-plugin-idea-proto/src/test/kotlin/org/jetbrains/kotlin/gradle/idea/proto/ExtrasSerializationTest.kt b/libraries/tools/kotlin-gradle-plugin-idea-proto/src/test/kotlin/org/jetbrains/kotlin/gradle/idea/proto/ExtrasSerializationTest.kt new file mode 100644 index 00000000000..09335e5da6a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-idea-proto/src/test/kotlin/org/jetbrains/kotlin/gradle/idea/proto/ExtrasSerializationTest.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2023 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.idea.proto + +import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.TestIdeaKotlinInstances +import org.jetbrains.kotlin.tooling.core.MutableExtras +import org.jetbrains.kotlin.tooling.core.mutableExtrasOf +import org.jetbrains.kotlin.tooling.core.toMutableExtras +import kotlin.test.Test +import kotlin.test.fail + +class ExtrasSerializationTest : AbstractSerializationTest() { + override fun serialize(value: MutableExtras): ByteArray = value.toByteArray(this) + override fun deserialize(data: ByteArray): MutableExtras = Extras(data) ?: fail() + + @Test + fun `sample - extrasWithIntAndStrings`() = testSerialization(TestIdeaKotlinInstances.extrasWithIntAndStrings.toMutableExtras()) + + @Test + fun `sample - emptyExtras`() = testSerialization(mutableExtrasOf()) +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport.kt index df35676e228..c2d1762c2a8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.gradle.targets.metadata.isSingleKotlinTargetSourceSe import org.jetbrains.kotlin.gradle.targets.metadata.isSinglePlatformTypeSourceSet import org.jetbrains.kotlin.gradle.utils.getOrPut import org.jetbrains.kotlin.tooling.core.Extras +import org.jetbrains.kotlin.tooling.core.HasMutableExtras interface IdeMultiplatformImport { @@ -37,6 +38,12 @@ interface IdeMultiplatformImport { fun resolveDependenciesSerialized(sourceSetName: String): List + /** + * @param owner: Should implement [HasMutableExtras]. Passing [Any] is fine to make it easier to cross + * ClassLoader boundaries. Passing some non [HasMutableExtras] will just return null + */ + fun resolveExtrasSerialized(owner: Any): ByteArray? + fun serialize(dependencies: Iterable): List fun serialize(key: Extras.Key, value: T): ByteArray? diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportImpl.kt index d0636f80963..00c51943893 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportImpl.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportImpl.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin.ide import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension import org.jetbrains.kotlin.gradle.idea.proto.tcs.toByteArray +import org.jetbrains.kotlin.gradle.idea.proto.toByteArray import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinExtrasSerializationExtension import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinSerializationContext import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency @@ -17,6 +18,7 @@ import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver.Companion.re import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport.* import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport.Companion.logger import org.jetbrains.kotlin.tooling.core.Extras +import org.jetbrains.kotlin.tooling.core.HasMutableExtras import org.jetbrains.kotlin.utils.addToStdlib.measureTimeMillisWithResult import kotlin.system.measureTimeMillis @@ -37,6 +39,11 @@ internal class IdeMultiplatformImportImpl( return serialize(resolveDependencies(sourceSetName)) } + override fun resolveExtrasSerialized(owner: Any): ByteArray? { + if (owner !is HasMutableExtras) return null + return owner.extras.toByteArray(createSerializationContext()) + } + override fun serialize(dependencies: Iterable): List { val context = createSerializationContext() return dependencies.map { dependency -> dependency.toByteArray(context) }