MPP: Use only explicitly specified source set dependencies

#KT-25985 Fixed
This commit is contained in:
Alexey Sedunov
2018-08-09 10:51:28 +03:00
committed by Mikhail Glukhikh
parent 543934762e
commit 36da80bdf5
4 changed files with 75 additions and 60 deletions
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.idea.configuration
import com.intellij.openapi.externalSystem.model.DataNode
import com.intellij.openapi.externalSystem.model.ProjectKeys
import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType
import com.intellij.openapi.externalSystem.model.project.ModuleData
import com.intellij.openapi.externalSystem.model.project.ProjectData
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
@@ -15,10 +14,6 @@ import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjec
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.LibraryOrderEntry
import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.openapi.roots.impl.libraries.LibraryEx
import com.intellij.openapi.roots.libraries.Library
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.config.CoroutineSupport
import org.jetbrains.kotlin.config.JvmTarget
@@ -32,9 +27,6 @@ import org.jetbrains.kotlin.idea.facet.applyCompilerArgumentsToFacet
import org.jetbrains.kotlin.idea.facet.configureFacet
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
import org.jetbrains.kotlin.idea.facet.noVersionAutoAdvance
import org.jetbrains.kotlin.idea.framework.CommonLibraryKind
import org.jetbrains.kotlin.idea.framework.JSLibraryKind
import org.jetbrains.kotlin.idea.framework.effectiveKind
import org.jetbrains.kotlin.idea.inspections.gradle.findAll
import org.jetbrains.kotlin.idea.inspections.gradle.findKotlinPluginVersion
import org.jetbrains.kotlin.idea.roots.migrateNonJvmSourceFolders
@@ -61,8 +53,6 @@ class KotlinSourceSetDataService : AbstractProjectDataService<GradleSourceSetDat
val platform = kotlinSourceSet.platform
val rootModel = modelsProvider.getModifiableRootModel(ideModule)
dropWrongLibraries(rootModel, platform, project)
if (platform != KotlinPlatform.JVM) {
migrateNonJvmSourceFolders(rootModel)
}
@@ -137,27 +127,4 @@ class KotlinSourceSetDataService : AbstractProjectDataService<GradleSourceSetDat
}
}
}
private fun dropWrongLibraries(
rootModel: ModifiableRootModel,
platform: KotlinPlatform,
project: Project
) {
rootModel.orderEntries().librariesOnly().forEach { orderEntry ->
val library = (orderEntry as? LibraryOrderEntry)?.library
if (library != null && !library.matchesPlatform(platform, project)) {
rootModel.removeOrderEntry(orderEntry)
}
true
}
}
private fun Library.matchesPlatform(platform: KotlinPlatform, project: Project): Boolean {
val kind = (this as? LibraryEx)?.effectiveKind(project)
return when (kind) {
CommonLibraryKind -> true
JSLibraryKind -> platform == KotlinPlatform.JS
else -> platform == KotlinPlatform.JVM
}
}
}
@@ -44,7 +44,7 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
true,
SourceSetCachedFinder(project)
)
val sourceSets = buildSourceSets(project) ?: return null
val sourceSets = buildSourceSets(dependencyResolver, project) ?: return null
val sourceSetMap = sourceSets.map { it.name to it }.toMap()
val targets = buildTargets(sourceSetMap, dependencyResolver, project) ?: return null
computeSourceSetsDeferredInfo(sourceSets, targets)
@@ -60,37 +60,42 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
return getCoroutines(experimentalExt) as? String
}
private fun buildSourceSets(project: Project): Collection<KotlinSourceSetImpl>? {
private fun buildSourceSets(dependencyResolver: DependencyResolver, project: Project): Collection<KotlinSourceSetImpl>? {
val kotlinExt = project.extensions.findByName("kotlin") ?: return null
val getSourceSets = kotlinExt.javaClass.getMethodOrNull("getSourceSets") ?: return null
@Suppress("UNCHECKED_CAST")
val sourceSets =
(getSourceSets(kotlinExt) as? NamedDomainObjectContainer<Named>)?.asMap?.values ?: emptyList<Named>()
return sourceSets.mapNotNull { buildSourceSet(it) }
return sourceSets.mapNotNull { buildSourceSet(it, dependencyResolver, project) }
}
private fun buildSourceSet(gradleSourceSet: Named): KotlinSourceSetImpl? {
private fun buildSourceSet(
gradleSourceSet: Named,
dependencyResolver: DependencyResolver,
project: Project
): KotlinSourceSetImpl? {
val sourceSetClass = gradleSourceSet.javaClass
val getSourceDirSet = sourceSetClass.getMethodOrNull("getKotlin") ?: return null
val getResourceDirSet = sourceSetClass.getMethodOrNull("getResources") ?: return null
val getDependsOn = sourceSetClass.getMethodOrNull("getDependsOn") ?: return null
val sourceDirs = (getSourceDirSet(gradleSourceSet) as? SourceDirectorySet)?.srcDirs ?: emptySet()
val resourceDirs = (getResourceDirSet(gradleSourceSet) as? SourceDirectorySet)?.srcDirs ?: emptySet()
val dependencies = buildSourceSetDependencies(gradleSourceSet, dependencyResolver, project)
@Suppress("UNCHECKED_CAST")
val dependsOnSourceSets = (getDependsOn(gradleSourceSet) as? Set<Named>)?.mapTo(LinkedHashSet()) { it.name } ?: emptySet<String>()
return KotlinSourceSetImpl(gradleSourceSet.name, sourceDirs, resourceDirs, dependsOnSourceSets)
return KotlinSourceSetImpl(gradleSourceSet.name, sourceDirs, resourceDirs, dependencies, dependsOnSourceSets)
}
private fun buildDependencies(
gradleCompilation: Any,
dependencyHolder: Any,
dependencyResolver: DependencyResolver,
configurationNameAccessor: String,
scope: String,
project: Project
): Collection<KotlinDependency> {
val gradleCompilationClass = gradleCompilation.javaClass
val getConfigurationName = gradleCompilationClass.getMethodOrNull(configurationNameAccessor) ?: return emptyList()
val configurationName = getConfigurationName(gradleCompilation) as? String ?: return emptyList()
val dependencyHolderClass = dependencyHolder.javaClass
val getConfigurationName = dependencyHolderClass.getMethodOrNull(configurationNameAccessor) ?: return emptyList()
val configurationName = getConfigurationName(dependencyHolder) as? String ?: return emptyList()
val configuration = project.configurations.findByName(configurationName) ?: return emptyList()
if (!configuration.isCanBeResolved) return emptyList()
val artifactsByProjectPath = configuration
@@ -180,11 +185,11 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
val output = buildCompilationOutput(gradleCompilation, compileKotlinTask) ?: return null
val arguments = buildCompilationArguments(compileKotlinTask) ?: return null
val dependencyClasspath = buildDependencyClasspath(compileKotlinTask)
val dependencies = buildDependencies(gradleCompilation, dependencyResolver, project)
val dependencies = buildCompilationDependencies(gradleCompilation, dependencyResolver, project)
return KotlinCompilationImpl(isAndroid, gradleCompilation.name, kotlinSourceSets, dependencies, output, arguments, dependencyClasspath)
}
private fun buildDependencies(
private fun buildCompilationDependencies(
gradleCompilation: Named,
dependencyResolver: DependencyResolver,
project: Project
@@ -199,6 +204,27 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
}
}
private fun buildSourceSetDependencies(
gradleSourceSet: Named,
dependencyResolver: DependencyResolver,
project: Project
): Set<KotlinDependency> {
return LinkedHashSet<KotlinDependency>().apply {
this += buildDependencies(
gradleSourceSet, dependencyResolver, "getApiConfigurationName", "COMPILE", project
)
this += buildDependencies(
gradleSourceSet, dependencyResolver, "getImplementationConfigurationName", "COMPILE", project
)
this += buildDependencies(
gradleSourceSet, dependencyResolver, "getCompileOnlyConfigurationName", "COMPILE", project
)
this += buildDependencies(
gradleSourceSet, dependencyResolver, "getRuntimeOnlyConfigurationName", "RUNTIME", project
)
}
}
private fun buildCompilationArguments(compileKotlinTask: Task): KotlinCompilationArguments? {
val compileTaskClass = compileKotlinTask.javaClass
val getCurrentArguments = compileTaskClass.getMethodOrNull("getSerializedCompilerArguments") ?: return null
@@ -252,7 +278,6 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
for (sourceSet in sourceSets) {
val compilations = sourceSetToCompilations[sourceSet] ?: continue
sourceSet.platform = compilations.map { it.platform }.distinct().singleOrNull() ?: KotlinPlatform.COMMON
sourceSet.dependencies = compilations.flatMapTo(LinkedHashSet()) { it.dependencies }
sourceSet.isTestModule = compilations.all { it.isTestModule }
sourceSet.isAndroid = compilations.all { it.isAndroid }
}
@@ -44,7 +44,7 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
true,
SourceSetCachedFinder(project)
)
val sourceSets = buildSourceSets(project) ?: return null
val sourceSets = buildSourceSets(dependencyResolver, project) ?: return null
val sourceSetMap = sourceSets.map { it.name to it }.toMap()
val targets = buildTargets(sourceSetMap, dependencyResolver, project) ?: return null
computeSourceSetsDeferredInfo(sourceSets, targets)
@@ -60,37 +60,42 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
return getCoroutines(experimentalExt) as? String
}
private fun buildSourceSets(project: Project): Collection<KotlinSourceSetImpl>? {
private fun buildSourceSets(dependencyResolver: DependencyResolver, project: Project): Collection<KotlinSourceSetImpl>? {
val kotlinExt = project.extensions.findByName("kotlin") ?: return null
val getSourceSets = kotlinExt.javaClass.getMethodOrNull("getSourceSets") ?: return null
@Suppress("UNCHECKED_CAST")
val sourceSets =
(getSourceSets(kotlinExt) as? NamedDomainObjectContainer<Named>)?.asMap?.values ?: emptyList<Named>()
return sourceSets.mapNotNull { buildSourceSet(it) }
return sourceSets.mapNotNull { buildSourceSet(it, dependencyResolver, project) }
}
private fun buildSourceSet(gradleSourceSet: Named): KotlinSourceSetImpl? {
private fun buildSourceSet(
gradleSourceSet: Named,
dependencyResolver: DependencyResolver,
project: Project
): KotlinSourceSetImpl? {
val sourceSetClass = gradleSourceSet.javaClass
val getSourceDirSet = sourceSetClass.getMethodOrNull("getKotlin") ?: return null
val getResourceDirSet = sourceSetClass.getMethodOrNull("getResources") ?: return null
val getDependsOn = sourceSetClass.getMethodOrNull("getDependsOn") ?: return null
val sourceDirs = (getSourceDirSet(gradleSourceSet) as? SourceDirectorySet)?.srcDirs ?: emptySet()
val resourceDirs = (getResourceDirSet(gradleSourceSet) as? SourceDirectorySet)?.srcDirs ?: emptySet()
val dependencies = buildSourceSetDependencies(gradleSourceSet, dependencyResolver, project)
@Suppress("UNCHECKED_CAST")
val dependsOnSourceSets = (getDependsOn(gradleSourceSet) as? Set<Named>)?.mapTo(LinkedHashSet()) { it.name } ?: emptySet<String>()
return KotlinSourceSetImpl(gradleSourceSet.name, sourceDirs, resourceDirs, dependsOnSourceSets)
return KotlinSourceSetImpl(gradleSourceSet.name, sourceDirs, resourceDirs, dependencies, dependsOnSourceSets)
}
private fun buildDependencies(
gradleCompilation: Any,
dependencyHolder: Any,
dependencyResolver: DependencyResolver,
configurationNameAccessor: String,
scope: String,
project: Project
): Collection<KotlinDependency> {
val gradleCompilationClass = gradleCompilation.javaClass
val getConfigurationName = gradleCompilationClass.getMethodOrNull(configurationNameAccessor) ?: return emptyList()
val configurationName = getConfigurationName(gradleCompilation) as? String ?: return emptyList()
val dependencyHolderClass = dependencyHolder.javaClass
val getConfigurationName = dependencyHolderClass.getMethodOrNull(configurationNameAccessor) ?: return emptyList()
val configurationName = getConfigurationName(dependencyHolder) as? String ?: return emptyList()
val configuration = project.configurations.findByName(configurationName) ?: return emptyList()
if (!configuration.isCanBeResolved) return emptyList()
val artifactsByProjectPath = configuration
@@ -180,11 +185,11 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
val output = buildCompilationOutput(gradleCompilation, compileKotlinTask) ?: return null
val arguments = buildCompilationArguments(compileKotlinTask) ?: return null
val dependencyClasspath = buildDependencyClasspath(compileKotlinTask)
val dependencies = buildDependencies(gradleCompilation, dependencyResolver, project)
val dependencies = buildCompilationDependencies(gradleCompilation, dependencyResolver, project)
return KotlinCompilationImpl(isAndroid, gradleCompilation.name, kotlinSourceSets, dependencies, output, arguments, dependencyClasspath)
}
private fun buildDependencies(
private fun buildCompilationDependencies(
gradleCompilation: Named,
dependencyResolver: DependencyResolver,
project: Project
@@ -199,6 +204,27 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
}
}
private fun buildSourceSetDependencies(
gradleSourceSet: Named,
dependencyResolver: DependencyResolver,
project: Project
): Set<KotlinDependency> {
return LinkedHashSet<KotlinDependency>().apply {
this += buildDependencies(
gradleSourceSet, dependencyResolver, "getApiConfigurationName", "COMPILE", project
)
this += buildDependencies(
gradleSourceSet, dependencyResolver, "getImplementationConfigurationName", "COMPILE", project
)
this += buildDependencies(
gradleSourceSet, dependencyResolver, "getCompileOnlyConfigurationName", "COMPILE", project
)
this += buildDependencies(
gradleSourceSet, dependencyResolver, "getRuntimeOnlyConfigurationName", "RUNTIME", project
)
}
}
private fun buildCompilationArguments(compileKotlinTask: Task): KotlinCompilationArguments? {
val compileTaskClass = compileKotlinTask.javaClass
val getCurrentArguments = compileTaskClass.getMethodOrNull("getSerializedCompilerArguments") ?: return null
@@ -252,7 +278,6 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
for (sourceSet in sourceSets) {
val compilations = sourceSetToCompilations[sourceSet] ?: continue
sourceSet.platform = compilations.map { it.platform }.distinct().singleOrNull() ?: KotlinPlatform.COMMON
sourceSet.dependencies = compilations.flatMapTo(LinkedHashSet()) { it.dependencies }
sourceSet.isTestModule = compilations.all { it.isTestModule }
sourceSet.isAndroid = compilations.all { it.isAndroid }
}
@@ -11,6 +11,7 @@ class KotlinSourceSetImpl(
override val name: String,
override val sourceDirs: Set<File>,
override val resourceDirs: Set<File>,
override val dependencies: Set<KotlinDependency>,
override val dependsOnSourceSets: Set<String>
) : KotlinSourceSet {
override var isAndroid: Boolean = false
@@ -19,9 +20,6 @@ class KotlinSourceSetImpl(
override var platform: KotlinPlatform = KotlinPlatform.COMMON
internal set
override var dependencies: Set<KotlinDependency> = emptySet()
internal set
override var isTestModule: Boolean = false
internal set