Gradle: Respect 'implement' when collecting transitive dependencies of
IDEA module This covers the cases when module is transitively reachable via sequence of "compile"/"implement" dependencies with at least one "implement" present (cases when module is transitively reachable via "compile" only are handled automatically) #KT-16926 Fixed
This commit is contained in:
+67
@@ -183,4 +183,71 @@ class MultiplatformProjectImportingTest : GradleImportingTestCase() {
|
||||
assertModuleModuleDepScope("js-app_main", "common-lib_main", DependencyScope.COMPILE)
|
||||
assertModuleModuleDepScope("js-app_main", "js-lib_main", DependencyScope.COMPILE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDependenciesReachableViaImpl() {
|
||||
createProjectSubFile(
|
||||
"settings.gradle",
|
||||
"include ':common-lib1', ':common-lib2', ':jvm-lib1', ':jvm-lib2', ':jvm-app'"
|
||||
)
|
||||
|
||||
val kotlinVersion = "1.1.0"
|
||||
|
||||
createProjectSubFile("build.gradle", """
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
|
||||
}
|
||||
}
|
||||
|
||||
project('common-lib1') {
|
||||
apply plugin: 'kotlin-platform-common'
|
||||
}
|
||||
|
||||
project('common-lib2') {
|
||||
apply plugin: 'kotlin-platform-common'
|
||||
}
|
||||
|
||||
project('jvm-lib1') {
|
||||
apply plugin: 'kotlin-platform-jvm'
|
||||
|
||||
dependencies {
|
||||
implement project(':common-lib1')
|
||||
}
|
||||
}
|
||||
|
||||
project('jvm-lib2') {
|
||||
apply plugin: 'kotlin-platform-jvm'
|
||||
|
||||
dependencies {
|
||||
implement project(':common-lib2')
|
||||
compile project(':jvm-lib1')
|
||||
}
|
||||
}
|
||||
|
||||
project('jvm-app') {
|
||||
apply plugin: 'kotlin-platform-jvm'
|
||||
|
||||
dependencies {
|
||||
compile project(':jvm-lib2')
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
importProject()
|
||||
|
||||
assertModuleModuleDepScope("jvm-app_main", "jvm-lib2_main", DependencyScope.COMPILE)
|
||||
assertModuleModuleDepScope("jvm-app_main", "jvm-lib1_main", DependencyScope.COMPILE)
|
||||
assertModuleModuleDepScope("jvm-app_main", "common-lib1_main", DependencyScope.COMPILE)
|
||||
assertModuleModuleDepScope("jvm-app_main", "common-lib2_main", DependencyScope.COMPILE)
|
||||
|
||||
assertModuleModuleDepScope("jvm-app_test", "jvm-lib2_main", DependencyScope.COMPILE)
|
||||
assertModuleModuleDepScope("jvm-app_test", "jvm-lib1_main", DependencyScope.COMPILE)
|
||||
assertModuleModuleDepScope("jvm-app_test", "common-lib1_test", DependencyScope.COMPILE)
|
||||
assertModuleModuleDepScope("jvm-app_test", "common-lib2_test", DependencyScope.COMPILE)
|
||||
}
|
||||
}
|
||||
@@ -96,34 +96,44 @@ class KotlinGradleModelBuilder : AbstractKotlinGradleModelBuilder() {
|
||||
return implementsProjectDependency?.dependencyProject
|
||||
}
|
||||
|
||||
private val Project.isCommon get() = plugins.hasPlugin(kotlinPlatformCommonPluginId)
|
||||
|
||||
private fun transitiveCommonDependencies(startingProject: Project): Set<String> {
|
||||
val toProcess = LinkedList<Project>()
|
||||
toProcess.add(startingProject)
|
||||
val toProcess = LinkedList<Pair<Project, Boolean>>()
|
||||
toProcess.add(startingProject to false)
|
||||
val processed = HashSet<String>()
|
||||
val result = HashSet<String>()
|
||||
result.add(startingProject.pathOrName())
|
||||
|
||||
while (toProcess.isNotEmpty()) {
|
||||
val project = toProcess.pollFirst()
|
||||
processed.add(project.path)
|
||||
fun enqueueDependencies(project: Project, isReachableViaImpl: Boolean, collectImpls: Boolean) {
|
||||
val isCommonProject = project.isCommon
|
||||
if (isCommonProject && collectImpls) return
|
||||
|
||||
if (!project.plugins.hasPlugin(kotlinPlatformCommonPluginId)) continue
|
||||
|
||||
result.add(project.pathOrName())
|
||||
|
||||
val compileConfiguration = project.configurations.findByName("compile") ?: continue
|
||||
val configName = if (collectImpls) "implement" else "compile"
|
||||
val compileConfiguration = project.configurations.findByName(configName) ?: return
|
||||
val dependencies = compileConfiguration
|
||||
.dependencies
|
||||
.filterIsInstance<ProjectDependency>()
|
||||
.map { it.dependencyProject }
|
||||
|
||||
for (dep in dependencies) {
|
||||
if (dep.path !in processed) {
|
||||
toProcess.add(dep)
|
||||
}
|
||||
if (dep.path in processed) continue
|
||||
if (!dep.isCommon && (collectImpls || isCommonProject)) continue
|
||||
toProcess.add(dep to (isReachableViaImpl || collectImpls))
|
||||
}
|
||||
}
|
||||
|
||||
while (toProcess.isNotEmpty()) {
|
||||
val (project, isReachableViaImpl) = toProcess.pollFirst()
|
||||
processed.add(project.path)
|
||||
|
||||
if (isReachableViaImpl) {
|
||||
result.add(project.pathOrName())
|
||||
}
|
||||
|
||||
enqueueDependencies(project, isReachableViaImpl, false)
|
||||
enqueueDependencies(project, isReachableViaImpl, true)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -196,7 +206,7 @@ class KotlinGradleModelBuilder : AbstractKotlinGradleModelBuilder() {
|
||||
|
||||
val platform = platformPluginId ?: pluginToPlatform.entries.singleOrNull { project.plugins.findPlugin(it.key) != null }?.value
|
||||
val implementedProject = getImplements(project)
|
||||
val transitiveCommon = implementedProject?.let { transitiveCommonDependencies(it) } ?: emptySet()
|
||||
val transitiveCommon = transitiveCommonDependencies(project)
|
||||
|
||||
return KotlinGradleModelImpl(
|
||||
kotlinPluginId != null || platformPluginId != null,
|
||||
|
||||
Reference in New Issue
Block a user