MPP: Fix import of dependencies on Android modules

This commit is contained in:
Alexey Sedunov
2018-09-12 18:29:35 +03:00
parent 1de0dbd67d
commit 14d8425e27
10 changed files with 56 additions and 41 deletions
@@ -24,6 +24,7 @@ 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.KotlinSourceSetDataService
import org.jetbrains.kotlin.idea.configuration.kotlinAndroidSourceSets
import java.io.File
class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<ModuleData, Void>() {
@@ -22,6 +22,7 @@ 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.KotlinSourceSetDataService
import org.jetbrains.kotlin.idea.configuration.kotlinAndroidSourceSets
import java.io.File
class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<ModuleData, Void>() {
@@ -24,6 +24,7 @@ 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.KotlinSourceSetDataService
import org.jetbrains.kotlin.idea.configuration.kotlinAndroidSourceSets
import java.io.File
class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<ModuleData, Void>() {
@@ -27,6 +27,7 @@ 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.KotlinSourceSetDataService
import org.jetbrains.kotlin.idea.configuration.kotlinAndroidSourceSets
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
import java.io.File
@@ -24,6 +24,7 @@ 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.KotlinSourceSetDataService
import org.jetbrains.kotlin.idea.configuration.kotlinAndroidSourceSets
import java.io.File
class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<ModuleData, Void>() {
@@ -15,21 +15,16 @@ import com.intellij.openapi.externalSystem.model.project.ProjectData
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants
import com.intellij.openapi.externalSystem.util.Order
import com.intellij.openapi.util.Key
import org.gradle.tooling.model.idea.IdeaModule
import org.jetbrains.kotlin.gradle.KotlinMPPGradleModel
import org.jetbrains.kotlin.gradle.KotlinMPPGradleModelBuilder
import org.jetbrains.kotlin.gradle.KotlinPlatform
import org.jetbrains.kotlin.idea.configuration.KotlinMPPGradleProjectResolver
import org.jetbrains.kotlin.idea.configuration.KotlinSourceSetInfo
import org.jetbrains.kotlin.idea.configuration.kotlinAndroidSourceSets
import org.jetbrains.kotlin.idea.configuration.kotlinSourceSet
import org.jetbrains.kotlin.idea.util.CopyableDataNodeUserDataProperty
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
var DataNode<ModuleData>.kotlinAndroidSourceSets: List<KotlinSourceSetInfo>?
by CopyableDataNodeUserDataProperty(Key.create("ANDROID_COMPILATIONS"))
@Order(ExternalSystemConstants.UNORDERED - 1)
class KotlinAndroidMPPGradleProjectResolver : AbstractProjectResolverExtension() {
private val isAndroidProject by lazy {
@@ -15,21 +15,16 @@ import com.intellij.openapi.externalSystem.model.project.ProjectData
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants
import com.intellij.openapi.externalSystem.util.Order
import com.intellij.openapi.util.Key
import org.gradle.tooling.model.idea.IdeaModule
import org.jetbrains.kotlin.gradle.KotlinMPPGradleModel
import org.jetbrains.kotlin.gradle.KotlinMPPGradleModelBuilder
import org.jetbrains.kotlin.gradle.KotlinPlatform
import org.jetbrains.kotlin.idea.configuration.KotlinMPPGradleProjectResolver
import org.jetbrains.kotlin.idea.configuration.KotlinSourceSetInfo
import org.jetbrains.kotlin.idea.configuration.kotlinAndroidSourceSets
import org.jetbrains.kotlin.idea.configuration.kotlinSourceSet
import org.jetbrains.kotlin.idea.util.CopyableDataNodeUserDataProperty
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
var DataNode<ModuleData>.kotlinAndroidSourceSets: List<KotlinSourceSetInfo>?
by CopyableDataNodeUserDataProperty(Key.create("ANDROID_COMPILATIONS"))
@Order(ExternalSystemConstants.UNORDERED - 1)
class KotlinAndroidMPPGradleProjectResolver : AbstractProjectResolverExtension() {
private val isAndroidProject by lazy {
@@ -15,21 +15,16 @@ import com.intellij.openapi.externalSystem.model.project.ProjectData
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants
import com.intellij.openapi.externalSystem.util.Order
import com.intellij.openapi.util.Key
import org.gradle.tooling.model.idea.IdeaModule
import org.jetbrains.kotlin.gradle.KotlinMPPGradleModel
import org.jetbrains.kotlin.gradle.KotlinMPPGradleModelBuilder
import org.jetbrains.kotlin.gradle.KotlinPlatform
import org.jetbrains.kotlin.idea.configuration.KotlinMPPGradleProjectResolver
import org.jetbrains.kotlin.idea.configuration.KotlinSourceSetInfo
import org.jetbrains.kotlin.idea.configuration.kotlinAndroidSourceSets
import org.jetbrains.kotlin.idea.configuration.kotlinSourceSet
import org.jetbrains.kotlin.idea.util.CopyableDataNodeUserDataProperty
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
var DataNode<ModuleData>.kotlinAndroidSourceSets: List<KotlinSourceSetInfo>?
by CopyableDataNodeUserDataProperty(Key.create("ANDROID_COMPILATIONS"))
@Order(ExternalSystemConstants.UNORDERED - 1)
class KotlinAndroidMPPGradleProjectResolver : AbstractProjectResolverExtension() {
private val isAndroidProject by lazy {
@@ -13,7 +13,6 @@ import com.intellij.openapi.util.Key
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.gradle.KotlinModule
import org.jetbrains.kotlin.gradle.KotlinPlatform
import org.jetbrains.kotlin.gradle.KotlinSourceSet
import org.jetbrains.kotlin.idea.util.CopyableDataNodeUserDataProperty
import org.jetbrains.plugins.gradle.util.GradleConstants
import java.io.File
@@ -25,6 +24,9 @@ var DataNode<out ModuleData>.kotlinSourceSet: KotlinSourceSetInfo?
var DataNode<out ModuleData>.kotlinTargetDataNode: DataNode<KotlinTargetData>?
by CopyableDataNodeUserDataProperty(Key.create("KOTLIN_TARGET_DATA_NODE"))
var DataNode<ModuleData>.kotlinAndroidSourceSets: List<KotlinSourceSetInfo>?
by CopyableDataNodeUserDataProperty(Key.create("ANDROID_COMPILATIONS"))
class KotlinSourceSetInfo(val kotlinModule: KotlinModule) {
var moduleId: String? = null
var platform: KotlinPlatform = KotlinPlatform.COMMON
@@ -32,7 +34,7 @@ class KotlinSourceSetInfo(val kotlinModule: KotlinModule) {
var compilerArguments: CommonCompilerArguments? = null
var dependencyClasspath: List<String> = emptyList()
var isTestModule: Boolean = false
var sourceSetIdsByName: Map<String, String> = emptyMap()
var sourceSetIdsByName: MutableMap<String, String> = LinkedHashMap()
}
class KotlinTargetData(name: String) : AbstractNamedData(GradleConstants.SYSTEM_ID, name) {
@@ -299,6 +299,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
) {
val mppModel = resolverCtx.getExtraProject(gradleModule, KotlinMPPGradleModel::class.java) ?: return
processSourceSets(gradleModule, mppModel, ideModule, resolverCtx) { dataNode, sourceSet ->
if (dataNode == null || sourceSet.platform == KotlinPlatform.ANDROID) return@processSourceSets
createContentRootData(sourceSet.sourceDirs, sourceSet.sourceType, dataNode)
createContentRootData(sourceSet.resourceDirs, sourceSet.resourceType, dataNode)
}
@@ -346,7 +347,9 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
val sourceSetGraph = GraphBuilder.directed().build<KotlinModule>()
processSourceSets(gradleModule, mppModel, ideModule, resolverCtx) { dataNode, sourceSet ->
sourceSetGraph.addNode(sourceSet)
val productionSourceSet = dataNode.data.productionModuleId
val productionSourceSet = dataNode
?.data
?.productionModuleId
?.let { ideModule.findChildModuleByInternalName(it) }
?.kotlinSourceSet
?.kotlinModule
@@ -361,21 +364,29 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
}
val closedSourceSetGraph = Graphs.transitiveClosure(sourceSetGraph)
for (sourceSet in closedSourceSetGraph.nodes()) {
val fromDataNode = getSiblingKotlinModuleData(sourceSet, gradleModule, ideModule, resolverCtx) ?: continue
val isAndroid = sourceSet.platform == KotlinPlatform.ANDROID
val fromDataNode = if (isAndroid) {
ideModule
} else {
getSiblingKotlinModuleData(sourceSet, gradleModule, ideModule, resolverCtx)
} ?: continue
val dependeeSourceSets = closedSourceSetGraph.successors(sourceSet)
val sourceSetInfo = if (isAndroid) {
ideModule.kotlinAndroidSourceSets?.firstOrNull {
(it.kotlinModule as? KotlinCompilation)?.sourceSets?.contains(sourceSet) ?: false
}
} else {
fromDataNode.kotlinSourceSet
}
if (sourceSetInfo != null && sourceSetInfo.kotlinModule is KotlinCompilation) {
val selfName = sourceSetInfo.kotlinModule.fullName()
sourceSetInfo.addSourceSets(dependeeSourceSets, selfName, gradleModule, resolverCtx)
}
if (sourceSet.platform == KotlinPlatform.ANDROID) continue
for (dependeeSourceSet in dependeeSourceSets) {
val toDataNode = getSiblingKotlinModuleData(dependeeSourceSet, gradleModule, ideModule, resolverCtx) ?: continue
addDependency(fromDataNode, toDataNode)
}
val sourceSetInfo = fromDataNode.kotlinSourceSet
if (sourceSetInfo != null && sourceSetInfo.kotlinModule is KotlinCompilation) {
val selfName = sourceSetInfo.kotlinModule.fullName()
sourceSetInfo.sourceSetIdsByName = dependeeSourceSets
.asSequence()
.filter { it.fullName() != selfName }
.map { it.name to getKotlinModuleId(gradleModule, it, resolverCtx) }
.toMap()
}
if (processedModuleIds.add(getKotlinModuleId(gradleModule, sourceSet, resolverCtx))) {
val mergedDependencies = LinkedHashSet<KotlinDependency>().apply {
addAll(sourceSet.dependencies)
@@ -477,7 +488,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
mppModel: KotlinMPPGradleModel,
ideModule: DataNode<ModuleData>,
resolverCtx: ProjectResolverContext,
processor: (DataNode<GradleSourceSetData>, KotlinSourceSet) -> Unit
processor: (DataNode<GradleSourceSetData>?, KotlinSourceSet) -> Unit
) {
val sourceSetsMap = HashMap<String, DataNode<GradleSourceSetData>>()
for (dataNode in ExternalSystemApiUtil.findAll(ideModule, GradleSourceSetData.KEY)) {
@@ -486,9 +497,8 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
}
}
for (sourceSet in mppModel.sourceSets.values) {
if (sourceSet.platform == KotlinPlatform.ANDROID) continue
val moduleId = getKotlinModuleId(gradleModule, sourceSet, resolverCtx)
val moduleDataNode = sourceSetsMap[moduleId] ?: continue
val moduleDataNode = sourceSetsMap[moduleId]
processor(moduleDataNode, sourceSet)
}
}
@@ -630,18 +640,31 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
gradleModule: IdeaModule,
resolverCtx: ProjectResolverContext
): KotlinSourceSetInfo {
return KotlinSourceSetInfo(compilation).also {
it.moduleId = getKotlinModuleId(gradleModule, compilation, resolverCtx)
it.platform = compilation.platform
it.isTestModule = compilation.isTestModule
it.compilerArguments = createCompilerArguments(compilation.arguments.currentArguments, compilation.platform).also {
return KotlinSourceSetInfo(compilation).also { sourceSetInfo ->
sourceSetInfo.moduleId = getKotlinModuleId(gradleModule, compilation, resolverCtx)
sourceSetInfo.platform = compilation.platform
sourceSetInfo.isTestModule = compilation.isTestModule
sourceSetInfo.compilerArguments = createCompilerArguments(compilation.arguments.currentArguments, compilation.platform).also {
it.multiPlatform = true
}
it.dependencyClasspath = compilation.dependencyClasspath
it.defaultCompilerArguments = createCompilerArguments(compilation.arguments.defaultArguments, compilation.platform)
sourceSetInfo.dependencyClasspath = compilation.dependencyClasspath
sourceSetInfo.defaultCompilerArguments = createCompilerArguments(compilation.arguments.defaultArguments, compilation.platform)
sourceSetInfo.addSourceSets(compilation.sourceSets, compilation.fullName(), gradleModule, resolverCtx)
}
}
private fun KotlinSourceSetInfo.addSourceSets(
sourceSets: Collection<KotlinModule>,
selfName: String,
gradleModule: IdeaModule,
resolverCtx: ProjectResolverContext
) {
sourceSets
.asSequence()
.filter { it.fullName() != selfName }
.forEach { sourceSetIdsByName[it.name] = getKotlinModuleId(gradleModule, it, resolverCtx) }
}
private fun createCompilerArguments(args: List<String>, platform: KotlinPlatform): CommonCompilerArguments {
val compilerArguments = IdePlatformKindTooling.getTooling(platform).kind.argumentsClass.newInstance()
parseCommandLineArguments(args, compilerArguments)