diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index 8f5eac6efdb..5389151e870 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.descriptors.annotations.*; import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor; import org.jetbrains.kotlin.incremental.components.NoLookupLocation; import org.jetbrains.kotlin.load.java.JvmAnnotationNames; +import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.resolve.AnnotationChecker; @@ -432,8 +433,13 @@ public abstract class AnnotationCodegen { @Override public Void visitEnumValue(EnumValue value, Void data) { - String enumClassInternalName = AsmUtil.asmTypeByClassId(value.getEnumClassId()).getDescriptor(); + ClassId enumClassId = value.getEnumClassId(); + String enumClassInternalName = AsmUtil.asmTypeByClassId(enumClassId).getDescriptor(); String enumEntryName = value.getEnumEntryName().asString(); + ClassDescriptor descriptor = FindClassInModuleKt.findClassAcrossModuleDependencies(state.getModule(), enumClassId); + if (descriptor != null) { + innerClassConsumer.addInnerClassInfoFromAnnotation(descriptor); + } annotationVisitor.visitEnum(name, enumClassInternalName, enumEntryName); return null; } @@ -450,8 +456,9 @@ public abstract class AnnotationCodegen { @Override public Void visitAnnotationValue(AnnotationValue value, Void data) { - String internalAnnName = typeMapper.mapType(value.getValue().getType()).getDescriptor(); - AnnotationVisitor visitor = annotationVisitor.visitAnnotation(name, internalAnnName); + KotlinType classType = value.getValue().getType(); + innerClassConsumer.addInnerClassInfoFromAnnotation(DescriptorUtils.getClassDescriptorForType(classType)); + AnnotationVisitor visitor = annotationVisitor.visitAnnotation(name, typeMapper.mapType(classType).getDescriptor()); genAnnotationArguments(value.getValue(), visitor); visitor.visitEnd(); return null; @@ -459,7 +466,9 @@ public abstract class AnnotationCodegen { @Override public Void visitKClassValue(KClassValue value, Void data) { - annotationVisitor.visit(name, typeMapper.mapType(value.getArgumentType(module))); + KotlinType classType = value.getArgumentType(module); + innerClassConsumer.addInnerClassInfoFromAnnotation(DescriptorUtils.getClassDescriptorForType(classType)); + annotationVisitor.visit(name, typeMapper.mapType(classType)); return null; } diff --git a/compiler/testData/codegen/bytecodeText/innerClasses/nestedClassInAnnotationArgument.kt b/compiler/testData/codegen/bytecodeText/innerClasses/nestedClassInAnnotationArgument.kt new file mode 100644 index 00000000000..070cd565b9c --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/innerClasses/nestedClassInAnnotationArgument.kt @@ -0,0 +1,44 @@ +// IGNORE_BACKEND: JVM_IR +// FILE: annotations.kt + +import kotlin.reflect.* + +annotation class Anno( + val k: KClass<*>, + val e: C.NestedEnum, + val a: C.NestedAnno, +) + +annotation class AnnoWithDefault(val k: KClass<*> = Nested0::class) { + class Nested0 +} + +class C { + class Nested1 + + enum class NestedEnum { E } + + annotation class NestedAnno(val k: KClass<*>) { + class Nested2 + } +} + +// FILE: usage.kt + +interface I { + @Anno( + C.Nested1::class, + C.NestedEnum.E, + C.NestedAnno(C.NestedAnno.Nested2::class), + ) + @AnnoWithDefault + fun foo(): String = "OK" +} + +// @I.class: +// 5 INNERCLASS +// 1 INNERCLASS C\$Nested1 C Nested1 +// 1 INNERCLASS C\$NestedEnum C NestedEnum +// 1 INNERCLASS C\$NestedAnno C NestedAnno +// 1 INNERCLASS C\$NestedAnno\$Nested2 C\$NestedAnno Nested2 +// 1 INNERCLASS I\$DefaultImpls I DefaultImpls diff --git a/compiler/testData/compileKotlinAgainstKotlin/nestedClassInAnnotationArgument.kt b/compiler/testData/compileKotlinAgainstKotlin/nestedClassInAnnotationArgument.kt new file mode 100644 index 00000000000..61b808630ec --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/nestedClassInAnnotationArgument.kt @@ -0,0 +1,42 @@ +// IGNORE_BACKEND: JVM_IR +// FILE: 1.kt + +import kotlin.reflect.* + +annotation class Anno( + val k: KClass<*>, + val e: C.NestedEnum, + val a: C.NestedAnno, +) + +annotation class AnnoWithDefault(val k: KClass<*> = Nested0::class) { + class Nested0 +} + +class C { + class Nested1 + + enum class NestedEnum { E } + + annotation class NestedAnno(val k: KClass<*>) { + class Nested2 + } +} + +interface I { + @Anno( + C.Nested1::class, + C.NestedEnum.E, + C.NestedAnno(C.NestedAnno.Nested2::class), + ) + @AnnoWithDefault + fun foo(): String = "OK" +} + +// FILE: 2.kt + +class D : I { + fun box(): String = foo() +} + +fun box(): String = D().box() diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 2d7480f2c05..e9886816e21 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -3052,6 +3052,24 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { } } + @TestMetadata("compiler/testData/codegen/bytecodeText/innerClasses") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InnerClasses extends AbstractBytecodeTextTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + public void testAllFilesPresentInInnerClasses() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/innerClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + + @TestMetadata("nestedClassInAnnotationArgument.kt") + public void testNestedClassInAnnotationArgument() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/innerClasses/nestedClassInAnnotationArgument.kt"); + } + } + @TestMetadata("compiler/testData/codegen/bytecodeText/interfaces") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java index 1772e5c439d..4345cba244f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java @@ -268,6 +268,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl runTest("compiler/testData/compileKotlinAgainstKotlin/nestedClass.kt"); } + @TestMetadata("nestedClassInAnnotationArgument.kt") + public void testNestedClassInAnnotationArgument() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/nestedClassInAnnotationArgument.kt"); + } + @TestMetadata("nestedEnum.kt") public void testNestedEnum() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/nestedEnum.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java index 61b0b40d75d..3bdd692037e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java @@ -3137,6 +3137,24 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { } } + @TestMetadata("compiler/testData/codegen/bytecodeText/innerClasses") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InnerClasses extends AbstractIrBytecodeTextTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath); + } + + public void testAllFilesPresentInInnerClasses() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/innerClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @TestMetadata("nestedClassInAnnotationArgument.kt") + public void testNestedClassInAnnotationArgument() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/innerClasses/nestedClassInAnnotationArgument.kt"); + } + } + @TestMetadata("compiler/testData/codegen/bytecodeText/interfaces") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java index f4edb51cb5d..ff2932f44ed 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java @@ -263,6 +263,11 @@ public class IrCompileKotlinAgainstKotlinTestGenerated extends AbstractIrCompile runTest("compiler/testData/compileKotlinAgainstKotlin/nestedClass.kt"); } + @TestMetadata("nestedClassInAnnotationArgument.kt") + public void testNestedClassInAnnotationArgument() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/nestedClassInAnnotationArgument.kt"); + } + @TestMetadata("nestedEnum.kt") public void testNestedEnum() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/nestedEnum.kt");