Add basic test for Kotlin Project Model compiler plugins

This commit is contained in:
Anton Lakotka
2021-04-25 23:08:34 +02:00
committed by Space
parent a0fb5c31ea
commit 26a2509ebb
3 changed files with 200 additions and 44 deletions
@@ -200,6 +200,31 @@ internal class CompilationSpecificPluginPath {
assertTrue("shared" !in project.subplugins("jvm"))
}
private abstract class FakeSubPlugin(
val id: String,
val idNative: String? = null,
val isApplicablePredicate: KotlinCompilation<*>.() -> Boolean
) : KotlinCompilerPluginSupportPlugin {
override fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean = kotlinCompilation.isApplicablePredicate()
override fun applyToCompilation(kotlinCompilation: KotlinCompilation<*>): Provider<List<SubpluginOption>> =
kotlinCompilation.target.project.provider { emptyList<SubpluginOption>() }
override fun getCompilerPluginId(): String = id
override fun getPluginArtifact(): SubpluginArtifact = SubpluginArtifact(
"test",
id
)
override fun getPluginArtifactForNative(): SubpluginArtifact? = idNative?.let {
SubpluginArtifact(
"test",
it
)
}
}
private fun pluginClassPathConfiguration(target: String, compilation: String) =
"kotlinCompilerPluginClasspath${target.capitalize()}${compilation.capitalize()}"
@@ -227,48 +252,4 @@ internal class CompilationSpecificPluginPath {
?.toSet()
?: emptySet()
private fun buildProject(
configBuilder: ProjectBuilder.() -> Unit = { Unit },
configProject: Project.() -> Unit
): ProjectInternal = ProjectBuilder
.builder()
.apply(configBuilder)
.build()
.apply(configProject)
.let { it as ProjectInternal }
private fun buildProjectWithMPP(code: Project.() -> Unit) = buildProject {
project.plugins.apply("kotlin-multiplatform")
code()
}
private fun Project.kotlin(code: KotlinMultiplatformExtension.() -> Unit) {
val kotlin = project.kotlinExtension as KotlinMultiplatformExtension
kotlin.code()
}
private abstract class FakeSubPlugin(
val id: String,
val idNative: String? = null,
val isApplicablePredicate: KotlinCompilation<*>.() -> Boolean
) : KotlinCompilerPluginSupportPlugin {
override fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean = kotlinCompilation.isApplicablePredicate()
override fun applyToCompilation(kotlinCompilation: KotlinCompilation<*>): Provider<List<SubpluginOption>> =
kotlinCompilation.target.project.provider { emptyList<SubpluginOption>() }
override fun getCompilerPluginId(): String = id
override fun getPluginArtifact(): SubpluginArtifact = SubpluginArtifact(
"test",
id
)
override fun getPluginArtifactForNative(): SubpluginArtifact? = idNative?.let {
SubpluginArtifact(
"test",
it
)
}
}
}
@@ -0,0 +1,131 @@
/*
* 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.
*/
@file:Suppress("invisible_reference", "invisible_member", "FunctionName")
package org.jetbrains.kotlin.gradle.mpp
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmCompilerPlugin
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinLinuxX64Variant
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.jvm
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinNativeCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerPluginData
import org.jetbrains.kotlin.project.model.*
import org.junit.Test
import kotlin.test.assertEquals
class KpmCompilerPluginTest {
@Test
fun `basic plugin with kpm`() {
class TestPlugin : FakeKpmPlugin(
id = "test",
options = mapOf("a" to "b"),
metadataArtifact = "metadata",
metadataNativeArtifact = "metadata-native",
platformArtifact = "platform"
)
/**
* Applies plugin only for Native Variant compilation
* nothing for fragment metadata compilation
*/
class NativeOnly : FakeKpmPlugin(
id = "native-only",
options = mapOf("a" to "c"),
platformArtifact = "native-only"
) {
override fun forPlatformCompilation(variant: KotlinModuleVariant): PluginData? =
if (variant.platform == KotlinPlatformTypeAttribute.NATIVE) {
super.forPlatformCompilation(variant)
} else {
null
}
}
val project = buildProjectWithKPM {
plugins.apply(TestPlugin::class.java)
plugins.apply(NativeOnly::class.java)
projectModel {
main {
jvm
val linuxX64 = fragments.create("linuxX64", KotlinLinuxX64Variant::class.java)
val jvmAndLinux = fragments.create("jvmAndLinux")
jvm.refines(jvmAndLinux)
linuxX64.refines(jvmAndLinux)
}
}
}
project.evaluate()
project.pluginDataOfTask("compileCommonMainKotlinMetadata").run {
assertEquals(setOf("metadata"), artifacts())
assertEquals(listOf("plugin:test:a=b"), options.arguments)
}
project.pluginDataOfTask("compileCommonMainKotlinNativeMetadata").run {
assertEquals(setOf("metadata-native"), artifacts())
assertEquals(listOf("plugin:test:a=b"), options.arguments)
}
project.pluginDataOfTask("compileKotlinJvm").run {
assertEquals(setOf("platform"), artifacts())
assertEquals(listOf("plugin:test:a=b"), options.arguments)
}
project.pluginDataOfTask("compileKotlinLinuxX64").run {
assertEquals(setOf("platform", "native-only"), artifacts())
assertEquals(listOf("plugin:test:a=b", "plugin:native-only:a=c"), options.arguments)
}
}
private fun Project.pluginDataOfTask(taskName: String) = this
.tasks
.getByName(taskName)
.let {
when(it) {
is AbstractKotlinCompile<*> -> it.kotlinPluginData
is AbstractKotlinNativeCompile<*, *> -> it.kotlinPluginData
else -> error("Unknown task type: $it")
}
}
?.get()
?: error("Plugin Data not found")
private fun KotlinCompilerPluginData.artifacts() = classpath
.let { it as Configuration }
.allDependencies
.map { it.name }
.toSet()
private open class FakeKpmPlugin(
val id: String,
val options: Map<String, String> = emptyMap(),
val metadataArtifact: String? = null,
val metadataNativeArtifact: String? = null,
val platformArtifact: String? = null
) : KpmCompilerPlugin, GradleKpmCompilerPlugin {
override fun apply(target: Project) = Unit
override val kpmCompilerPlugin get() = this
private fun pluginData(artifact: String) = PluginData(
pluginId = id,
artifact = PluginData.ArtifactCoordinates(
group = "test",
artifact = artifact
),
options = options.map { PluginData.PluginOption(it.key, it.value) }
)
override fun forMetadataCompilation(fragment: KotlinModuleFragment) = metadataArtifact?.let(::pluginData)
override fun forNativeMetadataCompilation(fragment: KotlinModuleFragment) = metadataNativeArtifact?.let(::pluginData)
override fun forPlatformCompilation(variant: KotlinModuleVariant) = platformArtifact?.let(::pluginData)
}
}
@@ -0,0 +1,44 @@
/*
* 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.gradle.mpp
import org.gradle.api.Project
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension
fun buildProject(
configBuilder: ProjectBuilder.() -> Unit = { Unit },
configProject: Project.() -> Unit
): ProjectInternal = ProjectBuilder
.builder()
.apply(configBuilder)
.build()
.apply(configProject)
.let { it as ProjectInternal }
fun buildProjectWithMPP(code: Project.() -> Unit) = buildProject {
project.plugins.apply("kotlin-multiplatform")
code()
}
fun buildProjectWithKPM(code: Project.() -> Unit) = buildProject {
project.plugins.apply("org.jetbrains.kotlin.multiplatform.pm20")
code()
}
fun Project.kotlin(code: KotlinMultiplatformExtension.() -> Unit) {
val kotlin = project.kotlinExtension as KotlinMultiplatformExtension
kotlin.code()
}
fun Project.projectModel(code: KotlinPm20ProjectExtension.() -> Unit) {
val extension = project.extensions.getByType(KotlinPm20ProjectExtension::class.java)
extension.code()
}