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 2027f47f8ed..0d36523d3da 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 @@ -141,7 +141,7 @@ public class VirtualFileKotlinClass implements KotlinJvmBinaryClass { @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - final AnnotationVisitor v = memberVisitor.visitMethod(Name.guess(name), desc); + final MethodAnnotationVisitor v = memberVisitor.visitMethod(Name.guess(name), desc); if (v == null) return null; return new MethodVisitor(ASM4) { @@ -150,6 +150,12 @@ public class VirtualFileKotlinClass implements KotlinJvmBinaryClass { return convertAnnotationVisitor(v, desc); } + @Override + public org.jetbrains.asm4.AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) { + AnnotationArgumentVisitor av = v.visitParameterAnnotation(parameter, classNameFromAsmDesc(desc)); + return av == null ? null : convertAnnotationVisitor(av); + } + @Override public void visitEnd() { v.visitEnd(); diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorDeserializer.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorDeserializer.java index 36532caa87d..b114f30d3f6 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorDeserializer.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorDeserializer.java @@ -237,7 +237,7 @@ public class DescriptorDeserializer { local.typeDeserializer.typeOrNull(proto.hasReceiverType() ? proto.getReceiverType() : null), getExpectedThisObject(), typeParameters, - local.valueParameters(proto.getValueParameterList()), + local.valueParameters(proto), local.typeDeserializer.type(proto.getReturnType()), modality(Flags.MODALITY.get(flags)), visibility(Flags.VISIBILITY.get(flags)), @@ -265,7 +265,7 @@ public class DescriptorDeserializer { DescriptorDeserializer local = createChildDeserializer(descriptor, Collections.emptyList(), typeParameters); descriptor.initialize( classDescriptor.getTypeConstructor().getParameters(), - local.valueParameters(proto.getValueParameterList()), + local.valueParameters(proto), visibility(Flags.VISIBILITY.get(proto.getFlags())), DescriptorUtils.isConstructorOfStaticNestedClass(descriptor) ); @@ -384,29 +384,37 @@ public class DescriptorDeserializer { } @NotNull - private List valueParameters(@NotNull List protos) { + private List valueParameters(@NotNull Callable callable) { + DeclarationDescriptor containerOfCallable = containingDeclaration.getContainingDeclaration(); + assert containerOfCallable instanceof ClassOrNamespaceDescriptor + : "Only members in classes or namespaces should be serialized: " + containerOfCallable; + ClassOrNamespaceDescriptor classOrNamespace = (ClassOrNamespaceDescriptor) containerOfCallable; + + List protos = callable.getValueParameterList(); List result = new ArrayList(protos.size()); for (int i = 0; i < protos.size(); i++) { Callable.ValueParameter proto = protos.get(i); - result.add(valueParameter(proto, i)); + result.add(new ValueParameterDescriptorImpl( + containingDeclaration, + i, + getAnnotations(classOrNamespace, callable, proto), + nameResolver.getName(proto.getName()), + typeDeserializer.type(proto.getType()), + Flags.DECLARES_DEFAULT_VALUE.get(proto.getFlags()), + typeDeserializer.typeOrNull(proto.hasVarargElementType() ? proto.getVarargElementType() : null)) + ); } return result; } - private ValueParameterDescriptor valueParameter(Callable.ValueParameter proto, int index) { - return new ValueParameterDescriptorImpl( - containingDeclaration, - index, - getAnnotations(proto), - nameResolver.getName(proto.getName()), - typeDeserializer.type(proto.getType()), - Flags.DECLARES_DEFAULT_VALUE.get(proto.getFlags()), - typeDeserializer.typeOrNull(proto.hasVarargElementType() ? proto.getVarargElementType() : null)); - } - - private List getAnnotations(Callable.ValueParameter proto) { - return Flags.HAS_ANNOTATIONS.get(proto.getFlags()) - ? annotationDeserializer.loadValueParameterAnnotations(proto) + @NotNull + private List getAnnotations( + @NotNull ClassOrNamespaceDescriptor classOrNamespace, + @NotNull Callable callable, + @NotNull Callable.ValueParameter valueParameter + ) { + return Flags.HAS_ANNOTATIONS.get(valueParameter.getFlags()) + ? annotationDeserializer.loadValueParameterAnnotations(classOrNamespace, callable, nameResolver, valueParameter) : Collections.emptyList(); } } diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/AnnotationDeserializer.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/AnnotationDeserializer.java index 9eff8676763..5fa07699c38 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/AnnotationDeserializer.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/AnnotationDeserializer.java @@ -1,3 +1,19 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.jetbrains.jet.descriptors.serialization.descriptors; import org.jetbrains.annotations.NotNull; @@ -30,7 +46,12 @@ public interface AnnotationDeserializer { @NotNull @Override - public List loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto) { + public List loadValueParameterAnnotations( + @NotNull ClassOrNamespaceDescriptor container, + @NotNull ProtoBuf.Callable callable, + @NotNull NameResolver nameResolver, + @NotNull ProtoBuf.Callable.ValueParameter proto + ) { return notSupported(); } @@ -59,5 +80,10 @@ public interface AnnotationDeserializer { ); @NotNull - List loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto); + List loadValueParameterAnnotations( + @NotNull ClassOrNamespaceDescriptor container, + @NotNull ProtoBuf.Callable callable, + @NotNull NameResolver nameResolver, + @NotNull ProtoBuf.Callable.ValueParameter proto + ); } diff --git a/compiler/testData/loadKotlin/annotations/parameters/Constructor.kt b/compiler/testData/loadKotlin/annotations/parameters/Constructor.kt new file mode 100644 index 00000000000..b0e0bfdc60b --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/Constructor.kt @@ -0,0 +1,6 @@ +package test + +annotation class A +annotation class B + +class Class([A] val x: Int, [B] y: String) diff --git a/compiler/testData/loadKotlin/annotations/parameters/Constructor.txt b/compiler/testData/loadKotlin/annotations/parameters/Constructor.txt new file mode 100644 index 00000000000..9d791272851 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/Constructor.txt @@ -0,0 +1,15 @@ +package test + +internal final annotation class A : jet.Annotation { + /*primary*/ public constructor A() +} + +internal final annotation class B : jet.Annotation { + /*primary*/ public constructor B() +} + +internal final class Class { + /*primary*/ public constructor Class(/*0*/ test.A() x: jet.Int, /*1*/ test.B() y: jet.String) + test.A() internal final val x: jet.Int + internal final fun (): jet.Int +} diff --git a/compiler/testData/loadKotlin/annotations/parameters/EnumConstructor.kt b/compiler/testData/loadKotlin/annotations/parameters/EnumConstructor.kt new file mode 100644 index 00000000000..12d28c6f6f7 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/EnumConstructor.kt @@ -0,0 +1,6 @@ +package test + +annotation class A +annotation class B + +enum class E([A] val x: String, [B] val y: Int) diff --git a/compiler/testData/loadKotlin/annotations/parameters/EnumConstructor.txt b/compiler/testData/loadKotlin/annotations/parameters/EnumConstructor.txt new file mode 100644 index 00000000000..8fdcb981de8 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/EnumConstructor.txt @@ -0,0 +1,25 @@ +package test + +internal final annotation class A : jet.Annotation { + /*primary*/ public constructor A() +} + +internal final annotation class B : jet.Annotation { + /*primary*/ public constructor B() +} + +internal final enum class E : jet.Enum { + /*primary*/ private constructor E(/*0*/ test.A() x: jet.String, /*1*/ test.B() y: jet.Int) + test.A() internal final val x: jet.String + internal final fun (): jet.String + test.B() internal final val y: jet.Int + internal final fun (): jet.Int + public final override /*1*/ /*fake_override*/ fun name(): jet.String + public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int + + internal class object { + /*primary*/ private constructor () + public final fun valueOf(/*0*/ value: jet.String): test.E + public final fun values(): jet.Array + } +} diff --git a/compiler/testData/loadKotlin/annotations/parameters/ExtensionFunction.kt b/compiler/testData/loadKotlin/annotations/parameters/ExtensionFunction.kt new file mode 100644 index 00000000000..232d2ea0e2e --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/ExtensionFunction.kt @@ -0,0 +1,5 @@ +package test + +annotation class A + +fun Int.foo([A] x: Int) {} diff --git a/compiler/testData/loadKotlin/annotations/parameters/ExtensionFunction.txt b/compiler/testData/loadKotlin/annotations/parameters/ExtensionFunction.txt new file mode 100644 index 00000000000..64ee1779d2e --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/ExtensionFunction.txt @@ -0,0 +1,7 @@ +package test + +internal fun jet.Int.foo(/*0*/ test.A() x: jet.Int): jet.Unit + +internal final annotation class A : jet.Annotation { + /*primary*/ public constructor A() +} diff --git a/compiler/testData/loadKotlin/annotations/parameters/ExtensionFunctionInClass.kt b/compiler/testData/loadKotlin/annotations/parameters/ExtensionFunctionInClass.kt new file mode 100644 index 00000000000..55637c80d6c --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/ExtensionFunctionInClass.kt @@ -0,0 +1,7 @@ +package test + +annotation class Anno + +class Class { + fun String.foo([Anno] x: Int) = 42 +} diff --git a/compiler/testData/loadKotlin/annotations/parameters/ExtensionFunctionInClass.txt b/compiler/testData/loadKotlin/annotations/parameters/ExtensionFunctionInClass.txt new file mode 100644 index 00000000000..1f5dc2c9061 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/ExtensionFunctionInClass.txt @@ -0,0 +1,10 @@ +package test + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} + +internal final class Class { + /*primary*/ public constructor Class() + internal final fun jet.String.foo(/*0*/ test.Anno() x: jet.Int): jet.Int +} diff --git a/compiler/testData/loadKotlin/annotations/parameters/FunctionInClass.kt b/compiler/testData/loadKotlin/annotations/parameters/FunctionInClass.kt new file mode 100644 index 00000000000..8b203adbe97 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/FunctionInClass.kt @@ -0,0 +1,7 @@ +package test + +annotation class Anno + +class Class { + fun foo([Anno] x: String) {} +} diff --git a/compiler/testData/loadKotlin/annotations/parameters/FunctionInClass.txt b/compiler/testData/loadKotlin/annotations/parameters/FunctionInClass.txt new file mode 100644 index 00000000000..b98e8a524e2 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/FunctionInClass.txt @@ -0,0 +1,10 @@ +package test + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} + +internal final class Class { + /*primary*/ public constructor Class() + internal final fun foo(/*0*/ test.Anno() x: jet.String): jet.Unit +} diff --git a/compiler/testData/loadKotlin/annotations/parameters/FunctionInTrait.kt b/compiler/testData/loadKotlin/annotations/parameters/FunctionInTrait.kt new file mode 100644 index 00000000000..3613f71a2a7 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/FunctionInTrait.kt @@ -0,0 +1,7 @@ +package test + +annotation class Anno + +trait Trait { + fun foo([Anno] x: String) = 42 +} diff --git a/compiler/testData/loadKotlin/annotations/parameters/FunctionInTrait.txt b/compiler/testData/loadKotlin/annotations/parameters/FunctionInTrait.txt new file mode 100644 index 00000000000..b5954ec6d62 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/FunctionInTrait.txt @@ -0,0 +1,9 @@ +package test + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} + +internal trait Trait { + internal open fun foo(/*0*/ test.Anno() x: jet.String): jet.Int +} diff --git a/compiler/testData/loadKotlin/annotations/parameters/ManyAnnotations.kt b/compiler/testData/loadKotlin/annotations/parameters/ManyAnnotations.kt new file mode 100644 index 00000000000..8c66ee274ac --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/ManyAnnotations.kt @@ -0,0 +1,10 @@ +package test + +annotation class A +annotation class B +annotation class C +annotation class D + +fun foo([A B] x: Int, [A C] y: Double, [B C D] z: String) {} + +fun bar([A B C D] x: Int) {} diff --git a/compiler/testData/loadKotlin/annotations/parameters/ManyAnnotations.txt b/compiler/testData/loadKotlin/annotations/parameters/ManyAnnotations.txt new file mode 100644 index 00000000000..94149cbd629 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/ManyAnnotations.txt @@ -0,0 +1,20 @@ +package test + +internal fun bar(/*0*/ test.A() test.B() test.C() test.D() x: jet.Int): jet.Unit +internal fun foo(/*0*/ test.A() test.B() x: jet.Int, /*1*/ test.A() test.C() y: jet.Double, /*2*/ test.B() test.C() test.D() z: jet.String): jet.Unit + +internal final annotation class A : jet.Annotation { + /*primary*/ public constructor A() +} + +internal final annotation class B : jet.Annotation { + /*primary*/ public constructor B() +} + +internal final annotation class C : jet.Annotation { + /*primary*/ public constructor C() +} + +internal final annotation class D : jet.Annotation { + /*primary*/ public constructor D() +} diff --git a/compiler/testData/loadKotlin/annotations/parameters/TopLevelFunction.kt b/compiler/testData/loadKotlin/annotations/parameters/TopLevelFunction.kt new file mode 100644 index 00000000000..88763bbb386 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/TopLevelFunction.kt @@ -0,0 +1,5 @@ +package test + +annotation class Anno + +fun foo([Anno] x: Int) {} diff --git a/compiler/testData/loadKotlin/annotations/parameters/TopLevelFunction.txt b/compiler/testData/loadKotlin/annotations/parameters/TopLevelFunction.txt new file mode 100644 index 00000000000..5eb8fbc1d11 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/parameters/TopLevelFunction.txt @@ -0,0 +1,7 @@ +package test + +internal fun foo(/*0*/ test.Anno() x: jet.Int): jet.Unit + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java index 90b7246382a..cfbac25cd03 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java @@ -38,7 +38,7 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT } @TestMetadata("compiler/testData/loadKotlin/annotations") - @InnerTestClasses({Annotations.ClassMembers.class, Annotations.Classes.class, Annotations.PackageMembers.class, Annotations.PropertiesWithoutBackingFields.class}) + @InnerTestClasses({Annotations.ClassMembers.class, Annotations.Classes.class, Annotations.PackageMembers.class, Annotations.Parameters.class, Annotations.PropertiesWithoutBackingFields.class}) public static class Annotations extends AbstractLoadCompiledKotlinTest { public void testAllFilesPresentInAnnotations() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/annotations"), Pattern.compile("^(.+)\\.kt$"), true); @@ -183,6 +183,54 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT } + @TestMetadata("compiler/testData/loadKotlin/annotations/parameters") + public static class Parameters extends AbstractLoadCompiledKotlinTest { + public void testAllFilesPresentInParameters() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/annotations/parameters"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("Constructor.kt") + public void testConstructor() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/parameters/Constructor.kt"); + } + + @TestMetadata("EnumConstructor.kt") + public void testEnumConstructor() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/parameters/EnumConstructor.kt"); + } + + @TestMetadata("ExtensionFunction.kt") + public void testExtensionFunction() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/parameters/ExtensionFunction.kt"); + } + + @TestMetadata("ExtensionFunctionInClass.kt") + public void testExtensionFunctionInClass() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/parameters/ExtensionFunctionInClass.kt"); + } + + @TestMetadata("FunctionInClass.kt") + public void testFunctionInClass() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/parameters/FunctionInClass.kt"); + } + + @TestMetadata("FunctionInTrait.kt") + public void testFunctionInTrait() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/parameters/FunctionInTrait.kt"); + } + + @TestMetadata("ManyAnnotations.kt") + public void testManyAnnotations() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/parameters/ManyAnnotations.kt"); + } + + @TestMetadata("TopLevelFunction.kt") + public void testTopLevelFunction() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/parameters/TopLevelFunction.kt"); + } + + } + @TestMetadata("compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields") public static class PropertiesWithoutBackingFields extends AbstractLoadCompiledKotlinTest { public void testAllFilesPresentInPropertiesWithoutBackingFields() throws Exception { @@ -237,6 +285,7 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT suite.addTestSuite(ClassMembers.class); suite.addTestSuite(Classes.class); suite.addTestSuite(PackageMembers.class); + suite.addTestSuite(Parameters.class); suite.addTestSuite(PropertiesWithoutBackingFields.class); return suite; } diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java index 8b451f091c2..0ad3930d74e 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java @@ -40,7 +40,7 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso } @TestMetadata("compiler/testData/loadKotlin/annotations") - @InnerTestClasses({Annotations.ClassMembers.class, Annotations.Classes.class, Annotations.PackageMembers.class, Annotations.PropertiesWithoutBackingFields.class}) + @InnerTestClasses({Annotations.ClassMembers.class, Annotations.Classes.class, Annotations.PackageMembers.class, Annotations.Parameters.class, Annotations.PropertiesWithoutBackingFields.class}) public static class Annotations extends AbstractLazyResolveNamespaceComparingTest { public void testAllFilesPresentInAnnotations() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/annotations"), Pattern.compile("^(.+)\\.kt$"), true); @@ -185,6 +185,54 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso } + @TestMetadata("compiler/testData/loadKotlin/annotations/parameters") + public static class Parameters extends AbstractLazyResolveNamespaceComparingTest { + public void testAllFilesPresentInParameters() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/annotations/parameters"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("Constructor.kt") + public void testConstructor() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/parameters/Constructor.kt"); + } + + @TestMetadata("EnumConstructor.kt") + public void testEnumConstructor() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/parameters/EnumConstructor.kt"); + } + + @TestMetadata("ExtensionFunction.kt") + public void testExtensionFunction() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/parameters/ExtensionFunction.kt"); + } + + @TestMetadata("ExtensionFunctionInClass.kt") + public void testExtensionFunctionInClass() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/parameters/ExtensionFunctionInClass.kt"); + } + + @TestMetadata("FunctionInClass.kt") + public void testFunctionInClass() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/parameters/FunctionInClass.kt"); + } + + @TestMetadata("FunctionInTrait.kt") + public void testFunctionInTrait() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/parameters/FunctionInTrait.kt"); + } + + @TestMetadata("ManyAnnotations.kt") + public void testManyAnnotations() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/parameters/ManyAnnotations.kt"); + } + + @TestMetadata("TopLevelFunction.kt") + public void testTopLevelFunction() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/parameters/TopLevelFunction.kt"); + } + + } + @TestMetadata("compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields") public static class PropertiesWithoutBackingFields extends AbstractLazyResolveNamespaceComparingTest { public void testAllFilesPresentInPropertiesWithoutBackingFields() throws Exception { @@ -239,6 +287,7 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso suite.addTestSuite(ClassMembers.class); suite.addTestSuite(Classes.class); suite.addTestSuite(PackageMembers.class); + suite.addTestSuite(Parameters.class); suite.addTestSuite(PropertiesWithoutBackingFields.class); return suite; } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java index bebcfdfb586..4d0c85ad5b5 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java @@ -233,6 +233,17 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer MemberSignature signature = getCallableSignature(proto, nameResolver, kind); if (signature == null) return Collections.emptyList(); + return findClassAndLoadMemberAnnotations(container, proto, nameResolver, kind, signature); + } + + @NotNull + private List findClassAndLoadMemberAnnotations( + @NotNull ClassOrNamespaceDescriptor container, + @NotNull ProtoBuf.Callable proto, + @NotNull NameResolver nameResolver, + @NotNull AnnotatedCallableKind kind, + @NotNull MemberSignature signature + ) { KotlinJvmBinaryClass kotlinClass = findClassWithMemberAnnotations(container, proto, nameResolver, kind); if (kotlinClass == null) { errorReporter.reportAnnotationLoadingError("Kotlin class for loading member annotations is not found: " + container, null); @@ -342,34 +353,54 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer kotlinClass.loadMemberAnnotations(new KotlinJvmBinaryClass.MemberVisitor() { @Nullable @Override - public KotlinJvmBinaryClass.AnnotationVisitor visitMethod(@NotNull Name name, @NotNull String desc) { - return annotationVisitor(MemberSignature.fromMethodNameAndDesc(name, desc)); + public KotlinJvmBinaryClass.MethodAnnotationVisitor visitMethod(@NotNull Name name, @NotNull String desc) { + return new AnnotationVisitorForMethod(MemberSignature.fromMethodNameAndDesc(name, desc)); } @Nullable @Override public KotlinJvmBinaryClass.AnnotationVisitor visitField(@NotNull Name name, @NotNull String desc) { - return annotationVisitor(MemberSignature.fromFieldNameAndDesc(name, desc)); + return new MemberAnnotationVisitor(MemberSignature.fromFieldNameAndDesc(name, desc)); } - @NotNull - private KotlinJvmBinaryClass.AnnotationVisitor annotationVisitor(@NotNull final MemberSignature signature) { - return new KotlinJvmBinaryClass.AnnotationVisitor() { - private final List result = new ArrayList(); + class AnnotationVisitorForMethod extends MemberAnnotationVisitor implements KotlinJvmBinaryClass.MethodAnnotationVisitor { + public AnnotationVisitorForMethod(@NotNull MemberSignature signature) { + super(signature); + } - @Nullable - @Override - public KotlinJvmBinaryClass.AnnotationArgumentVisitor visitAnnotation(@NotNull JvmClassName className) { - return resolveAnnotation(className, result); + @Nullable + @Override + public KotlinJvmBinaryClass.AnnotationArgumentVisitor visitParameterAnnotation(int index, @NotNull JvmClassName className) { + MemberSignature paramSignature = MemberSignature.fromMethodSignatureAndParameterIndex(signature, index); + List result = memberAnnotations.get(paramSignature); + if (result == null) { + result = new ArrayList(); + memberAnnotations.put(paramSignature, result); } + return resolveAnnotation(className, result); + } + } - @Override - public void visitEnd() { - if (!result.isEmpty()) { - memberAnnotations.put(signature, result); - } + class MemberAnnotationVisitor implements KotlinJvmBinaryClass.AnnotationVisitor { + private final List result = new ArrayList(); + protected final MemberSignature signature; + + public MemberAnnotationVisitor(@NotNull MemberSignature signature) { + this.signature = signature; + } + + @Nullable + @Override + public KotlinJvmBinaryClass.AnnotationArgumentVisitor visitAnnotation(@NotNull JvmClassName className) { + return resolveAnnotation(className, result); + } + + @Override + public void visitEnd() { + if (!result.isEmpty()) { + memberAnnotations.put(signature, result); } - }; + } } }); @@ -395,6 +426,11 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer return new MemberSignature(name.asString() + "#" + desc); } + @NotNull + public static MemberSignature fromMethodSignatureAndParameterIndex(@NotNull MemberSignature signature, int index) { + return new MemberSignature(signature.signature + "@" + index); + } + @Override public int hashCode() { return signature.hashCode(); @@ -467,7 +503,23 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer @NotNull @Override - public List loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto) { - throw new UnsupportedOperationException(); // TODO + public List loadValueParameterAnnotations( + @NotNull ClassOrNamespaceDescriptor container, + @NotNull ProtoBuf.Callable callable, + @NotNull NameResolver nameResolver, + @NotNull ProtoBuf.Callable.ValueParameter proto + ) { + // Kind = FUNCTION because properties and getters don't have any value parameters, and property setters are not supported yet + // TODO: support annotations on property setter value parameters + MemberSignature methodSignature = getCallableSignature(callable, nameResolver, AnnotatedCallableKind.FUNCTION); + if (methodSignature != null) { + if (proto.hasExtension(JavaProtoBuf.index)) { + MemberSignature paramSignature = + MemberSignature.fromMethodSignatureAndParameterIndex(methodSignature, proto.getExtension(JavaProtoBuf.index)); + return findClassAndLoadMemberAnnotations(container, callable, nameResolver, AnnotatedCallableKind.FUNCTION, paramSignature); + } + } + + return Collections.emptyList(); } } 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 ed79bd4aa8c..e0c74ea4973 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 @@ -33,7 +33,7 @@ public interface KotlinJvmBinaryClass { // TODO: abstract signatures for methods and fields instead of ASM 'desc' strings? @Nullable - AnnotationVisitor visitMethod(@NotNull Name name, @NotNull String desc); + MethodAnnotationVisitor visitMethod(@NotNull Name name, @NotNull String desc); @Nullable AnnotationVisitor visitField(@NotNull Name name, @NotNull String desc); @@ -46,6 +46,11 @@ public interface KotlinJvmBinaryClass { void visitEnd(); } + interface MethodAnnotationVisitor extends AnnotationVisitor { + @Nullable + AnnotationArgumentVisitor visitParameterAnnotation(int index, @NotNull JvmClassName className); + } + interface AnnotationArgumentVisitor { // TODO: annotations, java.lang.Class void visit(@Nullable Name name, @Nullable Object value); diff --git a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java index 714e6d2e806..92a168e054d 100644 --- a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java @@ -547,6 +547,7 @@ public class DescriptorRendererImpl implements DescriptorRenderer { builder.append("/*").append(valueParameter.getIndex()).append("*/ "); } + renderAnnotations(valueParameter, builder); renderVariable(valueParameter, builder, topLevel); boolean withDefaultValue = debugMode ? valueParameter.declaresDefaultValue() : valueParameter.hasDefaultValue(); if (withDefaultValue) {