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:
+12
@@ -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
|
||||||
+43
@@ -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);
|
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")
|
@TestMetadata("EnumArgumentWithCustomToString.kt")
|
||||||
public void testEnumArgumentWithCustomToString() throws Exception {
|
public void testEnumArgumentWithCustomToString() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/EnumArgumentWithCustomToString.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/EnumArgumentWithCustomToString.kt");
|
||||||
|
|||||||
+6
@@ -57,6 +57,12 @@ public class JvmRuntimeDescriptorLoaderTestGenerated extends AbstractJvmRuntimeD
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("EnumArgumentWithCustomToString.kt")
|
||||||
public void testEnumArgumentWithCustomToString() throws Exception {
|
public void testEnumArgumentWithCustomToString() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/EnumArgumentWithCustomToString.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/EnumArgumentWithCustomToString.kt");
|
||||||
|
|||||||
+1
-1
@@ -62,7 +62,7 @@ public interface KotlinJvmBinaryClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface AnnotationArgumentVisitor {
|
interface AnnotationArgumentVisitor {
|
||||||
// TODO: annotations, java.lang.Class
|
// TODO: class literals
|
||||||
void visit(@Nullable Name name, @Nullable Object value);
|
void visit(@Nullable Name name, @Nullable Object value);
|
||||||
|
|
||||||
void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName);
|
void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName);
|
||||||
|
|||||||
+8
-7
@@ -182,25 +182,26 @@ private object ReflectClassStructure {
|
|||||||
val classId = (if (clazz.isEnum()) clazz else clazz.getEnclosingClass()).classId
|
val classId = (if (clazz.isEnum()) clazz else clazz.getEnclosingClass()).classId
|
||||||
visitor.visitEnum(name, classId, Name.identifier((value as Enum<*>).name()))
|
visitor.visitEnum(name, classId, Name.identifier((value as Enum<*>).name()))
|
||||||
}
|
}
|
||||||
clazz.isAnnotation() -> {
|
javaClass<Annotation>().isAssignableFrom(clazz) -> {
|
||||||
// TODO: support values of annotation types
|
val annotationClass = clazz.getInterfaces().single()
|
||||||
throw UnsupportedOperationException("Values of annotation types are not yet supported in Kotlin reflection: $value")
|
val v = visitor.visitAnnotation(name, annotationClass.classId) ?: return
|
||||||
|
processAnnotationArguments(v, value as Annotation, annotationClass)
|
||||||
}
|
}
|
||||||
clazz.isArray() -> {
|
clazz.isArray() -> {
|
||||||
val elementVisitor = visitor.visitArray(name) ?: return
|
val v = visitor.visitArray(name) ?: return
|
||||||
val componentType = clazz.getComponentType()
|
val componentType = clazz.getComponentType()
|
||||||
if (componentType.isEnum()) {
|
if (componentType.isEnum()) {
|
||||||
val enumClassId = componentType.classId
|
val enumClassId = componentType.classId
|
||||||
for (element in value as Array<*>) {
|
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 {
|
else {
|
||||||
for (element in value as Array<*>) {
|
for (element in value as Array<*>) {
|
||||||
elementVisitor.visit(element)
|
v.visit(element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elementVisitor.visitEnd()
|
v.visitEnd()
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
throw UnsupportedOperationException("Unsupported annotation argument value ($clazz): $value")
|
throw UnsupportedOperationException("Unsupported annotation argument value ($clazz): $value")
|
||||||
|
|||||||
@@ -55,6 +55,12 @@ public class ResolveByStubTestGenerated extends AbstractResolveByStubTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("EnumArgumentWithCustomToString.kt")
|
||||||
public void testEnumArgumentWithCustomToString() throws Exception {
|
public void testEnumArgumentWithCustomToString() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/EnumArgumentWithCustomToString.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/EnumArgumentWithCustomToString.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user