diff --git a/libraries/tools/kotlin-gradle-plugin-idea/src/testFixtures/kotlin/org/jetbrains/kotlin/gradle/idea/testFixtures/tcs/ideaDependencyMatcherBuilders.kt b/libraries/tools/kotlin-gradle-plugin-idea/src/testFixtures/kotlin/org/jetbrains/kotlin/gradle/idea/testFixtures/tcs/ideaDependencyMatcherBuilders.kt index 80668ff9ecf..a98dd1fcd53 100644 --- a/libraries/tools/kotlin-gradle-plugin-idea/src/testFixtures/kotlin/org/jetbrains/kotlin/gradle/idea/testFixtures/tcs/ideaDependencyMatcherBuilders.kt +++ b/libraries/tools/kotlin-gradle-plugin-idea/src/testFixtures/kotlin/org/jetbrains/kotlin/gradle/idea/testFixtures/tcs/ideaDependencyMatcherBuilders.kt @@ -22,9 +22,23 @@ fun ideSourceDependency(type: IdeaKotlinSourceDependency.Type, project: Project, return IdeaKotlinSourceDependencyMatcher(type, project.path, sourceSetName) } +fun ideSourceDependency(type: IdeaKotlinSourceDependency.Type, path: String): IdeaKotlinDependencyMatcher { + val segments = path.split(":") + val projectPath = segments.dropLast(1).joinToString(":") + val sourceSetName = segments.last() + return IdeaKotlinSourceDependencyMatcher(type, projectPath, sourceSetName) +} + +fun regularSourceDependency(path: String) = ideSourceDependency(IdeaKotlinSourceDependency.Type.Regular, path) + +fun friendSourceDependency(path: String) = ideSourceDependency(IdeaKotlinSourceDependency.Type.Friend, path) + fun dependsOnDependency(project: Project, sourceSetName: String) = ideSourceDependency(IdeaKotlinSourceDependency.Type.DependsOn, project, sourceSetName) +fun dependsOnDependency(path: String) = ideSourceDependency(IdeaKotlinSourceDependency.Type.DependsOn, path) + + fun binaryCoordinates(regex: Regex): IdeaKotlinDependencyMatcher { return IdeaBinaryCoordinatesMatcher(regex) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt index e3518270a70..a08e0213340 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt @@ -20,6 +20,20 @@ fun IdeMultiplatformImport(extension: KotlinMultiplatformExtension): IdeMultipla level = IdeMultiplatformImport.DependencyResolutionLevel.Default ) + registerDependencyResolver( + resolver = IdeFriendSourceDependencyResolver, + constraint = IdeMultiplatformImport.SourceSetConstraint.unconstrained, + phase = IdeMultiplatformImport.DependencyResolutionPhase.SourceDependencyResolution, + level = IdeMultiplatformImport.DependencyResolutionLevel.Default + ) + + registerDependencyResolver( + resolver = IdeVisibleMultiplatformSourceDependencyResolver, + constraint = IdeMultiplatformImport.SourceSetConstraint.unconstrained, + phase = IdeMultiplatformImport.DependencyResolutionPhase.SourceDependencyResolution, + level = IdeMultiplatformImport.DependencyResolutionLevel.Default + ) + registerDependencyResolver( resolver = IdeTransformedMetadataDependencyResolver, constraint = IdeMultiplatformImport.SourceSetConstraint.isMetadata, diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeFriendSourceDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeFriendSourceDependencyResolver.kt new file mode 100644 index 00000000000..adc880572c0 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeFriendSourceDependencyResolver.kt @@ -0,0 +1,33 @@ +/* + * 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.plugin.ide.dependencyResolvers + +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinSourceCoordinates +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinSourceDependency +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.currentBuildId +import org.jetbrains.kotlin.gradle.plugin.sources.getVisibleSourceSetsFromAssociateCompilations +import org.jetbrains.kotlin.gradle.plugin.sources.project +import org.jetbrains.kotlin.tooling.core.mutableExtrasOf + +object IdeFriendSourceDependencyResolver : IdeDependencyResolver { + override fun resolve(sourceSet: KotlinSourceSet): Set { + return getVisibleSourceSetsFromAssociateCompilations(sourceSet).map { friendSourceSet -> + IdeaKotlinSourceDependency( + type = IdeaKotlinSourceDependency.Type.Friend, + extras = mutableExtrasOf(), + coordinates = IdeaKotlinSourceCoordinates( + buildId = friendSourceSet.project.currentBuildId().toString(), + projectPath = friendSourceSet.project.path, + projectName = friendSourceSet.project.name, + sourceSetName = friendSourceSet.name + ) + ) + }.toSet() + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeVisibleMultiplatformSourceDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeVisibleMultiplatformSourceDependencyResolver.kt new file mode 100644 index 00000000000..5765a6565a4 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeVisibleMultiplatformSourceDependencyResolver.kt @@ -0,0 +1,47 @@ +/* + * 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.plugin.ide.dependencyResolvers + +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinSourceCoordinates +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinSourceDependency +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver +import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.currentBuildId +import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope.* +import org.jetbrains.kotlin.tooling.core.mutableExtrasOf + +object IdeVisibleMultiplatformSourceDependencyResolver : IdeDependencyResolver { + override fun resolve(sourceSet: KotlinSourceSet): Set { + if (sourceSet !is DefaultKotlinSourceSet) return emptySet() + return sourceSet.dependencyTransformations[API_SCOPE]?.metadataDependencyResolutions?.toList().orEmpty() + .plus(sourceSet.dependencyTransformations[IMPLEMENTATION_SCOPE]?.metadataDependencyResolutions?.toList().orEmpty()) + .plus(sourceSet.dependencyTransformations[COMPILE_ONLY_SCOPE]?.metadataDependencyResolutions?.toList().orEmpty()) + .filterIsInstance() + .flatMap { resolution -> resolveSourceDependencies(resolution) } + .toSet() + } + + private fun resolveSourceDependencies( + resolution: MetadataDependencyResolution.ChooseVisibleSourceSets + ): Iterable { + val project = resolution.projectDependency ?: return emptyList() + return resolution.allVisibleSourceSetNames.map { visibleSourceSetName -> + IdeaKotlinSourceDependency( + type = IdeaKotlinSourceDependency.Type.Regular, + extras = mutableExtrasOf(), + coordinates = IdeaKotlinSourceCoordinates( + buildId = project.currentBuildId().toString(), + projectPath = project.path, + projectName = project.name, + sourceSetName = visibleSourceSetName + ) + ) + } + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeResolveSourceDependenciesTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeResolveSourceDependenciesTest.kt new file mode 100644 index 00000000000..b934ca2e139 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeResolveSourceDependenciesTest.kt @@ -0,0 +1,103 @@ +/* + * 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.ide + +import org.jetbrains.kotlin.gradle.applyMultiplatformPlugin +import org.jetbrains.kotlin.gradle.buildProject +import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension +import org.jetbrains.kotlin.gradle.enableDefaultStdlibDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinSourceDependency +import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.assertMatches +import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.dependsOnDependency +import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.friendSourceDependency +import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.regularSourceDependency +import org.jetbrains.kotlin.gradle.plugin.ide.kotlinIdeMultiplatformImport +import kotlin.test.Test + +class IdeResolveSourceDependenciesTest { + @Test + fun `test - multiplatform to multiplatform - sample 0`() { + val root = buildProject() + + val producer = buildProject({ withParent(root).withName("producer") }) { + enableDefaultStdlibDependency(false) + applyMultiplatformPlugin() + + multiplatformExtension.apply { + targetHierarchy.default() + linuxX64() + linuxArm64() + jvm() + } + } + + val consumer = buildProject({ withParent(root).withName("consumer") }) { + enableDefaultStdlibDependency(false) + applyMultiplatformPlugin() + + multiplatformExtension.apply { + targetHierarchy.default() + linuxX64() + linuxArm64() + jvm() + + sourceSets.getByName("commonMain").dependencies { + implementation(project(":producer")) + } + } + } + + root.evaluate() + producer.evaluate() + consumer.evaluate() + + fun resolveConsumerSourceSet(sourceSetName: String) = consumer.kotlinIdeMultiplatformImport + .resolveDependencies(consumer.multiplatformExtension.sourceSets.getByName(sourceSetName)) + .filterIsInstance() + + resolveConsumerSourceSet("commonMain").assertMatches( + regularSourceDependency(":producer:commonMain") + ) + + resolveConsumerSourceSet("nativeMain").assertMatches( + regularSourceDependency(":producer:commonMain"), + regularSourceDependency(":producer:nativeMain"), + regularSourceDependency(":producer:linuxMain"), + dependsOnDependency(":consumer:commonMain"), + ) + + resolveConsumerSourceSet("nativeTest").assertMatches( + regularSourceDependency(":producer:commonMain"), + regularSourceDependency(":producer:nativeMain"), + regularSourceDependency(":producer:linuxMain"), + friendSourceDependency(":consumer:commonMain"), + friendSourceDependency(":consumer:nativeMain"), + friendSourceDependency(":consumer:linuxMain"), + dependsOnDependency(":consumer:commonTest"), + ) + + resolveConsumerSourceSet("linuxMain").assertMatches( + regularSourceDependency(":producer:commonMain"), + regularSourceDependency(":producer:nativeMain"), + regularSourceDependency(":producer:linuxMain"), + dependsOnDependency(":consumer:commonMain"), + dependsOnDependency(":consumer:nativeMain"), + ) + + resolveConsumerSourceSet("linuxTest").assertMatches( + regularSourceDependency(":producer:commonMain"), + regularSourceDependency(":producer:nativeMain"), + regularSourceDependency(":producer:linuxMain"), + friendSourceDependency(":consumer:commonMain"), + friendSourceDependency(":consumer:nativeMain"), + friendSourceDependency(":consumer:linuxMain"), + dependsOnDependency(":consumer:commonTest"), + dependsOnDependency(":consumer:nativeTest"), + ) + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/ideaKotlinDependencyMatcherBuilders.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/ideaKotlinDependencyMatcherBuilders.kt index 0bcf66386d9..88832502180 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/ideaKotlinDependencyMatcherBuilders.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/ideaKotlinDependencyMatcherBuilders.kt @@ -5,8 +5,11 @@ package org.jetbrains.kotlin.gradle.ide +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinSourceDependency +import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.ideSourceDependency import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.sources.internal +import org.jetbrains.kotlin.gradle.plugin.sources.project fun dependsOnDependency(sourceSet: KotlinSourceSet) = org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.dependsOnDependency(sourceSet.internal.project, sourceSet.name) \ No newline at end of file