From 1c277c7780296553cd351535715a14bc01670129 Mon Sep 17 00:00:00 2001 From: Brian Norman Date: Sun, 29 Mar 2026 08:23:17 -0500 Subject: [PATCH] Add annotations as JS library for all tests --- compiler-plugin/build.gradle.kts | 24 +++++++++-- .../services/PluginAnnotationsProvider.kt | 43 ++++++++++++++++--- .../testData/box/simple.fir.ir.txt | 2 + compiler-plugin/testData/box/simple.fir.txt | 2 +- compiler-plugin/testData/box/simple.kt | 3 ++ 5 files changed, 63 insertions(+), 11 deletions(-) diff --git a/compiler-plugin/build.gradle.kts b/compiler-plugin/build.gradle.kts index 2913e26..52da70b 100644 --- a/compiler-plugin/build.gradle.kts +++ b/compiler-plugin/build.gradle.kts @@ -1,6 +1,8 @@ @file:OptIn(ExperimentalWasmDsl::class) import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages import org.jetbrains.kotlin.gradle.targets.wasm.d8.D8EnvSpec import org.jetbrains.kotlin.gradle.targets.wasm.d8.D8Plugin @@ -32,9 +34,22 @@ idea { module.generatedSourceDirs.add(projectDir.resolve("test-gen")) } -val annotationsRuntimeClasspath: Configuration by configurations.creating { isTransitive = false } val testArtifacts: Configuration by configurations.creating +val annotationsRuntimeClasspath by configurations.dependencyScope("annotationsRuntimeClasspath") { + isTransitive = false +} +val annotationsJvmRuntimeClasspath by configurations.resolvable("annotationsJvmRuntimeClasspath") { + extendsFrom(annotationsRuntimeClasspath) +} +val annotationsJsRuntimeClasspath by configurations.resolvable("annotationsJsRuntimeClasspath") { + extendsFrom(annotationsRuntimeClasspath) + attributes { + attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_RUNTIME)) + attribute(KotlinPlatformType.attribute, KotlinPlatformType.js) + } +} + dependencies { compileOnly(libs.kotlin.compiler) @@ -67,12 +82,15 @@ buildConfig { } tasks.test { - dependsOn(annotationsRuntimeClasspath) + dependsOn(testArtifacts) + dependsOn(annotationsJvmRuntimeClasspath) + dependsOn(annotationsJsRuntimeClasspath) useJUnitPlatform() workingDir = rootDir - systemProperty("annotationsRuntime.classpath", annotationsRuntimeClasspath.asPath) + systemProperty("annotationsRuntime.jvm.classpath", annotationsJvmRuntimeClasspath.asPath) + systemProperty("annotationsRuntime.js.classpath", annotationsJsRuntimeClasspath.asPath) // Properties required to run the internal test framework. setLibraryProperty("org.jetbrains.kotlin.test.kotlin-stdlib", "kotlin-stdlib") diff --git a/compiler-plugin/test-fixtures/org/jetbrains/kotlin/compiler/plugin/template/services/PluginAnnotationsProvider.kt b/compiler-plugin/test-fixtures/org/jetbrains/kotlin/compiler/plugin/template/services/PluginAnnotationsProvider.kt index 0a0cebc..716cd4f 100644 --- a/compiler-plugin/test-fixtures/org/jetbrains/kotlin/compiler/plugin/template/services/PluginAnnotationsProvider.kt +++ b/compiler-plugin/test-fixtures/org/jetbrains/kotlin/compiler/plugin/template/services/PluginAnnotationsProvider.kt @@ -2,17 +2,17 @@ package org.jetbrains.kotlin.compiler.plugin.template.services import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.js.config.JSConfigurationKeys +import org.jetbrains.kotlin.platform.isJs +import org.jetbrains.kotlin.platform.jvm.isJvm import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.services.EnvironmentConfigurator import org.jetbrains.kotlin.test.services.RuntimeClasspathProvider import org.jetbrains.kotlin.test.services.TestServices +import org.jetbrains.kotlin.test.services.targetPlatform import java.io.File -private val annotationsRuntimeClasspath = - System.getProperty("annotationsRuntime.classpath")?.split(File.pathSeparator)?.map(::File) - ?: error("Unable to get a valid classpath from 'annotationsRuntime.classpath' property") - fun TestConfigurationBuilder.configureAnnotations() { useConfigurators(::PluginAnnotationsProvider) useCustomRuntimeClasspathProviders(::PluginAnnotationsClasspathProvider) @@ -20,10 +20,39 @@ fun TestConfigurationBuilder.configureAnnotations() { private class PluginAnnotationsProvider(testServices: TestServices) : EnvironmentConfigurator(testServices) { override fun configureCompilerConfiguration(configuration: CompilerConfiguration, module: TestModule) { - configuration.addJvmClasspathRoots(annotationsRuntimeClasspath) + val platform = module.targetPlatform(testServices) + when { + platform.isJvm() -> { + configuration.addJvmClasspathRoots(annotationsJvmRuntimeClasspath) + } + + platform.isJs() -> { + val libraries = configuration.getList(JSConfigurationKeys.LIBRARIES) + configuration.put( + JSConfigurationKeys.LIBRARIES, + libraries + annotationsJsRuntimeClasspath.map { it.absolutePath }, + ) + } + } } } private class PluginAnnotationsClasspathProvider(testServices: TestServices) : RuntimeClasspathProvider(testServices) { - override fun runtimeClassPaths(module: TestModule) = annotationsRuntimeClasspath -} \ No newline at end of file + override fun runtimeClassPaths(module: TestModule): List { + val targetPlatform = module.targetPlatform(testServices) + return when { + targetPlatform.isJvm() -> annotationsJvmRuntimeClasspath + targetPlatform.isJs() -> annotationsJsRuntimeClasspath + else -> emptyList() + } + } +} + +private val annotationsJvmRuntimeClasspath = classpathFiles("annotationsRuntime.jvm.classpath") +private val annotationsJsRuntimeClasspath = classpathFiles("annotationsRuntime.js.classpath") + +private fun classpathFiles(property: String): List { + val property = System.getProperty(property) + ?: error("Unable to get a valid classpath from '$property' property") + return property.split(File.pathSeparator).map(::File) +} diff --git a/compiler-plugin/testData/box/simple.fir.ir.txt b/compiler-plugin/testData/box/simple.fir.ir.txt index 3478e8f..0eea3f9 100644 --- a/compiler-plugin/testData/box/simple.fir.ir.txt +++ b/compiler-plugin/testData/box/simple.fir.ir.txt @@ -1,5 +1,7 @@ FILE fqName:foo.bar fileName:/simple.kt FUN name:box visibility:public modality:FINAL returnType:kotlin.String + annotations: + SomeAnnotation BLOCK_BODY VAR name:result type:kotlin.String [val] CALL 'public final fun foo (): kotlin.String declared in foo.bar.MyClass' type=kotlin.String origin=null diff --git a/compiler-plugin/testData/box/simple.fir.txt b/compiler-plugin/testData/box/simple.fir.txt index f303b9d..91e7306 100644 --- a/compiler-plugin/testData/box/simple.fir.txt +++ b/compiler-plugin/testData/box/simple.fir.txt @@ -1,7 +1,7 @@ FILE: simple.kt package foo.bar - public final fun box(): R|kotlin/String| { + @R|org/jetbrains/kotlin/compiler/plugin/template/SomeAnnotation|() public final fun box(): R|kotlin/String| { lval result: R|kotlin/String| = R|foo/bar/MyClass|().R|foo/bar/MyClass.foo|() ^box when () { ==(R|/result|, String(Hello world)) -> { diff --git a/compiler-plugin/testData/box/simple.kt b/compiler-plugin/testData/box/simple.kt index 7768306..080ecbf 100644 --- a/compiler-plugin/testData/box/simple.kt +++ b/compiler-plugin/testData/box/simple.kt @@ -1,5 +1,8 @@ package foo.bar +import org.jetbrains.kotlin.compiler.plugin.template.SomeAnnotation + +@SomeAnnotation fun box(): String { val result = MyClass().foo() return if (result == "Hello world") { "OK" } else { "Fail: $result" }