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 32670423ace..13472e0fa30 100644 --- a/libraries/tools/kotlin-gradle-plugin/api/kotlin-gradle-plugin.api +++ b/libraries/tools/kotlin-gradle-plugin/api/kotlin-gradle-plugin.api @@ -1,3 +1,34 @@ +public abstract interface class org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver { + public static final field Companion Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver$Companion; + public static final field DOCUMENTATION_BINARY_TYPE Ljava/lang/String; + public static final field SOURCES_BINARY_TYPE Ljava/lang/String; + public abstract fun resolve (Lorg/jetbrains/kotlin/gradle/plugin/KotlinSourceSet;)Ljava/util/Set; +} + +public final class org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver$Companion { + public static final field DOCUMENTATION_BINARY_TYPE Ljava/lang/String; + public static final field SOURCES_BINARY_TYPE Ljava/lang/String; + public final fun getGradleArtifact (Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinDependency;)Lorg/gradle/api/artifacts/result/ResolvedArtifactResult; + public final fun getResolvedBy (Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinDependency;)Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver; + public final fun setGradleArtifact (Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinDependency;Lorg/gradle/api/artifacts/result/ResolvedArtifactResult;)V + public final fun setResolvedBy (Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinDependency;Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver;)V +} + +public final class org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver$Empty : org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver { + public static final field INSTANCE Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver$Empty; + public fun resolve (Lorg/jetbrains/kotlin/gradle/plugin/KotlinSourceSet;)Ljava/util/Set; +} + +public abstract interface class org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver$WithBuildDependencies { + public abstract fun dependencies (Lorg/gradle/api/Project;)Ljava/lang/Iterable; +} + +public final class org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolverKt { + public static final fun IdeDependencyResolver (Ljava/lang/Iterable;)Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver; + public static final fun IdeDependencyResolver ([Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver;)Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver; + public static final fun plus (Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver;Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver;)Lorg/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver; +} + public abstract interface class org/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 diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver.kt index ef2fe29b16b..7cbb827a2f0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver.kt @@ -7,13 +7,45 @@ package org.jetbrains.kotlin.gradle.plugin.ide import org.gradle.api.Project import org.gradle.api.artifacts.result.ResolvedArtifactResult +import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.tooling.core.extrasReadWriteProperty +/** + * Service interface that allows resolving dependencies for the IDE during Gradle sync + * + * #### Entry point + * [IdeMultiplatformImport]: Will allow registering implementations of this resolver using [IdeMultiplatformImport.registerDependencyResolver] + * + * #### Api Contract: + * A resolver always has to resolve *all* visible source sets for a given [KotlinSourceSet] as Set of [IdeaKotlinDependency] + * This includes dependencies that are transitively visible through the SourceSets dependsOn closure: + * + * e.g. if a resolver is invoked on a SourceSet structure like + * ``` + * commonMain + * dependencies(libraryA) + * ^ + * intermediateMain + * dependencies(libraryB) + * ^ + * jvmMain + * dependencies(libraryC) + * ``` + * + * Then calling the resolver on _jvmMain_ shall return setOf(libraryA, libraryB, libraryC) + * + * #### Resolvers that rely on task execution + * It might happen that some implementation of an [IdeDependencyResolver] has to rely on the execution + * of certain build tasks before it can return the dependencies. In order to tell the import subsystem to execute + * such tasks before Gradle sync (and therefore the resolver) is executed one can implement the [WithBuildDependencies] interface + */ +@ExternalKotlinTargetApi fun interface IdeDependencyResolver { fun resolve(sourceSet: KotlinSourceSet): Set + @ExternalKotlinTargetApi interface WithBuildDependencies { /** * return anything accepted to be passed to [org.gradle.api.Task.dependsOn] @@ -21,19 +53,50 @@ fun interface IdeDependencyResolver { fun dependencies(project: Project): Iterable } + @ExternalKotlinTargetApi object Empty : IdeDependencyResolver { override fun resolve(sourceSet: KotlinSourceSet): Set = emptySet() } + @ExternalKotlinTargetApi companion object { + /** + * Special binaryType String that indicates that a certain dependency is only a sources.jar and + * therefore should be attached as extra to the binary dependency. + * This is only necessary for resolvers that implement sources/documentation resolution as [IdeDependencyResolver] + * instead of [IdeAdditionalArtifactResolver] + */ const val SOURCES_BINARY_TYPE = "SOURCES" + + /** + * Special binaryType String that indicates that a certain dependency is only a javadoc.jar and + * therefore should be attached as extra to the binary dependency. + * This is only necessary for resolvers that implement sources/documentation resolution as [IdeDependencyResolver] + * instead of [IdeAdditionalArtifactResolver] + */ const val DOCUMENTATION_BINARY_TYPE = "DOCUMENTATION" + /** + * Extra on [IdeaKotlinDependency] to attach the resolver which created/resolved a certain dependency. + * This can be used for debugging and testing + */ var IdeaKotlinDependency.resolvedBy: IdeDependencyResolver? by extrasReadWriteProperty("resolvedBy") + + /** + * Extra on [IdeaKotlinDependency] to attach the [ResolvedArtifactResult] that which was used to create a certain dependency. + * This can be used for debugging and testing + */ var IdeaKotlinDependency.gradleArtifact: ResolvedArtifactResult? by extrasReadWriteProperty("gradleArtifact") } } +/** + * Creates a composite [IdeDependencyResolver] from the specified [resolvers] + * Resolvers that are `null` will be ignored. + * The composite will preserve the order and invoke the [resolvers] in the same order as specified. + * The resulting set of dependencies will be the superset of all results of individual resolvers. + */ +@ExternalKotlinTargetApi fun IdeDependencyResolver( resolvers: Iterable ): IdeDependencyResolver { @@ -42,11 +105,24 @@ fun IdeDependencyResolver( return IdeCompositeDependencyResolver(resolversList) } +/** + * Creates a composite [IdeDependencyResolver] from the specified [resolvers] + * Resolvers that are `null` will be ignored. + * The composite will preserve the order and invoke the [resolvers] in the same order as specified. + * The resulting set of dependencies will be the superset of all results of individual resolvers. + */ +@ExternalKotlinTargetApi fun IdeDependencyResolver( vararg resolvers: IdeDependencyResolver? ): IdeDependencyResolver = IdeDependencyResolver(resolvers.toList()) +/** + * Builds a composite [IdeDependencyResolver] by combining the receiver and the parameter resolver. + * The resulting composite resolver will be flat, so if either the receiver or the parameter resolver already + * is a composite, the resulting composite will aggregate the children in a flat manner. + */ +@ExternalKotlinTargetApi operator fun IdeDependencyResolver.plus(other: IdeDependencyResolver): IdeDependencyResolver { if (this is IdeCompositeDependencyResolver && other is IdeCompositeDependencyResolver) return IdeCompositeDependencyResolver(this.children + other.children)