Deserialize annotations on value parameters of functions
This commit is contained in:
+7
-1
@@ -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();
|
||||
|
||||
+26
-18
@@ -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.<TypeParameter>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<ValueParameterDescriptor> valueParameters(@NotNull List<Callable.ValueParameter> protos) {
|
||||
private List<ValueParameterDescriptor> 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<Callable.ValueParameter> protos = callable.getValueParameterList();
|
||||
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(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<AnnotationDescriptor> getAnnotations(Callable.ValueParameter proto) {
|
||||
return Flags.HAS_ANNOTATIONS.get(proto.getFlags())
|
||||
? annotationDeserializer.loadValueParameterAnnotations(proto)
|
||||
@NotNull
|
||||
private List<AnnotationDescriptor> 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.<AnnotationDescriptor>emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
+28
-2
@@ -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<AnnotationDescriptor> loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto) {
|
||||
public List<AnnotationDescriptor> 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<AnnotationDescriptor> loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto);
|
||||
List<AnnotationDescriptor> loadValueParameterAnnotations(
|
||||
@NotNull ClassOrNamespaceDescriptor container,
|
||||
@NotNull ProtoBuf.Callable callable,
|
||||
@NotNull NameResolver nameResolver,
|
||||
@NotNull ProtoBuf.Callable.ValueParameter proto
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
annotation class A
|
||||
annotation class B
|
||||
|
||||
class Class([A] val x: Int, [B] y: String)
|
||||
@@ -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 <get-x>(): jet.Int
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
annotation class A
|
||||
annotation class B
|
||||
|
||||
enum class E([A] val x: String, [B] val y: Int)
|
||||
@@ -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<test.E> {
|
||||
/*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 <get-x>(): jet.String
|
||||
test.B() internal final val y: jet.Int
|
||||
internal final fun <get-y>(): 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 <class-object-for-E> {
|
||||
/*primary*/ private constructor <class-object-for-E>()
|
||||
public final fun valueOf(/*0*/ value: jet.String): test.E
|
||||
public final fun values(): jet.Array<test.E>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package test
|
||||
|
||||
annotation class A
|
||||
|
||||
fun Int.foo([A] x: Int) {}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
annotation class Anno
|
||||
|
||||
class Class {
|
||||
fun String.foo([Anno] x: Int) = 42
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
annotation class Anno
|
||||
|
||||
class Class {
|
||||
fun foo([Anno] x: String) {}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
annotation class Anno
|
||||
|
||||
trait Trait {
|
||||
fun foo([Anno] x: String) = 42
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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) {}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package test
|
||||
|
||||
annotation class Anno
|
||||
|
||||
fun foo([Anno] x: Int) {}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+50
-1
@@ -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;
|
||||
}
|
||||
|
||||
+71
-19
@@ -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<AnnotationDescriptor> 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<AnnotationDescriptor> result = new ArrayList<AnnotationDescriptor>();
|
||||
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<AnnotationDescriptor> result = memberAnnotations.get(paramSignature);
|
||||
if (result == null) {
|
||||
result = new ArrayList<AnnotationDescriptor>();
|
||||
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<AnnotationDescriptor> result = new ArrayList<AnnotationDescriptor>();
|
||||
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<AnnotationDescriptor> loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
public List<AnnotationDescriptor> 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();
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user