Serializing basic descriptors

This commit is contained in:
Andrey Breslav
2013-05-14 12:50:57 +04:00
committed by Alexander Udalov
parent a0895e9046
commit 1e345b58f7
2 changed files with 550 additions and 0 deletions
@@ -0,0 +1,298 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.descriptors.serialization;
import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.types.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class DescriptorDeserializer {
@Nullable
private final DescriptorDeserializer parent;
private final DeclarationDescriptor containingDeclaration;
private final NameResolver nameResolver;
private final TIntObjectHashMap<TypeParameterDescriptorImpl> typeParameterDescriptors = new TIntObjectHashMap<TypeParameterDescriptorImpl>();
public DescriptorDeserializer(
@Nullable DescriptorDeserializer parent,
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull NameResolver nameResolver
) {
this.parent = parent;
this.containingDeclaration = containingDeclaration;
this.nameResolver = nameResolver;
}
@NotNull
private DescriptorDeserializer createChildDeserializer(@NotNull DeclarationDescriptor descriptor) {
return new DescriptorDeserializer(this, descriptor, nameResolver);
}
private void registerTypeParameter(int id, @NotNull TypeParameterDescriptorImpl descriptor) {
typeParameterDescriptors.put(id, descriptor);
}
@Nullable
private TypeParameterDescriptorImpl getTypeParameter(int id) {
TypeParameterDescriptorImpl descriptor = typeParameterDescriptors.get(id);
if (descriptor == null && parent != null) {
return parent.getTypeParameter(id);
}
return descriptor;
}
@NotNull
public ClassDescriptor loadClass(@NotNull ProtoBuf.Class proto) {
MutableClassDescriptor descriptor = new MutableClassDescriptor(
containingDeclaration,
// TODO: outerScope
JetScope.EMPTY,
// TODO: kind
ClassKind.CLASS,
// TODO: isInner
false,
nameResolver.getName(proto.getName())
);
// TODO: visibility
descriptor.setVisibility(Visibilities.INTERNAL);
// TODO: modality
descriptor.setModality(Modality.OPEN);
DescriptorDeserializer local = createChildDeserializer(descriptor);
descriptor.setTypeParameterDescriptors(local.typeParameters(proto.getTypeParametersList()));
// TODO: descriptor.setPrimaryConstructor();
// TODO: descriptor.setAnnotations();
WritableScopeImpl members = new WritableScopeImpl(JetScope.EMPTY, descriptor, RedeclarationHandler.DO_NOTHING,
"Members of " + descriptor.getName());
descriptor.setScopeForMemberLookup(members);
for (ProtoBuf.Callable callable : proto.getMembersList()) {
// TODO: properties, classes etc
members.addFunctionDescriptor(local.loadFunction(callable));
}
members.changeLockLevel(WritableScope.LockLevel.READING);
List<JetType> supertypes = new ArrayList<JetType>(proto.getSupertypesCount());
for (ProtoBuf.Type supertype : proto.getSupertypesList()) {
supertypes.add(local.type(supertype));
}
descriptor.setSupertypes(supertypes);
descriptor.createTypeConstructor();
return descriptor;
}
@NotNull
public FunctionDescriptor loadFunction(@NotNull ProtoBuf.Callable proto) {
// TODO: assert function flag
SimpleFunctionDescriptorImpl function = new SimpleFunctionDescriptorImpl(
containingDeclaration,
// TODO: annotations
Collections.<AnnotationDescriptor>emptyList(),
nameResolver.getName(proto.getName()),
// TODO: kind
CallableMemberDescriptor.Kind.DECLARATION
);
DescriptorDeserializer local = new DescriptorDeserializer(this, function, nameResolver);
function.initialize(
local.typeOrNull(proto.hasReceiverType() ? proto.getReceiverType() : null),
// TODO: expectedThisObject
null,
local.typeParameters(proto.getTypeParametersList()),
local.valueParameters(proto.getValueParametersList()),
local.type(proto.getReturnType()),
// TODO: modality
Modality.OPEN,
// TODO: visibility
Visibilities.PUBLIC,
// TODO: inline
false
);
return function;
}
@Nullable
private JetType typeOrNull(@Nullable ProtoBuf.Type proto) {
if (proto == null) {
return null;
}
return type(proto);
}
@NotNull
private JetType type(@NotNull ProtoBuf.Type proto) {
ProtoBuf.Type.Constructor constructorProto = proto.getConstructor();
int id = constructorProto.getId();
TypeConstructor typeConstructor = typeConstructor(constructorProto);
if (typeConstructor == null) {
String message = constructorProto.getKind() == ProtoBuf.Type.Constructor.Kind.CLASS
? nameResolver.getFqName(id).getFqName()
: "Unknown type parameter " + id;
return ErrorUtils.createErrorType(message);
}
List<TypeProjection> typeArguments = typeArguments(proto.getArgumentsList());
return new JetTypeImpl(
Collections.<AnnotationDescriptor>emptyList(),
typeConstructor,
proto.getNullable(),
typeArguments,
getTypeMemberScope(typeConstructor, typeArguments)
);
}
@NotNull
private static JetScope getTypeMemberScope(@NotNull TypeConstructor constructor, @NotNull List<TypeProjection> typeArguments) {
ClassifierDescriptor descriptor = constructor.getDeclarationDescriptor();
if (descriptor instanceof TypeParameterDescriptor) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
return typeParameterDescriptor.getDefaultType().getMemberScope();
}
return ((ClassDescriptor) descriptor).getMemberScope(typeArguments);
}
@Nullable
private TypeConstructor typeConstructor(@NotNull ProtoBuf.Type.Constructor proto) {
switch (proto.getKind()) {
case CLASS:
ClassDescriptor classDescriptor = nameResolver.getClassDescriptor(proto.getId());
if (classDescriptor == null) return null;
return classDescriptor.getTypeConstructor();
case TYPE_PARAMETER:
TypeParameterDescriptorImpl descriptor = getTypeParameter(proto.getId());
if (descriptor == null) return null;
return descriptor.getTypeConstructor();
}
throw new IllegalStateException("Unknown kind " + proto.getKind());
}
private List<TypeProjection> typeArguments(List<ProtoBuf.Type.Argument> protos) {
List<TypeProjection> result = new ArrayList<TypeProjection>(protos.size());
for (ProtoBuf.Type.Argument proto : protos) {
result.add(typeProjection(proto));
}
return result;
}
private TypeProjection typeProjection(ProtoBuf.Type.Argument proto) {
return new TypeProjection(
variance(proto.getProjection()),
type(proto.getType())
);
}
private static Variance variance(ProtoBuf.Type.Argument.Projection proto) {
switch (proto) {
case IN:
return Variance.IN_VARIANCE;
case OUT:
return Variance.OUT_VARIANCE;
case INV:
return Variance.INVARIANT;
}
throw new IllegalStateException("Unknown projection: " + proto);
}
@NotNull
private List<TypeParameterDescriptor> typeParameters(@NotNull List<ProtoBuf.TypeParameter> protos) {
List<TypeParameterDescriptor> result = new ArrayList<TypeParameterDescriptor>(protos.size());
for (int i = 0; i < protos.size(); i++) {
ProtoBuf.TypeParameter proto = protos.get(i);
TypeParameterDescriptorImpl descriptor = typeParameter(proto, i);
result.add(descriptor);
}
return result;
}
private TypeParameterDescriptorImpl typeParameter(ProtoBuf.TypeParameter proto, int index) {
int id = proto.getId();
TypeParameterDescriptorImpl descriptor = TypeParameterDescriptorImpl.createForFurtherModification(
containingDeclaration,
// TODO
Collections.<AnnotationDescriptor>emptyList(),
proto.getReified(),
variance(proto.getVariance()),
nameResolver.getName(proto.getName()),
index);
registerTypeParameter(id, descriptor);
// TODO: circular bounds
descriptor.setInitialized();
return descriptor;
}
private Variance variance(ProtoBuf.TypeParameter.Variance proto) {
switch (proto) {
case IN:
return Variance.IN_VARIANCE;
case OUT:
return Variance.OUT_VARIANCE;
case INV:
return Variance.INVARIANT;
}
throw new IllegalStateException("Unknown projection: " + proto);
}
@NotNull
private List<ValueParameterDescriptor> valueParameters(@NotNull List<ProtoBuf.Callable.ValueParameter> protos) {
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(protos.size());
for (int i = 0; i < protos.size(); i++) {
ProtoBuf.Callable.ValueParameter proto = protos.get(i);
result.add(valueParameter(proto, i));
}
return result;
}
private ValueParameterDescriptor valueParameter(ProtoBuf.Callable.ValueParameter proto, int index) {
return new ValueParameterDescriptorImpl(
containingDeclaration,
index,
// TODO
Collections.<AnnotationDescriptor>emptyList(),
nameResolver.getName(proto.getName()),
type(proto.getType()),
// TODO: declaresDefaultValue
false,
typeOrNull(proto.hasVarargElementType() ? proto.getVarargElementType() : null));
}
}
@@ -0,0 +1,252 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.descriptors.serialization;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.Variance;
public class DescriptorSerializer {
// TODO: flags
private final NameTable nameTable;
private final Interner<TypeParameterDescriptor> typeParameters;
public DescriptorSerializer() {
this(new NameTable(), new Interner<TypeParameterDescriptor>());
}
private DescriptorSerializer(NameTable nameTable, Interner<TypeParameterDescriptor> typeParameters) {
this.nameTable = nameTable;
this.typeParameters = typeParameters;
}
private DescriptorSerializer createChildSerializer() {
return new DescriptorSerializer(nameTable, new Interner<TypeParameterDescriptor>(typeParameters));
}
@NotNull
public NameTable getNameTable() {
return nameTable;
}
@NotNull
public ProtoBuf.Class.Builder classProto(@NotNull ClassDescriptor classDescriptor) {
ProtoBuf.Class.Builder builder = ProtoBuf.Class.newBuilder();
// TODO annotations
// TODO flags + extraVisibility
builder.setName(nameTable.getSimpleNameIndex(classDescriptor.getName()));
DescriptorSerializer local = createChildSerializer();
for (TypeParameterDescriptor typeParameterDescriptor : classDescriptor.getTypeConstructor().getParameters()) {
builder.addTypeParameters(local.typeParameter(typeParameterDescriptor));
}
for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
builder.addSupertypes(local.type(supertype));
}
// TODO: nested classes
// TODO: constructor
// TODO: class object
for (DeclarationDescriptor descriptor : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
// TODO: other than functions
if (descriptor instanceof FunctionDescriptor) {
FunctionDescriptor function = (FunctionDescriptor) descriptor;
builder.addMembers(local.functionProto(function));
}
}
return builder;
}
@NotNull
public ProtoBuf.Callable.Builder functionProto(@NotNull FunctionDescriptor function) {
ProtoBuf.Callable.Builder builder = ProtoBuf.Callable.newBuilder();
builder.setFlags(flags(function));
//TODO builder.setExtraVisibility()
//TODO builder.addAnnotations()
DescriptorSerializer local = this;//createChildSerializer();
for (TypeParameterDescriptor typeParameterDescriptor : function.getTypeParameters()) {
builder.addTypeParameters(local.typeParameter(typeParameterDescriptor));
}
ReceiverParameterDescriptor receiverParameter = function.getReceiverParameter();
if (receiverParameter != null) {
builder.setReceiverType(local.type(receiverParameter.getType()));
}
builder.setName(nameTable.getSimpleNameIndex(function.getName()));
for (ValueParameterDescriptor valueParameterDescriptor : function.getValueParameters()) {
builder.addValueParameters(local.valueParameter(valueParameterDescriptor));
}
builder.setReturnType(local.type(function.getReturnType()));
return builder;
}
private int flags(FunctionDescriptor function) {
// TODO
return 0;
}
private ProtoBuf.Callable.ValueParameter.Builder valueParameter(ValueParameterDescriptor descriptor) {
ProtoBuf.Callable.ValueParameter.Builder builder = ProtoBuf.Callable.ValueParameter.newBuilder();
builder.setFlags(flags(descriptor));
builder.setName(nameTable.getSimpleNameIndex(descriptor.getName()));
builder.setType(type(descriptor.getType()));
JetType varargElementType = descriptor.getVarargElementType();
if (varargElementType != null) {
builder.setVarargElementType(type(varargElementType));
}
return builder;
}
private int flags(ValueParameterDescriptor descriptor) {
// TODO
return 0;
}
private ProtoBuf.TypeParameter.Builder typeParameter(TypeParameterDescriptor typeParameter) {
ProtoBuf.TypeParameter.Builder builder = ProtoBuf.TypeParameter.newBuilder();
builder.setId(getTypeParameterId(typeParameter));
builder.setName(nameTable.getSimpleNameIndex(typeParameter.getName()));
// to avoid storing a default
if (typeParameter.isReified()) {
builder.setReified(true);
}
// to avoid storing a default
ProtoBuf.TypeParameter.Variance variance = variance(typeParameter.getVariance());
if (variance != ProtoBuf.TypeParameter.Variance.INV) {
builder.setVariance(variance);
}
for (JetType upperBound : typeParameter.getUpperBounds()) {
builder.addUpperBounds(type(upperBound));
}
return builder;
}
private static ProtoBuf.TypeParameter.Variance variance(Variance variance) {
switch (variance) {
case INVARIANT:
return ProtoBuf.TypeParameter.Variance.INV;
case IN_VARIANCE:
return ProtoBuf.TypeParameter.Variance.IN;
case OUT_VARIANCE:
return ProtoBuf.TypeParameter.Variance.OUT;
}
throw new IllegalStateException("Unknown variance: " + variance);
}
@NotNull
public ProtoBuf.Type.Builder type(@NotNull JetType type) {
ProtoBuf.Type.Builder builder = ProtoBuf.Type.newBuilder();
builder.setConstructor(typeConstructor(type.getConstructor()));
for (TypeProjection projection : type.getArguments()) {
builder.addArguments(typeArgument(projection));
}
// to avoid storing a default
if (type.isNullable()) {
builder.setNullable(true);
}
return builder;
}
@NotNull
private ProtoBuf.Type.Argument.Builder typeArgument(@NotNull TypeProjection typeProjection) {
ProtoBuf.Type.Argument.Builder builder = ProtoBuf.Type.Argument.newBuilder();
ProtoBuf.Type.Argument.Projection projection = projection(typeProjection.getProjectionKind());
// to avoid storing a default
if (projection != ProtoBuf.Type.Argument.Projection.INV) {
builder.setProjection(projection);
}
builder.setType(type(typeProjection.getType()));
return builder;
}
@NotNull
private ProtoBuf.Type.Constructor.Builder typeConstructor(@NotNull TypeConstructor typeConstructor) {
ProtoBuf.Type.Constructor.Builder builder = ProtoBuf.Type.Constructor.newBuilder();
ClassifierDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor();
assert declarationDescriptor instanceof TypeParameterDescriptor || declarationDescriptor instanceof ClassDescriptor
: "Unknown declaration descriptor: " + typeConstructor;
if (declarationDescriptor instanceof TypeParameterDescriptor) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor;
builder.setKind(ProtoBuf.Type.Constructor.Kind.TYPE_PARAMETER);
builder.setId(getTypeParameterId(typeParameterDescriptor));
}
else {
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
//default: builder.setKind(Type.Constructor.Kind.CLASS);
builder.setId(getClassId(classDescriptor));
}
return builder;
}
@NotNull
private static ProtoBuf.Type.Argument.Projection projection(@NotNull Variance projectionKind) {
switch (projectionKind) {
case INVARIANT:
return ProtoBuf.Type.Argument.Projection.INV;
case IN_VARIANCE:
return ProtoBuf.Type.Argument.Projection.IN;
case OUT_VARIANCE:
return ProtoBuf.Type.Argument.Projection.OUT;
}
throw new IllegalStateException("Unknown projectionKind: " + projectionKind);
}
private int getClassId(@NotNull ClassDescriptor descriptor) {
return nameTable.getFqNameIndex(descriptor);
}
private int getTypeParameterId(@NotNull TypeParameterDescriptor descriptor) {
return typeParameters.intern(descriptor);
}
}