MPP: Support multiple 'expectedBy' dependencies for single module

#KT-22865 Fixed
This commit is contained in:
Alexey Sedunov
2018-02-20 19:26:24 +03:00
parent e3a69d118f
commit d9aa1796cd
22 changed files with 197 additions and 108 deletions
@@ -49,8 +49,8 @@ var DataNode<ModuleData>.coroutines
by CopyableDataNodeUserDataProperty(Key.create<String>("KOTLIN_COROUTINES"))
var DataNode<ModuleData>.platformPluginId
by CopyableDataNodeUserDataProperty(Key.create<String>("PLATFORM_PLUGIN_ID"))
var DataNode<out ModuleData>.implementedModuleName
by CopyableDataNodeUserDataProperty(Key.create<String>("IMPLEMENTED_MODULE_NAME"))
var DataNode<out ModuleData>.implementedModuleNames
by NotNullableCopyableDataNodeUserDataProperty(Key.create<List<String>>("IMPLEMENTED_MODULE_NAME"), emptyList())
class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension() {
val isAndroidProjectKey = Key.findKeyByName("IS_ANDROID_PROJECT_KEY")
@@ -134,23 +134,23 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension()
gradleIdeaProject.modules.firstOrNull { it.gradleProject.path == moduleNodeForGradleModel?.data?.id }
}
else gradleModule
val implementsModuleId = resolverCtx.getExtraProject(ideaModule, KotlinGradleModel::class.java)?.implements
val implementsModuleIds = resolverCtx.getExtraProject(ideaModule, KotlinGradleModel::class.java)?.implements
?: emptyList()
val targetModule = implementsModuleId?.let {
for (implementsModuleId in implementsModuleIds) {
val compositePrefix = if (resolverCtx.models.ideaProject != gradleModule.project
&& it.startsWith(":")) {
&& implementsModuleId.startsWith(":")) {
gradleModule.project.name
} else {
""
}
findModuleById(ideProject, compositePrefix + it)
}
if (targetModule != null) {
val targetModule = findModuleById(ideProject, compositePrefix + implementsModuleId) ?: continue
if (useModulePerSourceSet()) {
val targetSourceSetsByName = ExternalSystemApiUtil
.findAll(targetModule, GradleSourceSetData.KEY)
.associateBy { it.sourceSetName }
.findAll(targetModule, GradleSourceSetData.KEY)
.associateBy { it.sourceSetName }
val targetMainSourceSet = targetSourceSetsByName["main"] ?: targetModule
val targetSourceSet = targetSourceSetsByName[currentModuleNode.sourceSetName]
if (targetSourceSet != null) {
@@ -193,17 +193,15 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension()
ideProject: DataNode<ProjectData>,
gradleModel: KotlinGradleModel
) {
val implementedModule = gradleModel.implements?.let { findModuleById(ideProject, it) } ?: return
val implementedModules = gradleModel.implements.mapNotNull { findModuleById(ideProject, it) }
if (resolverCtx.isResolveModulePerSourceSet) {
val dependentSourceSets = dependentModule.getSourceSetsMap()
val implementedSourceSets = implementedModule.getSourceSetsMap()
val implementedSourceSetMaps = implementedModules.map { it.getSourceSetsMap() }
for ((sourceSetName, dependentSourceSet) in dependentSourceSets) {
val implementedSourceSet = implementedSourceSets[sourceSetName] ?: continue
dependentSourceSet.implementedModuleName = implementedSourceSet.data.internalName
dependentSourceSet.implementedModuleNames = implementedSourceSetMaps.mapNotNull { it[sourceSetName]?.data?.internalName }
}
}
else {
dependentModule.implementedModuleName = implementedModule.data.internalName
} else {
dependentModule.implementedModuleNames = implementedModules.map { it.data.internalName }
}
}
@@ -214,7 +214,7 @@ private fun configureFacetByGradleModule(
}
with(kotlinFacet.configuration.settings) {
implementedModuleName = (sourceSetNode ?: moduleNode).implementedModuleName
implementedModuleNames = (sourceSetNode ?: moduleNode).implementedModuleNames
productionOutputPath = getExplicitOutputPath(moduleNode, platformKind, "main")
testOutputPath = getExplicitOutputPath(moduleNode, platformKind, "test")
}
@@ -175,5 +175,5 @@ class MultiplatformGradleOrderEnumeratorHandler(val factory: MultiplatformGradle
private fun Module.isMultiplatformModule(): Boolean {
val settings = KotlinFacetSettingsProvider.getInstance(project).getInitializedSettings(this)
return settings.targetPlatformKind is TargetPlatformKind.Common || settings.implementedModuleName != null
return settings.targetPlatformKind is TargetPlatformKind.Common || settings.implementedModuleNames.isNotEmpty()
}
@@ -17,14 +17,12 @@
package org.jetbrains.kotlin.gradle
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.util.text.StringUtil
import com.intellij.util.PathUtil
import junit.framework.TestCase
import org.jetbrains.kotlin.idea.codeInsight.gradle.GradleImportingTestCase
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.junit.Test
import java.io.File
class MultiplatformProjectImportingTest : GradleImportingTestCase() {
@Test
@@ -74,9 +72,9 @@ class MultiplatformProjectImportingTest : GradleImportingTestCase() {
@Test
fun testPlatformToCommonExpectedByDependency() {
createProjectSubFile("settings.gradle", "include ':common', ':jvm', ':js'")
createProjectSubFile("settings.gradle", "include ':common1', ':common2', ':jvm', ':js'")
val kotlinVersion = "1.2.0-beta-74"
val kotlinVersion = "1.2.40-dev-610"
createProjectSubFile("build.gradle", """
buildscript {
@@ -90,7 +88,11 @@ class MultiplatformProjectImportingTest : GradleImportingTestCase() {
}
}
project('common') {
project('common1') {
apply plugin: 'kotlin-platform-common'
}
project('common2') {
apply plugin: 'kotlin-platform-common'
}
@@ -98,7 +100,8 @@ class MultiplatformProjectImportingTest : GradleImportingTestCase() {
apply plugin: 'kotlin-platform-jvm'
dependencies {
expectedBy project(':common')
expectedBy project(':common1')
expectedBy project(':common2')
}
}
@@ -106,16 +109,20 @@ class MultiplatformProjectImportingTest : GradleImportingTestCase() {
apply plugin: 'kotlin-platform-js'
dependencies {
expectedBy project(':common')
expectedBy project(':common1')
}
}
""")
importProject()
assertModuleModuleDepScope("jvm_main", "common_main", DependencyScope.COMPILE)
assertModuleModuleDepScope("jvm_test", "common_test", DependencyScope.COMPILE)
assertModuleModuleDepScope("js_main", "common_main", DependencyScope.COMPILE)
assertModuleModuleDepScope("js_test", "common_test", DependencyScope.COMPILE)
assertModuleModuleDepScope("jvm_main", "common1_main", DependencyScope.COMPILE)
assertModuleModuleDepScope("jvm_main", "common2_main", DependencyScope.COMPILE)
assertModuleModuleDepScope("jvm_test", "common1_test", DependencyScope.COMPILE)
assertModuleModuleDepScope("jvm_test", "common2_test", DependencyScope.COMPILE)
assertModuleModuleDepScope("js_main", "common1_main", DependencyScope.COMPILE)
assertModuleModuleDepScope("js_test", "common1_test", DependencyScope.COMPILE)
assertNoDepForModule("js_main", "common2_main")
assertNoDepForModule("js_test", "common2_test")
}
@Test
@@ -128,6 +128,10 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest
expectedScopes, actualScopes);
}
protected void assertNoDepForModule(String moduleName, String depName) {
assertEmpty("No dependency '" + depName + "' was expected", collectModuleDeps(moduleName, depName, ModuleOrderEntry.class));
}
@NotNull
private List<ModuleOrderEntry> getModuleModuleDeps(@NotNull String moduleName, @NotNull String depName) {
return getModuleDep(moduleName, depName, ModuleOrderEntry.class);
@@ -139,6 +143,14 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest
@NotNull
private <T> List<T> getModuleDep(@NotNull String moduleName, @NotNull String depName, @NotNull Class<T> clazz) {
List<T> deps = collectModuleDeps(moduleName, depName, clazz);
assertTrue("Dependency '" + depName + "' for module '" + moduleName + "' not found among: " + collectModuleDepsNames(moduleName, clazz),
!deps.isEmpty());
return deps;
}
@NotNull
private <T> List<T> collectModuleDeps(@NotNull String moduleName, @NotNull String depName, @NotNull Class<T> clazz) {
List<T> deps = ContainerUtil.newArrayList();
for (OrderEntry e : getRootManager(moduleName).getOrderEntries()) {
@@ -146,8 +158,7 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest
deps.add((T)e);
}
}
assertTrue("Dependency '" + depName + "' for module '" + moduleName + "' not found among: " + collectModuleDepsNames(moduleName, clazz),
!deps.isEmpty());
return deps;
}
@@ -1481,10 +1481,10 @@ compileTestKotlin {
importProject()
Assert.assertEquals("MultiTest_main", facetSettings("MultiTest-jvm_main").implementedModuleName)
Assert.assertEquals("MultiTest_test", facetSettings("MultiTest-jvm_test").implementedModuleName)
Assert.assertEquals("MultiTest_main", facetSettings("MultiTest-js_main").implementedModuleName)
Assert.assertEquals("MultiTest_test", facetSettings("MultiTest-js_test").implementedModuleName)
Assert.assertEquals(listOf("MultiTest_main"), facetSettings("MultiTest-jvm_main").implementedModuleNames)
Assert.assertEquals(listOf("MultiTest_test"), facetSettings("MultiTest-jvm_test").implementedModuleNames)
Assert.assertEquals(listOf("MultiTest_main"), facetSettings("MultiTest-js_main").implementedModuleNames)
Assert.assertEquals(listOf("MultiTest_test"), facetSettings("MultiTest-js_test").implementedModuleNames)
}
@Test
@@ -1630,10 +1630,10 @@ compileTestKotlin {
importProject()
Assert.assertEquals("MultiTest_myMain", facetSettings("MultiTest-jvm_myMain").implementedModuleName)
Assert.assertEquals("MultiTest_myTest", facetSettings("MultiTest-jvm_myTest").implementedModuleName)
Assert.assertEquals("MultiTest_myMain", facetSettings("MultiTest-js_myMain").implementedModuleName)
Assert.assertEquals("MultiTest_myTest", facetSettings("MultiTest-js_myTest").implementedModuleName)
Assert.assertEquals(listOf("MultiTest_myMain"), facetSettings("MultiTest-jvm_myMain").implementedModuleNames)
Assert.assertEquals(listOf("MultiTest_myTest"), facetSettings("MultiTest-jvm_myTest").implementedModuleNames)
Assert.assertEquals(listOf("MultiTest_myMain"), facetSettings("MultiTest-js_myMain").implementedModuleNames)
Assert.assertEquals(listOf("MultiTest_myTest"), facetSettings("MultiTest-js_myTest").implementedModuleNames)
}
@Test