From 540b87a1dc12f15049c5e21c6662be0a4b23b23b Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 18 Jul 2014 19:38:44 +0400 Subject: [PATCH] Support object array annotation arguments in deserialization --- .../kotlin/VirtualFileKotlinClass.java | 19 ++++++++- .../packageMembers/EnumArrayArgument.kt | 12 ++++++ .../packageMembers/EnumArrayArgument.txt | 10 +++++ .../packageMembers/StringArrayArgument.kt | 10 +++++ .../packageMembers/StringArrayArgument.txt | 10 +++++ .../jvm/compiler/LoadJavaTestGenerated.java | 10 +++++ ...esolveRecursiveComparingTestGenerated.java | 10 +++++ .../kotlin/AnnotationDescriptorLoader.java | 41 +++++++++++++++---- .../resolve/kotlin/KotlinJvmBinaryClass.java | 10 ++++- ...eadKotlinClassHeaderAnnotationVisitor.java | 25 ++++------- .../lang/resolve/constants/ConstantUtils.kt | 1 + .../stubs/LazyResolveByStubTestGenerated.java | 10 +++++ 12 files changed, 140 insertions(+), 28 deletions(-) create mode 100644 compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/EnumArrayArgument.kt create mode 100644 compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/EnumArrayArgument.txt create mode 100644 compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/StringArrayArgument.kt create mode 100644 compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/StringArrayArgument.txt diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/VirtualFileKotlinClass.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/VirtualFileKotlinClass.java index c96be2ad270..e1b39eb368b 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/VirtualFileKotlinClass.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/VirtualFileKotlinClass.java @@ -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 diff --git a/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/EnumArrayArgument.kt b/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/EnumArrayArgument.kt new file mode 100644 index 00000000000..6f3e39ef8a2 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/EnumArrayArgument.kt @@ -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() {} diff --git a/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/EnumArrayArgument.txt b/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/EnumArrayArgument.txt new file mode 100644 index 00000000000..e89b7ff2d00 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/EnumArrayArgument.txt @@ -0,0 +1,10 @@ +package test + +test.Anno(t = {ElementType.PACKAGE}: kotlin.Array) internal val bar: kotlin.Int = 42 + internal fun (): kotlin.Int +test.Anno(t = {}: kotlin.Array) internal fun baz(): kotlin.Unit +test.Anno(t = {ElementType.METHOD, ElementType.FIELD}: kotlin.Array) 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*/) +} \ No newline at end of file diff --git a/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/StringArrayArgument.kt b/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/StringArrayArgument.kt new file mode 100644 index 00000000000..da6a4f0f714 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/StringArrayArgument.kt @@ -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() {} diff --git a/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/StringArrayArgument.txt b/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/StringArrayArgument.txt new file mode 100644 index 00000000000..3a8c6eeffca --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/StringArrayArgument.txt @@ -0,0 +1,10 @@ +package test + +test.Anno(t = {"prosper"}: kotlin.Array) internal val bar: kotlin.Int = 42 + internal fun (): kotlin.Int +test.Anno(t = {}: kotlin.Array) internal fun baz(): kotlin.Unit +test.Anno(t = {"live", "long"}: kotlin.Array) internal fun foo(): kotlin.Unit + +internal final annotation class Anno : kotlin.Annotation { + /*primary*/ public constructor Anno(/*0*/ vararg t: kotlin.String /*kotlin.Array*/) +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index a2603aff606..d6820a60bc2 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -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") diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java index 5a1ea4bfa20..09a13999233 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java @@ -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") diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorLoader.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorLoader.java index 1b46b901edc..66122c101ec 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorLoader.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorLoader.java @@ -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> elements = new ArrayList>(); + + @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) { diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/KotlinJvmBinaryClass.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/KotlinJvmBinaryClass.java index 53ed0a031ce..9a2108accc1 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/KotlinJvmBinaryClass.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/KotlinJvmBinaryClass.java @@ -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(); } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java index 1de3b4c7558..bd72e94f8c5 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java @@ -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 strings = new ArrayList(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); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt index 5fe1f759334..7e78546874c 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt @@ -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) diff --git a/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java index 1b017812a97..df33404a2d2 100644 --- a/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java @@ -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")