Refactor AbstractDescriptorSerializationTest

Use existing utility functions, replace ClassMetadata -> ClassData, add
annotations, etc.
This commit is contained in:
Alexander Udalov
2013-07-09 22:57:58 +04:00
parent 6ae81c3ade
commit eee9bb5a12
2 changed files with 58 additions and 99 deletions
@@ -36,7 +36,7 @@ public class JavaProtoBufUtil {
} }
@NotNull @NotNull
private static ExtensionRegistryLite getExtensionRegistry() { public static ExtensionRegistryLite getExtensionRegistry() {
ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
JavaProtoBuf.registerAllExtensions(registry); JavaProtoBuf.registerAllExtensions(registry);
return registry; return registry;
@@ -33,7 +33,6 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorImpl; import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorImpl;
import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.lang.resolve.lazy.KotlinTestWithEnvironment; import org.jetbrains.jet.lang.resolve.lazy.KotlinTestWithEnvironment;
import org.jetbrains.jet.lang.resolve.lazy.LazyResolveTestUtil; import org.jetbrains.jet.lang.resolve.lazy.LazyResolveTestUtil;
@@ -48,9 +47,15 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.test.util.NamespaceComparator; import org.jetbrains.jet.test.util.NamespaceComparator;
import java.io.*; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.*; import java.util.*;
import static org.jetbrains.jet.descriptors.serialization.ClassSerializationUtil.constantSerializer;
import static org.jetbrains.jet.descriptors.serialization.ClassSerializationUtil.getClassId;
import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.*;
import static org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationDeserializer.UNSUPPORTED; import static org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationDeserializer.UNSUPPORTED;
import static org.jetbrains.jet.lang.resolve.java.resolver.DeserializedResolverUtils.naiveKotlinFqName; import static org.jetbrains.jet.lang.resolve.java.resolver.DeserializedResolverUtils.naiveKotlinFqName;
@@ -62,7 +67,7 @@ public abstract class AbstractDescriptorSerializationTest extends KotlinTestWith
@NotNull @NotNull
@Override @Override
public List<AnnotationDescriptor> loadClassAnnotations(@NotNull ClassDescriptor descriptor, @NotNull ProtoBuf.Class classProto) { public List<AnnotationDescriptor> loadClassAnnotations(@NotNull ClassDescriptor descriptor, @NotNull ProtoBuf.Class classProto) {
// This is a hack for tests: only data annotations are present in test data so far // TODO: not only data annotations are present in tests
AnnotationDescriptor annotationDescriptor = new AnnotationDescriptor(); AnnotationDescriptor annotationDescriptor = new AnnotationDescriptor();
annotationDescriptor.setAnnotationType(KotlinBuiltIns.getInstance().getDataClassAnnotation().getDefaultType()); annotationDescriptor.setAnnotationType(KotlinBuiltIns.getInstance().getDataClassAnnotation().getDefaultType());
return Collections.singletonList(annotationDescriptor); return Collections.singletonList(annotationDescriptor);
@@ -88,7 +93,7 @@ public abstract class AbstractDescriptorSerializationTest extends KotlinTestWith
return createEnvironmentWithMockJdk(ConfigurationKind.JDK_ONLY); return createEnvironmentWithMockJdk(ConfigurationKind.JDK_ONLY);
} }
protected void doTest(String path) throws IOException { protected void doTest(@NotNull String path) throws IOException {
File ktFile = new File(path); File ktFile = new File(path);
ModuleDescriptor moduleDescriptor = LazyResolveTestUtil.resolveEagerly(Collections.singletonList( ModuleDescriptor moduleDescriptor = LazyResolveTestUtil.resolveEagerly(Collections.singletonList(
JetTestUtils.createFile(ktFile.getName(), FileUtil.loadFile(ktFile), getProject()) JetTestUtils.createFile(ktFile.getName(), FileUtil.loadFile(ktFile), getProject())
@@ -109,20 +114,19 @@ public abstract class AbstractDescriptorSerializationTest extends KotlinTestWith
NamespaceComparator.validateAndCompareNamespaces(testNamespace, deserialized, NamespaceComparator.RECURSIVE, null); NamespaceComparator.validateAndCompareNamespaces(testNamespace, deserialized, NamespaceComparator.RECURSIVE, null);
} }
@NotNull
private static NamespaceDescriptor serializeAndDeserialize( private static NamespaceDescriptor serializeAndDeserialize(
JavaDescriptorResolver javaDescriptorResolver, @NotNull JavaDescriptorResolver javaDescriptorResolver,
Collection<DeclarationDescriptor> initial @NotNull Collection<DeclarationDescriptor> initial
) throws IOException { ) throws IOException {
List<ClassDescriptor> classes = Lists.newArrayList(); List<ClassDescriptor> classes = Lists.newArrayList();
List<CallableMemberDescriptor> callables = Lists.newArrayList(); List<CallableMemberDescriptor> callables = Lists.newArrayList();
for (DeclarationDescriptor descriptor : initial) { for (DeclarationDescriptor descriptor : initial) {
if (descriptor instanceof ClassDescriptor) { if (descriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; classes.add((ClassDescriptor) descriptor);
classes.add(classDescriptor);
} }
else if (descriptor instanceof CallableMemberDescriptor) { else if (descriptor instanceof CallableMemberDescriptor) {
CallableMemberDescriptor memberDescriptor = (CallableMemberDescriptor) descriptor; callables.add((CallableMemberDescriptor) descriptor);
callables.add(memberDescriptor);
} }
else { else {
fail("Unsupported descriptor type: " + descriptor); fail("Unsupported descriptor type: " + descriptor);
@@ -131,28 +135,21 @@ public abstract class AbstractDescriptorSerializationTest extends KotlinTestWith
return getDeserializedDescriptors(javaDescriptorResolver, classes, callables); return getDeserializedDescriptors(javaDescriptorResolver, classes, callables);
} }
@NotNull
private static NamespaceDescriptor getDeserializedDescriptors( private static NamespaceDescriptor getDeserializedDescriptors(
JavaDescriptorResolver javaDescriptorResolver, @NotNull JavaDescriptorResolver javaDescriptorResolver,
List<ClassDescriptor> classes, @NotNull List<ClassDescriptor> classes,
List<CallableMemberDescriptor> callables @NotNull List<CallableMemberDescriptor> callables
) throws IOException { ) throws IOException {
ByteArrayOutputStream serializedCallables = new ByteArrayOutputStream(); Map<ClassDescriptor, byte[]> serializedClasses = serializeClasses(classes);
Map<ClassDescriptor, byte[]> serializedClasses = Maps.newHashMap(); byte[] serializedCallables = serializeCallables(callables);
serialize(classes, callables, serializedClasses, serializedCallables);
final Map<String, ClassMetadata> classMetadata = Maps.newHashMap(); final Map<String, ClassData> classDataMap = Maps.newHashMap();
for (Map.Entry<ClassDescriptor, byte[]> entry : serializedClasses.entrySet()) { for (Map.Entry<ClassDescriptor, byte[]> entry : serializedClasses.entrySet()) {
ClassDescriptor classDescriptor = entry.getKey(); String key = naiveKotlinFqName(entry.getKey()).asString();
byte[] bytes = entry.getValue(); ClassData value = ClassData.read(entry.getValue(), JavaProtoBufUtil.getExtensionRegistry());
classDataMap.put(key, value);
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
ProtoBuf.SimpleNameTable simpleNames = ProtoBuf.SimpleNameTable.parseDelimitedFrom(in);
ProtoBuf.QualifiedNameTable qualifiedNames = ProtoBuf.QualifiedNameTable.parseDelimitedFrom(in);
ProtoBuf.Class proto = ProtoBuf.Class.parseFrom(in);
classMetadata.put(naiveKotlinFqName(classDescriptor).asString(), new ClassMetadata(simpleNames, qualifiedNames, proto));
} }
NamespaceDescriptorImpl namespace = JetTestUtils.createTestNamespace(TEST_PACKAGE_NAME); NamespaceDescriptorImpl namespace = JetTestUtils.createTestNamespace(TEST_PACKAGE_NAME);
@@ -160,18 +157,17 @@ public abstract class AbstractDescriptorSerializationTest extends KotlinTestWith
DescriptorFinderImpl descriptorFinder = new DescriptorFinderImpl( DescriptorFinderImpl descriptorFinder = new DescriptorFinderImpl(
javaDescriptorFinder, namespace, javaDescriptorFinder, namespace,
new NullableFunction<String, ClassMetadata>() { new NullableFunction<String, ClassData>() {
@Nullable @Nullable
@Override @Override
public ClassMetadata fun(String fqName) { public ClassData fun(String fqName) {
return classMetadata.get(fqName); return classDataMap.get(fqName);
} }
} }
); );
for (ClassDescriptor classDescriptor : classes) { for (ClassDescriptor classDescriptor : classes) {
ClassId classId = new ClassId(DescriptorUtils.getFQName(classDescriptor.getContainingDeclaration()).toSafe(), ClassId classId = getClassId(classDescriptor);
FqNameUnsafe.topLevel(classDescriptor.getName()));
ClassDescriptor descriptor = descriptorFinder.findClass(classId); ClassDescriptor descriptor = descriptorFinder.findClass(classId);
assert descriptor != null : "Class not loaded: " + classId; assert descriptor != null : "Class not loaded: " + classId;
if (descriptor.getKind().isObject()) { if (descriptor.getKind().isObject()) {
@@ -182,9 +178,8 @@ public abstract class AbstractDescriptorSerializationTest extends KotlinTestWith
} }
} }
ByteArrayInputStream in = new ByteArrayInputStream(serializedCallables.toByteArray()); ByteArrayInputStream in = new ByteArrayInputStream(serializedCallables);
ProtoBuf.SimpleNameTable simpleNames = ProtoBuf.SimpleNameTable.parseDelimitedFrom(in); NameResolver nameResolver = deserializeNameResolver(in);
ProtoBuf.QualifiedNameTable qualifiedNames = ProtoBuf.QualifiedNameTable.parseDelimitedFrom(in);
List<ProtoBuf.Callable> callableProtos = Lists.newArrayList(); List<ProtoBuf.Callable> callableProtos = Lists.newArrayList();
for (int i = 0; i < callables.size(); i++) { for (int i = 0; i < callables.size(); i++) {
@@ -193,8 +188,7 @@ public abstract class AbstractDescriptorSerializationTest extends KotlinTestWith
} }
DescriptorDeserializer deserializer = DescriptorDeserializer deserializer =
DescriptorDeserializer.create(new LockBasedStorageManager(), namespace, new NameResolver(simpleNames, qualifiedNames), DescriptorDeserializer.create(new LockBasedStorageManager(), namespace, nameResolver, descriptorFinder, UNSUPPORTED);
descriptorFinder, UNSUPPORTED);
for (ProtoBuf.Callable proto : callableProtos) { for (ProtoBuf.Callable proto : callableProtos) {
CallableMemberDescriptor descriptor = deserializer.loadCallable(proto); CallableMemberDescriptor descriptor = deserializer.loadCallable(proto);
if (descriptor instanceof FunctionDescriptor) { if (descriptor instanceof FunctionDescriptor) {
@@ -212,85 +206,57 @@ public abstract class AbstractDescriptorSerializationTest extends KotlinTestWith
return namespace; return namespace;
} }
public static void serialize( @NotNull
List<ClassDescriptor> classes, List<CallableMemberDescriptor> callables, private static byte[] serializeCallables(@NotNull List<CallableMemberDescriptor> callables) throws IOException {
Map<ClassDescriptor, byte[]> serializedClasses, OutputStream serializedCallables DescriptorSerializer serializer = new DescriptorSerializer();
) throws IOException {
serializeClasses(classes, serializedClasses);
DescriptorSerializer descriptorSerializer = new DescriptorSerializer();
List<MessageLite> messages = Lists.newArrayList(); List<MessageLite> messages = Lists.newArrayList();
for (CallableMemberDescriptor callable : callables) { for (CallableMemberDescriptor callable : callables) {
messages.add(descriptorSerializer.callableProto(callable).build()); messages.add(serializer.callableProto(callable).build());
} }
NameSerializationUtil.serializeNameTable(serializedCallables, descriptorSerializer.getNameTable()); ByteArrayOutputStream serializedCallables = new ByteArrayOutputStream();
serializeNameTable(serializedCallables, serializer.getNameTable());
for (MessageLite message : messages) { for (MessageLite message : messages) {
message.writeDelimitedTo(serializedCallables); message.writeDelimitedTo(serializedCallables);
} }
return serializedCallables.toByteArray();
} }
private static void serializeClasses(Collection<ClassDescriptor> classes, Map<ClassDescriptor, byte[]> serializedClasses) @NotNull
throws IOException { private static Map<ClassDescriptor, byte[]> serializeClasses(@NotNull Collection<ClassDescriptor> classes) {
for (ClassDescriptor classDescriptor : classes) { final Map<ClassDescriptor, byte[]> serializedClasses = Maps.newHashMap();
DescriptorSerializer descriptorSerializer = new DescriptorSerializer(); final DescriptorSerializer serializer = new DescriptorSerializer();
ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ClassSerializationUtil.serializeClasses(classes, constantSerializer(serializer), new ClassSerializationUtil.Sink() {
ProtoBuf.Class classProto = descriptorSerializer.classProto(classDescriptor).build(); @Override
public void writeClass(@NotNull ClassDescriptor classDescriptor, @NotNull ProtoBuf.Class classProto) {
NameSerializationUtil.serializeNameTable(bytes, descriptorSerializer.getNameTable()); serializedClasses.put(classDescriptor, new ClassData(createNameResolver(serializer.getNameTable()), classProto).toBytes());
classProto.writeTo(bytes);
serializedClasses.put(classDescriptor, bytes.toByteArray());
//noinspection unchecked
serializeClasses((Collection) classDescriptor.getUnsubstitutedInnerClassesScope().getAllDescriptors(), serializedClasses);
//noinspection unchecked
serializeClasses((Collection) classDescriptor.getUnsubstitutedInnerClassesScope().getObjectDescriptors(), serializedClasses);
ClassDescriptor classObjectDescriptor = classDescriptor.getClassObjectDescriptor();
if (classObjectDescriptor != null) {
serializeClasses(Collections.singletonList(classObjectDescriptor), serializedClasses);
} }
} });
}
private static class ClassMetadata { return serializedClasses;
private final ProtoBuf.SimpleNameTable simpleNames;
private final ProtoBuf.QualifiedNameTable qualifiedNames;
private final ProtoBuf.Class classProto;
private ClassMetadata(
ProtoBuf.SimpleNameTable simpleNames,
ProtoBuf.QualifiedNameTable qualifiedNames,
ProtoBuf.Class classProto
) {
this.simpleNames = simpleNames;
this.qualifiedNames = qualifiedNames;
this.classProto = classProto;
}
} }
private static class DescriptorFinderImpl implements DescriptorFinder { private static class DescriptorFinderImpl implements DescriptorFinder {
private final DescriptorFinder parentResolver; private final DescriptorFinder parentResolver;
private final DeclarationDescriptor parentForClasses; private final DeclarationDescriptor parentForClasses;
private final NullableFunction<String, ClassMetadata> classMetadata; private final NullableFunction<String, ClassData> classData;
private final MemoizedFunctionToNullable<ClassId, ClassDescriptor> classes; private final MemoizedFunctionToNullable<ClassId, ClassDescriptor> classes;
public DescriptorFinderImpl( public DescriptorFinderImpl(
@NotNull DescriptorFinder parentResolver, @NotNull DescriptorFinder parentResolver,
@NotNull DeclarationDescriptor parentForClasses, @NotNull DeclarationDescriptor parentForClasses,
@NotNull NullableFunction<String, ClassMetadata> classMetadata @NotNull NullableFunction<String, ClassData> classData
) { ) {
this.parentResolver = parentResolver; this.parentResolver = parentResolver;
this.parentForClasses = parentForClasses; this.parentForClasses = parentForClasses;
this.classMetadata = classMetadata; this.classData = classData;
this.classes = new MemoizedFunctionToNullableImpl<ClassId, ClassDescriptor>() { this.classes = new MemoizedFunctionToNullableImpl<ClassId, ClassDescriptor>() {
@Nullable @Nullable
@@ -305,21 +271,14 @@ public abstract class AbstractDescriptorSerializationTest extends KotlinTestWith
} }
@Nullable @Nullable
private ClassDescriptor resolveClass( private ClassDescriptor resolveClass(@NotNull DeclarationDescriptor containingDeclaration, @NotNull ClassId classId) {
@NotNull DeclarationDescriptor containingDeclaration, ClassData classData = this.classData.fun(classId.asSingleFqName().asString());
@NotNull ClassId classId if (classData == null) {
) {
FqNameUnsafe fqName = classId.asSingleFqName();
ClassMetadata classMetadata = this.classMetadata.fun(fqName.asString());
if (classMetadata == null) {
return parentResolver.findClass(classId); return parentResolver.findClass(classId);
} }
NameResolver nameResolver = new NameResolver(classMetadata.simpleNames, classMetadata.qualifiedNames); return new DeserializedClassDescriptor(classId, new LockBasedStorageManager(), containingDeclaration,
return new DeserializedClassDescriptor(classId, new LockBasedStorageManager(), containingDeclaration, nameResolver, classData.getNameResolver(), DUMMY_ANNOTATION_DESERIALIZER, this, classData.getClassProto(), null);
DUMMY_ANNOTATION_DESERIALIZER, this,
classMetadata.classProto, null);
} }
@Nullable @Nullable