Skip to content

Commit

Permalink
Plugin sandbox: add test with metadata printed by kotlinp
Browse files Browse the repository at this point in the history
This is mainly to check that plugin-supplied annotations are serialized
correctly to metadata (KT-57919).
  • Loading branch information
udalov authored and Space Team committed Feb 18, 2025
1 parent 11ce2cf commit 5c09cae
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ import org.jetbrains.kotlin.lombok.AbstractFirPsiDiagnosticTestForLombok
import org.jetbrains.kotlin.lombok.AbstractIrBlackBoxCodegenTestForLombok
import org.jetbrains.kotlin.noarg.*
import org.jetbrains.kotlin.parcelize.test.runners.*
import org.jetbrains.kotlin.plugin.sandbox.AbstractFirLightTreePluginBlackBoxCodegenTest
import org.jetbrains.kotlin.plugin.sandbox.AbstractFirLoadK2CompiledWithPluginJsKotlinTest
import org.jetbrains.kotlin.plugin.sandbox.AbstractFirLoadK2CompiledWithPluginJvmKotlinTest
import org.jetbrains.kotlin.plugin.sandbox.AbstractFirPsiPluginDiagnosticTest
import org.jetbrains.kotlin.plugin.sandbox.*
import org.jetbrains.kotlin.powerassert.AbstractFirLightTreeBlackBoxCodegenTestForPowerAssert
import org.jetbrains.kotlin.powerassert.AbstractIrBlackBoxCodegenTestForPowerAssert
import org.jetbrains.kotlin.samWithReceiver.*
Expand Down Expand Up @@ -234,6 +231,10 @@ fun main(args: Array<String>) {
testClass<AbstractFirLoadK2CompiledWithPluginJsKotlinTest> {
model("firLoadK2Compiled")
}

testClass<AbstractFirMetadataPluginSandboxTest> {
model("metadata")
}
}

testGroup(
Expand Down
1 change: 1 addition & 0 deletions plugins/plugin-sandbox/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ dependencies {
testApi(project(":compiler:fir:checkers:checkers.native"))
testApi(project(":compiler:fir:checkers:checkers.wasm"))
testApi(project(":compiler:fir:plugin-utils"))
testImplementation(project(":tools:kotlinp-jvm"))

testRuntimeOnly(project(":core:descriptors.runtime"))
testRuntimeOnly(project(":compiler:fir:fir-serialization"))
Expand Down
10 changes: 10 additions & 0 deletions plugins/plugin-sandbox/testData/metadata/annotations.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package test

import org.jetbrains.kotlin.plugin.sandbox.AddAnnotations

@AddAnnotations
class Some(val x: Int) {
fun foo() {}

class Derived
}
34 changes: 34 additions & 0 deletions plugins/plugin-sandbox/testData/metadata/annotations.metadata.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// test/Some.class
// ------------------------------------------
@org/jetbrains/kotlin/plugin/sandbox/AddAnnotations
@org/jetbrains/kotlin/plugin/sandbox/AnnotationToAdd(booleanValue = true, byteValue = 1.toByte(), charValue = 'c', doubleValue = 4.2, floatValue = 2.4f, intValue = 42, longValue = 24L, shortValue = 7.toShort(), stringValue = "OK", vararg = [org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = []), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 1)]), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 2), org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 3)])])
public final class test/Some : kotlin/Any {

// signature: <init>(I)V
@org/jetbrains/kotlin/plugin/sandbox/AnnotationToAdd(booleanValue = true, byteValue = 1.toByte(), charValue = 'c', doubleValue = 4.2, floatValue = 2.4f, intValue = 42, longValue = 24L, shortValue = 7.toShort(), stringValue = "OK", vararg = [org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = []), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 1)]), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 2), org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 3)])])
public constructor(@org/jetbrains/kotlin/plugin/sandbox/AnnotationToAdd(booleanValue = true, byteValue = 1.toByte(), charValue = 'c', doubleValue = 4.2, floatValue = 2.4f, intValue = 42, longValue = 24L, shortValue = 7.toShort(), stringValue = "OK", vararg = [org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = []), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 1)]), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 2), org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 3)])]) x: kotlin/Int)

// signature: foo()V
@org/jetbrains/kotlin/plugin/sandbox/AnnotationToAdd(booleanValue = true, byteValue = 1.toByte(), charValue = 'c', doubleValue = 4.2, floatValue = 2.4f, intValue = 42, longValue = 24L, shortValue = 7.toShort(), stringValue = "OK", vararg = [org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = []), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 1)]), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 2), org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 3)])])
public final fun foo(): kotlin/Unit

// field: x:I
// getter: getX()I
// synthetic method for annotations: getX$annotations()V
@org/jetbrains/kotlin/plugin/sandbox/AnnotationToAdd(booleanValue = true, byteValue = 1.toByte(), charValue = 'c', doubleValue = 4.2, floatValue = 2.4f, intValue = 42, longValue = 24L, shortValue = 7.toShort(), stringValue = "OK", vararg = [org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = []), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 1)]), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 2), org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 3)])])
@org/jetbrains/kotlin/plugin/sandbox/AnnotationToAdd(booleanValue = true, byteValue = 1.toByte(), charValue = 'c', doubleValue = 4.2, floatValue = 2.4f, intValue = 42, longValue = 24L, shortValue = 7.toShort(), stringValue = "OK", vararg = [org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = []), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 1)]), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 2), org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 3)])])
public final val x: kotlin/Int
@org/jetbrains/kotlin/plugin/sandbox/AnnotationToAdd(booleanValue = true, byteValue = 1.toByte(), charValue = 'c', doubleValue = 4.2, floatValue = 2.4f, intValue = 42, longValue = 24L, shortValue = 7.toShort(), stringValue = "OK", vararg = [org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = []), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 1)]), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 2), org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 3)])])
public final /* non-default */ get

// nested class: Derived
}
// test/Some$Derived.class
// ------------------------------------------
@org/jetbrains/kotlin/plugin/sandbox/AnnotationToAdd(booleanValue = true, byteValue = 1.toByte(), charValue = 'c', doubleValue = 4.2, floatValue = 2.4f, intValue = 42, longValue = 24L, shortValue = 7.toShort(), stringValue = "OK", vararg = [org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = []), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 1)]), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 2), org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 3)])])
public final class test/Some.Derived : kotlin/Any {

// signature: <init>()V
@org/jetbrains/kotlin/plugin/sandbox/AnnotationToAdd(booleanValue = true, byteValue = 1.toByte(), charValue = 'c', doubleValue = 4.2, floatValue = 2.4f, intValue = 42, longValue = 24L, shortValue = 7.toShort(), stringValue = "OK", vararg = [org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = []), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 1)]), org/jetbrains/kotlin/plugin/sandbox/ArrayAnnotation(annotations = [org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 2), org/jetbrains/kotlin/plugin/sandbox/SimpleAnnotation(x = 3)])])
public constructor()
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,43 @@

package org.jetbrains.kotlin.plugin.sandbox

import org.jetbrains.kotlin.codegen.getClassFiles
import org.jetbrains.kotlin.js.test.fir.AbstractFirLoadK2CompiledJsKotlinTest
import org.jetbrains.kotlin.kotlinp.Settings
import org.jetbrains.kotlin.kotlinp.jvm.JvmKotlinp
import org.jetbrains.kotlin.kotlinp.jvm.readKotlinClassHeader
import org.jetbrains.kotlin.plugin.sandbox.PluginSandboxDirectives.DONT_LOAD_IN_SYNTHETIC_MODULES
import org.jetbrains.kotlin.test.FirParser
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.backend.handlers.IrPrettyKotlinDumpHandler
import org.jetbrains.kotlin.test.backend.handlers.JvmBinaryArtifactHandler
import org.jetbrains.kotlin.test.backend.ir.BackendCliJvmFacade
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.builders.configureFirHandlersStep
import org.jetbrains.kotlin.test.builders.configureIrHandlersStep
import org.jetbrains.kotlin.test.builders.configureJvmArtifactsHandlersStep
import org.jetbrains.kotlin.test.configuration.commonConfigurationForJvmTest
import org.jetbrains.kotlin.test.configuration.enableLazyResolvePhaseChecking
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives.ENABLE_PLUGIN_PHASES
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives.FIR_DUMP
import org.jetbrains.kotlin.test.directives.configureFirParser
import org.jetbrains.kotlin.test.frontend.fir.Fir2IrCliJvmFacade
import org.jetbrains.kotlin.test.frontend.fir.FirCliJvmFacade
import org.jetbrains.kotlin.test.frontend.fir.FirFailingTestSuppressor
import org.jetbrains.kotlin.test.frontend.fir.handlers.FirDiagnosticsHandler
import org.jetbrains.kotlin.test.model.BinaryArtifacts
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.runners.AbstractFirLoadK2CompiledJvmKotlinTest
import org.jetbrains.kotlin.test.runners.AbstractFirPsiDiagnosticTest
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerWithTargetBackendTest
import org.jetbrains.kotlin.test.runners.codegen.AbstractFirLightTreeBlackBoxCodegenTest
import org.jetbrains.kotlin.test.configuration.enableLazyResolvePhaseChecking
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.moduleStructure
import org.jetbrains.kotlin.test.utils.MultiModuleInfoDumper
import org.jetbrains.kotlin.test.utils.withExtension
import org.jetbrains.org.objectweb.asm.ClassReader
import kotlin.metadata.jvm.KotlinClassMetadata

open class AbstractFirLightTreePluginBlackBoxCodegenTest : AbstractFirLightTreeBlackBoxCodegenTest() {
override fun configure(builder: TestConfigurationBuilder) {
Expand Down Expand Up @@ -62,12 +87,52 @@ open class AbstractFirLoadK2CompiledWithPluginJsKotlinTest : AbstractFirLoadK2Co
}
}

fun TestConfigurationBuilder.commonFirWithPluginFrontendConfiguration() {
open class AbstractFirMetadataPluginSandboxTest : AbstractKotlinCompilerWithTargetBackendTest(TargetBackend.JVM_IR) {
override fun configure(builder: TestConfigurationBuilder) {
with(builder) {
commonConfigurationForJvmTest(FrontendKinds.FIR, ::FirCliJvmFacade, ::Fir2IrCliJvmFacade, ::BackendCliJvmFacade)
configureFirHandlersStep {
useHandlers(::FirDiagnosticsHandler)
}
enableMetaInfoHandler()
configureFirParser(FirParser.LightTree)
commonFirWithPluginFrontendConfiguration(dumpFir = false)
configureJvmArtifactsHandlersStep {
useHandlers(::CompareMetadataHandler)
}
}
}
}

class CompareMetadataHandler(testServices: TestServices) : JvmBinaryArtifactHandler(testServices) {
private val multiModuleInfoDumper = MultiModuleInfoDumper()

override fun processModule(module: TestModule, info: BinaryArtifacts.Jvm) {
val kotlinp = JvmKotlinp(Settings(isVerbose = false, sortDeclarations = false))
multiModuleInfoDumper.builderForModule(module).append(buildString {
for (outputFile in info.classFileFactory.getClassFiles()) {
val metadata = ClassReader(outputFile.asByteArray().inputStream()).readKotlinClassHeader()!!
appendLine("// ${outputFile.relativePath}")
appendLine("// ------------------------------------------")
append(kotlinp.printClassFile(KotlinClassMetadata.readStrict(metadata)))
}
})
}

override fun processAfterAllModules(someAssertionWasFailed: Boolean) {
val sourceFile = testServices.moduleStructure.originalTestDataFiles.first()
assertions.assertEqualsToFile(sourceFile.withExtension(".metadata.txt"), multiModuleInfoDumper.generateResultingDump())
}
}

fun TestConfigurationBuilder.commonFirWithPluginFrontendConfiguration(dumpFir: Boolean = true) {
enableLazyResolvePhaseChecking()

defaultDirectives {
+ENABLE_PLUGIN_PHASES
+FIR_DUMP
if (dumpFir) {
+FIR_DUMP
}
}

useConfigurators(
Expand All @@ -83,4 +148,3 @@ fun TestConfigurationBuilder.commonFirWithPluginFrontendConfiguration() {
::FirFailingTestSuppressor,
)
}

0 comments on commit 5c09cae

Please sign in to comment.