Import 'implement' dependency of platform project transitively

#KT-16926 fixed
This commit is contained in:
Alexey Tsvetkov
2017-03-24 18:51:54 +03:00
parent e9c47d6498
commit 54ee779ba1
3 changed files with 120 additions and 15 deletions
@@ -25,23 +25,25 @@ import java.io.Serializable
import java.lang.Exception import java.lang.Exception
import java.lang.reflect.InvocationTargetException import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method import java.lang.reflect.Method
import java.util.*
import kotlin.collections.HashSet
typealias CompilerArgumentsBySourceSet = Map<String, List<String>> typealias CompilerArgumentsBySourceSet = Map<String, List<String>>
interface KotlinGradleModel : Serializable { interface KotlinGradleModel : Serializable {
val implements: String?
val currentCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet val currentCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet
val defaultCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet val defaultCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet
val coroutines: String? val coroutines: String?
val platformPluginId: String? val platformPluginId: String?
val transitiveCommonDependencies: Set<String>
} }
class KotlinGradleModelImpl( class KotlinGradleModelImpl(
override val implements: String?,
override val currentCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet, override val currentCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet,
override val defaultCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet, override val defaultCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet,
override val coroutines: String?, override val coroutines: String?,
override val platformPluginId: String? override val platformPluginId: String?,
override val transitiveCommonDependencies: Set<String>
) : KotlinGradleModel ) : KotlinGradleModel
class KotlinGradleModelBuilder : ModelBuilderService { class KotlinGradleModelBuilder : ModelBuilderService {
@@ -53,6 +55,7 @@ class KotlinGradleModelBuilder : ModelBuilderService {
"kotlin" to "kotlin-platform-jvm", "kotlin" to "kotlin-platform-jvm",
"kotlin2js" to "kotlin-platform-js" "kotlin2js" to "kotlin-platform-js"
) )
private val kotlinPlatformCommonPluginId = "kotlin-platform-common"
} }
override fun getErrorMessageBuilder(project: Project, e: Exception): ErrorMessageBuilder { 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 override fun canBuild(modelName: String?): Boolean = modelName == KotlinGradleModel::class.java.name
private fun getImplements(project: Project): String? { private fun getImplements(project: Project): Project? {
val implementsConfiguration = project.configurations.findByName("implement") val implementsConfiguration = project.configurations.findByName("implement") ?: return null
if (implementsConfiguration != null) { val implementsProjectDependency = implementsConfiguration.dependencies.filterIsInstance<ProjectDependency>().firstOrNull()
val implementsProjectDependency = implementsConfiguration.dependencies.filterIsInstance<ProjectDependency>().firstOrNull() return implementsProjectDependency?.dependencyProject
if (implementsProjectDependency != null) return implementsProjectDependency.dependencyProject.path }
private fun transitiveCommonDependencies(startingProject: Project): Set<String> {
val toProcess = LinkedList<Project>()
toProcess.add(startingProject)
val processed = HashSet<String>()
val result = HashSet<String>()
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<ProjectDependency>()
.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? { private fun Class<*>.findGetterMethod(name: String): Method? {
@@ -132,13 +163,14 @@ class KotlinGradleModelBuilder : ModelBuilderService {
val platform = platformPluginIds.singleOrNull { project.plugins.findPlugin(it) != null } val platform = platformPluginIds.singleOrNull { project.plugins.findPlugin(it) != null }
?: pluginToPlatform.entries.singleOrNull { project.plugins.findPlugin(it.key) != null }?.value ?: pluginToPlatform.entries.singleOrNull { project.plugins.findPlugin(it.key) != null }?.value
val transitiveCommon = getImplements(project)?.let { transitiveCommonDependencies(it) } ?: emptySet()
return KotlinGradleModelImpl( return KotlinGradleModelImpl(
getImplements(project),
currentCompilerArgumentsBySourceSet, currentCompilerArgumentsBySourceSet,
defaultCompilerArgumentsBySourceSet, defaultCompilerArgumentsBySourceSet,
getCoroutines(project), getCoroutines(project),
platform platform,
transitiveCommon
) )
} }
} }
@@ -57,7 +57,7 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension()
ideProject: DataNode<ProjectData>) { ideProject: DataNode<ProjectData>) {
val gradleModel = resolverCtx.getExtraProject(gradleModule, KotlinGradleModel::class.java) ?: return val gradleModel = resolverCtx.getExtraProject(gradleModule, KotlinGradleModel::class.java) ?: return
gradleModel.implements?.let { implementsModuleId -> gradleModel.transitiveCommonDependencies.forEach { implementsModuleId ->
val targetModule = findModule(ideProject, implementsModuleId) ?: return val targetModule = findModule(ideProject, implementsModuleId) ?: return
if (resolverCtx.isResolveModulePerSourceSet) { if (resolverCtx.isResolveModulePerSourceSet) {
populateSourceSetDependencies(gradleModule, ideModule, targetModule) populateSourceSetDependencies(gradleModule, ideModule, targetModule)
@@ -25,13 +25,11 @@ class MultiplatformProjectImportingTest : GradleImportingTestCase() {
fun testPlatformToCommonDependency() { fun testPlatformToCommonDependency() {
createProjectSubFile("settings.gradle", "include ':common', ':jvm', ':js'") createProjectSubFile("settings.gradle", "include ':common', ':jvm', ':js'")
val kotlinVersion = "1.1-M04" val kotlinVersion = "1.1.0"
val kotlinRepo = "maven { url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1' }"
createProjectSubFile("build.gradle", """ createProjectSubFile("build.gradle", """
buildscript { buildscript {
repositories { repositories {
$kotlinRepo
mavenCentral() mavenCentral()
} }
@@ -67,4 +65,79 @@ class MultiplatformProjectImportingTest : GradleImportingTestCase() {
assertModuleModuleDepScope("js_main", "common_main", DependencyScope.COMPILE) assertModuleModuleDepScope("js_main", "common_main", DependencyScope.COMPILE)
assertModuleModuleDepScope("js_test", "common_test", 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)
}
} }