Gradle: Import project dependency with non-default configuration by its artifacts

This commit is contained in:
Alexey Sedunov
2018-04-18 17:10:23 +03:00
parent 2a684684a5
commit 36975786e8
3 changed files with 135 additions and 13 deletions
@@ -25,6 +25,7 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.io.FileUtil
import org.gradle.api.artifacts.Dependency
import org.gradle.tooling.model.idea.IdeaModule
import org.jetbrains.kotlin.gradle.CompilerArgumentsBySourceSet
import org.jetbrains.kotlin.gradle.KotlinGradleModel
@@ -37,6 +38,7 @@ import org.jetbrains.plugins.gradle.model.FileCollectionDependency
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolver
import java.io.File
import java.util.*
var DataNode<ModuleData>.isResolved
@@ -84,6 +86,14 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension()
val gradleIdeaProject = gradleModule.project
fun getDependencyByFiles(files: Collection<File>) = files
.mapTo(HashSet()) {
val path = FileUtil.toSystemIndependentName(it.path)
val targetSourceSetId = outputToSourceSet?.get(path)?.first ?: return@mapTo null
sourceSetByName?.get(targetSourceSetId)?.first
}
.singleOrNull()
fun DataNode<out ModuleData>.getDependencies(): Collection<DataNode<out ModuleData>> {
if (useModulePerSourceSet()) {
if (sourceSetByName == null) return emptySet()
@@ -91,20 +101,18 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension()
return externalSourceSet.dependencies.mapNotNullTo(LinkedHashSet()) { dependency ->
when (dependency) {
is ExternalProjectDependency -> {
val targetModuleNode = ExternalSystemApiUtil.findFirstRecursively(ideProject) {
(it.data as? ModuleData)?.id == dependency.projectPath
} as DataNode<ModuleData>? ?: return@mapNotNullTo null
ExternalSystemApiUtil.findAll(targetModuleNode, GradleSourceSetData.KEY)
.firstOrNull { it.sourceSetName == "main" }
if (dependency.configurationName == Dependency.DEFAULT_CONFIGURATION) {
val targetModuleNode = ExternalSystemApiUtil.findFirstRecursively(ideProject) {
(it.data as? ModuleData)?.id == dependency.projectPath
} as DataNode<ModuleData>? ?: return@mapNotNullTo null
ExternalSystemApiUtil.findAll(targetModuleNode, GradleSourceSetData.KEY)
.firstOrNull { it.sourceSetName == "main" }
} else {
getDependencyByFiles(dependency.projectDependencyArtifacts)
}
}
is FileCollectionDependency -> {
dependency.files
.mapTo(HashSet()) {
val path = FileUtil.toSystemIndependentName(it.path)
val targetSourceSetId = outputToSourceSet?.get(path)?.first ?: return@mapTo null
sourceSetByName[targetSourceSetId]?.first
}
.singleOrNull()
getDependencyByFiles(dependency.files)
}
else -> null
}
@@ -17,6 +17,8 @@
package org.jetbrains.kotlin.gradle
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.LibraryOrderEntry
import com.intellij.openapi.roots.OrderRootType
import com.intellij.util.PathUtil
import junit.framework.TestCase
import org.jetbrains.kotlin.idea.codeInsight.gradle.GradleImportingTestCase
@@ -26,6 +28,12 @@ import org.jetbrains.kotlin.test.KotlinTestUtils
import org.junit.Test
class MultiplatformProjectImportingTest : GradleImportingTestCase() {
private fun getDependencyLibraryUrls(moduleName: String) =
getRootManager(moduleName)
.orderEntries
.filterIsInstance<LibraryOrderEntry>()
.flatMap { it.getUrls(OrderRootType.CLASSES).map { it.replace(projectPath, "") } }
@Test
fun testPlatformToCommonDependency() {
createProjectSubFile("settings.gradle", "include ':common', ':jvm', ':js'")
@@ -492,6 +500,112 @@ class MultiplatformProjectImportingTest : GradleImportingTestCase() {
}
}
@Test
fun testTransitiveImplementWithNonDefaultConfig() {
createProjectSubFile(
"settings.gradle",
"include ':project1', ':project2', ':project3'"
)
val kotlinVersion = "1.2.31"
createProjectSubFile(
"build.gradle", """
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
}
}
project('project1') {
apply plugin: 'kotlin-platform-common'
}
project('project2') {
repositories {
mavenCentral()
}
apply plugin: 'kotlin-platform-jvm'
sourceSets {
main
main2
}
task myJar(type: Jar) {
baseName = 'project2-jar'
from sourceSets.main.output
from sourceSets.main2.output
}
configurations {
myConfig
}
artifacts {
myConfig myJar
}
dependencies {
implement project(':project1')
}
}
project('project3') {
repositories {
mavenCentral()
}
apply plugin: 'kotlin-platform-jvm'
apply plugin: 'kotlin'
dependencies {
compile(project(path: ':project2', configuration: 'myConfig')) { transitive = false }
}
}
"""
)
val isResolveModulePerSourceSet = getCurrentExternalProjectSettings().isResolveModulePerSourceSet
try {
currentExternalProjectSettings.isResolveModulePerSourceSet = true
importProject()
assertModuleModuleDepScope("project2_main", "project1_main", DependencyScope.COMPILE)
assertModuleModuleDepScope("project3_main", "project2_main", DependencyScope.COMPILE)
assertNoDepForModule("project3_main", "project1_main")
TestCase.assertEquals(
listOf("jar:///project2/build/libs/project2-jar.jar!/"),
getDependencyLibraryUrls("project3_main")
)
currentExternalProjectSettings.isResolveModulePerSourceSet = false
importProject()
/*
* Note that currently such dependencies can't be imported correctly in "No separate module per source set" mode
* due to IDEA importer limitations
*/
assertModuleModuleDepScope("project2", "project1", DependencyScope.COMPILE)
assertModuleModuleDepScope("project3", "project2", DependencyScope.TEST, DependencyScope.PROVIDED, DependencyScope.RUNTIME)
assertModuleModuleDepScope("project3", "project1", DependencyScope.COMPILE)
TestCase.assertEquals(
emptyList<String>(),
getDependencyLibraryUrls("project3")
)
} finally {
currentExternalProjectSettings.isResolveModulePerSourceSet = isResolveModulePerSourceSet
}
}
@Test
fun testTransitiveImplementWithAndroid() {
createProjectSubFile(
@@ -138,7 +138,7 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest
return getModuleDep(moduleName, depName, ModuleOrderEntry.class);
}
private ModuleRootManager getRootManager(String module) {
protected ModuleRootManager getRootManager(String module) {
return ModuleRootManager.getInstance(getModule(module));
}