Support annotations as annotation arguments in reflection, add test

A follow-up to 281acb8 where this was supported in the compiler
This commit is contained in:
Alexander Udalov
2015-05-28 22:04:53 +03:00
parent 158b3ba102
commit d1df234cfe
7 changed files with 82 additions and 8 deletions
@@ -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
@@ -0,0 +1,43 @@
package test
test.OptionGroups(o1 = test.StringOptions(option = {"abc", "d", "ef"}: kotlin.Array<out kotlin.String>): 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<test.E> {
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<test.E>
}
internal final annotation class EnumOption : kotlin.Annotation {
/*primary*/ public constructor EnumOption(/*0*/ option: test.E)
internal final val option: test.E
internal final fun <get-option>(): 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 <get-o1>(): test.StringOptions
internal final val o2: test.EnumOption
internal final fun <get-o2>(): test.EnumOption
}
internal final annotation class StringOptions : kotlin.Annotation {
/*primary*/ public constructor StringOptions(/*0*/ vararg option: kotlin.String /*kotlin.Array<out kotlin.String>*/)
internal final val option: kotlin.Array<out kotlin.String>
internal final fun <get-option>(): kotlin.Array<out kotlin.String>
}
@@ -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");
@@ -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");
@@ -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);
@@ -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<Annotation>().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")
@@ -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");