diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt index 8ae2ccc41d3..e6aa26a7fcc 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt @@ -98,7 +98,22 @@ interface KotlinNativeCompilationExtensions : Serializable { } interface KotlinCompilation : KotlinModule { + /** + * All source sets participated in this compilation, including those available + * via dependsOn. + */ val sourceSets: Collection + + /** + * Only default source sets of this compilation, i.e. those which are included + * into compilations directly. + * + * Usually, those are automatically created source sets for automatically created + * compilations (like jvmMain for JVM compilations) or manually included source sets + * (like 'jvm().compilations["main"].source(mySourceSet)' ) + */ + val defaultSourceSets: Collection + val output: KotlinCompilationOutput val arguments: KotlinCompilationArguments val dependencyClasspath: Array diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt index f606ade930e..f045f701d7a 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt @@ -363,16 +363,10 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { ): KotlinCompilationImpl { val dependsOnSourceSets = this.sourceSets.flatMap { it.dependsOnSourceSets }.mapNotNull { importingContext.sourceSetByName(it) } - if (!importingContext.getProperty(IS_HMPP_ENABLED)) { - // intermediate source sets should be common if HMPP is disabled - dependsOnSourceSets.subtract(this.sourceSets).forEach { - it.actualPlatforms.addSimplePlatforms(listOf(KotlinPlatform.COMMON)) - } - } - return KotlinCompilationImpl( this.name, this.sourceSets.union(dependsOnSourceSets), + this.sourceSets, this.dependencies, this.output, this.arguments, @@ -520,6 +514,7 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { return KotlinCompilationImpl( gradleCompilation.name, + kotlinSourceSets, // In fact, it's only default source-sets. It will be corrected later, see [addDependsOnSourceSetsToCompilation] kotlinSourceSets, dependencies.map { dependencyMapper.getId(it) }.distinct().toTypedArray(), output, @@ -740,14 +735,25 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { sourceSet.isTestModule = importingContext.compilationsBySourceSet(sourceSet)?.all { it.isTestModule } ?: false - importingContext.compilationsBySourceSet(sourceSet)?.let { compilations -> - val platforms = compilations.map { it.platform } - sourceSet.actualPlatforms.addSimplePlatforms(platforms) - } + importingContext.computeSourceSetPlatforms(sourceSet) + } + } - if (importingContext.shouldCoerceToCommon(sourceSet)) { - sourceSet.actualPlatforms.addSimplePlatforms(listOf(KotlinPlatform.COMMON)) - } + private fun MultiplatformModelImportingContext.computeSourceSetPlatforms(sourceSet: KotlinSourceSetImpl) { + if (shouldCoerceToCommon(sourceSet)) { + sourceSet.actualPlatforms.addSimplePlatforms(listOf(KotlinPlatform.COMMON)) + return + } + + if (!getProperty(IS_HMPP_ENABLED) && !isDefaultSourceSet(sourceSet)) { + // intermediate source sets should be common if HMPP is disabled + sourceSet.actualPlatforms.addSimplePlatforms(listOf(KotlinPlatform.COMMON)) + return + } + + compilationsBySourceSet(sourceSet)?.let { compilations -> + val platforms = compilations.map { it.platform } + sourceSet.actualPlatforms.addSimplePlatforms(platforms) } } diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt index 1791edf052f..965fcfb4158 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt @@ -128,6 +128,7 @@ data class KotlinNativeCompilationExtensionsImpl( data class KotlinCompilationImpl( override val name: String, override val sourceSets: Collection, + override val defaultSourceSets: Collection, override val dependencies: Array, override val output: KotlinCompilationOutput, override val arguments: KotlinCompilationArguments, @@ -139,11 +140,8 @@ data class KotlinCompilationImpl( // create deep copy constructor(kotlinCompilation: KotlinCompilation, cloningCache: MutableMap) : this( kotlinCompilation.name, - kotlinCompilation.sourceSets.map { initialSourceSet -> - (cloningCache[initialSourceSet] as? KotlinSourceSet) ?: KotlinSourceSetImpl(initialSourceSet, cloningCache).also { - cloningCache[initialSourceSet] = it - } - }.toList(), + cloneSourceSetsWithCaching(kotlinCompilation.sourceSets, cloningCache), + cloneSourceSetsWithCaching(kotlinCompilation.defaultSourceSets, cloningCache), kotlinCompilation.dependencies, KotlinCompilationOutputImpl(kotlinCompilation.output), KotlinCompilationArgumentsImpl(kotlinCompilation.arguments), @@ -166,6 +164,19 @@ data class KotlinCompilationImpl( || platform == KotlinPlatform.ANDROID && name.contains("Test") override fun toString() = name + + companion object { + private fun cloneSourceSetsWithCaching( + sourceSets: Collection, + cloningCache: MutableMap + ): List = + sourceSets.map { initialSourceSet -> + (cloningCache[initialSourceSet] as? KotlinSourceSet) ?: KotlinSourceSetImpl(initialSourceSet, cloningCache).also { + cloningCache[initialSourceSet] = it + } + } + + } } data class KotlinTargetJarImpl( diff --git a/idea/kotlin-gradle-tooling/src/MultiplatformModelImportingContext.kt b/idea/kotlin-gradle-tooling/src/MultiplatformModelImportingContext.kt index 1d760b09508..003236a7a14 100644 --- a/idea/kotlin-gradle-tooling/src/MultiplatformModelImportingContext.kt +++ b/idea/kotlin-gradle-tooling/src/MultiplatformModelImportingContext.kt @@ -34,6 +34,14 @@ internal interface MultiplatformModelImportingContext { * it anywhere (essentially this is a misconfiguration) */ fun isOrphanSourceSet(sourceSet: KotlinSourceSet): Boolean = compilationsBySourceSet(sourceSet) == null + + /** + * "Default" source-set is a source-set which is included into compilation directly, rather + * through closure over dependsOn-relation. + * + * See also KDoc for [KotlinCompilation.defaultSourceSets] + */ + fun isDefaultSourceSet(sourceSet: KotlinSourceSet): Boolean } internal fun MultiplatformModelImportingContext.getProperty(property: GradleImportProperties): Boolean = project.getProperty(property) @@ -71,6 +79,7 @@ internal class MultiplatformModelImportingContextImpl(override val project: Proj override lateinit var compilations: Collection private set private lateinit var sourceSetToParticipatedCompilations: Map> + private lateinit var allDefaultSourceSets: Set /** see [initializeTargets] */ @@ -102,6 +111,8 @@ internal class MultiplatformModelImportingContextImpl(override val project: Proj } this.sourceSetToParticipatedCompilations = sourceSetToCompilations + + this.allDefaultSourceSets = compilations.flatMapTo(mutableSetOf()) { it.defaultSourceSets } } internal fun initializeTargets(targets: Collection) { @@ -112,6 +123,8 @@ internal class MultiplatformModelImportingContextImpl(override val project: Proj // overload for small optimization override fun isOrphanSourceSet(sourceSet: KotlinSourceSet): Boolean = sourceSet !in sourceSetToParticipatedCompilations.keys + override fun isDefaultSourceSet(sourceSet: KotlinSourceSet): Boolean = sourceSet in allDefaultSourceSets + override fun compilationsBySourceSet(sourceSet: KotlinSourceSet): Collection? = sourceSetToParticipatedCompilations[sourceSet]