Deserialize annotations on class properties w/o fields

Annotations on properties without backing fields are stored on a special
synthesized method inside the class
This commit is contained in:
Alexander Udalov
2013-07-11 23:03:05 +04:00
parent c853c9be03
commit 87d4e35388
14 changed files with 336 additions and 59 deletions
@@ -24,9 +24,8 @@ import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil;
import org.jetbrains.jet.descriptors.serialization.NameTable; import org.jetbrains.jet.descriptors.serialization.NameTable;
import org.jetbrains.jet.descriptors.serialization.ProtoBuf; import org.jetbrains.jet.descriptors.serialization.ProtoBuf;
import org.jetbrains.jet.descriptors.serialization.SerializerExtension; import org.jetbrains.jet.descriptors.serialization.SerializerExtension;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
public class JavaSerializerExtension extends SerializerExtension { public class JavaSerializerExtension extends SerializerExtension {
private final JetTypeMapper typeMapper; private final JetTypeMapper typeMapper;
@@ -49,12 +48,24 @@ public class JavaSerializerExtension extends SerializerExtension {
else if (callable instanceof PropertyDescriptor) { else if (callable instanceof PropertyDescriptor) {
PropertyDescriptor property = (PropertyDescriptor) callable; PropertyDescriptor property = (PropertyDescriptor) callable;
Type type = typeMapper.mapType(property.getType()); Type type = typeMapper.mapType(property.getType());
Method getter = PropertyGetterDescriptor getter = property.getGetter();
property.getGetter() == null ? null : typeMapper.mapGetterSignature(property, OwnerKind.IMPLEMENTATION).getAsmMethod(); PropertySetterDescriptor setter = property.getSetter();
Method setter = Method getterMethod = getter == null ? null : typeMapper.mapGetterSignature(property, OwnerKind.IMPLEMENTATION).getAsmMethod();
property.getSetter() == null ? null : typeMapper.mapSetterSignature(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);
} }
} }
} }
@@ -50,9 +50,13 @@ message JavaMethodSignature {
message JavaPropertySignature { message JavaPropertySignature {
required JavaType type = 1; required JavaType type = 1;
// One of these should be present
optional int32 field_name = 2; optional int32 field_name = 2;
optional JavaMethodSignature getter = 3; optional int32 synthetic_method_name = 3; // Name of the synthetic method created to store property annotations
optional JavaMethodSignature setter = 4;
optional JavaMethodSignature getter = 4;
optional JavaMethodSignature setter = 5;
} }
extend Callable { extend Callable {
@@ -1016,11 +1016,15 @@ public final class JavaProtoBuf {
boolean hasFieldName(); boolean hasFieldName();
int getFieldName(); 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(); boolean hasGetter();
org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getGetter(); 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(); boolean hasSetter();
org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getSetter(); org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getSetter();
} }
@@ -1063,21 +1067,31 @@ public final class JavaProtoBuf {
return fieldName_; return fieldName_;
} }
// optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature getter = 3; // optional int32 synthetic_method_name = 3;
public static final int GETTER_FIELD_NUMBER = 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_; private org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getter_;
public boolean hasGetter() { public boolean hasGetter() {
return ((bitField0_ & 0x00000004) == 0x00000004); return ((bitField0_ & 0x00000008) == 0x00000008);
} }
public org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getGetter() { public org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getGetter() {
return getter_; return getter_;
} }
// optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature setter = 4; // optional .org.jetbrains.jet.descriptors.serialization.JavaMethodSignature setter = 5;
public static final int SETTER_FIELD_NUMBER = 4; public static final int SETTER_FIELD_NUMBER = 5;
private org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature setter_; private org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature setter_;
public boolean hasSetter() { public boolean hasSetter() {
return ((bitField0_ & 0x00000008) == 0x00000008); return ((bitField0_ & 0x00000010) == 0x00000010);
} }
public org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getSetter() { public org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getSetter() {
return setter_; return setter_;
@@ -1086,6 +1100,7 @@ public final class JavaProtoBuf {
private void initFields() { private void initFields() {
type_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaType.getDefaultInstance(); type_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaType.getDefaultInstance();
fieldName_ = 0; fieldName_ = 0;
syntheticMethodName_ = 0;
getter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); getter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance();
setter_ = 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_); output.writeInt32(2, fieldName_);
} }
if (((bitField0_ & 0x00000004) == 0x00000004)) { if (((bitField0_ & 0x00000004) == 0x00000004)) {
output.writeMessage(3, getter_); output.writeInt32(3, syntheticMethodName_);
} }
if (((bitField0_ & 0x00000008) == 0x00000008)) { 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)) { if (((bitField0_ & 0x00000004) == 0x00000004)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeMessageSize(3, getter_); .computeInt32Size(3, syntheticMethodName_);
} }
if (((bitField0_ & 0x00000008) == 0x00000008)) { if (((bitField0_ & 0x00000008) == 0x00000008)) {
size += com.google.protobuf.CodedOutputStream 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; memoizedSerializedSize = size;
return size; return size;
@@ -1259,10 +1281,12 @@ public final class JavaProtoBuf {
bitField0_ = (bitField0_ & ~0x00000001); bitField0_ = (bitField0_ & ~0x00000001);
fieldName_ = 0; fieldName_ = 0;
bitField0_ = (bitField0_ & ~0x00000002); bitField0_ = (bitField0_ & ~0x00000002);
getter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); syntheticMethodName_ = 0;
bitField0_ = (bitField0_ & ~0x00000004); bitField0_ = (bitField0_ & ~0x00000004);
setter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); getter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance();
bitField0_ = (bitField0_ & ~0x00000008); bitField0_ = (bitField0_ & ~0x00000008);
setter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance();
bitField0_ = (bitField0_ & ~0x00000010);
return this; return this;
} }
@@ -1307,10 +1331,14 @@ public final class JavaProtoBuf {
if (((from_bitField0_ & 0x00000004) == 0x00000004)) { if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
to_bitField0_ |= 0x00000004; to_bitField0_ |= 0x00000004;
} }
result.getter_ = getter_; result.syntheticMethodName_ = syntheticMethodName_;
if (((from_bitField0_ & 0x00000008) == 0x00000008)) { if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
to_bitField0_ |= 0x00000008; to_bitField0_ |= 0x00000008;
} }
result.getter_ = getter_;
if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
to_bitField0_ |= 0x00000010;
}
result.setter_ = setter_; result.setter_ = setter_;
result.bitField0_ = to_bitField0_; result.bitField0_ = to_bitField0_;
return result; return result;
@@ -1324,6 +1352,9 @@ public final class JavaProtoBuf {
if (other.hasFieldName()) { if (other.hasFieldName()) {
setFieldName(other.getFieldName()); setFieldName(other.getFieldName());
} }
if (other.hasSyntheticMethodName()) {
setSyntheticMethodName(other.getSyntheticMethodName());
}
if (other.hasGetter()) { if (other.hasGetter()) {
mergeGetter(other.getGetter()); mergeGetter(other.getGetter());
} }
@@ -1384,7 +1415,12 @@ public final class JavaProtoBuf {
fieldName_ = input.readInt32(); fieldName_ = input.readInt32();
break; 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(); org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.Builder subBuilder = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.newBuilder();
if (hasGetter()) { if (hasGetter()) {
subBuilder.mergeFrom(getGetter()); subBuilder.mergeFrom(getGetter());
@@ -1393,7 +1429,7 @@ public final class JavaProtoBuf {
setGetter(subBuilder.buildPartial()); setGetter(subBuilder.buildPartial());
break; break;
} }
case 34: { case 42: {
org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.Builder subBuilder = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.newBuilder(); org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.Builder subBuilder = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.newBuilder();
if (hasSetter()) { if (hasSetter()) {
subBuilder.mergeFrom(getSetter()); subBuilder.mergeFrom(getSetter());
@@ -1472,10 +1508,31 @@ public final class JavaProtoBuf {
return this; 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(); private org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance();
public boolean hasGetter() { public boolean hasGetter() {
return ((bitField0_ & 0x00000004) == 0x00000004); return ((bitField0_ & 0x00000008) == 0x00000008);
} }
public org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getGetter() { public org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getGetter() {
return getter_; return getter_;
@@ -1486,18 +1543,18 @@ public final class JavaProtoBuf {
} }
getter_ = value; getter_ = value;
bitField0_ |= 0x00000004; bitField0_ |= 0x00000008;
return this; return this;
} }
public Builder setGetter( public Builder setGetter(
org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.Builder builderForValue) { org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.Builder builderForValue) {
getter_ = builderForValue.build(); getter_ = builderForValue.build();
bitField0_ |= 0x00000004; bitField0_ |= 0x00000008;
return this; return this;
} }
public Builder mergeGetter(org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature value) { 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.getDefaultInstance()) {
getter_ = getter_ =
org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.newBuilder(getter_).mergeFrom(value).buildPartial(); org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.newBuilder(getter_).mergeFrom(value).buildPartial();
@@ -1505,20 +1562,20 @@ public final class JavaProtoBuf {
getter_ = value; getter_ = value;
} }
bitField0_ |= 0x00000004; bitField0_ |= 0x00000008;
return this; return this;
} }
public Builder clearGetter() { public Builder clearGetter() {
getter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); getter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance();
bitField0_ = (bitField0_ & ~0x00000004); bitField0_ = (bitField0_ & ~0x00000008);
return this; 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(); private org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature setter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance();
public boolean hasSetter() { public boolean hasSetter() {
return ((bitField0_ & 0x00000008) == 0x00000008); return ((bitField0_ & 0x00000010) == 0x00000010);
} }
public org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getSetter() { public org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature getSetter() {
return setter_; return setter_;
@@ -1529,18 +1586,18 @@ public final class JavaProtoBuf {
} }
setter_ = value; setter_ = value;
bitField0_ |= 0x00000008; bitField0_ |= 0x00000010;
return this; return this;
} }
public Builder setSetter( public Builder setSetter(
org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.Builder builderForValue) { org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.Builder builderForValue) {
setter_ = builderForValue.build(); setter_ = builderForValue.build();
bitField0_ |= 0x00000008; bitField0_ |= 0x00000010;
return this; return this;
} }
public Builder mergeSetter(org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature value) { 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.getDefaultInstance()) {
setter_ = setter_ =
org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.newBuilder(setter_).mergeFrom(value).buildPartial(); org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.newBuilder(setter_).mergeFrom(value).buildPartial();
@@ -1548,13 +1605,13 @@ public final class JavaProtoBuf {
setter_ = value; setter_ = value;
} }
bitField0_ |= 0x00000008; bitField0_ |= 0x00000010;
return this; return this;
} }
public Builder clearSetter() { public Builder clearSetter() {
setter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance(); setter_ = org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.JavaMethodSignature.getDefaultInstance();
bitField0_ = (bitField0_ & ~0x00000008); bitField0_ = (bitField0_ & ~0x00000010);
return this; return this;
} }
@@ -33,24 +33,72 @@ public class JavaProtoBufUtil {
} }
@Nullable @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; if (!proto.hasExtension(JavaProtoBuf.methodSignature)) return null;
JavaProtoBuf.JavaMethodSignature signature = proto.getExtension(JavaProtoBuf.methodSignature); JavaProtoBuf.JavaMethodSignature signature = proto.getExtension(JavaProtoBuf.methodSignature);
return new Deserializer(nameResolver).methodSignature(signature).toString(); return new Deserializer(nameResolver).methodSignature(signature);
} }
@Nullable @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; if (!proto.hasExtension(JavaProtoBuf.propertySignature)) return null;
JavaProtoBuf.JavaPropertySignature propertySignature = proto.getExtension(JavaProtoBuf.propertySignature); JavaProtoBuf.JavaPropertySignature propertySignature = proto.getExtension(JavaProtoBuf.propertySignature);
return new Deserializer(nameResolver).methodSignature(propertySignature.getGetter()).toString(); return new Deserializer(nameResolver).methodSignature(propertySignature.getGetter());
} }
@Nullable @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; if (!proto.hasExtension(JavaProtoBuf.propertySignature)) return null;
JavaProtoBuf.JavaPropertySignature propertySignature = proto.getExtension(JavaProtoBuf.propertySignature); 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) { 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 ProtoBuf.Callable.Builder proto,
@NotNull Type type, @NotNull Type type,
@Nullable String fieldName, @Nullable String fieldName,
@Nullable String syntheticMethodName,
@Nullable Method getter, @Nullable Method getter,
@Nullable Method setter, @Nullable Method setter,
@NotNull NameTable nameTable @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 { private static class Serializer {
@@ -94,6 +144,7 @@ public class JavaProtoBufUtil {
public JavaProtoBuf.JavaPropertySignature propertySignature( public JavaProtoBuf.JavaPropertySignature propertySignature(
@NotNull Type type, @NotNull Type type,
@Nullable String fieldName, @Nullable String fieldName,
@Nullable String syntheticMethodName,
@Nullable Method getter, @Nullable Method getter,
@Nullable Method setter @Nullable Method setter
) { ) {
@@ -105,6 +156,10 @@ public class JavaProtoBufUtil {
signature.setFieldName(nameTable.getSimpleNameIndex(Name.guess(fieldName))); signature.setFieldName(nameTable.getSimpleNameIndex(Name.guess(fieldName)));
} }
if (syntheticMethodName != null) {
signature.setSyntheticMethodName(nameTable.getSimpleNameIndex(Name.guess(syntheticMethodName)));
}
if (getter != null) { if (getter != null) {
signature.setGetter(methodSignature(getter)); signature.setGetter(methodSignature(getter));
} }
@@ -116,7 +171,7 @@ public class JavaProtoBufUtil {
} }
@NotNull @NotNull
private JavaProtoBuf.JavaType type(@NotNull Type givenType) { public JavaProtoBuf.JavaType type(@NotNull Type givenType) {
JavaProtoBuf.JavaType.Builder builder = JavaProtoBuf.JavaType.newBuilder(); JavaProtoBuf.JavaType.Builder builder = JavaProtoBuf.JavaType.newBuilder();
int arrayDimension = 0; int arrayDimension = 0;
@@ -21,6 +21,7 @@ import com.intellij.psi.PsiClass;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.*; import org.jetbrains.asm4.*;
import org.jetbrains.asm4.commons.Method;
import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil; import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil;
import org.jetbrains.jet.descriptors.serialization.NameResolver; import org.jetbrains.jet.descriptors.serialization.NameResolver;
import org.jetbrains.jet.descriptors.serialization.ProtoBuf; 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.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils; 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.PackageClassUtils;
import org.jetbrains.jet.lang.resolve.java.PsiClassFinder; import org.jetbrains.jet.lang.resolve.java.PsiClassFinder;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -180,14 +182,14 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
@NotNull NameResolver nameResolver, @NotNull NameResolver nameResolver,
@NotNull AnnotatedCallableKind kind @NotNull AnnotatedCallableKind kind
) { ) {
String signature = getCallableSignature(proto, nameResolver, kind); MemberSignature signature = getCallableSignature(proto, nameResolver, kind);
if (signature == null) return Collections.emptyList(); if (signature == null) return Collections.emptyList();
VirtualFile file = findVirtualFileByDescriptor(container); VirtualFile file = findVirtualFileByDescriptor(container);
try { try {
// TODO: calculate this only once for each container // TODO: calculate this only once for each container
Map<String, List<AnnotationDescriptor>> memberAnnotations = loadMemberAnnotationsFromFile(file); Map<MemberSignature, List<AnnotationDescriptor>> memberAnnotations = loadMemberAnnotationsFromFile(file);
List<AnnotationDescriptor> annotations = memberAnnotations.get(signature); List<AnnotationDescriptor> annotations = memberAnnotations.get(signature);
return annotations == null ? Collections.<AnnotationDescriptor>emptyList() : annotations; return annotations == null ? Collections.<AnnotationDescriptor>emptyList() : annotations;
@@ -198,31 +200,35 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
} }
@Nullable @Nullable
private static String getCallableSignature( private static MemberSignature getCallableSignature(
@NotNull ProtoBuf.Callable proto, @NotNull ProtoBuf.Callable proto,
@NotNull NameResolver nameResolver, @NotNull NameResolver nameResolver,
@NotNull AnnotatedCallableKind kind @NotNull AnnotatedCallableKind kind
) { ) {
switch (kind) { switch (kind) {
case FUNCTION: case FUNCTION:
return JavaProtoBufUtil.loadMethodSignature(proto, nameResolver); return MemberSignature.fromMethod(JavaProtoBufUtil.loadMethodSignature(proto, nameResolver));
case PROPERTY_GETTER: case PROPERTY_GETTER:
return JavaProtoBufUtil.loadPropertyGetterSignature(proto, nameResolver); return MemberSignature.fromMethod(JavaProtoBufUtil.loadPropertyGetterSignature(proto, nameResolver));
case PROPERTY_SETTER: 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: default:
return null; return null;
} }
} }
@NotNull @NotNull
private Map<String, List<AnnotationDescriptor>> loadMemberAnnotationsFromFile(@NotNull VirtualFile file) throws IOException { private Map<MemberSignature, List<AnnotationDescriptor>> loadMemberAnnotationsFromFile(@NotNull VirtualFile file) throws IOException {
final Map<String, List<AnnotationDescriptor>> memberAnnotations = new HashMap<String, List<AnnotationDescriptor>>(); final Map<MemberSignature, List<AnnotationDescriptor>> memberAnnotations = new HashMap<MemberSignature, List<AnnotationDescriptor>>();
new ClassReader(file.getInputStream()).accept(new ClassVisitor(Opcodes.ASM4) { new ClassReader(file.getInputStream()).accept(new ClassVisitor(Opcodes.ASM4) {
@Override @Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 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<AnnotationDescriptor> result = new ArrayList<AnnotationDescriptor>(); final List<AnnotationDescriptor> result = new ArrayList<AnnotationDescriptor>();
return new MethodVisitor(Opcodes.ASM4) { 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<AnnotationDescriptor> result = new ArrayList<AnnotationDescriptor>();
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); }, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES);
return memberAnnotations; 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 @NotNull
@Override @Override
public List<AnnotationDescriptor> loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto) { public List<AnnotationDescriptor> loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto) {
@@ -193,7 +193,7 @@ public class DescriptorDeserializer {
private PropertyDescriptorImpl createPropertyDescriptor(@NotNull Callable proto) { private PropertyDescriptorImpl createPropertyDescriptor(@NotNull Callable proto) {
int flags = proto.getFlags(); int flags = proto.getFlags();
Name name = nameResolver.getName(proto.getName()); Name name = nameResolver.getName(proto.getName());
List<AnnotationDescriptor> annotations = Collections.emptyList(); // TODO: getAnnotations(proto, flags, PROPERTY); List<AnnotationDescriptor> annotations = getAnnotations(proto, flags, AnnotatedCallableKind.PROPERTY);
Visibility visibility = visibility(Flags.VISIBILITY.get(flags)); Visibility visibility = visibility(Flags.VISIBILITY.get(flags));
Callable.CallableKind callableKind = Flags.CALLABLE_KIND.get(flags); Callable.CallableKind callableKind = Flags.CALLABLE_KIND.get(flags);
@@ -42,6 +42,7 @@ public interface AnnotationDeserializer {
enum AnnotatedCallableKind { enum AnnotatedCallableKind {
FUNCTION, FUNCTION,
PROPERTY,
PROPERTY_GETTER, PROPERTY_GETTER,
PROPERTY_SETTER PROPERTY_SETTER
} }
@@ -0,0 +1,7 @@
package test
annotation class Anno
class Class {
[Anno] var property: Int = 42
}
@@ -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 <get-property>(): jet.Int
internal final fun <set-property>(/*0*/ <set-?>: jet.Int): jet.Unit
}
@@ -0,0 +1,8 @@
package test
annotation class Anno
class Class {
[Anno] val property: Int
get() = 42
}
@@ -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 <get-property>(): jet.Int
}
@@ -60,6 +60,16 @@ public class DescriptorSerializationTestGenerated extends AbstractDescriptorSeri
doTest("compiler/testData/loadKotlin/annotations/classMembers/Getter.kt"); 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") @TestMetadata("Setter.kt")
public void testSetter() throws Exception { public void testSetter() throws Exception {
doTest("compiler/testData/loadKotlin/annotations/classMembers/Setter.kt"); doTest("compiler/testData/loadKotlin/annotations/classMembers/Setter.kt");
@@ -60,6 +60,16 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT
doTestWithAccessors("compiler/testData/loadKotlin/annotations/classMembers/Getter.kt"); 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") @TestMetadata("Setter.kt")
public void testSetter() throws Exception { public void testSetter() throws Exception {
doTestWithAccessors("compiler/testData/loadKotlin/annotations/classMembers/Setter.kt"); doTestWithAccessors("compiler/testData/loadKotlin/annotations/classMembers/Setter.kt");
@@ -62,6 +62,16 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classMembers/Getter.kt"); 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") @TestMetadata("Setter.kt")
public void testSetter() throws Exception { public void testSetter() throws Exception {
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classMembers/Setter.kt"); doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classMembers/Setter.kt");