MPP: Support MPP-dependent Java modules in Android projects

#KT-27265 Fixed
This commit is contained in:
Alexey Sedunov
2018-10-04 20:53:15 +03:00
parent dcdd42ba00
commit fea397a2ad
4 changed files with 220 additions and 64 deletions
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.android.configure package org.jetbrains.kotlin.android.configure
import com.android.tools.idea.gradle.project.model.AndroidModuleModel import com.android.tools.idea.gradle.project.sync.idea.data.service.AndroidProjectKeys
import com.android.tools.idea.gradle.util.ContentEntries.findParentContentEntry import com.android.tools.idea.gradle.util.ContentEntries.findParentContentEntry
import com.android.tools.idea.io.FilePaths import com.android.tools.idea.io.FilePaths
import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.Logger
@@ -20,6 +20,7 @@ import com.intellij.openapi.externalSystem.service.project.manage.ContentRootDat
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.module.Module import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.ModifiableRootModel import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VfsUtil
import com.intellij.util.SmartList import com.intellij.util.SmartList
@@ -78,7 +79,9 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
} }
val androidModel = module.getAndroidModel(modelsProvider) ?: continue addExtraDependeeModules(nodeToImport, projectNode, modelsProvider, rootModel, false)
addExtraDependeeModules(nodeToImport, projectNode, modelsProvider, rootModel, true)
val androidModel = getAndroidModuleModel(nodeToImport) ?: continue
val variantName = androidModel.selectedVariant.name val variantName = androidModel.selectedVariant.name
val activeSourceSetInfos = nodeToImport.kotlinAndroidSourceSets?.filter { it.kotlinModule.name.startsWith(variantName) } ?: emptyList() val activeSourceSetInfos = nodeToImport.kotlinAndroidSourceSets?.filter { it.kotlinModule.name.startsWith(variantName) } ?: emptyList()
for (activeSourceSetInfo in activeSourceSetInfos) { for (activeSourceSetInfo in activeSourceSetInfos) {
@@ -94,8 +97,6 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
} }
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, false)
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, true)
val mainSourceSetInfo = activeSourceSetInfos.firstOrNull { it.kotlinModule.name == variantName } val mainSourceSetInfo = activeSourceSetInfos.firstOrNull { it.kotlinModule.name == variantName }
if (mainSourceSetInfo != null) { if (mainSourceSetInfo != null) {
@@ -109,32 +110,64 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
private fun getDependeeModuleNodes(
moduleNode: DataNode<ModuleData>,
projectNode: DataNode<ProjectData>,
modelsProvider: IdeModifiableModelsProvider,
testScope: Boolean
): List<DataNode<out ModuleData>> {
val androidModel = getAndroidModuleModel(moduleNode)
if (androidModel != null) {
val dependencies = if (testScope) {
androidModel.selectedAndroidTestCompileDependencies
} else {
androidModel.selectedMainCompileLevel2Dependencies
} ?: return emptyList()
return dependencies
.moduleDependencies
.mapNotNull { projectNode.findChildModuleById(it.projectPath) }
}
val javaModel = getJavaModuleModel(moduleNode)
if (javaModel != null) {
val scope = if (testScope) DependencyScope.TEST.name else DependencyScope.COMPILE.name
val moduleNames = javaModel
.javaModuleDependencies
.filter { scope == it.scope ?: DependencyScope.COMPILE.name }
.mapTo(HashSet()) { it.moduleName }
return ExternalSystemApiUtil
.getChildren(projectNode, ProjectKeys.MODULE)
.filter { modelsProvider.findIdeModule(it.data)?.name in moduleNames }
}
return emptyList()
}
private fun List<DataNode<GradleSourceSetData>>.firstByPlatformOrNull(platform: KotlinPlatform) = firstOrNull {
it.kotlinSourceSet?.platform == platform
}
private fun addExtraDependeeModules( private fun addExtraDependeeModules(
androidModel: AndroidModuleModel, moduleNode: DataNode<ModuleData>,
projectNode: DataNode<ProjectData>, projectNode: DataNode<ProjectData>,
modelsProvider: IdeModifiableModelsProvider, modelsProvider: IdeModifiableModelsProvider,
rootModel: ModifiableRootModel, rootModel: ModifiableRootModel,
testScope: Boolean testScope: Boolean
) { ) {
val dependencies = if (testScope) { val dependeeModuleNodes = getDependeeModuleNodes(moduleNode, projectNode, modelsProvider, testScope)
androidModel.selectedAndroidTestCompileDependencies val relevantNodes = dependeeModuleNodes
} else {
androidModel.selectedMainCompileLevel2Dependencies
} ?: return
val commonSourceSetName = KotlinSourceSet.commonName(testScope)
val relevantNodes = dependencies
.moduleDependencies
.mapNotNull { projectNode.findChildModuleById(it.projectPath) }
.flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) } .flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) }
.filter { .filter {
val ktModule = it.kotlinSourceSet?.kotlinModule val ktModule = it.kotlinSourceSet?.kotlinModule
ktModule != null && ktModule.isTestModule == testScope ktModule != null && ktModule.isTestModule == testScope
} }
val commonSourceSetName = KotlinSourceSet.commonName(testScope)
val isAndroidModule = getAndroidModuleModel(moduleNode) != null
SmartList<DataNode<GradleSourceSetData>>() SmartList<DataNode<GradleSourceSetData>>()
.apply { .apply {
addIfNotNull( addIfNotNull(
relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.ANDROID } (if (isAndroidModule) relevantNodes.firstByPlatformOrNull(KotlinPlatform.ANDROID) else null)
?: relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.JVM } ?: relevantNodes.firstByPlatformOrNull(KotlinPlatform.JVM)
) )
addIfNotNull( addIfNotNull(
relevantNodes.firstOrNull { relevantNodes.firstOrNull {
@@ -152,6 +185,12 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
private fun getAndroidModuleModel(moduleNode: DataNode<ModuleData>) =
ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.ANDROID_MODEL).firstOrNull()?.data
private fun getJavaModuleModel(moduleNode: DataNode<ModuleData>) =
ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.JAVA_MODULE_MODEL).firstOrNull()?.data
private fun addSourceRoot( private fun addSourceRoot(
sourceRoot: File, sourceRoot: File,
type: JpsModuleSourceRootType<*>, type: JpsModuleSourceRootType<*>,
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.android.configure package org.jetbrains.kotlin.android.configure
import com.android.tools.idea.gradle.project.model.AndroidModuleModel import com.android.tools.idea.gradle.project.sync.idea.data.service.AndroidProjectKeys
import com.android.tools.idea.gradle.util.ContentEntries.findParentContentEntry import com.android.tools.idea.gradle.util.ContentEntries.findParentContentEntry
import com.android.tools.idea.gradle.util.FilePaths import com.android.tools.idea.gradle.util.FilePaths
import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.Logger
@@ -20,6 +20,7 @@ import com.intellij.openapi.externalSystem.service.project.manage.ContentRootDat
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.module.Module import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.ModifiableRootModel import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VfsUtil
import com.intellij.util.SmartList import com.intellij.util.SmartList
@@ -78,7 +79,9 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
} }
val androidModel = module.getAndroidModel(modelsProvider) ?: continue addExtraDependeeModules(nodeToImport, projectNode, modelsProvider, rootModel, false)
addExtraDependeeModules(nodeToImport, projectNode, modelsProvider, rootModel, true)
val androidModel = getAndroidModuleModel(nodeToImport) ?: continue
val variantName = androidModel.selectedVariant.name val variantName = androidModel.selectedVariant.name
val activeSourceSetInfos = nodeToImport.kotlinAndroidSourceSets?.filter { it.kotlinModule.name.startsWith(variantName) } ?: emptyList() val activeSourceSetInfos = nodeToImport.kotlinAndroidSourceSets?.filter { it.kotlinModule.name.startsWith(variantName) } ?: emptyList()
for (activeSourceSetInfo in activeSourceSetInfos) { for (activeSourceSetInfo in activeSourceSetInfos) {
@@ -94,8 +97,6 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
} }
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, false)
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, true)
val mainSourceSetInfo = activeSourceSetInfos.firstOrNull { it.kotlinModule.name == variantName } val mainSourceSetInfo = activeSourceSetInfos.firstOrNull { it.kotlinModule.name == variantName }
if (mainSourceSetInfo != null) { if (mainSourceSetInfo != null) {
@@ -109,32 +110,64 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
private fun getDependeeModuleNodes(
moduleNode: DataNode<ModuleData>,
projectNode: DataNode<ProjectData>,
modelsProvider: IdeModifiableModelsProvider,
testScope: Boolean
): List<DataNode<out ModuleData>> {
val androidModel = getAndroidModuleModel(moduleNode)
if (androidModel != null) {
val dependencies = if (testScope) {
androidModel.selectedAndroidTestCompileDependencies
} else {
androidModel.selectedMainCompileLevel2Dependencies
} ?: return emptyList()
return dependencies
.moduleDependencies
.mapNotNull { projectNode.findChildModuleById(it.projectPath) }
}
val javaModel = getJavaModuleModel(moduleNode)
if (javaModel != null) {
val scope = if (testScope) DependencyScope.TEST.name else DependencyScope.COMPILE.name
val moduleNames = javaModel
.javaModuleDependencies
.filter { scope == it.scope ?: DependencyScope.COMPILE.name }
.mapTo(HashSet()) { it.moduleName }
return ExternalSystemApiUtil
.getChildren(projectNode, ProjectKeys.MODULE)
.filter { modelsProvider.findIdeModule(it.data)?.name in moduleNames }
}
return emptyList()
}
private fun List<DataNode<GradleSourceSetData>>.firstByPlatformOrNull(platform: KotlinPlatform) = firstOrNull {
it.kotlinSourceSet?.platform == platform
}
private fun addExtraDependeeModules( private fun addExtraDependeeModules(
androidModel: AndroidModuleModel, moduleNode: DataNode<ModuleData>,
projectNode: DataNode<ProjectData>, projectNode: DataNode<ProjectData>,
modelsProvider: IdeModifiableModelsProvider, modelsProvider: IdeModifiableModelsProvider,
rootModel: ModifiableRootModel, rootModel: ModifiableRootModel,
testScope: Boolean testScope: Boolean
) { ) {
val dependencies = if (testScope) { val dependeeModuleNodes = getDependeeModuleNodes(moduleNode, projectNode, modelsProvider, testScope)
androidModel.selectedAndroidTestCompileDependencies val relevantNodes = dependeeModuleNodes
} else {
androidModel.selectedMainCompileLevel2Dependencies
} ?: return
val commonSourceSetName = KotlinSourceSet.commonName(testScope)
val relevantNodes = dependencies
.moduleDependencies
.mapNotNull { projectNode.findChildModuleById(it.projectPath) }
.flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) } .flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) }
.filter { .filter {
val ktModule = it.kotlinSourceSet?.kotlinModule val ktModule = it.kotlinSourceSet?.kotlinModule
ktModule != null && ktModule.isTestModule == testScope ktModule != null && ktModule.isTestModule == testScope
} }
val commonSourceSetName = KotlinSourceSet.commonName(testScope)
val isAndroidModule = getAndroidModuleModel(moduleNode) != null
SmartList<DataNode<GradleSourceSetData>>() SmartList<DataNode<GradleSourceSetData>>()
.apply { .apply {
addIfNotNull( addIfNotNull(
relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.ANDROID } (if (isAndroidModule) relevantNodes.firstByPlatformOrNull(KotlinPlatform.ANDROID) else null)
?: relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.JVM } ?: relevantNodes.firstByPlatformOrNull(KotlinPlatform.JVM)
) )
addIfNotNull( addIfNotNull(
relevantNodes.firstOrNull { relevantNodes.firstOrNull {
@@ -152,6 +185,12 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
private fun getAndroidModuleModel(moduleNode: DataNode<ModuleData>) =
ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.ANDROID_MODEL).firstOrNull()?.data
private fun getJavaModuleModel(moduleNode: DataNode<ModuleData>) =
ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.JAVA_MODULE_MODEL).firstOrNull()?.data
private fun addSourceRoot( private fun addSourceRoot(
sourceRoot: File, sourceRoot: File,
type: JpsModuleSourceRootType<*>, type: JpsModuleSourceRootType<*>,
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.android.configure package org.jetbrains.kotlin.android.configure
import com.android.tools.idea.gradle.project.model.AndroidModuleModel import com.android.tools.idea.gradle.project.sync.idea.data.service.AndroidProjectKeys
import com.android.tools.idea.gradle.util.ContentEntries.findParentContentEntry import com.android.tools.idea.gradle.util.ContentEntries.findParentContentEntry
import com.android.tools.idea.io.FilePaths import com.android.tools.idea.io.FilePaths
import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.Logger
@@ -22,6 +22,7 @@ import com.intellij.openapi.externalSystem.service.project.manage.ContentRootDat
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.module.Module import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.ModifiableRootModel import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VfsUtil
import com.intellij.util.SmartList import com.intellij.util.SmartList
@@ -89,7 +90,9 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
} }
val androidModel = module.getAndroidModel(modelsProvider) ?: continue addExtraDependeeModules(nodeToImport, projectNode, modelsProvider, rootModel, false)
addExtraDependeeModules(nodeToImport, projectNode, modelsProvider, rootModel, true)
val androidModel = getAndroidModuleModel(nodeToImport) ?: continue
val variantName = androidModel.selectedVariant.name val variantName = androidModel.selectedVariant.name
val activeSourceSetInfos = nodeToImport.kotlinAndroidSourceSets?.filter { it.kotlinModule.name.startsWith(variantName) } ?: emptyList() val activeSourceSetInfos = nodeToImport.kotlinAndroidSourceSets?.filter { it.kotlinModule.name.startsWith(variantName) } ?: emptyList()
for (activeSourceSetInfo in activeSourceSetInfos) { for (activeSourceSetInfo in activeSourceSetInfos) {
@@ -105,8 +108,6 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
} }
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, false)
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, true)
val mainSourceSetInfo = activeSourceSetInfos.firstOrNull { it.kotlinModule.name == variantName } val mainSourceSetInfo = activeSourceSetInfos.firstOrNull { it.kotlinModule.name == variantName }
if (mainSourceSetInfo != null) { if (mainSourceSetInfo != null) {
@@ -120,32 +121,64 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
private fun getDependeeModuleNodes(
moduleNode: DataNode<ModuleData>,
projectNode: DataNode<ProjectData>,
modelsProvider: IdeModifiableModelsProvider,
testScope: Boolean
): List<DataNode<out ModuleData>> {
val androidModel = getAndroidModuleModel(moduleNode)
if (androidModel != null) {
val dependencies = if (testScope) {
androidModel.selectedAndroidTestCompileDependencies
} else {
androidModel.selectedMainCompileLevel2Dependencies
} ?: return emptyList()
return dependencies
.moduleDependencies
.mapNotNull { projectNode.findChildModuleById(it.projectPath) }
}
val javaModel = getJavaModuleModel(moduleNode)
if (javaModel != null) {
val scope = if (testScope) DependencyScope.TEST.name else DependencyScope.COMPILE.name
val moduleNames = javaModel
.javaModuleDependencies
.filter { scope == it.scope ?: DependencyScope.COMPILE.name }
.mapTo(HashSet()) { it.moduleName }
return ExternalSystemApiUtil
.getChildren(projectNode, ProjectKeys.MODULE)
.filter { modelsProvider.findIdeModule(it.data)?.name in moduleNames }
}
return emptyList()
}
private fun List<DataNode<GradleSourceSetData>>.firstByPlatformOrNull(platform: KotlinPlatform) = firstOrNull {
it.kotlinSourceSet?.platform == platform
}
private fun addExtraDependeeModules( private fun addExtraDependeeModules(
androidModel: AndroidModuleModel, moduleNode: DataNode<ModuleData>,
projectNode: DataNode<ProjectData>, projectNode: DataNode<ProjectData>,
modelsProvider: IdeModifiableModelsProvider, modelsProvider: IdeModifiableModelsProvider,
rootModel: ModifiableRootModel, rootModel: ModifiableRootModel,
testScope: Boolean testScope: Boolean
) { ) {
val dependencies = if (testScope) { val dependeeModuleNodes = getDependeeModuleNodes(moduleNode, projectNode, modelsProvider, testScope)
androidModel.selectedAndroidTestCompileDependencies val relevantNodes = dependeeModuleNodes
} else {
androidModel.selectedMainCompileLevel2Dependencies
} ?: return
val commonSourceSetName = KotlinSourceSet.commonName(testScope)
val relevantNodes = dependencies
.moduleDependencies
.mapNotNull { projectNode.findChildModuleById(it.projectPath) }
.flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) } .flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) }
.filter { .filter {
val ktModule = it.kotlinSourceSet?.kotlinModule val ktModule = it.kotlinSourceSet?.kotlinModule
ktModule != null && ktModule.isTestModule == testScope ktModule != null && ktModule.isTestModule == testScope
} }
val commonSourceSetName = KotlinSourceSet.commonName(testScope)
val isAndroidModule = getAndroidModuleModel(moduleNode) != null
SmartList<DataNode<GradleSourceSetData>>() SmartList<DataNode<GradleSourceSetData>>()
.apply { .apply {
addIfNotNull( addIfNotNull(
relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.ANDROID } (if (isAndroidModule) relevantNodes.firstByPlatformOrNull(KotlinPlatform.ANDROID) else null)
?: relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.JVM } ?: relevantNodes.firstByPlatformOrNull(KotlinPlatform.JVM)
) )
addIfNotNull( addIfNotNull(
relevantNodes.firstOrNull { relevantNodes.firstOrNull {
@@ -163,6 +196,12 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
private fun getAndroidModuleModel(moduleNode: DataNode<ModuleData>) =
ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.ANDROID_MODEL).firstOrNull()?.data
private fun getJavaModuleModel(moduleNode: DataNode<ModuleData>) =
ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.JAVA_MODULE_MODEL).firstOrNull()?.data
private fun addSourceRoot( private fun addSourceRoot(
sourceRoot: File, sourceRoot: File,
type: JpsModuleSourceRootType<*>, type: JpsModuleSourceRootType<*>,
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.android.configure package org.jetbrains.kotlin.android.configure
import com.android.tools.idea.gradle.project.model.AndroidModuleModel import com.android.tools.idea.gradle.project.sync.idea.data.service.AndroidProjectKeys
import com.android.tools.idea.gradle.util.ContentEntries.findParentContentEntry import com.android.tools.idea.gradle.util.ContentEntries.findParentContentEntry
import com.android.tools.idea.io.FilePaths import com.android.tools.idea.io.FilePaths
import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.Logger
@@ -20,6 +20,7 @@ import com.intellij.openapi.externalSystem.service.project.manage.ContentRootDat
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.module.Module import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.ModifiableRootModel import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VfsUtil
import com.intellij.util.SmartList import com.intellij.util.SmartList
@@ -78,7 +79,9 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
} }
val androidModel = module.getAndroidModel(modelsProvider) ?: continue addExtraDependeeModules(nodeToImport, projectNode, modelsProvider, rootModel, false)
addExtraDependeeModules(nodeToImport, projectNode, modelsProvider, rootModel, true)
val androidModel = getAndroidModuleModel(nodeToImport) ?: continue
val variantName = androidModel.selectedVariant.name val variantName = androidModel.selectedVariant.name
val activeSourceSetInfos = nodeToImport.kotlinAndroidSourceSets?.filter { it.kotlinModule.name.startsWith(variantName) } ?: emptyList() val activeSourceSetInfos = nodeToImport.kotlinAndroidSourceSets?.filter { it.kotlinModule.name.startsWith(variantName) } ?: emptyList()
for (activeSourceSetInfo in activeSourceSetInfos) { for (activeSourceSetInfo in activeSourceSetInfos) {
@@ -94,8 +97,6 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
} }
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, false)
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, true)
val mainSourceSetInfo = activeSourceSetInfos.firstOrNull { it.kotlinModule.name == variantName } val mainSourceSetInfo = activeSourceSetInfos.firstOrNull { it.kotlinModule.name == variantName }
if (mainSourceSetInfo != null) { if (mainSourceSetInfo != null) {
@@ -109,32 +110,64 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
private fun getDependeeModuleNodes(
moduleNode: DataNode<ModuleData>,
projectNode: DataNode<ProjectData>,
modelsProvider: IdeModifiableModelsProvider,
testScope: Boolean
): List<DataNode<out ModuleData>> {
val androidModel = getAndroidModuleModel(moduleNode)
if (androidModel != null) {
val dependencies = if (testScope) {
androidModel.selectedAndroidTestCompileDependencies
} else {
androidModel.selectedMainCompileLevel2Dependencies
} ?: return emptyList()
return dependencies
.moduleDependencies
.mapNotNull { projectNode.findChildModuleById(it.projectPath) }
}
val javaModel = getJavaModuleModel(moduleNode)
if (javaModel != null) {
val scope = if (testScope) DependencyScope.TEST.name else DependencyScope.COMPILE.name
val moduleNames = javaModel
.javaModuleDependencies
.filter { scope == it.scope ?: DependencyScope.COMPILE.name }
.mapTo(HashSet()) { it.moduleName }
return ExternalSystemApiUtil
.getChildren(projectNode, ProjectKeys.MODULE)
.filter { modelsProvider.findIdeModule(it.data)?.name in moduleNames }
}
return emptyList()
}
private fun List<DataNode<GradleSourceSetData>>.firstByPlatformOrNull(platform: KotlinPlatform) = firstOrNull {
it.kotlinSourceSet?.platform == platform
}
private fun addExtraDependeeModules( private fun addExtraDependeeModules(
androidModel: AndroidModuleModel, moduleNode: DataNode<ModuleData>,
projectNode: DataNode<ProjectData>, projectNode: DataNode<ProjectData>,
modelsProvider: IdeModifiableModelsProvider, modelsProvider: IdeModifiableModelsProvider,
rootModel: ModifiableRootModel, rootModel: ModifiableRootModel,
testScope: Boolean testScope: Boolean
) { ) {
val dependencies = if (testScope) { val dependeeModuleNodes = getDependeeModuleNodes(moduleNode, projectNode, modelsProvider, testScope)
androidModel.selectedAndroidTestCompileDependencies val relevantNodes = dependeeModuleNodes
} else {
androidModel.selectedMainCompileLevel2Dependencies
} ?: return
val commonSourceSetName = KotlinSourceSet.commonName(testScope)
val relevantNodes = dependencies
.moduleDependencies
.mapNotNull { projectNode.findChildModuleById(it.projectPath) }
.flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) } .flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) }
.filter { .filter {
val ktModule = it.kotlinSourceSet?.kotlinModule val ktModule = it.kotlinSourceSet?.kotlinModule
ktModule != null && ktModule.isTestModule == testScope ktModule != null && ktModule.isTestModule == testScope
} }
val commonSourceSetName = KotlinSourceSet.commonName(testScope)
val isAndroidModule = getAndroidModuleModel(moduleNode) != null
SmartList<DataNode<GradleSourceSetData>>() SmartList<DataNode<GradleSourceSetData>>()
.apply { .apply {
addIfNotNull( addIfNotNull(
relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.ANDROID } (if (isAndroidModule) relevantNodes.firstByPlatformOrNull(KotlinPlatform.ANDROID) else null)
?: relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.JVM } ?: relevantNodes.firstByPlatformOrNull(KotlinPlatform.JVM)
) )
addIfNotNull( addIfNotNull(
relevantNodes.firstOrNull { relevantNodes.firstOrNull {
@@ -152,6 +185,12 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
} }
} }
private fun getAndroidModuleModel(moduleNode: DataNode<ModuleData>) =
ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.ANDROID_MODEL).firstOrNull()?.data
private fun getJavaModuleModel(moduleNode: DataNode<ModuleData>) =
ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.JAVA_MODULE_MODEL).firstOrNull()?.data
private fun addSourceRoot( private fun addSourceRoot(
sourceRoot: File, sourceRoot: File,
type: JpsModuleSourceRootType<*>, type: JpsModuleSourceRootType<*>,