Change object deserialization strategy

Objects now have synthetic class objects in deserialization as well. "Class"
proto message now can have a synthetic class object proto within, if it's not
contained in any external class file, which is the case with objects. Drop
"class_object_present" field from binary format, since its value is equivalent
to the presence of "class_object" field
This commit is contained in:
Alexander Udalov
2013-10-29 22:11:07 +04:00
parent 26bd1ff189
commit c04f63e157
17 changed files with 709 additions and 165 deletions
@@ -210,14 +210,12 @@ public class NamespaceCodegen extends MemberCodegen {
* @param namespaceFiles all files should have same package name * @param namespaceFiles all files should have same package name
* @return * @return
*/ */
public static boolean shouldGenerateNSClass(Collection<JetFile> namespaceFiles) { public static boolean shouldGenerateNSClass(@NotNull Collection<JetFile> namespaceFiles) {
checkAllFilesHaveSameNamespace(namespaceFiles); checkAllFilesHaveSameNamespace(namespaceFiles);
for (JetFile file : namespaceFiles) { for (JetFile file : namespaceFiles) {
for (JetDeclaration declaration : file.getDeclarations()) { for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetProperty || if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
declaration instanceof JetNamedFunction ||
declaration instanceof JetObjectDeclaration) {
return true; return true;
} }
} }
Binary file not shown.
Binary file not shown.
@@ -110,6 +110,15 @@ message Class {
required int32 fq_name = 3; required int32 fq_name = 3;
message ClassObject {
// If this field is present, it contains serialized data for a synthetic class object, for which there's no class file.
// Otherwise class object was compiled to a separate class file and serialized data can be found in the annotation on that class
optional Class data = 1;
}
// This field is present if and only if the class has a class object. Its proto should be found either here or in the separate file
optional ClassObject class_object = 4;
repeated TypeParameter type_parameter = 5; repeated TypeParameter type_parameter = 5;
repeated Type supertype = 6; repeated Type supertype = 6;
@@ -118,8 +127,6 @@ message Class {
repeated int32 nested_class_name = 7; repeated int32 nested_class_name = 7;
repeated int32 nested_object_name = 8; repeated int32 nested_object_name = 8;
optional bool class_object_present = 9 [default = false];
repeated Callable member = 11; repeated Callable member = 11;
repeated int32 enum_entry = 12; repeated int32 enum_entry = 12;
@@ -26,7 +26,6 @@ import org.jetbrains.jet.storage.MemoizedFunctionToNullable;
import org.jetbrains.jet.storage.StorageManager; import org.jetbrains.jet.storage.StorageManager;
public abstract class AbstractDescriptorFinder implements DescriptorFinder { public abstract class AbstractDescriptorFinder implements DescriptorFinder {
private final MemoizedFunctionToNullable<ClassId, ClassDescriptor> findClass; private final MemoizedFunctionToNullable<ClassId, ClassDescriptor> findClass;
private final AnnotationDeserializer annotationDeserializer; private final AnnotationDeserializer annotationDeserializer;
@@ -46,7 +45,8 @@ public abstract class AbstractDescriptorFinder implements DescriptorFinder {
AbstractDescriptorFinder _this = AbstractDescriptorFinder.this; AbstractDescriptorFinder _this = AbstractDescriptorFinder.this;
ClassDescriptor classDescriptor = ClassDescriptor classDescriptor =
new DeserializedClassDescriptor(storageManager, _this.annotationDeserializer, _this, classData); new DeserializedClassDescriptor(storageManager, _this.annotationDeserializer, _this, classData.getNameResolver(),
classData.getClassProto());
classDescriptorCreated(classDescriptor); classDescriptorCreated(classDescriptor);
return classDescriptor; return classDescriptor;
} }
@@ -29,17 +29,14 @@ import org.jetbrains.jet.renderer.DescriptorRenderer;
import java.util.*; import java.util.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getEnumEntriesScope; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isTopLevelOrInnerClass;
public class DescriptorSerializer { public class DescriptorSerializer {
private static final DescriptorRenderer RENDERER = DescriptorRenderer.STARTS_FROM_NAME; private static final DescriptorRenderer RENDERER = DescriptorRenderer.STARTS_FROM_NAME;
private static final Comparator<DeclarationDescriptor> DESCRIPTOR_COMPARATOR = new Comparator<DeclarationDescriptor>() { private static final Comparator<DeclarationDescriptor> DESCRIPTOR_COMPARATOR = new Comparator<DeclarationDescriptor>() {
@Override @Override
public int compare( public int compare(@NotNull DeclarationDescriptor o1, @NotNull DeclarationDescriptor o2) {
DeclarationDescriptor o1, DeclarationDescriptor o2
) {
int names = o1.getName().compareTo(o2.getName()); int names = o1.getName().compareTo(o2.getName());
if (names != 0) return names; if (names != 0) return names;
@@ -134,9 +131,9 @@ public class DescriptorSerializer {
builder.addNestedObjectName(nameIndex); builder.addNestedObjectName(nameIndex);
} }
if (classDescriptor.getClassObjectDescriptor() != null) { ClassDescriptor classObject = classDescriptor.getClassObjectDescriptor();
// false is default if (classObject != null) {
builder.setClassObjectPresent(true); builder.setClassObject(classObjectProto(classObject));
} }
if (classDescriptor.getKind() == ClassKind.ENUM_CLASS) { if (classDescriptor.getKind() == ClassKind.ENUM_CLASS) {
@@ -150,6 +147,15 @@ public class DescriptorSerializer {
return builder; return builder;
} }
@NotNull
private ProtoBuf.Class.ClassObject classObjectProto(@NotNull ClassDescriptor classObject) {
if (isObject(classObject.getContainingDeclaration())) {
return ProtoBuf.Class.ClassObject.newBuilder().setData(classProto(classObject)).build();
}
return ProtoBuf.Class.ClassObject.getDefaultInstance();
}
@NotNull @NotNull
public ProtoBuf.Callable.Builder callableProto(@NotNull CallableMemberDescriptor descriptor) { public ProtoBuf.Callable.Builder callableProto(@NotNull CallableMemberDescriptor descriptor) {
ProtoBuf.Callable.Builder builder = ProtoBuf.Callable.newBuilder(); ProtoBuf.Callable.Builder builder = ProtoBuf.Callable.newBuilder();
@@ -48,6 +48,7 @@ public class DeserializedClassDescriptor extends AbstractClassDescriptor impleme
private final ClassId classId; private final ClassId classId;
private final ProtoBuf.Class classProto; private final ProtoBuf.Class classProto;
private final StorageManager storageManager;
private final TypeDeserializer typeDeserializer; private final TypeDeserializer typeDeserializer;
private final DescriptorDeserializer deserializer; private final DescriptorDeserializer deserializer;
private final DeserializedMemberScope memberScope; private final DeserializedMemberScope memberScope;
@@ -74,14 +75,13 @@ public class DeserializedClassDescriptor extends AbstractClassDescriptor impleme
@NotNull StorageManager storageManager, @NotNull StorageManager storageManager,
@NotNull AnnotationDeserializer annotationResolver, @NotNull AnnotationDeserializer annotationResolver,
@NotNull DescriptorFinder descriptorFinder, @NotNull DescriptorFinder descriptorFinder,
@NotNull ClassData classData @NotNull NameResolver nameResolver,
@NotNull ProtoBuf.Class classProto
) { ) {
super(storageManager, super(storageManager, nameResolver.getClassId(classProto.getFqName()).getRelativeClassName().shortName());
classData.getNameResolver().getClassId(classData.getClassProto().getFqName()).getRelativeClassName().shortName()); this.classProto = classProto;
NameResolver nameResolver = classData.getNameResolver();
this.classProto = classData.getClassProto();
this.classId = nameResolver.getClassId(classProto.getFqName()); this.classId = nameResolver.getClassId(classProto.getFqName());
this.storageManager = storageManager;
this.descriptorFinder = descriptorFinder; this.descriptorFinder = descriptorFinder;
TypeDeserializer notNullTypeDeserializer = new TypeDeserializer(storageManager, null, nameResolver, TypeDeserializer notNullTypeDeserializer = new TypeDeserializer(storageManager, null, nameResolver,
@@ -238,7 +238,7 @@ public class DeserializedClassDescriptor extends AbstractClassDescriptor impleme
@Nullable @Nullable
private ClassDescriptor computeClassObjectDescriptor() { private ClassDescriptor computeClassObjectDescriptor() {
if (!classProto.getClassObjectPresent()) { if (!classProto.hasClassObject()) {
return null; return null;
} }
@@ -252,6 +252,16 @@ public class DeserializedClassDescriptor extends AbstractClassDescriptor impleme
return classObject; return classObject;
} }
if (getKind() == ClassKind.OBJECT) {
ProtoBuf.Class.ClassObject classObjectProto = classProto.getClassObject();
if (!classObjectProto.hasData()) {
throw new IllegalStateException("Object should have a serialized class object: " + classId);
}
return new DeserializedClassDescriptor(storageManager, annotationDeserializer, descriptorFinder, deserializer.getNameResolver(),
classObjectProto.getData());
}
return descriptorFinder.findClass(classId.createNestedClassId(getClassObjectName(getName()))); return descriptorFinder.findClass(classId.createNestedClassId(getClassObjectName(getName())));
} }
@@ -55,11 +55,7 @@ public final class JavaPackageScope extends JavaBaseScope {
@Override @Override
public ClassifierDescriptor getClassifier(@NotNull Name name) { public ClassifierDescriptor getClassifier(@NotNull Name name) {
ClassDescriptor classDescriptor = memberResolver.resolveClass(packageFQN.child(name), IGNORE_KOTLIN_SOURCES); return memberResolver.resolveClass(packageFQN.child(name), IGNORE_KOTLIN_SOURCES);
if (classDescriptor == null || classDescriptor.getKind().isSingleton()) {
return null;
}
return classDescriptor;
} }
@Override @Override
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve.kotlin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.descriptors.serialization.ClassData;
import org.jetbrains.jet.descriptors.serialization.ClassId; import org.jetbrains.jet.descriptors.serialization.ClassId;
import org.jetbrains.jet.descriptors.serialization.DescriptorFinder; import org.jetbrains.jet.descriptors.serialization.DescriptorFinder;
import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil; import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil;
@@ -97,15 +98,22 @@ public final class DeserializedDescriptorResolver {
@Nullable @Nullable
public ClassDescriptor resolveClass(@NotNull KotlinJvmBinaryClass kotlinClass) { public ClassDescriptor resolveClass(@NotNull KotlinJvmBinaryClass kotlinClass) {
String[] data = readData(kotlinClass); String[] data = readData(kotlinClass);
return data == null ? null : new DeserializedClassDescriptor(storageManager, annotationDeserializer, javaDescriptorFinder, if (data != null) {
JavaProtoBufUtil.readClassDataFrom(data)); ClassData classData = JavaProtoBufUtil.readClassDataFrom(data);
return new DeserializedClassDescriptor(storageManager, annotationDeserializer, javaDescriptorFinder,
classData.getNameResolver(), classData.getClassProto());
}
return null;
} }
@Nullable @Nullable
public JetScope createKotlinPackageScope(@NotNull NamespaceDescriptor descriptor, @NotNull KotlinJvmBinaryClass kotlinClass) { public JetScope createKotlinPackageScope(@NotNull NamespaceDescriptor descriptor, @NotNull KotlinJvmBinaryClass kotlinClass) {
String[] data = readData(kotlinClass); String[] data = readData(kotlinClass);
return data == null ? null : new DeserializedPackageMemberScope(storageManager, descriptor, annotationDeserializer, if (data != null) {
javaDescriptorFinder, JavaProtoBufUtil.readPackageDataFrom(data)); return new DeserializedPackageMemberScope(storageManager, descriptor, annotationDeserializer, javaDescriptorFinder,
JavaProtoBufUtil.readPackageDataFrom(data));
}
return null;
} }
@Nullable @Nullable