diff --git a/libraries/tools/kotlin-gradle-plugin/api/kotlin-gradle-plugin.api b/libraries/tools/kotlin-gradle-plugin/api/kotlin-gradle-plugin.api index 13472e0fa30..bee7ac90851 100644 --- a/libraries/tools/kotlin-gradle-plugin/api/kotlin-gradle-plugin.api +++ b/libraries/tools/kotlin-gradle-plugin/api/kotlin-gradle-plugin.api @@ -30,14 +30,86 @@ public final class org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolverK } public abstract interface class org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport { + public static final field Companion Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$Companion; + public static fun instance (Lorg/gradle/api/Project;)Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport; public abstract fun registerAdditionalArtifactResolver (Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeAdditionalArtifactResolver;Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint;Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$AdditionalArtifactResolutionPhase;Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$AdditionalArtifactResolutionLevel;)V public abstract fun registerDependencyEffect (Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyEffect;Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint;)V public abstract fun registerDependencyResolver (Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver;Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint;Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionPhase;Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionLevel;)V public abstract fun registerDependencyTransformer (Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyTransformer;Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint;Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyTransformationPhase;)V public abstract fun registerExtrasSerializationExtension (Lorg/jetbrains/kotlin/gradle/idea/serialize/IdeaKotlinExtrasSerializationExtension;)V + public abstract fun resolveDependencies (Ljava/lang/String;)Ljava/util/Set; + public abstract fun resolveDependencies (Lorg/jetbrains/kotlin/gradle/plugin/KotlinSourceSet;)Ljava/util/Set; + public abstract fun resolveDependenciesSerialized (Ljava/lang/String;)Ljava/util/List; + public abstract fun resolveExtrasSerialized (Ljava/lang/Object;)[B + public abstract fun serialize (Ljava/lang/Iterable;)Ljava/util/List; + public abstract fun serialize (Lorg/jetbrains/kotlin/tooling/core/Extras$Key;Ljava/lang/Object;)[B +} + +public final class org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$AdditionalArtifactResolutionLevel : java/lang/Enum { + public static final field Default Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$AdditionalArtifactResolutionLevel; + public static final field Overwrite Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$AdditionalArtifactResolutionLevel; + public static fun valueOf (Ljava/lang/String;)Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$AdditionalArtifactResolutionLevel; + public static fun values ()[Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$AdditionalArtifactResolutionLevel; +} + +public final class org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$AdditionalArtifactResolutionPhase : java/lang/Enum { + public static final field PostAdditionalArtifactResolution Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$AdditionalArtifactResolutionPhase; + public static final field PreAdditionalArtifactResolution Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$AdditionalArtifactResolutionPhase; + public static final field SourcesAndDocumentationResolution Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$AdditionalArtifactResolutionPhase; + public static fun valueOf (Ljava/lang/String;)Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$AdditionalArtifactResolutionPhase; + public static fun values ()[Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$AdditionalArtifactResolutionPhase; +} + +public final class org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$Companion { + public final fun instance (Lorg/gradle/api/Project;)Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport; +} + +public final class org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionLevel : java/lang/Enum { + public static final field Default Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionLevel; + public static final field Overwrite Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionLevel; + public static fun valueOf (Ljava/lang/String;)Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionLevel; + public static fun values ()[Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionLevel; +} + +public final class org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionPhase : java/lang/Enum { + public static final field BinaryDependencyResolution Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionPhase; + public static final field PostDependencyResolution Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionPhase; + public static final field PreDependencyResolution Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionPhase; + public static final field SourceDependencyResolution Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionPhase; + public static final field SourcesAndDocumentationResolution Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionPhase; + public static fun valueOf (Ljava/lang/String;)Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionPhase; + public static fun values ()[Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyResolutionPhase; +} + +public final class org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyTransformationPhase : java/lang/Enum { + public static final field DependencyFilteringPhase Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyTransformationPhase; + public static final field FreeDependencyTransformationPhase Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyTransformationPhase; + public static final field PostDependencyTransformationPhase Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyTransformationPhase; + public static final field PreDependencyTransformationPhase Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyTransformationPhase; + public static fun valueOf (Ljava/lang/String;)Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyTransformationPhase; + public static fun values ()[Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$DependencyTransformationPhase; +} + +public abstract interface class org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint { + public static final field Companion Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint$Companion; + public abstract fun invoke (Lorg/jetbrains/kotlin/gradle/plugin/KotlinSourceSet;)Z +} + +public final class org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint$Companion { + public final fun getUnconstrained ()Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint; + public final fun isAndroid ()Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint; + public final fun isJvmAndAndroid ()Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint; + public final fun isLeaf ()Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint; + public final fun isNative ()Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint; + public final fun isSharedNative ()Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint; + public final fun isSingleKotlinTarget ()Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint; + public final fun isSinglePlatformType ()Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint; } public final class org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportKt { + public static final fun and (Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint;Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint;)Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint; + public static final fun not (Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint;)Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint; + public static final fun or (Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint;Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint;)Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport$SourceSetConstraint; public static final fun registerExtrasSerializationExtension (Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport;Lkotlin/jvm/functions/Function1;)V } 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 c2b914b94d9..5fad2a0e794 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 @@ -10,13 +10,16 @@ import org.gradle.api.Project import org.gradle.api.logging.Logger import org.gradle.api.logging.Logging import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi +import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinExtrasSerializationExtension import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinExtrasSerializationExtensionBuilder import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency +import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.* import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.KotlinTarget import org.jetbrains.kotlin.gradle.plugin.extraProperties import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport.DependencyResolutionLevel.Default import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport.DependencyResolutionLevel.Overwrite @@ -30,6 +33,7 @@ import org.jetbrains.kotlin.gradle.utils.getOrPut import org.jetbrains.kotlin.tooling.core.Extras import org.jetbrains.kotlin.tooling.core.HasMutableExtras +@ExternalKotlinTargetApi interface IdeMultiplatformImport { fun resolveDependencies(sourceSetName: String): Set @@ -48,6 +52,11 @@ interface IdeMultiplatformImport { fun serialize(key: Extras.Key, value: T): ByteArray? + /** + * Registers a given [resolver] to run during Gradle import: + * The given resolver will only run if [constraint] matches and if not overwritten by another + * resolver registered in the same [phase] and level=[DependencyResolutionLevel.Overwrite] + */ @ExternalKotlinTargetApi fun registerDependencyResolver( resolver: IdeDependencyResolver, @@ -56,6 +65,11 @@ interface IdeMultiplatformImport { level: DependencyResolutionLevel = Default, ) + /** + * Registers a given [resolver] to run during Gradle import: + * The given resolver will only run if [constraint] matches and if not overwritten by another + * resolver registered in the same [phase] and level [AdditionalArtifactResolutionLevel.Overwrite] + */ @ExternalKotlinTargetApi fun registerAdditionalArtifactResolver( resolver: IdeAdditionalArtifactResolver, @@ -64,6 +78,10 @@ interface IdeMultiplatformImport { level: AdditionalArtifactResolutionLevel = AdditionalArtifactResolutionLevel.Default ) + /** + * Registers a given [transformer] to run during Gradle import: + * The resolver will only run if the [constraint] matches the SourceSet + */ @ExternalKotlinTargetApi fun registerDependencyTransformer( transformer: IdeDependencyTransformer, @@ -71,12 +89,28 @@ interface IdeMultiplatformImport { phase: DependencyTransformationPhase ) + /** + * Registers a given [effect] to run during Gradle import: + * The effect will only run for SourceSets matching the given [constraint] + */ @ExternalKotlinTargetApi fun registerDependencyEffect( effect: IdeDependencyEffect, constraint: SourceSetConstraint ) + /** + * Registers a [IdeaKotlinExtrasSerializationExtension] for transporting generic/external data into the + * IDE process using the [Extras]. Entities that implement [HasMutableExtras] which are imported to the IDE + * (like KotlinTarget, KotlinCompilation and KotlinSourceSet) will automatically retain their attached extras using + * the serializers registered as [extension]. + * + * Note 1: In order to access the extras in the IDE during (or after) Gradle import, a similar + * extension needs to be registered in the IDE plugin to deserialize the payload. + * Note 2: Extras that do not have a serializer attached will not be transported into the IDE process + * Note 3: This transport mechanism will only act as transport mechanics of data. Keeping serializers and deserializers compatible + * shall be handled by the implementers of the [extension] + */ @ExternalKotlinTargetApi fun registerExtrasSerializationExtension( extension: IdeaKotlinExtrasSerializationExtension @@ -86,6 +120,7 @@ interface IdeMultiplatformImport { * Any [IdeDependencyResolver] has to be registered for a given dependency resolution phase in which it participates * The resolution phases will be executed in the order of their enum's ordinal. */ + @ExternalKotlinTargetApi enum class DependencyResolutionPhase { /** * Generic phase intended to run before all other resolvers @@ -122,16 +157,19 @@ interface IdeMultiplatformImport { * If resolvers with level [Overwrite] are found, then only those will contribute to the dependency resolution. * Otherwise, all [Default] resolvers will run. */ + @ExternalKotlinTargetApi enum class DependencyResolutionLevel { Default, Overwrite } + @ExternalKotlinTargetApi enum class AdditionalArtifactResolutionPhase { PreAdditionalArtifactResolution, SourcesAndDocumentationResolution, PostAdditionalArtifactResolution } + @ExternalKotlinTargetApi enum class AdditionalArtifactResolutionLevel { Default, Overwrite } @@ -140,6 +178,7 @@ interface IdeMultiplatformImport { * Any [IdeDependencyResolver] has to be registered for a given transformation phase. * The phases will be executed in the order of this enums ordinal. */ + @ExternalKotlinTargetApi enum class DependencyTransformationPhase { /** * Generic dependency transformation phase, intended to run a transformation before all other transformers. @@ -168,39 +207,72 @@ interface IdeMultiplatformImport { /** * Used for scoping [IdeDependencyResolver], [IdeDependencyResolver] and [IdeDependencyEffect] */ + @ExternalKotlinTargetApi fun interface SourceSetConstraint { operator fun invoke(sourceSet: KotlinSourceSet): Boolean + @ExternalKotlinTargetApi companion object { + /** + * Indicating that all SourceSets will *always* match this constraint + */ val unconstrained = SourceSetConstraint { true } + /** + * Will only match SourceSets that will be compiled by the Native compiler + * Note: this includes shared native SourceSets, sharing code between multiple native targets + */ val isNative = SourceSetConstraint { it.isNativeSourceSet.getOrThrow() } + /** + * Only matches SourceSets that share code between at least two native targets, but no non-native target + */ val isSharedNative = isNative and SourceSetConstraint { sourceSet -> sourceSet.internal.compilations.filterIsInstance() .map { compilation -> compilation.konanTarget } .toSet().size > 1 } + /** + * Matches SourceSets which only have a single [KotlinPlatformType] associated. + */ val isSinglePlatformType = SourceSetConstraint { isSinglePlatformTypeSourceSet(it) } + /** + * Matches SourceSets which only participate in compilations of a single [KotlinTarget] + */ val isSingleKotlinTarget = SourceSetConstraint { isSingleKotlinTargetSourceSet(it) } + /** + * Matches SourceSets that do not have any other SourceSets that declare a 'dependsOn' this SourceSet + */ val isLeaf = SourceSetConstraint { sourceSet -> (sourceSet.project.multiplatformExtensionOrNull ?: return@SourceSetConstraint true).sourceSets .none { otherSourceSet -> sourceSet in otherSourceSet.dependsOn } } + /** + * Matches SourceSets that share code between compilations with [KotlinPlatformType.jvm] and [KotlinPlatformType.androidJvm] + * platform types. + * NB: The external Android target maintained by Google will likely also use the [KotlinPlatformType.jvm] + * and therefore will not match this constraint. + */ val isJvmAndAndroid = SourceSetConstraint { sourceSet -> sourceSet.internal.compilations.map { it.platformType }.filter { it != common }.toSet() == setOf(jvm, androidJvm) } + /** + * Matches SourceSets that only compile for compilations with [KotlinPlatformType.androidJvm] + * NB: The external Android target maintained by Google will likely also use the [KotlinPlatformType.jvm] + * and therefore will not match this constraint. + */ val isAndroid = SourceSetConstraint { sourceSet -> sourceSet.internal.compilations.map { it.platformType }.toSet() == setOf(androidJvm) } } } + @ExternalKotlinTargetApi companion object { internal val logger: Logger = Logging.getLogger(IdeMultiplatformImport::class.java) @@ -215,6 +287,12 @@ interface IdeMultiplatformImport { internal val Project.kotlinIdeMultiplatformImport: IdeMultiplatformImport get() = IdeMultiplatformImport.instance(project) +/** + * Convenience shortcut method for + * `registerExtrasSerializationExtension(IdeaKotlinExtrasSerializationExtension(builder))` + * see [IdeMultiplatformImport.registerExtrasSerializationExtension] + */ +@Suppress("unused") @ExternalKotlinTargetApi fun IdeMultiplatformImport.registerExtrasSerializationExtension( builder: IdeaKotlinExtrasSerializationExtensionBuilder.() -> Unit @@ -222,18 +300,33 @@ fun IdeMultiplatformImport.registerExtrasSerializationExtension( registerExtrasSerializationExtension(IdeaKotlinExtrasSerializationExtension(builder)) } +/** + * Combines two given [SourceSetConstraint] using a logical 'or': + * The resulting constraint will match any SourceSet that matches at least one of the specified constraints + */ +@ExternalKotlinTargetApi infix fun SourceSetConstraint.or( other: SourceSetConstraint ) = SourceSetConstraint { sourceSet -> this@or(sourceSet) || other(sourceSet) } +/** + * Combines two given [SourceSetConstraint] using a logical 'and': + * The resulting constraint will match only SourceSets that matches both of the specified constraints + */ +@ExternalKotlinTargetApi infix fun SourceSetConstraint.and( other: SourceSetConstraint ) = SourceSetConstraint { sourceSet -> this@and(sourceSet) && other(sourceSet) } +/** + * Negates a given [SourceSetConstraint]: + * The resulting constraint will match only SourceSets that would *not* have been matched by the source constraint + */ +@ExternalKotlinTargetApi operator fun SourceSetConstraint.not() = SourceSetConstraint { sourceSet -> this@not(sourceSet).not() }