diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java b/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java index 7db45c62d5d..4b7792d6f3e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java @@ -24,9 +24,8 @@ import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil; import org.jetbrains.jet.descriptors.serialization.NameTable; import org.jetbrains.jet.descriptors.serialization.ProtoBuf; import org.jetbrains.jet.descriptors.serialization.SerializerExtension; -import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor; -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; -import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; public class JavaSerializerExtension extends SerializerExtension { private final JetTypeMapper typeMapper; @@ -49,12 +48,24 @@ public class JavaSerializerExtension extends SerializerExtension { else if (callable instanceof PropertyDescriptor) { PropertyDescriptor property = (PropertyDescriptor) callable; Type type = typeMapper.mapType(property.getType()); - Method getter = - property.getGetter() == null ? null : typeMapper.mapGetterSignature(property, OwnerKind.IMPLEMENTATION).getAsmMethod(); - Method setter = - property.getSetter() == null ? null : typeMapper.mapSetterSignature(property, OwnerKind.IMPLEMENTATION).getAsmMethod(); + PropertyGetterDescriptor getter = property.getGetter(); + PropertySetterDescriptor setter = property.getSetter(); + Method getterMethod = getter == null ? null : typeMapper.mapGetterSignature(property, OwnerKind.IMPLEMENTATION).getAsmMethod(); + Method setterMethod = setter == null ? null : typeMapper.mapSetterSignature(property, OwnerKind.IMPLEMENTATION).getAsmMethod(); - JavaProtoBufUtil.savePropertySignature(proto, type, null /* TODO */, getter, setter, nameTable); + // This is very wrong, see above todo + String fieldName; + String syntheticMethodName; + if ((getter == null || getter.isDefault()) && (setter == null || setter.isDefault())) { + fieldName = property.getName().asString(); + syntheticMethodName = null; + } + else { + fieldName = null; + syntheticMethodName = JvmAbi.getSyntheticMethodNameForAnnotatedProperty(property.getName()); + } + + JavaProtoBufUtil.savePropertySignature(proto, type, fieldName, syntheticMethodName, getterMethod, setterMethod, nameTable); } } } diff --git a/compiler/frontend.java/serialization.java/src/java_descriptors.proto b/compiler/frontend.java/serialization.java/src/java_descriptors.proto index 39115e7ffcb..a8297e758a7 100644 --- a/compiler/frontend.java/serialization.java/src/java_descriptors.proto +++ b/compiler/frontend.java/serialization.java/src/java_descriptors.proto @@ -50,9 +50,13 @@ message JavaMethodSignature { message JavaPropertySignature { required JavaType type = 1; + + // One of these should be present optional int32 field_name = 2; - optional JavaMethodSignature getter = 3; - optional JavaMethodSignature setter = 4; + optional int32 synthetic_method_name = 3; // Name of the synthetic method created to store property annotations + + optional JavaMethodSignature getter = 4; + optional JavaMethodSignature setter = 5; } extend Callable { diff --git a/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBuf.java b/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBuf.java index eccb8ddaea6..3c8dc39b1d0 100644 --- a/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBuf.java +++ b/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBuf.java @@ -1016,11 +1016,15 @@ public final class JavaProtoBuf { boolean hasFieldName(); int getFieldName(); - // optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature getter = 3; + // optional int32 synthetic_method_name = 3; + boolean hasSyntheticMethodName(); + int getSyntheticMethodName(); + + // optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature getter = 4; boolean hasGetter(); org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getGetter(); - // optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature setter = 4; + // optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature setter = 5; boolean hasSetter(); org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getSetter(); } @@ -1063,21 +1067,31 @@ public final class JavaProtoBuf { return fieldName_; } - // optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature getter = 3; - public static final int GETTER_FIELD_NUMBER = 3; + // optional int32 synthetic_method_name = 3; + public static final int SYNTHETIC_METHOD_NAME_FIELD_NUMBER = 3; + private int syntheticMethodName_; + public boolean hasSyntheticMethodName() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + public int getSyntheticMethodName() { + return syntheticMethodName_; + } + + // optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature getter = 4; + public static final int GETTER_FIELD_NUMBER = 4; private org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getter_; public boolean hasGetter() { - return ((bitField0_ & 0x00000004) == 0x00000004); + return ((bitField0_ & 0x00000008) == 0x00000008); } public org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getGetter() { return getter_; } - // optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature setter = 4; - public static final int SETTER_FIELD_NUMBER = 4; + // optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature setter = 5; + public static final int SETTER_FIELD_NUMBER = 5; private org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature setter_; public boolean hasSetter() { - return ((bitField0_ & 0x00000008) == 0x00000008); + return ((bitField0_ & 0x00000010) == 0x00000010); } public org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getSetter() { return setter_; @@ -1086,6 +1100,7 @@ public final class JavaProtoBuf { private void initFields() { type_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaType.getDefaultInstance(); fieldName_ = 0; + syntheticMethodName_ = 0; getter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); setter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); } @@ -1124,10 +1139,13 @@ public final class JavaProtoBuf { output.writeInt32(2, fieldName_); } if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeMessage(3, getter_); + output.writeInt32(3, syntheticMethodName_); } if (((bitField0_ & 0x00000008) == 0x00000008)) { - output.writeMessage(4, setter_); + output.writeMessage(4, getter_); + } + if (((bitField0_ & 0x00000010) == 0x00000010)) { + output.writeMessage(5, setter_); } } @@ -1147,11 +1165,15 @@ public final class JavaProtoBuf { } if (((bitField0_ & 0x00000004) == 0x00000004)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, getter_); + .computeInt32Size(3, syntheticMethodName_); } if (((bitField0_ & 0x00000008) == 0x00000008)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, setter_); + .computeMessageSize(4, getter_); + } + if (((bitField0_ & 0x00000010) == 0x00000010)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, setter_); } memoizedSerializedSize = size; return size; @@ -1259,10 +1281,12 @@ public final class JavaProtoBuf { bitField0_ = (bitField0_ & ~0x00000001); fieldName_ = 0; bitField0_ = (bitField0_ & ~0x00000002); - getter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); + syntheticMethodName_ = 0; bitField0_ = (bitField0_ & ~0x00000004); - setter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); + getter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); bitField0_ = (bitField0_ & ~0x00000008); + setter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); + bitField0_ = (bitField0_ & ~0x00000010); return this; } @@ -1307,10 +1331,14 @@ public final class JavaProtoBuf { if (((from_bitField0_ & 0x00000004) == 0x00000004)) { to_bitField0_ |= 0x00000004; } - result.getter_ = getter_; + result.syntheticMethodName_ = syntheticMethodName_; if (((from_bitField0_ & 0x00000008) == 0x00000008)) { to_bitField0_ |= 0x00000008; } + result.getter_ = getter_; + if (((from_bitField0_ & 0x00000010) == 0x00000010)) { + to_bitField0_ |= 0x00000010; + } result.setter_ = setter_; result.bitField0_ = to_bitField0_; return result; @@ -1324,6 +1352,9 @@ public final class JavaProtoBuf { if (other.hasFieldName()) { setFieldName(other.getFieldName()); } + if (other.hasSyntheticMethodName()) { + setSyntheticMethodName(other.getSyntheticMethodName()); + } if (other.hasGetter()) { mergeGetter(other.getGetter()); } @@ -1384,7 +1415,12 @@ public final class JavaProtoBuf { fieldName_ = input.readInt32(); break; } - case 26: { + case 24: { + bitField0_ |= 0x00000004; + syntheticMethodName_ = input.readInt32(); + break; + } + case 34: { org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.Builder subBuilder = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.newBuilder(); if (hasGetter()) { subBuilder.mergeFrom(getGetter()); @@ -1393,7 +1429,7 @@ public final class JavaProtoBuf { setGetter(subBuilder.buildPartial()); break; } - case 34: { + case 42: { org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.Builder subBuilder = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.newBuilder(); if (hasSetter()) { subBuilder.mergeFrom(getSetter()); @@ -1472,10 +1508,31 @@ public final class JavaProtoBuf { return this; } - // optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature getter = 3; + // optional int32 synthetic_method_name = 3; + private int syntheticMethodName_ ; + public boolean hasSyntheticMethodName() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + public int getSyntheticMethodName() { + return syntheticMethodName_; + } + public Builder setSyntheticMethodName(int value) { + bitField0_ |= 0x00000004; + syntheticMethodName_ = value; + + return this; + } + public Builder clearSyntheticMethodName() { + bitField0_ = (bitField0_ & ~0x00000004); + syntheticMethodName_ = 0; + + return this; + } + + // optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature getter = 4; private org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); public boolean hasGetter() { - return ((bitField0_ & 0x00000004) == 0x00000004); + return ((bitField0_ & 0x00000008) == 0x00000008); } public org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getGetter() { return getter_; @@ -1486,18 +1543,18 @@ public final class JavaProtoBuf { } getter_ = value; - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000008; return this; } public Builder setGetter( org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.Builder builderForValue) { getter_ = builderForValue.build(); - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000008; return this; } public Builder mergeGetter(org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature value) { - if (((bitField0_ & 0x00000004) == 0x00000004) && + if (((bitField0_ & 0x00000008) == 0x00000008) && getter_ != org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance()) { getter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.newBuilder(getter_).mergeFrom(value).buildPartial(); @@ -1505,20 +1562,20 @@ public final class JavaProtoBuf { getter_ = value; } - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000008; return this; } public Builder clearGetter() { getter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); - bitField0_ = (bitField0_ & ~0x00000004); + bitField0_ = (bitField0_ & ~0x00000008); return this; } - // optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature setter = 4; + // optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature setter = 5; private org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature setter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); public boolean hasSetter() { - return ((bitField0_ & 0x00000008) == 0x00000008); + return ((bitField0_ & 0x00000010) == 0x00000010); } public org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getSetter() { return setter_; @@ -1529,18 +1586,18 @@ public final class JavaProtoBuf { } setter_ = value; - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000010; return this; } public Builder setSetter( org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.Builder builderForValue) { setter_ = builderForValue.build(); - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000010; return this; } public Builder mergeSetter(org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature value) { - if (((bitField0_ & 0x00000008) == 0x00000008) && + if (((bitField0_ & 0x00000010) == 0x00000010) && setter_ != org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance()) { setter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.newBuilder(setter_).mergeFrom(value).buildPartial(); @@ -1548,13 +1605,13 @@ public final class JavaProtoBuf { setter_ = value; } - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000010; return this; } public Builder clearSetter() { setter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); - bitField0_ = (bitField0_ & ~0x00000008); + bitField0_ = (bitField0_ & ~0x00000010); return this; } diff --git a/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBufUtil.java b/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBufUtil.java index 483ef005db3..311880859e4 100644 --- a/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBufUtil.java +++ b/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBufUtil.java @@ -33,24 +33,72 @@ public class JavaProtoBufUtil { } @Nullable - public static String loadMethodSignature(@NotNull ProtoBuf.Callable proto, @NotNull NameResolver nameResolver) { + public static Method loadMethodSignature(@NotNull ProtoBuf.Callable proto, @NotNull NameResolver nameResolver) { if (!proto.hasExtension(JavaProtoBuf.methodSignature)) return null; JavaProtoBuf.JavaMethodSignature signature = proto.getExtension(JavaProtoBuf.methodSignature); - return new Deserializer(nameResolver).methodSignature(signature).toString(); + return new Deserializer(nameResolver).methodSignature(signature); } @Nullable - public static String loadPropertyGetterSignature(@NotNull ProtoBuf.Callable proto, @NotNull NameResolver nameResolver) { + public static Method loadPropertyGetterSignature(@NotNull ProtoBuf.Callable proto, @NotNull NameResolver nameResolver) { if (!proto.hasExtension(JavaProtoBuf.propertySignature)) return null; JavaProtoBuf.JavaPropertySignature propertySignature = proto.getExtension(JavaProtoBuf.propertySignature); - return new Deserializer(nameResolver).methodSignature(propertySignature.getGetter()).toString(); + return new Deserializer(nameResolver).methodSignature(propertySignature.getGetter()); } @Nullable - public static String loadPropertySetterSignature(@NotNull ProtoBuf.Callable proto, @NotNull NameResolver nameResolver) { + public static Method loadPropertySetterSignature(@NotNull ProtoBuf.Callable proto, @NotNull NameResolver nameResolver) { if (!proto.hasExtension(JavaProtoBuf.propertySignature)) return null; JavaProtoBuf.JavaPropertySignature propertySignature = proto.getExtension(JavaProtoBuf.propertySignature); - return new Deserializer(nameResolver).methodSignature(propertySignature.getSetter()).toString(); + return new Deserializer(nameResolver).methodSignature(propertySignature.getSetter()); + } + + public static class PropertyData { + private final Type type; + private final String fieldName; + private final String syntheticMethodName; + + public PropertyData(@NotNull Type type, @Nullable String fieldName, @Nullable String syntheticMethodName) { + this.type = type; + this.fieldName = fieldName; + this.syntheticMethodName = syntheticMethodName; + } + + @NotNull + public Type getType() { + return type; + } + + @Nullable + public String getFieldName() { + return fieldName; + } + + @Nullable + public String getSyntheticMethodName() { + return syntheticMethodName; + } + + @Override + public String toString() { + return (fieldName != null ? "Field " + fieldName : "Synthetic method " + syntheticMethodName) + " " + type; + } + } + + @Nullable + public static PropertyData loadPropertyData(@NotNull ProtoBuf.Callable proto, @NotNull NameResolver nameResolver) { + if (!proto.hasExtension(JavaProtoBuf.propertySignature)) return null; + JavaProtoBuf.JavaPropertySignature propertySignature = proto.getExtension(JavaProtoBuf.propertySignature); + + Type type = new Deserializer(nameResolver).type(propertySignature.getType()); + String fieldName = propertySignature.hasFieldName() + ? nameResolver.getName(propertySignature.getFieldName()).asString() + : null; + String syntheticMethodName = propertySignature.hasSyntheticMethodName() + ? nameResolver.getName(propertySignature.getSyntheticMethodName()).asString() + : null; + + return new PropertyData(type, fieldName, syntheticMethodName); } public static void saveMethodSignature(@NotNull ProtoBuf.Callable.Builder proto, @NotNull Method method, @NotNull NameTable nameTable) { @@ -61,11 +109,13 @@ public class JavaProtoBufUtil { @NotNull ProtoBuf.Callable.Builder proto, @NotNull Type type, @Nullable String fieldName, + @Nullable String syntheticMethodName, @Nullable Method getter, @Nullable Method setter, @NotNull NameTable nameTable ) { - proto.setExtension(JavaProtoBuf.propertySignature, new Serializer(nameTable).propertySignature(type, fieldName, getter, setter)); + proto.setExtension(JavaProtoBuf.propertySignature, + new Serializer(nameTable).propertySignature(type, fieldName, syntheticMethodName, getter, setter)); } private static class Serializer { @@ -94,6 +144,7 @@ public class JavaProtoBufUtil { public JavaProtoBuf.JavaPropertySignature propertySignature( @NotNull Type type, @Nullable String fieldName, + @Nullable String syntheticMethodName, @Nullable Method getter, @Nullable Method setter ) { @@ -105,6 +156,10 @@ public class JavaProtoBufUtil { signature.setFieldName(nameTable.getSimpleNameIndex(Name.guess(fieldName))); } + if (syntheticMethodName != null) { + signature.setSyntheticMethodName(nameTable.getSimpleNameIndex(Name.guess(syntheticMethodName))); + } + if (getter != null) { signature.setGetter(methodSignature(getter)); } @@ -116,7 +171,7 @@ public class JavaProtoBufUtil { } @NotNull - private JavaProtoBuf.JavaType type(@NotNull Type givenType) { + public JavaProtoBuf.JavaType type(@NotNull Type givenType) { JavaProtoBuf.JavaType.Builder builder = JavaProtoBuf.JavaType.newBuilder(); int arrayDimension = 0; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java index 38e8a3de3f4..60d0cd78062 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java @@ -21,6 +21,7 @@ import com.intellij.psi.PsiClass; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.asm4.*; +import org.jetbrains.asm4.commons.Method; import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil; import org.jetbrains.jet.descriptors.serialization.NameResolver; import org.jetbrains.jet.descriptors.serialization.ProtoBuf; @@ -33,6 +34,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; import org.jetbrains.jet.lang.resolve.java.PsiClassFinder; import org.jetbrains.jet.lang.resolve.name.FqName; @@ -180,14 +182,14 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer @NotNull NameResolver nameResolver, @NotNull AnnotatedCallableKind kind ) { - String signature = getCallableSignature(proto, nameResolver, kind); + MemberSignature signature = getCallableSignature(proto, nameResolver, kind); if (signature == null) return Collections.emptyList(); VirtualFile file = findVirtualFileByDescriptor(container); try { // TODO: calculate this only once for each container - Map> memberAnnotations = loadMemberAnnotationsFromFile(file); + Map> memberAnnotations = loadMemberAnnotationsFromFile(file); List annotations = memberAnnotations.get(signature); return annotations == null ? Collections.emptyList() : annotations; @@ -198,31 +200,35 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer } @Nullable - private static String getCallableSignature( + private static MemberSignature getCallableSignature( @NotNull ProtoBuf.Callable proto, @NotNull NameResolver nameResolver, @NotNull AnnotatedCallableKind kind ) { switch (kind) { case FUNCTION: - return JavaProtoBufUtil.loadMethodSignature(proto, nameResolver); + return MemberSignature.fromMethod(JavaProtoBufUtil.loadMethodSignature(proto, nameResolver)); case PROPERTY_GETTER: - return JavaProtoBufUtil.loadPropertyGetterSignature(proto, nameResolver); + return MemberSignature.fromMethod(JavaProtoBufUtil.loadPropertyGetterSignature(proto, nameResolver)); case PROPERTY_SETTER: - return JavaProtoBufUtil.loadPropertySetterSignature(proto, nameResolver); + return MemberSignature.fromMethod(JavaProtoBufUtil.loadPropertySetterSignature(proto, nameResolver)); + case PROPERTY: + JavaProtoBufUtil.PropertyData data = JavaProtoBufUtil.loadPropertyData(proto, nameResolver); + return data == null ? null : + MemberSignature.fromPropertyData(data.getType(), data.getFieldName(), data.getSyntheticMethodName()); default: return null; } } @NotNull - private Map> loadMemberAnnotationsFromFile(@NotNull VirtualFile file) throws IOException { - final Map> memberAnnotations = new HashMap>(); + private Map> loadMemberAnnotationsFromFile(@NotNull VirtualFile file) throws IOException { + final Map> memberAnnotations = new HashMap>(); new ClassReader(file.getInputStream()).accept(new ClassVisitor(Opcodes.ASM4) { @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - final String methodSignature = name + desc; + final MemberSignature methodSignature = MemberSignature.fromMethodNameAndDesc(name, desc); final List result = new ArrayList(); return new MethodVisitor(Opcodes.ASM4) { @@ -239,11 +245,86 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer } }; } + + @Override + public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { + final MemberSignature fieldSignature = MemberSignature.fromFieldNameAndDesc(name, desc); + final List result = new ArrayList(); + + return new FieldVisitor(Opcodes.ASM4) { + @Override + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + return resolveAnnotation(desc, result); + } + + @Override + public void visitEnd() { + if (!result.isEmpty()) { + memberAnnotations.put(fieldSignature, result); + } + } + }; + } }, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES); return memberAnnotations; } + // The purpose of this class is to hold a unique signature of either a method or a field, so that annotations on a member can be put + // into a map indexed by these signatures + private static final class MemberSignature { + private final String signature; + + private MemberSignature(@NotNull String signature) { + this.signature = signature; + } + + @Nullable + public static MemberSignature fromPropertyData( + @NotNull Type type, + @Nullable String fieldName, + @Nullable String syntheticMethodName + ) { + if (fieldName != null) { + return fromFieldNameAndDesc(fieldName, type.getDescriptor()); + } + else if (syntheticMethodName != null) { + return fromMethodNameAndDesc(syntheticMethodName, JvmAbi.ANNOTATED_PROPERTY_METHOD_SIGNATURE); + } + else return null; + } + + @Nullable + public static MemberSignature fromMethod(@Nullable Method method) { + return method == null ? null : fromMethodNameAndDesc(method.getName(), method.getDescriptor()); + } + + @NotNull + public static MemberSignature fromMethodNameAndDesc(@NotNull String name, @NotNull String desc) { + return new MemberSignature(name + desc); + } + + @NotNull + public static MemberSignature fromFieldNameAndDesc(@NotNull String name, @NotNull String desc) { + return new MemberSignature(name + "#" + desc); + } + + @Override + public int hashCode() { + return signature.hashCode(); + } + + @Override + public boolean equals(Object o) { + return o instanceof MemberSignature && signature.equals(((MemberSignature) o).signature); + } + + @Override + public String toString() { + return signature; + } + } + @NotNull @Override public List loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto) { 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 88197c4aeff..00eb52a81cb 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 @@ -193,7 +193,7 @@ public class DescriptorDeserializer { private PropertyDescriptorImpl createPropertyDescriptor(@NotNull Callable proto) { int flags = proto.getFlags(); Name name = nameResolver.getName(proto.getName()); - List annotations = Collections.emptyList(); // TODO: getAnnotations(proto, flags, PROPERTY); + List annotations = getAnnotations(proto, flags, AnnotatedCallableKind.PROPERTY); Visibility visibility = visibility(Flags.VISIBILITY.get(flags)); Callable.CallableKind callableKind = Flags.CALLABLE_KIND.get(flags); 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 20c2bf1e29e..9eff8676763 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 @@ -42,6 +42,7 @@ public interface AnnotationDeserializer { enum AnnotatedCallableKind { FUNCTION, + PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER } diff --git a/compiler/testData/loadKotlin/annotations/classMembers/PropertyField.kt b/compiler/testData/loadKotlin/annotations/classMembers/PropertyField.kt new file mode 100644 index 00000000000..6fd5d0f8cdb --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classMembers/PropertyField.kt @@ -0,0 +1,7 @@ +package test + +annotation class Anno + +class Class { + [Anno] var property: Int = 42 +} diff --git a/compiler/testData/loadKotlin/annotations/classMembers/PropertyField.txt b/compiler/testData/loadKotlin/annotations/classMembers/PropertyField.txt new file mode 100644 index 00000000000..bb7cd422709 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classMembers/PropertyField.txt @@ -0,0 +1,12 @@ +package test + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} + +internal final class Class { + /*primary*/ public constructor Class() + test.Anno() internal final var property: jet.Int + internal final fun (): jet.Int + internal final fun (/*0*/ : jet.Int): jet.Unit +} diff --git a/compiler/testData/loadKotlin/annotations/classMembers/PropertyNoField.kt b/compiler/testData/loadKotlin/annotations/classMembers/PropertyNoField.kt new file mode 100644 index 00000000000..1f8ba0cc075 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classMembers/PropertyNoField.kt @@ -0,0 +1,8 @@ +package test + +annotation class Anno + +class Class { + [Anno] val property: Int + get() = 42 +} diff --git a/compiler/testData/loadKotlin/annotations/classMembers/PropertyNoField.txt b/compiler/testData/loadKotlin/annotations/classMembers/PropertyNoField.txt new file mode 100644 index 00000000000..cd0c4b43ead --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classMembers/PropertyNoField.txt @@ -0,0 +1,11 @@ +package test + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} + +internal final class Class { + /*primary*/ public constructor Class() + test.Anno() internal final val property: jet.Int + internal final fun (): jet.Int +} diff --git a/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java b/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java index b487ed40d9f..bbe5c7107e6 100644 --- a/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java @@ -60,6 +60,16 @@ public class DescriptorSerializationTestGenerated extends AbstractDescriptorSeri doTest("compiler/testData/loadKotlin/annotations/classMembers/Getter.kt"); } + @TestMetadata("PropertyField.kt") + public void testPropertyField() throws Exception { + doTest("compiler/testData/loadKotlin/annotations/classMembers/PropertyField.kt"); + } + + @TestMetadata("PropertyNoField.kt") + public void testPropertyNoField() throws Exception { + doTest("compiler/testData/loadKotlin/annotations/classMembers/PropertyNoField.kt"); + } + @TestMetadata("Setter.kt") public void testSetter() throws Exception { doTest("compiler/testData/loadKotlin/annotations/classMembers/Setter.kt"); diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java index 31c057045a2..339ee94de4e 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java @@ -60,6 +60,16 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT doTestWithAccessors("compiler/testData/loadKotlin/annotations/classMembers/Getter.kt"); } + @TestMetadata("PropertyField.kt") + public void testPropertyField() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/classMembers/PropertyField.kt"); + } + + @TestMetadata("PropertyNoField.kt") + public void testPropertyNoField() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/classMembers/PropertyNoField.kt"); + } + @TestMetadata("Setter.kt") public void testSetter() throws Exception { doTestWithAccessors("compiler/testData/loadKotlin/annotations/classMembers/Setter.kt"); 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 ae5c7e2e7c8..67b35560ac6 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java @@ -62,6 +62,16 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classMembers/Getter.kt"); } + @TestMetadata("PropertyField.kt") + public void testPropertyField() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classMembers/PropertyField.kt"); + } + + @TestMetadata("PropertyNoField.kt") + public void testPropertyNoField() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classMembers/PropertyNoField.kt"); + } + @TestMetadata("Setter.kt") public void testSetter() throws Exception { doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classMembers/Setter.kt");