From 54ee779ba11565da85bf1b565a8e3aad19474340 Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Fri, 24 Mar 2017 18:51:54 +0300 Subject: [PATCH] Import 'implement' dependency of platform project transitively #KT-16926 fixed --- .../src/KotlinGradleModelBuilder.kt | 54 ++++++++++--- .../KotlinGradleProjectResolverExtension.kt | 2 +- .../MultiplatformProjectImportingTest.kt | 79 ++++++++++++++++++- 3 files changed, 120 insertions(+), 15 deletions(-) diff --git a/idea/kotlin-gradle-tooling/src/KotlinGradleModelBuilder.kt b/idea/kotlin-gradle-tooling/src/KotlinGradleModelBuilder.kt index d82908da8d7..4af9fc9f99d 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinGradleModelBuilder.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinGradleModelBuilder.kt @@ -25,23 +25,25 @@ import java.io.Serializable import java.lang.Exception import java.lang.reflect.InvocationTargetException import java.lang.reflect.Method +import java.util.* +import kotlin.collections.HashSet typealias CompilerArgumentsBySourceSet = Map> interface KotlinGradleModel : Serializable { - val implements: String? val currentCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet val defaultCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet val coroutines: String? val platformPluginId: String? + val transitiveCommonDependencies: Set } class KotlinGradleModelImpl( - override val implements: String?, override val currentCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet, override val defaultCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet, override val coroutines: String?, - override val platformPluginId: String? + override val platformPluginId: String?, + override val transitiveCommonDependencies: Set ) : KotlinGradleModel class KotlinGradleModelBuilder : ModelBuilderService { @@ -53,6 +55,7 @@ class KotlinGradleModelBuilder : ModelBuilderService { "kotlin" to "kotlin-platform-jvm", "kotlin2js" to "kotlin-platform-js" ) + private val kotlinPlatformCommonPluginId = "kotlin-platform-common" } override fun getErrorMessageBuilder(project: Project, e: Exception): ErrorMessageBuilder { @@ -61,13 +64,41 @@ class KotlinGradleModelBuilder : ModelBuilderService { override fun canBuild(modelName: String?): Boolean = modelName == KotlinGradleModel::class.java.name - private fun getImplements(project: Project): String? { - val implementsConfiguration = project.configurations.findByName("implement") - if (implementsConfiguration != null) { - val implementsProjectDependency = implementsConfiguration.dependencies.filterIsInstance().firstOrNull() - if (implementsProjectDependency != null) return implementsProjectDependency.dependencyProject.path + private fun getImplements(project: Project): Project? { + val implementsConfiguration = project.configurations.findByName("implement") ?: return null + val implementsProjectDependency = implementsConfiguration.dependencies.filterIsInstance().firstOrNull() + return implementsProjectDependency?.dependencyProject + } + + private fun transitiveCommonDependencies(startingProject: Project): Set { + val toProcess = LinkedList() + toProcess.add(startingProject) + val processed = HashSet() + val result = HashSet() + result.add(startingProject.path) + + while (toProcess.isNotEmpty()) { + val project = toProcess.pollFirst() + processed.add(project.path) + + if (!project.plugins.hasPlugin(kotlinPlatformCommonPluginId)) continue + + result.add(project.path) + + val compileConfiguration = project.configurations.findByName("compile") ?: continue + val dependencies = compileConfiguration + .dependencies + .filterIsInstance() + .map { it.dependencyProject } + + for (dep in dependencies) { + if (dep.path !in processed) { + toProcess.add(dep) + } + } } - return null + + return result } private fun Class<*>.findGetterMethod(name: String): Method? { @@ -132,13 +163,14 @@ class KotlinGradleModelBuilder : ModelBuilderService { val platform = platformPluginIds.singleOrNull { project.plugins.findPlugin(it) != null } ?: pluginToPlatform.entries.singleOrNull { project.plugins.findPlugin(it.key) != null }?.value + val transitiveCommon = getImplements(project)?.let { transitiveCommonDependencies(it) } ?: emptySet() return KotlinGradleModelImpl( - getImplements(project), currentCompilerArgumentsBySourceSet, defaultCompilerArgumentsBySourceSet, getCoroutines(project), - platform + platform, + transitiveCommon ) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectResolverExtension.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectResolverExtension.kt index f9fa8643881..23f6db48b93 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectResolverExtension.kt +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectResolverExtension.kt @@ -57,7 +57,7 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension() ideProject: DataNode) { val gradleModel = resolverCtx.getExtraProject(gradleModule, KotlinGradleModel::class.java) ?: return - gradleModel.implements?.let { implementsModuleId -> + gradleModel.transitiveCommonDependencies.forEach { implementsModuleId -> val targetModule = findModule(ideProject, implementsModuleId) ?: return if (resolverCtx.isResolveModulePerSourceSet) { populateSourceSetDependencies(gradleModule, ideModule, targetModule) diff --git a/idea/tests/org/jetbrains/kotlin/gradle/MultiplatformProjectImportingTest.kt b/idea/tests/org/jetbrains/kotlin/gradle/MultiplatformProjectImportingTest.kt index f2b2fda93a9..db2a1ea2998 100644 --- a/idea/tests/org/jetbrains/kotlin/gradle/MultiplatformProjectImportingTest.kt +++ b/idea/tests/org/jetbrains/kotlin/gradle/MultiplatformProjectImportingTest.kt @@ -25,13 +25,11 @@ class MultiplatformProjectImportingTest : GradleImportingTestCase() { fun testPlatformToCommonDependency() { createProjectSubFile("settings.gradle", "include ':common', ':jvm', ':js'") - val kotlinVersion = "1.1-M04" - val kotlinRepo = "maven { url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1' }" + val kotlinVersion = "1.1.0" createProjectSubFile("build.gradle", """ buildscript { repositories { - $kotlinRepo mavenCentral() } @@ -67,4 +65,79 @@ class MultiplatformProjectImportingTest : GradleImportingTestCase() { assertModuleModuleDepScope("js_main", "common_main", DependencyScope.COMPILE) assertModuleModuleDepScope("js_test", "common_test", DependencyScope.COMPILE) } + + @Test + fun testMultiProject() { + createProjectSubFile("settings.gradle", "include ':common-lib', ':jvm-lib', ':js-lib', ':common-app', ':jvm-app', ':js-app'") + + val kotlinVersion = "1.1.0" + + createProjectSubFile("build.gradle", """ + buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") + } + } + + project('common-lib') { + apply plugin: 'kotlin-platform-common' + } + + project('jvm-lib') { + apply plugin: 'kotlin-platform-jvm' + + dependencies { + implement project(':common-lib') + } + } + + project('js-lib') { + apply plugin: 'kotlin-platform-js' + + dependencies { + implement project(':common-lib') + } + } + + project('common-app') { + apply plugin: 'kotlin-platform-common' + + dependencies { + compile project(':common-lib') + } + } + + project('jvm-app') { + apply plugin: 'kotlin-platform-jvm' + + dependencies { + implement project(':common-app') + compile project(':jvm-lib') + } + } + + project('js-app') { + apply plugin: 'kotlin-platform-js' + + dependencies { + implement project(':common-app') + compile project(':js-lib') + } + } + """) + + importProject() + + assertModuleModuleDepScope("jvm-app_main", "common-app_main", DependencyScope.COMPILE) + assertModuleModuleDepScope("jvm-app_main", "common-lib_main", DependencyScope.COMPILE) + assertModuleModuleDepScope("jvm-app_main", "jvm-lib_main", DependencyScope.COMPILE) + + assertModuleModuleDepScope("js-app_main", "common-app_main", DependencyScope.COMPILE) + assertModuleModuleDepScope("js-app_main", "common-lib_main", DependencyScope.COMPILE) + assertModuleModuleDepScope("js-app_main", "js-lib_main", DependencyScope.COMPILE) + } } \ No newline at end of file