MPP: Add MPP sources roots to dependent Android module

#KT-27331 Fixed
This commit is contained in:
Alexey Sedunov
2018-10-01 18:41:06 +03:00
parent 62edf29cbf
commit b5d3520db9
5 changed files with 253 additions and 31 deletions
@@ -23,16 +23,18 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.util.SmartList
import com.intellij.util.containers.stream
import org.jetbrains.jps.model.java.JavaResourceRootType
import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
import org.jetbrains.kotlin.gradle.KotlinCompilation
import org.jetbrains.kotlin.gradle.KotlinPlatform
import org.jetbrains.kotlin.idea.configuration.GradleProjectImportHandler
import org.jetbrains.kotlin.idea.configuration.KotlinSourceSetDataService
import org.jetbrains.kotlin.idea.configuration.kotlinAndroidSourceSets
import org.jetbrains.kotlin.gradle.KotlinSourceSet
import org.jetbrains.kotlin.idea.configuration.*
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
import java.io.File
import java.io.IOException
@@ -88,13 +90,13 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
(it.data as? ModuleData)?.id == sourceSetId
}?.data as? ModuleData ?: continue
val sourceSetModule = modelsProvider.findIdeModule(sourceSetData) ?: continue
val existingEntry = rootModel.findModuleOrderEntry(sourceSetModule)
val dependencyScope = if (activeSourceSetInfo.isTestModule) DependencyScope.TEST else DependencyScope.COMPILE
if (existingEntry != null && existingEntry.scope == dependencyScope) continue
rootModel.addModuleOrderEntry(sourceSetModule).also { it.scope = dependencyScope }
addModuleDependencyIfNeeded(rootModel, sourceSetModule, activeSourceSetInfo.isTestModule)
}
}
}
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, false)
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, true)
val mainSourceSetInfo = activeSourceSetInfos.firstOrNull { it.kotlinModule.name == variantName }
if (mainSourceSetInfo != null) {
KotlinSourceSetDataService.configureFacet(moduleData, mainSourceSetInfo, nodeToImport, module, modelsProvider)
@@ -107,6 +109,60 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
}
}
private fun addModuleDependencyIfNeeded(
rootModel: ModifiableRootModel,
dependeeModule: Module,
testScope: Boolean
) {
val dependencyScope = if (testScope) DependencyScope.TEST else DependencyScope.COMPILE
val existingEntry = rootModel.findModuleOrderEntry(dependeeModule)
if (existingEntry != null && existingEntry.scope == dependencyScope) return
rootModel.addModuleOrderEntry(dependeeModule).also { it.scope = dependencyScope }
}
private fun addExtraDependeeModules(
androidModel: AndroidModuleModel,
projectNode: DataNode<ProjectData>,
modelsProvider: IdeModifiableModelsProvider,
rootModel: ModifiableRootModel,
testScope: Boolean
) {
val dependencies = if (testScope) {
androidModel.selectedAndroidTestCompileDependencies
} else {
androidModel.selectedMainCompileLevel2Dependencies
} ?: return
val commonSourceSetName = KotlinSourceSet.commonName(testScope)
val relevantNodes = dependencies
.moduleDependencies
.mapNotNull { projectNode.findChildModuleById(it.projectPath) }
.flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) }
.filter {
val ktModule = it.kotlinSourceSet?.kotlinModule
ktModule != null && ktModule.isTestModule == testScope
}
SmartList<DataNode<GradleSourceSetData>>()
.apply {
addIfNotNull(
relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.ANDROID }
?: relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.JVM }
)
addIfNotNull(
relevantNodes.firstOrNull {
it.kotlinSourceSet?.platform == KotlinPlatform.COMMON && it.kotlinSourceSet?.kotlinModule?.name == commonSourceSetName
}
)
}
.mapNotNull { modelsProvider.findIdeModule(it.data) }
.forEach {
addModuleDependencyIfNeeded(rootModel, it, testScope)
val dependeeRootModel = modelsProvider.getModifiableRootModel(it)
dependeeRootModel.getModuleDependencies(testScope).forEach { transitiveDependee ->
addModuleDependencyIfNeeded(rootModel, transitiveDependee, testScope)
}
}
}
private fun addSourceRoot(
sourceRoot: File,
type: JpsModuleSourceRootType<*>,
@@ -23,16 +23,18 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.util.SmartList
import com.intellij.util.containers.stream
import org.jetbrains.jps.model.java.JavaResourceRootType
import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
import org.jetbrains.kotlin.gradle.KotlinCompilation
import org.jetbrains.kotlin.gradle.KotlinPlatform
import org.jetbrains.kotlin.idea.configuration.GradleProjectImportHandler
import org.jetbrains.kotlin.idea.configuration.KotlinSourceSetDataService
import org.jetbrains.kotlin.idea.configuration.kotlinAndroidSourceSets
import org.jetbrains.kotlin.gradle.KotlinSourceSet
import org.jetbrains.kotlin.idea.configuration.*
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
import java.io.File
import java.io.IOException
@@ -88,13 +90,13 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
(it.data as? ModuleData)?.id == sourceSetId
}?.data as? ModuleData ?: continue
val sourceSetModule = modelsProvider.findIdeModule(sourceSetData) ?: continue
val existingEntry = rootModel.findModuleOrderEntry(sourceSetModule)
val dependencyScope = if (activeSourceSetInfo.isTestModule) DependencyScope.TEST else DependencyScope.COMPILE
if (existingEntry != null && existingEntry.scope == dependencyScope) continue
rootModel.addModuleOrderEntry(sourceSetModule).also { it.scope = dependencyScope }
addModuleDependencyIfNeeded(rootModel, sourceSetModule, activeSourceSetInfo.isTestModule)
}
}
}
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, false)
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, true)
val mainSourceSetInfo = activeSourceSetInfos.firstOrNull { it.kotlinModule.name == variantName }
if (mainSourceSetInfo != null) {
KotlinSourceSetDataService.configureFacet(moduleData, mainSourceSetInfo, nodeToImport, module, modelsProvider)
@@ -107,6 +109,60 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
}
}
private fun addModuleDependencyIfNeeded(
rootModel: ModifiableRootModel,
dependeeModule: Module,
testScope: Boolean
) {
val dependencyScope = if (testScope) DependencyScope.TEST else DependencyScope.COMPILE
val existingEntry = rootModel.findModuleOrderEntry(dependeeModule)
if (existingEntry != null && existingEntry.scope == dependencyScope) return
rootModel.addModuleOrderEntry(dependeeModule).also { it.scope = dependencyScope }
}
private fun addExtraDependeeModules(
androidModel: AndroidModuleModel,
projectNode: DataNode<ProjectData>,
modelsProvider: IdeModifiableModelsProvider,
rootModel: ModifiableRootModel,
testScope: Boolean
) {
val dependencies = if (testScope) {
androidModel.selectedAndroidTestCompileDependencies
} else {
androidModel.selectedMainCompileLevel2Dependencies
} ?: return
val commonSourceSetName = KotlinSourceSet.commonName(testScope)
val relevantNodes = dependencies
.moduleDependencies
.mapNotNull { projectNode.findChildModuleById(it.projectPath) }
.flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) }
.filter {
val ktModule = it.kotlinSourceSet?.kotlinModule
ktModule != null && ktModule.isTestModule == testScope
}
SmartList<DataNode<GradleSourceSetData>>()
.apply {
addIfNotNull(
relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.ANDROID }
?: relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.JVM }
)
addIfNotNull(
relevantNodes.firstOrNull {
it.kotlinSourceSet?.platform == KotlinPlatform.COMMON && it.kotlinSourceSet?.kotlinModule?.name == commonSourceSetName
}
)
}
.mapNotNull { modelsProvider.findIdeModule(it.data) }
.forEach {
addModuleDependencyIfNeeded(rootModel, it, testScope)
val dependeeRootModel = modelsProvider.getModifiableRootModel(it)
dependeeRootModel.getModuleDependencies(testScope).forEach { transitiveDependee ->
addModuleDependencyIfNeeded(rootModel, transitiveDependee, testScope)
}
}
}
private fun addSourceRoot(
sourceRoot: File,
type: JpsModuleSourceRootType<*>,
@@ -25,18 +25,18 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.util.SmartList
import com.intellij.util.containers.stream
import org.jetbrains.jps.model.java.JavaResourceRootType
import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
import org.jetbrains.kotlin.gradle.KotlinCompilation
import org.jetbrains.kotlin.gradle.KotlinPlatform
import org.jetbrains.kotlin.idea.configuration.kotlinSourceSet
import org.jetbrains.kotlin.idea.configuration.GradleProjectImportHandler
import org.jetbrains.kotlin.idea.configuration.KotlinSourceSetDataService
import org.jetbrains.kotlin.idea.configuration.kotlinAndroidSourceSets
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
import org.jetbrains.kotlin.gradle.KotlinSourceSet
import org.jetbrains.kotlin.idea.configuration.*
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
import java.io.File
import java.io.IOException
@@ -101,13 +101,13 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
(it.data as? ModuleData)?.id == sourceSetId
}?.data as? ModuleData ?: continue
val sourceSetModule = modelsProvider.findIdeModule(sourceSetData) ?: continue
val existingEntry = rootModel.findModuleOrderEntry(sourceSetModule)
val dependencyScope = if (activeSourceSetInfo.isTestModule) DependencyScope.TEST else DependencyScope.COMPILE
if (existingEntry != null && existingEntry.scope == dependencyScope) continue
rootModel.addModuleOrderEntry(sourceSetModule).also { it.scope = dependencyScope }
addModuleDependencyIfNeeded(rootModel, sourceSetModule, activeSourceSetInfo.isTestModule)
}
}
}
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, false)
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, true)
val mainSourceSetInfo = activeSourceSetInfos.firstOrNull { it.kotlinModule.name == variantName }
if (mainSourceSetInfo != null) {
KotlinSourceSetDataService.configureFacet(moduleData, mainSourceSetInfo, nodeToImport, module, modelsProvider)
@@ -118,8 +118,60 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
GradleProjectImportHandler.getInstances(project).forEach { it.importByModule(kotlinFacet, nodeToImport) }
}
}
}
ContentRootDataService().importData(contentRootsToImport, projectData, project, modelsProvider)
private fun addModuleDependencyIfNeeded(
rootModel: ModifiableRootModel,
dependeeModule: Module,
testScope: Boolean
) {
val dependencyScope = if (testScope) DependencyScope.TEST else DependencyScope.COMPILE
val existingEntry = rootModel.findModuleOrderEntry(dependeeModule)
if (existingEntry != null && existingEntry.scope == dependencyScope) return
rootModel.addModuleOrderEntry(dependeeModule).also { it.scope = dependencyScope }
}
private fun addExtraDependeeModules(
androidModel: AndroidModuleModel,
projectNode: DataNode<ProjectData>,
modelsProvider: IdeModifiableModelsProvider,
rootModel: ModifiableRootModel,
testScope: Boolean
) {
val dependencies = if (testScope) {
androidModel.selectedAndroidTestCompileDependencies
} else {
androidModel.selectedMainCompileLevel2Dependencies
} ?: return
val commonSourceSetName = KotlinSourceSet.commonName(testScope)
val relevantNodes = dependencies
.moduleDependencies
.mapNotNull { projectNode.findChildModuleById(it.projectPath) }
.flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) }
.filter {
val ktModule = it.kotlinSourceSet?.kotlinModule
ktModule != null && ktModule.isTestModule == testScope
}
SmartList<DataNode<GradleSourceSetData>>()
.apply {
addIfNotNull(
relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.ANDROID }
?: relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.JVM }
)
addIfNotNull(
relevantNodes.firstOrNull {
it.kotlinSourceSet?.platform == KotlinPlatform.COMMON && it.kotlinSourceSet?.kotlinModule?.name == commonSourceSetName
}
)
}
.mapNotNull { modelsProvider.findIdeModule(it.data) }
.forEach {
addModuleDependencyIfNeeded(rootModel, it, testScope)
val dependeeRootModel = modelsProvider.getModifiableRootModel(it)
dependeeRootModel.getModuleDependencies(testScope).forEach { transitiveDependee ->
addModuleDependencyIfNeeded(rootModel, transitiveDependee, testScope)
}
}
}
private fun addSourceRoot(
@@ -23,16 +23,18 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.util.SmartList
import com.intellij.util.containers.stream
import org.jetbrains.jps.model.java.JavaResourceRootType
import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
import org.jetbrains.kotlin.gradle.KotlinCompilation
import org.jetbrains.kotlin.gradle.KotlinPlatform
import org.jetbrains.kotlin.idea.configuration.GradleProjectImportHandler
import org.jetbrains.kotlin.idea.configuration.KotlinSourceSetDataService
import org.jetbrains.kotlin.idea.configuration.kotlinAndroidSourceSets
import org.jetbrains.kotlin.gradle.KotlinSourceSet
import org.jetbrains.kotlin.idea.configuration.*
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
import java.io.File
import java.io.IOException
@@ -88,13 +90,13 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
(it.data as? ModuleData)?.id == sourceSetId
}?.data as? ModuleData ?: continue
val sourceSetModule = modelsProvider.findIdeModule(sourceSetData) ?: continue
val existingEntry = rootModel.findModuleOrderEntry(sourceSetModule)
val dependencyScope = if (activeSourceSetInfo.isTestModule) DependencyScope.TEST else DependencyScope.COMPILE
if (existingEntry != null && existingEntry.scope == dependencyScope) continue
rootModel.addModuleOrderEntry(sourceSetModule).also { it.scope = dependencyScope }
addModuleDependencyIfNeeded(rootModel, sourceSetModule, activeSourceSetInfo.isTestModule)
}
}
}
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, false)
addExtraDependeeModules(androidModel, projectNode, modelsProvider, rootModel, true)
val mainSourceSetInfo = activeSourceSetInfos.firstOrNull { it.kotlinModule.name == variantName }
if (mainSourceSetInfo != null) {
KotlinSourceSetDataService.configureFacet(moduleData, mainSourceSetInfo, nodeToImport, module, modelsProvider)
@@ -107,6 +109,60 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<Modul
}
}
private fun addModuleDependencyIfNeeded(
rootModel: ModifiableRootModel,
dependeeModule: Module,
testScope: Boolean
) {
val dependencyScope = if (testScope) DependencyScope.TEST else DependencyScope.COMPILE
val existingEntry = rootModel.findModuleOrderEntry(dependeeModule)
if (existingEntry != null && existingEntry.scope == dependencyScope) return
rootModel.addModuleOrderEntry(dependeeModule).also { it.scope = dependencyScope }
}
private fun addExtraDependeeModules(
androidModel: AndroidModuleModel,
projectNode: DataNode<ProjectData>,
modelsProvider: IdeModifiableModelsProvider,
rootModel: ModifiableRootModel,
testScope: Boolean
) {
val dependencies = if (testScope) {
androidModel.selectedAndroidTestCompileDependencies
} else {
androidModel.selectedMainCompileLevel2Dependencies
} ?: return
val commonSourceSetName = KotlinSourceSet.commonName(testScope)
val relevantNodes = dependencies
.moduleDependencies
.mapNotNull { projectNode.findChildModuleById(it.projectPath) }
.flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) }
.filter {
val ktModule = it.kotlinSourceSet?.kotlinModule
ktModule != null && ktModule.isTestModule == testScope
}
SmartList<DataNode<GradleSourceSetData>>()
.apply {
addIfNotNull(
relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.ANDROID }
?: relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.JVM }
)
addIfNotNull(
relevantNodes.firstOrNull {
it.kotlinSourceSet?.platform == KotlinPlatform.COMMON && it.kotlinSourceSet?.kotlinModule?.name == commonSourceSetName
}
)
}
.mapNotNull { modelsProvider.findIdeModule(it.data) }
.forEach {
addModuleDependencyIfNeeded(rootModel, it, testScope)
val dependeeRootModel = modelsProvider.getModifiableRootModel(it)
dependeeRootModel.getModuleDependencies(testScope).forEach { transitiveDependee ->
addModuleDependencyIfNeeded(rootModel, transitiveDependee, testScope)
}
}
}
private fun addSourceRoot(
sourceRoot: File,
type: JpsModuleSourceRootType<*>,
@@ -27,6 +27,8 @@ interface KotlinSourceSet : KotlinModule {
companion object {
const val COMMON_MAIN_SOURCE_SET_NAME = "commonMain"
const val COMMON_TEST_SOURCE_SET_NAME = "commonTest"
fun commonName(forTests: Boolean) = if (forTests) COMMON_TEST_SOURCE_SET_NAME else COMMON_MAIN_SOURCE_SET_NAME
}
}