Using ClassId instead of FqName

This commit is contained in:
Andrey Breslav
2013-05-17 16:46:16 +04:00
committed by Alexander Udalov
parent bb27d5c283
commit d04865cea3
9 changed files with 394 additions and 113 deletions
@@ -0,0 +1,62 @@
package org.jetbrains.jet.descriptors.serialization;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
public final class ClassId {
private final FqName packageFqName;
private final FqName relativeClassName;
public ClassId(@NotNull FqName packageFqName, @NotNull FqName relativeClassName) {
this.packageFqName = packageFqName;
assert !relativeClassName.isRoot() : "Class name must not be root. " + packageFqName;
this.relativeClassName = relativeClassName;
}
@NotNull
public FqName getPackageFqName() {
return packageFqName;
}
@NotNull
public FqName getRelativeClassName() {
return relativeClassName;
}
@NotNull
public ClassId createNestedClassId(@NotNull Name name) {
return new ClassId(getPackageFqName(), relativeClassName.child(name));
}
public FqName asSingleFqName() {
if (packageFqName.isRoot()) return relativeClassName;
return new FqName(packageFqName.getFqName() + "." + relativeClassName.getFqName());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ClassId id = (ClassId) o;
if (!packageFqName.equals(id.packageFqName)) return false;
if (!relativeClassName.equals(id.relativeClassName)) return false;
return true;
}
@Override
public int hashCode() {
int result = packageFqName.hashCode();
result = 31 * result + relativeClassName.hashCode();
return result;
}
@Override
public String toString() {
if (packageFqName.isRoot()) return "/" + relativeClassName;
return packageFqName.toString().replace('.', '/') + "/" + relativeClassName;
}
}
@@ -19,18 +19,17 @@ package org.jetbrains.jet.descriptors.serialization;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.resolve.name.FqName;
public interface ClassResolver {
ClassResolver EMPTY = new ClassResolver() {
@Nullable
@Override
public ClassDescriptor findClass(@NotNull FqName fqName) {
public ClassDescriptor findClass(@NotNull ClassId classId) {
return null;
}
};
@Nullable
ClassDescriptor findClass(@NotNull FqName fqName);
ClassDescriptor findClass(@NotNull ClassId classId);
}
@@ -23,6 +23,8 @@ import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.Variance;
import java.util.Collection;
public class DescriptorSerializer {
// TODO: flags
@@ -72,18 +74,13 @@ public class DescriptorSerializer {
builder.addSupertypes(local.type(supertype));
}
// TODO: nested classes
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
if (primaryConstructor != null) {
builder.setPrimaryConstructor(local.callableProto(primaryConstructor));
}
// TODO: other constructors
// TODO: class object
for (DeclarationDescriptor descriptor : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
// TODO: other than functions
if (descriptor instanceof CallableMemberDescriptor) {
CallableMemberDescriptor member = (CallableMemberDescriptor) descriptor;
if (member.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) continue;
@@ -91,6 +88,23 @@ public class DescriptorSerializer {
}
}
Collection<DeclarationDescriptor> nestedClasses = classDescriptor.getUnsubstitutedInnerClassesScope().getAllDescriptors();
for (DeclarationDescriptor descriptor : nestedClasses) {
ClassDescriptor nestedClass = (ClassDescriptor) descriptor;
int nameIndex = nameTable.getSimpleNameIndex(nestedClass.getName());
if (nestedClass.getKind().isObject()) {
builder.addNestedObjectNames(nameIndex);
}
else {
builder.addNestedClassNames(nameIndex);
}
}
if (classDescriptor.getClassObjectDescriptor() != null) {
// false is default
builder.setClassObjectPresent(true);
}
return builder;
}
@@ -22,6 +22,8 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import static org.jetbrains.jet.descriptors.serialization.ProtoBuf.QualifiedNameTable.*;
public class NameResolver {
private final ProtoBuf.SimpleNameTable simpleNames;
private final ProtoBuf.QualifiedNameTable qualifiedNames;
@@ -51,26 +53,54 @@ public class NameResolver {
return classDescriptors[fqNameIndex];
}
ProtoBuf.QualifiedNameTable.QualifiedName fqNameProto = qualifiedNames.getQualifiedNames(fqNameIndex);
assert fqNameProto.getKind() == ProtoBuf.QualifiedNameTable.QualifiedName.Kind.CLASS : "Not a class fqName: " + getFqName(fqNameIndex);
QualifiedName fqNameProto = qualifiedNames.getQualifiedNames(fqNameIndex);
assert fqNameProto.getKind() == QualifiedName.Kind.CLASS : "Not a class fqName: " + getClassId(fqNameIndex);
return classResolver.findClass(getFqName(fqNameIndex));
ClassId classId = getClassId(fqNameIndex);
return classResolver.findClass(classId);
}
@NotNull
public FqName getFqName(int index) {
ProtoBuf.QualifiedNameTable.QualifiedName fqNameProto = qualifiedNames.getQualifiedNames(index);
StringBuilder sb = renderFqName(new StringBuilder(), fqNameProto);
return new FqName(sb.toString());
public ClassId getClassId(int index) {
QualifiedName fqNameProto = qualifiedNames.getQualifiedNames(index);
StringBuilder relativeClassName = new StringBuilder();
QualifiedName packageFqNameProto = renderFqName(relativeClassName, fqNameProto, QualifiedName.Kind.CLASS);
FqName packageFqName;
if (packageFqNameProto != null) {
StringBuilder sb = new StringBuilder();
QualifiedName mustBeNull = renderFqName(sb, packageFqNameProto, QualifiedName.Kind.PACKAGE);
assert mustBeNull == null : "Prefix of an fqName must be all of kind PACKAGE";
packageFqName = new FqName(sb.toString());
}
else {
packageFqName = FqName.ROOT;
}
return new ClassId(packageFqName, new FqName(relativeClassName.toString()));
}
private StringBuilder renderFqName(StringBuilder sb, ProtoBuf.QualifiedNameTable.QualifiedName fqNameProto) {
@Nullable
private QualifiedName renderFqName(
StringBuilder sb,
QualifiedName fqNameProto,
QualifiedName.Kind kind
) {
QualifiedName result = null;
if (fqNameProto.hasParentQualifiedName()) {
ProtoBuf.QualifiedNameTable.QualifiedName parentProto = qualifiedNames.getQualifiedNames(fqNameProto.getParentQualifiedName());
renderFqName(sb, parentProto);
sb.append(".");
QualifiedName parentProto = qualifiedNames.getQualifiedNames(fqNameProto.getParentQualifiedName());
if (kind == null || parentProto.getKind() == kind) {
result = renderFqName(sb, parentProto, kind);
sb.append(".");
}
else {
result = parentProto;
}
}
sb.append(simpleNames.getNames(fqNameProto.getShortName()));
return sb;
return result;
}
}
@@ -0,0 +1,14 @@
package org.jetbrains.jet.descriptors.serialization;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.resolve.name.Name;
public interface NestedClassResolver {
@Nullable
ClassDescriptor resolveNestedClass(@NotNull ClassDescriptor outerClass, @NotNull Name name);
@Nullable
ClassDescriptor resolveClassObject(@NotNull ClassDescriptor outerClass);
}
@@ -119,7 +119,7 @@ public class TypeDeserializer {
TypeConstructor typeConstructor = typeConstructor(constructorProto);
if (typeConstructor == null) {
String message = constructorProto.getKind() == ProtoBuf.Type.Constructor.Kind.CLASS
? nameResolver.getFqName(id).asString()
? nameResolver.getClassId(id).asSingleFqName().asString()
: "Unknown type parameter " + id;
typeConstructor = ErrorUtils.createErrorType(message).getConstructor();
}
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorBase;
import org.jetbrains.jet.lang.descriptors.impl.ReceiverParameterDescriptorImpl;
import org.jetbrains.jet.lang.resolve.OverrideResolver;
import org.jetbrains.jet.lang.resolve.TraceUtil;
import org.jetbrains.jet.lang.resolve.lazy.storage.MemoizedFunctionToNullableImpl;
import org.jetbrains.jet.lang.resolve.lazy.storage.NullableLazyValue;
import org.jetbrains.jet.lang.resolve.lazy.storage.NullableLazyValueImpl;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -45,6 +46,12 @@ public class DeserializedClassDescriptor extends ClassDescriptorBase implements
private final NullableLazyValue<ConstructorDescriptor> primaryConstructor;
private final NestedClassResolver nestedClassResolver;
private final NullableLazyValue<ClassDescriptor> classObjectDescriptor;
private final NestedClassDescriptors nestedClasses;
private final NestedClassDescriptors nestedObjects;
private final Name name;
private final DeclarationDescriptor containingDeclaration;
private final DeserializedClassTypeConstructor typeConstructor;
@@ -56,7 +63,7 @@ public class DeserializedClassDescriptor extends ClassDescriptorBase implements
public DeserializedClassDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull NameResolver nameResolver,
@NotNull ClassResolver classResolver,
@NotNull NestedClassResolver _nestedClassResolver,
@NotNull ProtoBuf.Class classProto,
@Nullable TypeDeserializer outerTypeDeserializer
) {
@@ -82,6 +89,35 @@ public class DeserializedClassDescriptor extends ClassDescriptorBase implements
return computePrimaryConstructor();
}
};
this.nestedClassResolver = _nestedClassResolver;
this.classObjectDescriptor = new NullableLazyValueImpl<ClassDescriptor>() {
@Override
protected ClassDescriptor doCompute() {
return computeClassObjectDecriptor();
}
};
this.nestedClasses = new NestedClassDescriptors(stringSet(classProto.getNestedClassNamesList(), nameResolver)) {
@Override
protected ClassDescriptor resolveNestedClass(@NotNull Name name) {
return nestedClassResolver.resolveNestedClass(DeserializedClassDescriptor.this, name);
}
};
this.nestedObjects = new NestedClassDescriptors(stringSet(classProto.getNestedObjectNamesList(), nameResolver)) {
@Override
protected ClassDescriptor resolveNestedClass(@NotNull Name name) {
return nestedClassResolver.resolveNestedClass(DeserializedClassDescriptor.this, name);
}
};
}
@NotNull
private static Set<String> stringSet(@NotNull List<Integer> nameIndices, @NotNull NameResolver nameResolver) {
Set<String> result = new HashSet<String>(nameIndices.size());
for (Integer index : nameIndices) {
result.add(nameResolver.getName(index).getName());
}
return result;
}
@NotNull
@@ -180,10 +216,19 @@ public class DeserializedClassDescriptor extends ClassDescriptorBase implements
return classObjectDescriptor == null ? null : classObjectDescriptor.getDefaultType();
}
@Nullable
private ClassDescriptor computeClassObjectDecriptor() {
if (!classProto.getClassObjectPresent()) {
return null;
}
return nestedClassResolver.resolveClassObject(this);
}
@Nullable
@Override
public ClassDescriptor getClassObjectDescriptor() {
return null; // TODO
return classObjectDescriptor.compute();
}
@NotNull
@@ -314,12 +359,54 @@ public class DeserializedClassDescriptor extends ClassDescriptorBase implements
@Nullable
@Override
protected ClassifierDescriptor getClassDescriptor(@NotNull Name name) {
return null; // TODO inner classes
return classDescriptor.nestedClasses.fun(name);
}
@Override
protected void addAllClassDescriptors(@NotNull Collection<DeclarationDescriptor> result) {
// TODO inner classes
result.addAll(classDescriptor.nestedClasses.getAllDescriptors());
}
@Nullable
@Override
public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
return classDescriptor.nestedObjects.fun(name);
}
@NotNull
@Override
protected Collection<ClassDescriptor> computeAllObjectDescriptors() {
return classDescriptor.nestedObjects.getAllDescriptors();
}
}
private abstract static class NestedClassDescriptors extends MemoizedFunctionToNullableImpl<Name, ClassDescriptor> {
private final Set<String> declaredNames;
public NestedClassDescriptors(@NotNull Set<String> declaredNames) {
this.declaredNames = declaredNames;
}
@Nullable
@Override
protected final ClassDescriptor doCompute(@NotNull Name name) {
if (!declaredNames.contains(name.getName())) return null;
return resolveNestedClass(name);
}
protected abstract ClassDescriptor resolveNestedClass(@NotNull Name name);
@NotNull
public Collection<ClassDescriptor> getAllDescriptors() {
Collection<ClassDescriptor> result = new ArrayList<ClassDescriptor>(declaredNames.size());
for (String name : declaredNames) {
ClassDescriptor descriptor = fun(Name.identifier(name));
if (descriptor != null) {
result.add(descriptor);
}
}
return result;
}
}
}
@@ -54,6 +54,7 @@ public abstract class DeserializedMemberScope implements JetScope {
private final MemoizedFunctionToNotNull<Name, Collection<FunctionDescriptor>> functions;
private final MemoizedFunctionToNotNull<Name, Collection<VariableDescriptor>> properties;
private final NotNullLazyValue<Collection<DeclarationDescriptor>> allDescriptors;
private final NotNullLazyValue<Collection<ClassDescriptor>> objectDescriptors;
public DeserializedMemberScope(
@NotNull DeclarationDescriptor containingDeclaration,
@@ -85,6 +86,13 @@ public abstract class DeserializedMemberScope implements JetScope {
return computeAllDescriptors();
}
};
this.objectDescriptors = new NotNullLazyValueImpl<Collection<ClassDescriptor>>() {
@NotNull
@Override
protected Collection<ClassDescriptor> doCompute() {
return computeAllObjectDescriptors();
}
};
}
@NotNull
@@ -164,14 +172,15 @@ public abstract class DeserializedMemberScope implements JetScope {
@Nullable
@Override
public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
return null; // TODO
}
public abstract ClassDescriptor getObjectDescriptor(@NotNull Name name);
@NotNull
protected abstract Collection<ClassDescriptor> computeAllObjectDescriptors();
@NotNull
@Override
public Collection<ClassDescriptor> getObjectDescriptors() {
return Collections.emptyList(); // TODO
return objectDescriptors.compute();
}
@Nullable