diff --git a/compiler/testData/loadJava/compiledKotlin/annotations/AnnotationInAnnotationArguments.kt b/compiler/testData/loadJava/compiledKotlin/annotations/AnnotationInAnnotationArguments.kt new file mode 100644 index 00000000000..9af533b28df --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/annotations/AnnotationInAnnotationArguments.kt @@ -0,0 +1,12 @@ +// ALLOW_AST_ACCESS +package test + +enum class E { ENTRY } + +annotation class StringOptions(vararg val option: String) +annotation class EnumOption(val option: E) + +annotation class OptionGroups(val o1: StringOptions, val o2: EnumOption) + +OptionGroups(StringOptions("abc", "d", "ef"), EnumOption(E.ENTRY)) +public class AnnotationInAnnotationArguments diff --git a/compiler/testData/loadJava/compiledKotlin/annotations/AnnotationInAnnotationArguments.txt b/compiler/testData/loadJava/compiledKotlin/annotations/AnnotationInAnnotationArguments.txt new file mode 100644 index 00000000000..1687bc3e4dc --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/annotations/AnnotationInAnnotationArguments.txt @@ -0,0 +1,43 @@ +package test + +test.OptionGroups(o1 = test.StringOptions(option = {"abc", "d", "ef"}: kotlin.Array): test.StringOptions, o2 = test.EnumOption(option = E.ENTRY: test.E): test.EnumOption) public final class AnnotationInAnnotationArguments { + /*primary*/ public constructor AnnotationInAnnotationArguments() +} + +internal final enum class E : kotlin.Enum { + public enum entry ENTRY : test.E { + /*primary*/ private constructor ENTRY() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + } + + /*primary*/ private constructor E() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): test.E + public final /*synthesized*/ fun values(): kotlin.Array +} + +internal final annotation class EnumOption : kotlin.Annotation { + /*primary*/ public constructor EnumOption(/*0*/ option: test.E) + internal final val option: test.E + internal final fun (): test.E +} + +internal final annotation class OptionGroups : kotlin.Annotation { + /*primary*/ public constructor OptionGroups(/*0*/ o1: test.StringOptions, /*1*/ o2: test.EnumOption) + internal final val o1: test.StringOptions + internal final fun (): test.StringOptions + internal final val o2: test.EnumOption + internal final fun (): test.EnumOption +} + +internal final annotation class StringOptions : kotlin.Annotation { + /*primary*/ public constructor StringOptions(/*0*/ vararg option: kotlin.String /*kotlin.Array*/) + internal final val option: kotlin.Array + internal final fun (): kotlin.Array +} diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java index 38318e901ed..33bfdde1adb 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java @@ -1900,6 +1900,12 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTestCompiledKotlin(fileName); } + @TestMetadata("AnnotationInAnnotationArguments.kt") + public void testAnnotationInAnnotationArguments() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/AnnotationInAnnotationArguments.kt"); + doTestCompiledKotlin(fileName); + } + @TestMetadata("EnumArgumentWithCustomToString.kt") public void testEnumArgumentWithCustomToString() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/EnumArgumentWithCustomToString.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java index 1ab40610ef3..14267cfa3c1 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java @@ -57,6 +57,12 @@ public class JvmRuntimeDescriptorLoaderTestGenerated extends AbstractJvmRuntimeD doTest(fileName); } + @TestMetadata("AnnotationInAnnotationArguments.kt") + public void testAnnotationInAnnotationArguments() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/AnnotationInAnnotationArguments.kt"); + doTest(fileName); + } + @TestMetadata("EnumArgumentWithCustomToString.kt") public void testEnumArgumentWithCustomToString() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/EnumArgumentWithCustomToString.kt"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinaryClass.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinaryClass.java index c5d452be9e5..6b15e0d6501 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinaryClass.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinaryClass.java @@ -62,7 +62,7 @@ public interface KotlinJvmBinaryClass { } interface AnnotationArgumentVisitor { - // TODO: annotations, java.lang.Class + // TODO: class literals void visit(@Nullable Name name, @Nullable Object value); void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName); diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/ReflectKotlinClass.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/ReflectKotlinClass.kt index 8f5d7fb4bc7..a648ee33cda 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/ReflectKotlinClass.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/ReflectKotlinClass.kt @@ -182,25 +182,26 @@ private object ReflectClassStructure { val classId = (if (clazz.isEnum()) clazz else clazz.getEnclosingClass()).classId visitor.visitEnum(name, classId, Name.identifier((value as Enum<*>).name())) } - clazz.isAnnotation() -> { - // TODO: support values of annotation types - throw UnsupportedOperationException("Values of annotation types are not yet supported in Kotlin reflection: $value") + javaClass().isAssignableFrom(clazz) -> { + val annotationClass = clazz.getInterfaces().single() + val v = visitor.visitAnnotation(name, annotationClass.classId) ?: return + processAnnotationArguments(v, value as Annotation, annotationClass) } clazz.isArray() -> { - val elementVisitor = visitor.visitArray(name) ?: return + val v = visitor.visitArray(name) ?: return val componentType = clazz.getComponentType() if (componentType.isEnum()) { val enumClassId = componentType.classId for (element in value as Array<*>) { - elementVisitor.visitEnum(enumClassId, Name.identifier((element as Enum<*>).name())) + v.visitEnum(enumClassId, Name.identifier((element as Enum<*>).name())) } } else { for (element in value as Array<*>) { - elementVisitor.visit(element) + v.visit(element) } } - elementVisitor.visitEnd() + v.visitEnd() } else -> { throw UnsupportedOperationException("Unsupported annotation argument value ($clazz): $value") diff --git a/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java index bc65a783377..cceda1b65f6 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java @@ -55,6 +55,12 @@ public class ResolveByStubTestGenerated extends AbstractResolveByStubTest { doTest(fileName); } + @TestMetadata("AnnotationInAnnotationArguments.kt") + public void testAnnotationInAnnotationArguments() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/AnnotationInAnnotationArguments.kt"); + doTest(fileName); + } + @TestMetadata("EnumArgumentWithCustomToString.kt") public void testEnumArgumentWithCustomToString() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/EnumArgumentWithCustomToString.kt");