[Kotlin Project Model] Add compiler plugin support

This commit is contained in:
Anton Lakotka
2021-04-23 16:42:45 +02:00
committed by Space
parent 16e6fe0e08
commit 5a58c1c437
13 changed files with 292 additions and 25 deletions
@@ -5,6 +5,10 @@
package org.jetbrains.kotlin.project.model
// TODO: Add better Kotlin Variant Attributes management
// Ideally we should respect the nature of Attributes and express values in form of Complete Lattice
// Moreover we can add support for default and most used Value Types (eg. Enums)
open class KotlinAttributeKey(
val uniqueName: String
) {
@@ -15,6 +19,7 @@ open class KotlinAttributeKey(
uniqueName.hashCode()
}
// TODO: Introduce ENUM
object KotlinPlatformTypeAttribute : KotlinAttributeKey("org.jetbrains.kotlin.platform.type") {
const val JVM = "jvm"
const val ANDROID_JVM = "androidJvm"
@@ -42,6 +42,8 @@ interface KotlinModule {
val variants: Iterable<KotlinModuleVariant>
get() = fragments.filterIsInstance<KotlinModuleVariant>()
val plugins: Iterable<KpmCompilerPlugin>
// TODO: isSynthetic?
}
@@ -50,5 +52,7 @@ open class BasicKotlinModule(
) : KotlinModule {
override val fragments = mutableListOf<BasicKotlinModuleFragment>()
override val plugins = mutableListOf<KpmCompilerPlugin>()
override fun toString(): String = "module $moduleIdentifier"
}
@@ -45,6 +45,7 @@ val KotlinModuleFragment.refinesClosure: Set<KotlinModuleFragment>
visit(this@refinesClosure)
}
val KotlinModuleVariant.platform get() = variantAttributes[KotlinPlatformTypeAttribute]
open class BasicKotlinModuleFragment(
override val containingModule: KotlinModule,
@@ -0,0 +1,102 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.project.model
/**
* Adapts Kotlin Compiler Plugin for Multiplatform Kotlin Project Model
* Build System uses this interface to identify applicable plugin artifacts and its options
* before executing actual Kotlin Compilation
*/
interface KpmCompilerPlugin {
/**
* Returns [PluginData] when applicable for [fragment] compilation
* Returns [null] if not applicable
*/
fun forMetadataCompilation(fragment: KotlinModuleFragment): PluginData?
/**
* Returns [PluginData] when applicable for [fragment] compilation
* Returns [null] if not applicable
*/
fun forNativeMetadataCompilation(fragment: KotlinModuleFragment): PluginData?
/**
* Returns [PluginData] when applicable for [variant] compilation
* Returns [null] if not applicable
*/
fun forPlatformCompilation(variant: KotlinModuleVariant): PluginData?
}
/**
* Plugin data can be used for changing some compilation request
*/
data class PluginData(
val pluginId: String,
val artifact: ArtifactCoordinates,
val options: List<PluginOption>
) {
// FIXME: (?) Is it common thing or gradle/maven centric?
data class ArtifactCoordinates(
val group: String,
val artifact: String,
val version: String? = null
)
data class PluginOption(
val key: String,
val value: String
)
}
// TODO: It should be part of "Compilation Process": KotlinModule.compilationRequestFor(METADATA | PLATFORM) -> CompilationRequest
// But there is no such thing at the moment :)
fun KotlinModuleFragment.metadataCompilationPluginData(): List<PluginData> =
containingModule
.plugins
.mapNotNull { plugin -> plugin.forMetadataCompilation(this) }
fun KotlinModuleFragment.nativeMetadataCompilationPluginData(): List<PluginData> =
containingModule
.plugins
.mapNotNull { plugin -> plugin.forNativeMetadataCompilation(this) }
fun KotlinModuleVariant.platformCompilationPluginData(): List<PluginData> =
containingModule
.plugins
.mapNotNull { plugin -> plugin.forPlatformCompilation(this) }
/**
* Represents trivial Compiler Plugin adapter for Kotlin Project Model
* Where Compiler Plugin can have common and native artifacts
*/
abstract class BasicKpmCompilerPlugin : KpmCompilerPlugin {
abstract val pluginId: String
protected abstract fun commonPluginArtifact(): PluginData.ArtifactCoordinates?
protected abstract fun nativePluginArtifact(): PluginData.ArtifactCoordinates?
protected abstract val pluginOptions: List<PluginData.PluginOption>
override fun forMetadataCompilation(fragment: KotlinModuleFragment) = pluginDataOrNull(commonPluginArtifact())
override fun forNativeMetadataCompilation(fragment: KotlinModuleFragment) = pluginDataOrNull(nativePluginArtifact())
override fun forPlatformCompilation(variant: KotlinModuleVariant) =
when (variant.platform) {
KotlinPlatformTypeAttribute.NATIVE -> nativePluginArtifact()
else -> commonPluginArtifact()
}.let(::pluginDataOrNull)
private fun pluginDataOrNull(artifact: PluginData.ArtifactCoordinates?) =
if (artifact != null) PluginData(pluginId, artifact, pluginOptions)
else null
}