ModuleOrigin -> ModuleIdentifier
This commit is contained in:
committed by
TeamCityServer
parent
66b8a444c2
commit
7103aa3100
+12
-14
@@ -18,18 +18,18 @@ import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.currentBuildId
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.matchesModule
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.representsProject
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.getVisibleSourceSetsFromAssociateCompilations
|
||||
import org.jetbrains.kotlin.project.model.*
|
||||
|
||||
class ProjectStructureMetadataModuleBuilder {
|
||||
private val modulesCache = mutableMapOf<String, KotlinModule>()
|
||||
private val modulesCache = mutableMapOf<ModuleIdentifier, KotlinModule>()
|
||||
|
||||
private fun buildModuleFromProjectStructureMetadata(
|
||||
moduleName: String,
|
||||
moduleOrigin: ModuleOrigin,
|
||||
moduleIdentifier: ModuleIdentifier,
|
||||
metadata: KotlinProjectStructureMetadata
|
||||
): KotlinModule =
|
||||
BasicKotlinModule(moduleName, moduleOrigin).apply {
|
||||
BasicKotlinModule(moduleIdentifier).apply {
|
||||
metadata.sourceSetNamesByVariantName.keys.forEach { variantName ->
|
||||
fragments.add(BasicKotlinModuleVariant(this@apply, variantName))
|
||||
}
|
||||
@@ -53,11 +53,10 @@ class ProjectStructureMetadataModuleBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
fun getModule(name: String, moduleOrigin: ModuleOrigin, projectStructureMetadata: KotlinProjectStructureMetadata): KotlinModule {
|
||||
return modulesCache.getOrPut(name) {
|
||||
fun getModule(moduleIdentifier: ModuleIdentifier, projectStructureMetadata: KotlinProjectStructureMetadata): KotlinModule {
|
||||
return modulesCache.getOrPut(moduleIdentifier) {
|
||||
buildModuleFromProjectStructureMetadata(
|
||||
name,
|
||||
moduleOrigin,
|
||||
moduleIdentifier,
|
||||
projectStructureMetadata
|
||||
)
|
||||
}
|
||||
@@ -77,7 +76,7 @@ class GradleProjectModuleBuilder(private val addInferredSourceSetVisibilityAsExp
|
||||
else -> return null
|
||||
}
|
||||
|
||||
return BasicKotlinModule(project.path, LocalBuild(project.currentBuildId().name)).apply {
|
||||
return BasicKotlinModule(LocalModuleIdentifier(project.currentBuildId().name, project.path)).apply {
|
||||
val variantToCompilation = mutableMapOf<KotlinModuleFragment, KotlinCompilation<*>>()
|
||||
|
||||
targets.forEach { target ->
|
||||
@@ -109,7 +108,7 @@ class GradleProjectModuleBuilder(private val addInferredSourceSetVisibilityAsExp
|
||||
extension.sourceSets.forEach { sourceSet ->
|
||||
val existingVariant = fragments.filterIsInstance<BasicKotlinModuleVariant>().find { it.fragmentName == sourceSet.name }
|
||||
val fragment = existingVariant ?: BasicKotlinModuleFragment(this@apply, sourceSet.name).also { fragments.add(it) }
|
||||
fragment.kotlinSourceRoots = sourceSet.kotlin.sourceDirectories.toList()
|
||||
fragment.kotlinSourceDirectories = sourceSet.kotlin.sourceDirectories.toList()
|
||||
|
||||
// FIXME: Kotlin/Native implementation-effective-api dependencies are missing here. Introduce dependency scopes
|
||||
project.configurations.getByName(sourceSet.apiConfigurationName).allDependencies.forEach {
|
||||
@@ -163,9 +162,9 @@ internal fun Dependency.toModuleDependency(
|
||||
project: Project
|
||||
) = when (val dependency = this) {
|
||||
is ProjectDependency ->
|
||||
LocalModuleDependency(LocalBuild(project.currentBuildId().name), dependency.dependencyProject.path)
|
||||
ModuleDependency(LocalModuleIdentifier(project.currentBuildId().name, dependency.dependencyProject.path))
|
||||
else ->
|
||||
ExternalModuleDependency(ExternalOrigin(listOfNotNull(dependency.group, dependency.name)))
|
||||
ModuleDependency(MavenModuleIdentifier(dependency.group.orEmpty(), dependency.name))
|
||||
}
|
||||
|
||||
private fun BasicKotlinModule.fragmentByName(name: String) =
|
||||
@@ -184,8 +183,7 @@ class GradleModuleVariantResolver(val project: Project) : ModuleVariantResolver
|
||||
val module = requestingVariant.containingModule
|
||||
|
||||
// This implementation can only resolve variants for the current project's KotlinModule
|
||||
require(module.moduleName == project.path)
|
||||
require(module.moduleOrigin.let { it is LocalBuild && it.buildId == project.currentBuildId().name })
|
||||
require(module.representsProject(project))
|
||||
|
||||
val targets =
|
||||
project.multiplatformExtensionOrNull?.targets ?: listOf((project.kotlinExtension as KotlinSingleTargetExtension).target)
|
||||
|
||||
+31
-30
@@ -13,7 +13,6 @@ import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
||||
import org.gradle.api.artifacts.result.ResolvedComponentResult
|
||||
import org.gradle.api.artifacts.result.ResolvedDependencyResult
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.GradleModuleVariantResolver
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.ProjectStructureMetadataModuleBuilder
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.GradleProjectModuleBuilder
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.getProjectStructureMetadata
|
||||
@@ -41,7 +40,7 @@ class GradleModuleDependencyResolver(
|
||||
projectModuleBuilder.buildModuleFromProject(project.project(id.projectPath))
|
||||
id is ModuleComponentIdentifier -> {
|
||||
val metadata = getProjectStructureMetadata(project, component, configurationToResolve) ?: return null
|
||||
projectStructureMetadataModuleBuilder.getModule(id.displayName, id.toModuleOrigin(), metadata)
|
||||
projectStructureMetadataModuleBuilder.getModule(id.toModuleIdentifier(), metadata)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
@@ -110,11 +109,7 @@ class FragmentDependenciesDiscovery(
|
||||
// TODO think about multi-variant stub modules for non-Kotlin modules which got more than one chosen variant
|
||||
private fun buildStubModule(resolvedComponentResult: ResolvedComponentResult, singleVariantName: String): KotlinModule {
|
||||
val moduleDependency = resolvedComponentResult.toModuleDependency()
|
||||
val moduleName = when (val id = resolvedComponentResult.id) {
|
||||
is ProjectComponentIdentifier -> id.projectPath
|
||||
else -> id.displayName
|
||||
}
|
||||
return BasicKotlinModule(moduleName, moduleDependency.moduleOrigin).apply {
|
||||
return BasicKotlinModule(moduleDependency.moduleIdentifier).apply {
|
||||
BasicKotlinModuleVariant(this@apply, singleVariantName).apply {
|
||||
fragments.add(this)
|
||||
this.declaredModuleDependencies.addAll(
|
||||
@@ -140,6 +135,7 @@ class VariantDependencyDiscovery(
|
||||
.find { it.defaultSourceSetName == fragment.fragmentName }
|
||||
requireNotNull(compilation)
|
||||
|
||||
// TODO distinguish between compile and runtime dependencies?
|
||||
val configuration = project.configurations.getByName(compilation.compileDependencyConfigurationName)
|
||||
return configuration.incoming.resolutionResult.allComponents
|
||||
}
|
||||
@@ -150,45 +146,50 @@ class VariantDependencyDiscovery(
|
||||
|
||||
val components = resolvedComponentResults(fragment)
|
||||
return components.mapNotNull { component ->
|
||||
when (val id = component.id) {
|
||||
is ProjectComponentIdentifier -> LocalModuleDependency(LocalBuild(id.build.name), id.projectPath)
|
||||
is ModuleComponentIdentifier -> ExternalModuleDependency(id.toModuleOrigin())
|
||||
else -> null // TODO check that no other options are possible, throw errors
|
||||
val moduleIdentifier = when (val id = component.id) {
|
||||
is ProjectComponentIdentifier -> LocalModuleIdentifier(id.build.name, id.projectPath)
|
||||
is ModuleComponentIdentifier -> id.toModuleIdentifier()
|
||||
else -> return@mapNotNull null // TODO check that no other options are possible, throw errors?
|
||||
}
|
||||
ModuleDependency(moduleIdentifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun ModuleComponentIdentifier.toModuleOrigin(): ExternalOrigin =
|
||||
ExternalOrigin(listOf(moduleIdentifier.group, moduleIdentifier.name))
|
||||
private fun ModuleComponentIdentifier.toModuleIdentifier(): MavenModuleIdentifier =
|
||||
MavenModuleIdentifier(moduleIdentifier.group, moduleIdentifier.name)
|
||||
|
||||
internal fun ComponentIdentifier.matchesModule(module: KotlinModule): Boolean {
|
||||
return when (val moduleSource = module.moduleOrigin) {
|
||||
is LocalBuild -> {
|
||||
return when (val moduleId = module.moduleIdentifier) {
|
||||
is LocalModuleIdentifier -> {
|
||||
val projectId = this as? ProjectComponentIdentifier
|
||||
projectId?.build?.name == moduleSource.buildId && projectId.projectPath == module.moduleName
|
||||
projectId?.build?.name == moduleId.buildId && projectId.projectPath == moduleId.projectId
|
||||
}
|
||||
is ExternalOrigin -> {
|
||||
val moduleId = this as? ModuleComponentIdentifier
|
||||
moduleId?.toModuleOrigin() == moduleSource
|
||||
is MavenModuleIdentifier -> {
|
||||
val componentId = this as? ModuleComponentIdentifier
|
||||
componentId?.toModuleIdentifier() == moduleId
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ResolvedComponentResult.toModuleDependency(): ModuleDependency = when (val id = id) {
|
||||
is ProjectComponentIdentifier -> LocalModuleDependency(LocalBuild(id.build.name), id.projectPath)
|
||||
is ModuleComponentIdentifier -> ExternalModuleDependency(id.toModuleOrigin())
|
||||
else -> ExternalModuleDependency(ExternalOrigin(listOf(moduleVersion?.group.orEmpty(), moduleVersion?.name.orEmpty())))
|
||||
}
|
||||
internal fun ResolvedComponentResult.toModuleDependency(): ModuleDependency = ModuleDependency(
|
||||
when (val id = id) {
|
||||
is ProjectComponentIdentifier -> LocalModuleIdentifier(id.build.name, id.projectPath)
|
||||
is ModuleComponentIdentifier -> id.toModuleIdentifier()
|
||||
else -> MavenModuleIdentifier(moduleVersion?.group.orEmpty(), moduleVersion?.name.orEmpty())
|
||||
}
|
||||
)
|
||||
|
||||
internal fun ComponentIdentifier.matchesModuleDependency(moduleDependency: ModuleDependency) =
|
||||
when (moduleDependency) {
|
||||
is LocalModuleDependency -> {
|
||||
when (val id = moduleDependency.moduleIdentifier) {
|
||||
is LocalModuleIdentifier -> {
|
||||
val projectId = this as? ProjectComponentIdentifier
|
||||
projectId?.build?.name == moduleDependency.moduleOrigin.buildId && projectId.projectPath == moduleDependency.moduleName
|
||||
projectId?.build?.name == id.buildId && projectId.projectPath == id.projectId
|
||||
}
|
||||
is ExternalModuleDependency -> {
|
||||
val moduleId = this as? ModuleComponentIdentifier
|
||||
moduleId?.toModuleOrigin() == moduleDependency.moduleOrigin
|
||||
is MavenModuleIdentifier -> {
|
||||
val componentId = this as? ModuleComponentIdentifier
|
||||
componentId?.toModuleIdentifier() == id
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
import org.jetbrains.kotlin.project.model.KotlinModule
|
||||
import org.jetbrains.kotlin.project.model.LocalBuild
|
||||
import org.jetbrains.kotlin.project.model.LocalModuleIdentifier
|
||||
|
||||
val KotlinProjectExtension.targets: Iterable<KotlinTarget>
|
||||
get() = when (this) {
|
||||
@@ -24,7 +24,7 @@ val KotlinProjectExtension.targets: Iterable<KotlinTarget>
|
||||
}
|
||||
|
||||
fun KotlinModule.representsProject(project: Project): Boolean =
|
||||
moduleOrigin.let { it is LocalBuild && it.buildId == project.currentBuildId().name } && moduleName == project.path
|
||||
moduleIdentifier.let { it is LocalModuleIdentifier && it.buildId == project.currentBuildId().name && it.projectId == project.path }
|
||||
|
||||
// FIXME internal API?
|
||||
fun Project.currentBuildId(): BuildIdentifier =
|
||||
|
||||
@@ -5,10 +5,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.project.model
|
||||
|
||||
// TODO ensure that resolvers are pluggable + custom dependency kinds (& result kinds?)
|
||||
// TODO think about state management: unresolved -> (known dependency graph?) ... -> completely resolved
|
||||
// it seems to be important to learn whether or not the model is final
|
||||
interface ModuleDependencyResolver {
|
||||
fun resolveDependency(moduleDependency: ModuleDependency): KotlinModule?
|
||||
}
|
||||
|
||||
// TODO merge with ModuleDependencyResolver?
|
||||
// Semantically, they are close and may use shared caches and other shared state in the implementations
|
||||
interface DependencyDiscovery {
|
||||
// TODO return dependency graph rather than just iterable?
|
||||
// TODO make this a partial function, too
|
||||
|
||||
@@ -5,13 +5,26 @@
|
||||
|
||||
package org.jetbrains.kotlin.project.model
|
||||
|
||||
sealed class ModuleOrigin
|
||||
data class LocalBuild(val buildId: String) : ModuleOrigin() // TODO add project ID?
|
||||
data class ExternalOrigin(val dependencyIdParts: List<String>) : ModuleOrigin()
|
||||
// TODO sealed with an abstract subclass? this will make exhaustive checks work
|
||||
open class ModuleIdentifier
|
||||
|
||||
// TODO consider id: Any, to allow IDs with custom equality?
|
||||
data class LocalModuleIdentifier(val buildId: String, val projectId: String) : ModuleIdentifier() {
|
||||
companion object {
|
||||
private const val SINGLE_BUILD_ID = ":"
|
||||
}
|
||||
|
||||
override fun toString(): String = "project '$projectId'" + buildId.takeIf { it != SINGLE_BUILD_ID }?.let { "(build '$it')" }.orEmpty()
|
||||
}
|
||||
|
||||
data class MavenModuleIdentifier(val group: String, val name: String) : ModuleIdentifier() {
|
||||
override fun toString(): String = "$group:$name"
|
||||
}
|
||||
|
||||
// TODO Gradle allows having multiple capabilities in a published module, we need to figure out how we can include them in the module IDs
|
||||
|
||||
interface KotlinModule {
|
||||
val moduleName: String
|
||||
val moduleOrigin: ModuleOrigin
|
||||
val moduleIdentifier: ModuleIdentifier
|
||||
|
||||
val fragments: Iterable<KotlinModuleFragment>
|
||||
|
||||
@@ -20,10 +33,9 @@ interface KotlinModule {
|
||||
}
|
||||
|
||||
class BasicKotlinModule(
|
||||
override val moduleName: String,
|
||||
override val moduleOrigin: ModuleOrigin
|
||||
override val moduleIdentifier: ModuleIdentifier
|
||||
) : KotlinModule {
|
||||
override val fragments = mutableListOf<BasicKotlinModuleFragment>()
|
||||
|
||||
override fun toString(): String = "module '$moduleName'"
|
||||
override fun toString(): String = "module $moduleIdentifier"
|
||||
}
|
||||
@@ -5,13 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.project.model
|
||||
|
||||
sealed class ModuleDependency(open val moduleOrigin: ModuleOrigin)
|
||||
|
||||
data class ExternalModuleDependency(override val moduleOrigin: ExternalOrigin) : ModuleDependency(moduleOrigin) {
|
||||
override fun toString() = "external dependency ${moduleOrigin.dependencyIdParts.joinToString(":")}"
|
||||
data class ModuleDependency(val moduleIdentifier: ModuleIdentifier) {
|
||||
override fun toString(): String = "dependency $moduleIdentifier"
|
||||
}
|
||||
|
||||
data class LocalModuleDependency(override val moduleOrigin: LocalBuild, val moduleName: String) :
|
||||
ModuleDependency(moduleOrigin) {
|
||||
override fun toString() = "local module $moduleName (build ${moduleOrigin.buildId})"
|
||||
}
|
||||
/**
|
||||
* TODO other kinds of dependencies: non-Kotlin: cinterop, CocoaPods, NPM dependencies?
|
||||
* support with different moduleIdentifiers? Introduce other kinds of dependencies than ModuleDependency?
|
||||
*/
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.project.model
|
||||
|
||||
fun module(name: String) = BasicKotlinModule(name, LocalBuild("current"))
|
||||
fun module(name: String) = BasicKotlinModule(LocalModuleIdentifier("current", name))
|
||||
|
||||
fun BasicKotlinModule.fragment(vararg nameParts: String): BasicKotlinModuleFragment =
|
||||
fragment(nameParts.drop(1).joinToString("", nameParts.first()) { it.capitalize() })
|
||||
|
||||
Reference in New Issue
Block a user