From fea397a2ad855b05a9548280c159011a8cd0295a Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Thu, 4 Oct 2018 20:53:15 +0300 Subject: [PATCH] MPP: Support MPP-dependent Java modules in Android projects #KT-27265 Fixed --- ...KotlinAndroidGradleMPPModuleDataService.kt | 71 ++++++++++++++----- ...inAndroidGradleMPPModuleDataService.kt.181 | 71 ++++++++++++++----- ...nAndroidGradleMPPModuleDataService.kt.as31 | 71 ++++++++++++++----- ...nAndroidGradleMPPModuleDataService.kt.as32 | 71 ++++++++++++++----- 4 files changed, 220 insertions(+), 64 deletions(-) diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt b/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt index 76a73502b26..80e1381ca60 100644 --- a/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt +++ b/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt @@ -5,7 +5,7 @@ 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.io.FilePaths 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.module.Module 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 @@ -78,7 +79,9 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService, + projectNode: DataNode, + modelsProvider: IdeModifiableModelsProvider, + testScope: Boolean + ): List> { + 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>.firstByPlatformOrNull(platform: KotlinPlatform) = firstOrNull { + it.kotlinSourceSet?.platform == platform + } + private fun addExtraDependeeModules( - androidModel: AndroidModuleModel, + moduleNode: DataNode, projectNode: DataNode, 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) } + val dependeeModuleNodes = getDependeeModuleNodes(moduleNode, projectNode, modelsProvider, testScope) + val relevantNodes = dependeeModuleNodes .flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) } .filter { val ktModule = it.kotlinSourceSet?.kotlinModule ktModule != null && ktModule.isTestModule == testScope } + val commonSourceSetName = KotlinSourceSet.commonName(testScope) + val isAndroidModule = getAndroidModuleModel(moduleNode) != null SmartList>() .apply { addIfNotNull( - relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.ANDROID } - ?: relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.JVM } + (if (isAndroidModule) relevantNodes.firstByPlatformOrNull(KotlinPlatform.ANDROID) else null) + ?: relevantNodes.firstByPlatformOrNull(KotlinPlatform.JVM) ) addIfNotNull( relevantNodes.firstOrNull { @@ -152,6 +185,12 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService) = + ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.ANDROID_MODEL).firstOrNull()?.data + + private fun getJavaModuleModel(moduleNode: DataNode) = + ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.JAVA_MODULE_MODEL).firstOrNull()?.data + private fun addSourceRoot( sourceRoot: File, type: JpsModuleSourceRootType<*>, diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.181 b/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.181 index 2b1f20b4113..c665deeb634 100644 --- a/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.181 +++ b/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.181 @@ -5,7 +5,7 @@ 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.FilePaths 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.module.Module 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 @@ -78,7 +79,9 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService, + projectNode: DataNode, + modelsProvider: IdeModifiableModelsProvider, + testScope: Boolean + ): List> { + 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>.firstByPlatformOrNull(platform: KotlinPlatform) = firstOrNull { + it.kotlinSourceSet?.platform == platform + } + private fun addExtraDependeeModules( - androidModel: AndroidModuleModel, + moduleNode: DataNode, projectNode: DataNode, 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) } + val dependeeModuleNodes = getDependeeModuleNodes(moduleNode, projectNode, modelsProvider, testScope) + val relevantNodes = dependeeModuleNodes .flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) } .filter { val ktModule = it.kotlinSourceSet?.kotlinModule ktModule != null && ktModule.isTestModule == testScope } + val commonSourceSetName = KotlinSourceSet.commonName(testScope) + val isAndroidModule = getAndroidModuleModel(moduleNode) != null SmartList>() .apply { addIfNotNull( - relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.ANDROID } - ?: relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.JVM } + (if (isAndroidModule) relevantNodes.firstByPlatformOrNull(KotlinPlatform.ANDROID) else null) + ?: relevantNodes.firstByPlatformOrNull(KotlinPlatform.JVM) ) addIfNotNull( relevantNodes.firstOrNull { @@ -152,6 +185,12 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService) = + ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.ANDROID_MODEL).firstOrNull()?.data + + private fun getJavaModuleModel(moduleNode: DataNode) = + ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.JAVA_MODULE_MODEL).firstOrNull()?.data + private fun addSourceRoot( sourceRoot: File, type: JpsModuleSourceRootType<*>, diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.as31 b/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.as31 index 06bfa3b4fb4..19f210ea27d 100644 --- a/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.as31 +++ b/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.as31 @@ -5,7 +5,7 @@ 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.io.FilePaths 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.module.Module 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 @@ -89,7 +90,9 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService, + projectNode: DataNode, + modelsProvider: IdeModifiableModelsProvider, + testScope: Boolean + ): List> { + 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>.firstByPlatformOrNull(platform: KotlinPlatform) = firstOrNull { + it.kotlinSourceSet?.platform == platform + } + private fun addExtraDependeeModules( - androidModel: AndroidModuleModel, + moduleNode: DataNode, projectNode: DataNode, 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) } + val dependeeModuleNodes = getDependeeModuleNodes(moduleNode, projectNode, modelsProvider, testScope) + val relevantNodes = dependeeModuleNodes .flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) } .filter { val ktModule = it.kotlinSourceSet?.kotlinModule ktModule != null && ktModule.isTestModule == testScope } + val commonSourceSetName = KotlinSourceSet.commonName(testScope) + val isAndroidModule = getAndroidModuleModel(moduleNode) != null SmartList>() .apply { addIfNotNull( - relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.ANDROID } - ?: relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.JVM } + (if (isAndroidModule) relevantNodes.firstByPlatformOrNull(KotlinPlatform.ANDROID) else null) + ?: relevantNodes.firstByPlatformOrNull(KotlinPlatform.JVM) ) addIfNotNull( relevantNodes.firstOrNull { @@ -163,6 +196,12 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService) = + ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.ANDROID_MODEL).firstOrNull()?.data + + private fun getJavaModuleModel(moduleNode: DataNode) = + ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.JAVA_MODULE_MODEL).firstOrNull()?.data + private fun addSourceRoot( sourceRoot: File, type: JpsModuleSourceRootType<*>, diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.as32 b/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.as32 index 76a73502b26..80e1381ca60 100644 --- a/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.as32 +++ b/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.as32 @@ -5,7 +5,7 @@ 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.io.FilePaths 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.module.Module 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 @@ -78,7 +79,9 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService, + projectNode: DataNode, + modelsProvider: IdeModifiableModelsProvider, + testScope: Boolean + ): List> { + 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>.firstByPlatformOrNull(platform: KotlinPlatform) = firstOrNull { + it.kotlinSourceSet?.platform == platform + } + private fun addExtraDependeeModules( - androidModel: AndroidModuleModel, + moduleNode: DataNode, projectNode: DataNode, 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) } + val dependeeModuleNodes = getDependeeModuleNodes(moduleNode, projectNode, modelsProvider, testScope) + val relevantNodes = dependeeModuleNodes .flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) } .filter { val ktModule = it.kotlinSourceSet?.kotlinModule ktModule != null && ktModule.isTestModule == testScope } + val commonSourceSetName = KotlinSourceSet.commonName(testScope) + val isAndroidModule = getAndroidModuleModel(moduleNode) != null SmartList>() .apply { addIfNotNull( - relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.ANDROID } - ?: relevantNodes.firstOrNull { it.kotlinSourceSet?.platform == KotlinPlatform.JVM } + (if (isAndroidModule) relevantNodes.firstByPlatformOrNull(KotlinPlatform.ANDROID) else null) + ?: relevantNodes.firstByPlatformOrNull(KotlinPlatform.JVM) ) addIfNotNull( relevantNodes.firstOrNull { @@ -152,6 +185,12 @@ class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService) = + ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.ANDROID_MODEL).firstOrNull()?.data + + private fun getJavaModuleModel(moduleNode: DataNode) = + ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.JAVA_MODULE_MODEL).firstOrNull()?.data + private fun addSourceRoot( sourceRoot: File, type: JpsModuleSourceRootType<*>,