JVM IR: Mark annotation implementation classes as anonymous
And add tests to ensure that annotation implementation classes are handled correctly in jvm-abi-gen.
This commit is contained in:
committed by
Alexander Udalov
parent
19660f11a7
commit
6d518c8e57
+6
-2
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.ANNOTATION_IMPLEMENTATION
|
||||||
import org.jetbrains.kotlin.backend.common.psi.PsiSourceManager
|
import org.jetbrains.kotlin.backend.common.psi.PsiSourceManager
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
@@ -450,7 +451,7 @@ class ClassCodegen private constructor(
|
|||||||
for (klass in innerClasses) {
|
for (klass in innerClasses) {
|
||||||
val innerClass = typeMapper.classInternalName(klass)
|
val innerClass = typeMapper.classInternalName(klass)
|
||||||
val outerClass =
|
val outerClass =
|
||||||
if (klass.isSamWrapper || klass.attributeOwnerId in context.isEnclosedInConstructor)
|
if (klass.isSamWrapper || klass.isAnnotationImplementation || klass.attributeOwnerId in context.isEnclosedInConstructor)
|
||||||
null
|
null
|
||||||
else {
|
else {
|
||||||
when (val parent = klass.parent) {
|
when (val parent = klass.parent) {
|
||||||
@@ -465,7 +466,7 @@ class ClassCodegen private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val IrClass.isAnonymousInnerClass: Boolean
|
private val IrClass.isAnonymousInnerClass: Boolean
|
||||||
get() = isSamWrapper || name.isSpecial // NB '<Continuation>' is treated as anonymous inner class here
|
get() = isSamWrapper || name.isSpecial || isAnnotationImplementation // NB '<Continuation>' is treated as anonymous inner class here
|
||||||
|
|
||||||
private val IrClass.isInlineSamWrapper: Boolean
|
private val IrClass.isInlineSamWrapper: Boolean
|
||||||
get() = isSamWrapper && visibility == DescriptorVisibilities.PUBLIC
|
get() = isSamWrapper && visibility == DescriptorVisibilities.PUBLIC
|
||||||
@@ -473,6 +474,9 @@ class ClassCodegen private constructor(
|
|||||||
private val IrClass.isSamWrapper: Boolean
|
private val IrClass.isSamWrapper: Boolean
|
||||||
get() = origin == IrDeclarationOrigin.GENERATED_SAM_IMPLEMENTATION
|
get() = origin == IrDeclarationOrigin.GENERATED_SAM_IMPLEMENTATION
|
||||||
|
|
||||||
|
private val IrClass.isAnnotationImplementation: Boolean
|
||||||
|
get() = origin == ANNOTATION_IMPLEMENTATION
|
||||||
|
|
||||||
override fun addInnerClassInfoFromAnnotation(innerClass: IrClass) {
|
override fun addInnerClassInfoFromAnnotation(innerClass: IrClass) {
|
||||||
// It's necessary for proper recovering of classId by plain string JVM descriptor when loading annotations
|
// It's necessary for proper recovering of classId by plain string JVM descriptor when loading annotations
|
||||||
// See FileBasedKotlinClass.convertAnnotationVisitor
|
// See FileBasedKotlinClass.convertAnnotationVisitor
|
||||||
|
|||||||
Vendored
+3
-2
@@ -1,21 +1,22 @@
|
|||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
public synthetic final class AnnotationCtorCallGenerateSyntheticKt$annotationImpl$Foo$0 {
|
public synthetic final class AnnotationCtorCallGenerateSyntheticKt$annotationImpl$Foo$0 {
|
||||||
// source: 'annotationCtorCallGenerateSynthetic.kt'
|
// source: 'annotationCtorCallGenerateSynthetic.kt'
|
||||||
|
enclosing class AnnotationCtorCallGenerateSyntheticKt
|
||||||
private synthetic final field int: int
|
private synthetic final field int: int
|
||||||
|
inner (anonymous) class AnnotationCtorCallGenerateSyntheticKt$annotationImpl$Foo$0
|
||||||
public method <init>(p0: int): void
|
public method <init>(p0: int): void
|
||||||
public synthetic final method annotationType(): java.lang.Class
|
public synthetic final method annotationType(): java.lang.Class
|
||||||
public final method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
public final method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||||
public final method hashCode(): int
|
public final method hashCode(): int
|
||||||
public synthetic final method int(): int
|
public synthetic final method int(): int
|
||||||
public final @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
public final @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||||
public synthetic inner class AnnotationCtorCallGenerateSyntheticKt$annotationImpl$Foo$0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
public final class AnnotationCtorCallGenerateSyntheticKt {
|
public final class AnnotationCtorCallGenerateSyntheticKt {
|
||||||
// source: 'annotationCtorCallGenerateSynthetic.kt'
|
// source: 'annotationCtorCallGenerateSynthetic.kt'
|
||||||
|
inner (anonymous) class AnnotationCtorCallGenerateSyntheticKt$annotationImpl$Foo$0
|
||||||
public final static method box(): void
|
public final static method box(): void
|
||||||
public synthetic inner class AnnotationCtorCallGenerateSyntheticKt$annotationImpl$Foo$0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@java.lang.annotation.Retention(value=RUNTIME)
|
@java.lang.annotation.Retention(value=RUNTIME)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
|||||||
import org.jetbrains.kotlin.codegen.CodegenTestUtil
|
import org.jetbrains.kotlin.codegen.CodegenTestUtil
|
||||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
||||||
import org.jetbrains.kotlin.config.Services
|
import org.jetbrains.kotlin.config.Services
|
||||||
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.io.path.ExperimentalPathApi
|
import kotlin.io.path.ExperimentalPathApi
|
||||||
@@ -52,6 +53,9 @@ abstract class BaseJvmAbiTest : TestCase() {
|
|||||||
val javaDestinationDir: File
|
val javaDestinationDir: File
|
||||||
get() = if (name == null) workingDir.resolve("javaOut") else workingDir.resolve("$name/javaOut")
|
get() = if (name == null) workingDir.resolve("javaOut") else workingDir.resolve("$name/javaOut")
|
||||||
|
|
||||||
|
val directives: File
|
||||||
|
get() = workingDir.resolve("directives.txt")
|
||||||
|
|
||||||
override fun toString(): String =
|
override fun toString(): String =
|
||||||
"compilation '$name'"
|
"compilation '$name'"
|
||||||
}
|
}
|
||||||
@@ -77,6 +81,9 @@ abstract class BaseJvmAbiTest : TestCase() {
|
|||||||
).toTypedArray()
|
).toTypedArray()
|
||||||
destination = compilation.destinationDir.canonicalPath
|
destination = compilation.destinationDir.canonicalPath
|
||||||
useOldBackend = !useIrBackend
|
useOldBackend = !useIrBackend
|
||||||
|
languageVersion = if (!compilation.directives.exists()) null else {
|
||||||
|
InTextDirectivesUtils.findStringWithPrefixes(compilation.directives.readText(), "// LANGUAGE_VERSION:")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val exitCode = compiler.exec(messageCollector, Services.EMPTY, args)
|
val exitCode = compiler.exec(messageCollector, Services.EMPTY, args)
|
||||||
if (exitCode != ExitCode.OK || messageCollector.errors.isNotEmpty()) {
|
if (exitCode != ExitCode.OK || messageCollector.errors.isNotEmpty()) {
|
||||||
|
|||||||
Generated
+5
@@ -45,6 +45,11 @@ public class CompileAgainstJvmAbiTestGenerated extends AbstractCompileAgainstJvm
|
|||||||
runTest("plugins/jvm-abi-gen/testData/compile/clinit/");
|
runTest("plugins/jvm-abi-gen/testData/compile/clinit/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineAnnotationInstantiation")
|
||||||
|
public void testInlineAnnotationInstantiation() throws Exception {
|
||||||
|
runTest("plugins/jvm-abi-gen/testData/compile/inlineAnnotationInstantiation/");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inlineAnonymousObject")
|
@TestMetadata("inlineAnonymousObject")
|
||||||
public void testInlineAnonymousObject() throws Exception {
|
public void testInlineAnonymousObject() throws Exception {
|
||||||
runTest("plugins/jvm-abi-gen/testData/compile/inlineAnonymousObject/");
|
runTest("plugins/jvm-abi-gen/testData/compile/inlineAnonymousObject/");
|
||||||
|
|||||||
Generated
+5
@@ -45,6 +45,11 @@ public class IrCompileAgainstJvmAbiTestGenerated extends AbstractIrCompileAgains
|
|||||||
runTest("plugins/jvm-abi-gen/testData/compile/clinit/");
|
runTest("plugins/jvm-abi-gen/testData/compile/clinit/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineAnnotationInstantiation")
|
||||||
|
public void testInlineAnnotationInstantiation() throws Exception {
|
||||||
|
runTest("plugins/jvm-abi-gen/testData/compile/inlineAnnotationInstantiation/");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inlineAnonymousObject")
|
@TestMetadata("inlineAnonymousObject")
|
||||||
public void testInlineAnonymousObject() throws Exception {
|
public void testInlineAnonymousObject() throws Exception {
|
||||||
runTest("plugins/jvm-abi-gen/testData/compile/inlineAnonymousObject/");
|
runTest("plugins/jvm-abi-gen/testData/compile/inlineAnonymousObject/");
|
||||||
|
|||||||
+10
@@ -35,6 +35,16 @@ public class IrJvmAbiContentTestGenerated extends AbstractIrJvmAbiContentTest {
|
|||||||
runTest("plugins/jvm-abi-gen/testData/content/annotation/");
|
runTest("plugins/jvm-abi-gen/testData/content/annotation/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotationInstantiation")
|
||||||
|
public void testAnnotationInstantiation() throws Exception {
|
||||||
|
runTest("plugins/jvm-abi-gen/testData/content/annotationInstantiation/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("anonymousAnnotationInstantiation")
|
||||||
|
public void testAnonymousAnnotationInstantiation() throws Exception {
|
||||||
|
runTest("plugins/jvm-abi-gen/testData/content/anonymousAnnotationInstantiation/");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("anonymousWhenMapping")
|
@TestMetadata("anonymousWhenMapping")
|
||||||
public void testAnonymousWhenMapping() throws Exception {
|
public void testAnonymousWhenMapping() throws Exception {
|
||||||
runTest("plugins/jvm-abi-gen/testData/content/anonymousWhenMapping/");
|
runTest("plugins/jvm-abi-gen/testData/content/anonymousWhenMapping/");
|
||||||
|
|||||||
+10
@@ -35,6 +35,16 @@ public class JvmAbiContentTestGenerated extends AbstractJvmAbiContentTest {
|
|||||||
runTest("plugins/jvm-abi-gen/testData/content/annotation/");
|
runTest("plugins/jvm-abi-gen/testData/content/annotation/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotationInstantiation")
|
||||||
|
public void testAnnotationInstantiation() throws Exception {
|
||||||
|
runTest("plugins/jvm-abi-gen/testData/content/annotationInstantiation/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("anonymousAnnotationInstantiation")
|
||||||
|
public void testAnonymousAnnotationInstantiation() throws Exception {
|
||||||
|
runTest("plugins/jvm-abi-gen/testData/content/anonymousAnnotationInstantiation/");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("anonymousWhenMapping")
|
@TestMetadata("anonymousWhenMapping")
|
||||||
public void testAnonymousWhenMapping() throws Exception {
|
public void testAnonymousWhenMapping() throws Exception {
|
||||||
runTest("plugins/jvm-abi-gen/testData/content/anonymousWhenMapping/");
|
runTest("plugins/jvm-abi-gen/testData/content/anonymousWhenMapping/");
|
||||||
|
|||||||
Generated
+5
@@ -45,6 +45,11 @@ public class LegacyCompileAgainstJvmAbiTestGenerated extends AbstractLegacyCompi
|
|||||||
runTest("plugins/jvm-abi-gen/testData/compile/clinit/");
|
runTest("plugins/jvm-abi-gen/testData/compile/clinit/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineAnnotationInstantiation")
|
||||||
|
public void testInlineAnnotationInstantiation() throws Exception {
|
||||||
|
runTest("plugins/jvm-abi-gen/testData/compile/inlineAnnotationInstantiation/");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inlineAnonymousObject")
|
@TestMetadata("inlineAnonymousObject")
|
||||||
public void testInlineAnonymousObject() throws Exception {
|
public void testInlineAnonymousObject() throws Exception {
|
||||||
runTest("plugins/jvm-abi-gen/testData/compile/inlineAnonymousObject/");
|
runTest("plugins/jvm-abi-gen/testData/compile/inlineAnonymousObject/");
|
||||||
|
|||||||
Generated
+10
@@ -35,6 +35,16 @@ public class LegacyJvmAbiContentTestGenerated extends AbstractLegacyJvmAbiConten
|
|||||||
runTest("plugins/jvm-abi-gen/testData/content/annotation/");
|
runTest("plugins/jvm-abi-gen/testData/content/annotation/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotationInstantiation")
|
||||||
|
public void testAnnotationInstantiation() throws Exception {
|
||||||
|
runTest("plugins/jvm-abi-gen/testData/content/annotationInstantiation/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("anonymousAnnotationInstantiation")
|
||||||
|
public void testAnonymousAnnotationInstantiation() throws Exception {
|
||||||
|
runTest("plugins/jvm-abi-gen/testData/content/anonymousAnnotationInstantiation/");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("anonymousWhenMapping")
|
@TestMetadata("anonymousWhenMapping")
|
||||||
public void testAnonymousWhenMapping() throws Exception {
|
public void testAnonymousWhenMapping() throws Exception {
|
||||||
runTest("plugins/jvm-abi-gen/testData/content/anonymousWhenMapping/");
|
runTest("plugins/jvm-abi-gen/testData/content/anonymousWhenMapping/");
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import lib.*
|
||||||
|
|
||||||
|
fun runAppAndReturnOk(): String {
|
||||||
|
return a().value
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// LANGUAGE_VERSION: 1.6
|
||||||
|
// IGNORE_BACKEND_LEGACY: JVM
|
||||||
|
// IGNORE_BACKEND: JVM
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package lib
|
||||||
|
|
||||||
|
annotation class A(val value: String)
|
||||||
|
|
||||||
|
inline fun a() = A("OK")
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// LANGUAGE_VERSION: 1.6
|
||||||
|
// IGNORE_BACKEND_LEGACY: JVM
|
||||||
|
// IGNORE_BACKEND: JVM
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
@java.lang.annotation.Retention(value=RUNTIME)
|
||||||
|
@kotlin.Metadata
|
||||||
|
public annotation class test/A {
|
||||||
|
// source: 'test.kt'
|
||||||
|
}
|
||||||
|
@kotlin.Metadata
|
||||||
|
public synthetic final class test/Test$annotationImpl$test_A$0 {
|
||||||
|
// source: 'test.kt'
|
||||||
|
enclosing class test/Test
|
||||||
|
inner (anonymous) class test/Test$annotationImpl$test_A$0
|
||||||
|
public method <init>(): void
|
||||||
|
public synthetic final method annotationType(): java.lang.Class
|
||||||
|
public final method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||||
|
public final method hashCode(): int
|
||||||
|
public final @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||||
|
}
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class test/Test {
|
||||||
|
// source: 'test.kt'
|
||||||
|
inner (anonymous) class test/Test$annotationImpl$test_A$0
|
||||||
|
public method <init>(): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method annotationInstantiation(): test.A
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
annotation class A
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
inline fun annotationInstantiation() = A()
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
// LANGUAGE_VERSION: 1.6
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
@java.lang.annotation.Retention(value=RUNTIME)
|
||||||
|
@kotlin.Metadata
|
||||||
|
public annotation class test/A {
|
||||||
|
// source: 'test.kt'
|
||||||
|
}
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class test/Test {
|
||||||
|
// source: 'test.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method anonymousAnnotationInstantiation(): test.A
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
annotation class A
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
fun anonymousAnnotationInstantiation() = A()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user