Support object array annotation arguments in deserialization

This commit is contained in:
Alexander Udalov
2014-07-18 19:38:44 +04:00
parent d5681540ec
commit 540b87a1dc
12 changed files with 140 additions and 28 deletions
@@ -157,8 +157,23 @@ public class VirtualFileKotlinClass implements KotlinJvmBinaryClass {
@Override
public org.jetbrains.org.objectweb.asm.AnnotationVisitor visitArray(String name) {
AnnotationArgumentVisitor av = v.visitArray(Name.guess(name));
return av == null ? null : convertAnnotationVisitor(av);
final AnnotationArrayArgumentVisitor arv = v.visitArray(Name.guess(name));
return arv == null ? null : new org.jetbrains.org.objectweb.asm.AnnotationVisitor(ASM5) {
@Override
public void visit(String name, Object value) {
arv.visit(value);
}
@Override
public void visitEnum(String name, String desc, String value) {
arv.visitEnum(classNameFromAsmDesc(desc), Name.identifier(value));
}
@Override
public void visitEnd() {
arv.visitEnd();
}
};
}
@Override
@@ -0,0 +1,12 @@
//ALLOW_AST_ACCESS
package test
import java.lang.annotation.ElementType
annotation class Anno(vararg t: ElementType)
Anno(ElementType.METHOD, ElementType.FIELD) fun foo() {}
Anno(ElementType.PACKAGE) val bar = 42
Anno() fun baz() {}
@@ -0,0 +1,10 @@
package test
test.Anno(t = {ElementType.PACKAGE}: kotlin.Array<java.lang.annotation.ElementType>) internal val bar: kotlin.Int = 42
internal fun <get-bar>(): kotlin.Int
test.Anno(t = {}: kotlin.Array<java.lang.annotation.ElementType>) internal fun baz(): kotlin.Unit
test.Anno(t = {ElementType.METHOD, ElementType.FIELD}: kotlin.Array<java.lang.annotation.ElementType>) internal fun foo(): kotlin.Unit
internal final annotation class Anno : kotlin.Annotation {
/*primary*/ public constructor Anno(/*0*/ vararg t: java.lang.annotation.ElementType /*kotlin.Array<java.lang.annotation.ElementType>*/)
}
@@ -0,0 +1,10 @@
//ALLOW_AST_ACCESS
package test
annotation class Anno(vararg t: String)
Anno("live", "long") fun foo() {}
Anno("prosper") val bar = 42
Anno() fun baz() {}
@@ -0,0 +1,10 @@
package test
test.Anno(t = {"prosper"}: kotlin.Array<kotlin.String>) internal val bar: kotlin.Int = 42
internal fun <get-bar>(): kotlin.Int
test.Anno(t = {}: kotlin.Array<kotlin.String>) internal fun baz(): kotlin.Unit
test.Anno(t = {"live", "long"}: kotlin.Array<kotlin.String>) internal fun foo(): kotlin.Unit
internal final annotation class Anno : kotlin.Annotation {
/*primary*/ public constructor Anno(/*0*/ vararg t: kotlin.String /*kotlin.Array<kotlin.String>*/)
}
@@ -1715,6 +1715,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
doTestCompiledKotlin("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/EnumArgument.kt");
}
@TestMetadata("EnumArrayArgument.kt")
public void testEnumArrayArgument() throws Exception {
doTestCompiledKotlin("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/EnumArrayArgument.kt");
}
@TestMetadata("Function.kt")
public void testFunction() throws Exception {
doTestCompiledKotlin("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/Function.kt");
@@ -1735,6 +1740,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
doTestCompiledKotlin("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/Setter.kt");
}
@TestMetadata("StringArrayArgument.kt")
public void testStringArrayArgument() throws Exception {
doTestCompiledKotlin("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/StringArrayArgument.kt");
}
}
@TestMetadata("compiler/testData/loadJava/compiledKotlin/annotations/parameters")
@@ -183,6 +183,11 @@ public class LazyResolveRecursiveComparingTestGenerated extends AbstractLazyReso
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/EnumArgument.kt");
}
@TestMetadata("EnumArrayArgument.kt")
public void testEnumArrayArgument() throws Exception {
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/EnumArrayArgument.kt");
}
@TestMetadata("Function.kt")
public void testFunction() throws Exception {
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/Function.kt");
@@ -203,6 +208,11 @@ public class LazyResolveRecursiveComparingTestGenerated extends AbstractLazyReso
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/Setter.kt");
}
@TestMetadata("StringArrayArgument.kt")
public void testStringArrayArgument() throws Exception {
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/StringArrayArgument.kt");
}
}
@TestMetadata("compiler/testData/loadJava/compiledKotlin/annotations/parameters")
@@ -26,14 +26,12 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationsImpl;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.constants.ConstantsPackage;
import org.jetbrains.jet.lang.resolve.constants.EnumValue;
import org.jetbrains.jet.lang.resolve.constants.ErrorValue;
import org.jetbrains.jet.lang.resolve.constants.*;
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils;
import org.jetbrains.jet.lang.resolve.java.resolver.ErrorReporter;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -130,8 +128,7 @@ public class AnnotationDescriptorLoader extends BaseDescriptorLoader implements
@Override
public void visit(@Nullable Name name, @Nullable Object value) {
if (name != null) {
CompileTimeConstant<?> argument = ConstantsPackage.createCompileTimeConstant(value, true, false, false, null);
setArgumentValueByName(name, argument != null ? argument : ErrorValue.create("Unsupported annotation argument: " + name));
setArgumentValueByName(name, createConstant(name, value));
}
}
@@ -142,9 +139,29 @@ public class AnnotationDescriptorLoader extends BaseDescriptorLoader implements
@Nullable
@Override
public KotlinJvmBinaryClass.AnnotationArgumentVisitor visitArray(@NotNull Name name) {
// TODO: support arrays
return null;
public AnnotationArrayArgumentVisitor visitArray(@NotNull final Name name) {
return new KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor() {
private final ArrayList<CompileTimeConstant<?>> elements = new ArrayList<CompileTimeConstant<?>>();
@Override
public void visit(@Nullable Object value) {
elements.add(createConstant(name, value));
}
@Override
public void visitEnum(@NotNull JvmClassName enumClassName, @NotNull Name enumEntryName) {
elements.add(enumEntryValue(enumClassName, enumEntryName));
}
@Override
public void visitEnd() {
ValueParameterDescriptor parameter = DescriptorResolverUtils.getAnnotationParameterByName(name, annotationClass);
if (parameter != null) {
elements.trimToSize();
arguments.put(parameter, new ArrayValue(elements, parameter.getType(), true, false));
}
}
};
}
@NotNull
@@ -167,6 +184,12 @@ public class AnnotationDescriptorLoader extends BaseDescriptorLoader implements
));
}
@NotNull
private CompileTimeConstant<?> createConstant(@Nullable Name name, @Nullable Object value) {
CompileTimeConstant<?> argument = ConstantsPackage.createCompileTimeConstant(value, true, false, false, null);
return argument != null ? argument : ErrorValue.create("Unsupported annotation argument: " + name);
}
private void setArgumentValueByName(@NotNull Name name, @NotNull CompileTimeConstant<?> argumentValue) {
ValueParameterDescriptor parameter = DescriptorResolverUtils.getAnnotationParameterByName(name, annotationClass);
if (parameter != null) {
@@ -62,7 +62,15 @@ public interface KotlinJvmBinaryClass {
void visitEnum(@NotNull Name name, @NotNull JvmClassName enumClassName, @NotNull Name enumEntryName);
@Nullable
AnnotationArgumentVisitor visitArray(@NotNull Name name);
AnnotationArrayArgumentVisitor visitArray(@NotNull Name name);
void visitEnd();
}
interface AnnotationArrayArgumentVisitor {
void visit(@Nullable Object value);
void visitEnum(@NotNull JvmClassName enumClassName, @NotNull Name enumEntryName);
void visitEnd();
}
@@ -27,8 +27,7 @@ import java.util.*;
import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCompatible;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.*;
import static org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.AnnotationArgumentVisitor;
import static org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.AnnotationVisitor;
import static org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.*;
import static org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader.Kind.*;
public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor {
@@ -113,7 +112,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
@Override
@Nullable
public AnnotationArgumentVisitor visitArray(@NotNull Name name) {
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
if (name.asString().equals(DATA_FIELD_NAME)) {
return stringArrayVisitor();
}
@@ -125,11 +124,11 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
}
@NotNull
private AnnotationArgumentVisitor stringArrayVisitor() {
private AnnotationArrayArgumentVisitor stringArrayVisitor() {
final List<String> strings = new ArrayList<String>(1);
return new AnnotationArgumentVisitor() {
return new AnnotationArrayArgumentVisitor() {
@Override
public void visit(@Nullable Name name, @Nullable Object value) {
public void visit(@Nullable Object value) {
if (!(value instanceof String)) {
throw new IllegalStateException("Unexpected argument value: " + value);
}
@@ -138,14 +137,8 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
}
@Override
public void visitEnum(@NotNull Name name, @NotNull JvmClassName enumClassName, @NotNull Name enumEntryName) {
unexpectedArgument(name, annotationClassName);
}
@Nullable
@Override
public AnnotationArgumentVisitor visitArray(@NotNull Name name) {
return unexpectedArgument(name, annotationClassName);
public void visitEnum(@NotNull JvmClassName enumClassName, @NotNull Name enumEntryName) {
unexpectedArgument(null, annotationClassName);
}
@Override
@@ -186,7 +179,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
@Nullable
@Override
public AnnotationArgumentVisitor visitArray(@NotNull Name name) {
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
return unexpectedArgument(name, KotlinSyntheticClass.CLASS_NAME);
}
@@ -206,7 +199,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
}
@Nullable
private AnnotationArgumentVisitor unexpectedArgument(@Nullable Name name, @NotNull JvmClassName annotationClassName) {
private AnnotationArrayArgumentVisitor unexpectedArgument(@Nullable Name name, @NotNull JvmClassName annotationClassName) {
if (isAbiVersionCompatible(version)) {
throw new IllegalStateException("Unexpected argument " + name + " for annotation " + annotationClassName);
}
@@ -27,6 +27,7 @@ public fun createCompileTimeConstant(
usesVariableAsConstant: Boolean = false,
expectedType: JetType? = null
): CompileTimeConstant<*>? {
// TODO: primitive arrays
if (expectedType == null) {
when(value) {
is Byte -> return ByteValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
@@ -183,6 +183,11 @@ public class LazyResolveByStubTestGenerated extends AbstractLazyResolveByStubTes
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/EnumArgument.kt");
}
@TestMetadata("EnumArrayArgument.kt")
public void testEnumArrayArgument() throws Exception {
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/EnumArrayArgument.kt");
}
@TestMetadata("Function.kt")
public void testFunction() throws Exception {
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/Function.kt");
@@ -203,6 +208,11 @@ public class LazyResolveByStubTestGenerated extends AbstractLazyResolveByStubTes
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/Setter.kt");
}
@TestMetadata("StringArrayArgument.kt")
public void testStringArrayArgument() throws Exception {
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/StringArrayArgument.kt");
}
}
@TestMetadata("compiler/testData/loadJava/compiledKotlin/annotations/parameters")