Serializing/Deserializing simple and qualified names
This commit is contained in:
committed by
Alexander Udalov
parent
099b3ffc9f
commit
a0895e9046
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
|
||||
public interface ClassResolver {
|
||||
|
||||
@Nullable
|
||||
ClassDescriptor findClass(@NotNull FqName fqName);
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.TObjectHashingStrategy;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class Interner<T> {
|
||||
private final Interner<T> parent;
|
||||
private final int firstIndex;
|
||||
private final TObjectIntHashMap<T> interned;
|
||||
private final List<T> all = new ArrayList<T>();
|
||||
|
||||
public Interner(Interner<T> parent, @NotNull TObjectHashingStrategy<T> hashing) {
|
||||
this.parent = parent;
|
||||
this.firstIndex = parent == null ? 0 : parent.all.size();
|
||||
this.interned = new TObjectIntHashMap<T>(hashing);
|
||||
}
|
||||
|
||||
public Interner(@NotNull TObjectHashingStrategy<T> hashing) {
|
||||
this(null, hashing);
|
||||
}
|
||||
|
||||
public Interner(@Nullable Interner<T> parent) {
|
||||
//noinspection unchecked
|
||||
this(parent, TObjectHashingStrategy.CANONICAL);
|
||||
}
|
||||
|
||||
public Interner() {
|
||||
//noinspection unchecked
|
||||
this((Interner) null);
|
||||
}
|
||||
|
||||
public int intern(@NotNull T obj) {
|
||||
assert parent == null || parent.all.size() == firstIndex : "Parent changed in parallel with child: indexes will be wrong";
|
||||
if (interned.contains(obj)) {
|
||||
return interned.get(obj);
|
||||
}
|
||||
int index = firstIndex + interned.size();
|
||||
interned.put(obj, index);
|
||||
all.add(obj);
|
||||
return index;
|
||||
}
|
||||
|
||||
public List<T> getAllInternedObjects() {
|
||||
return all;
|
||||
}
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
|
||||
public class NameResolver {
|
||||
private final ProtoBuf.SimpleNameTable simpleNames;
|
||||
private final ProtoBuf.QualifiedNameTable qualifiedNames;
|
||||
private final ClassDescriptor[] classDescriptors;
|
||||
private final ClassResolver classResolver;
|
||||
|
||||
public NameResolver(
|
||||
@NotNull ProtoBuf.SimpleNameTable simpleNames,
|
||||
@NotNull ProtoBuf.QualifiedNameTable qualifiedNames,
|
||||
@NotNull ClassResolver classResolver
|
||||
) {
|
||||
this.simpleNames = simpleNames;
|
||||
this.qualifiedNames = qualifiedNames;
|
||||
this.classDescriptors = new ClassDescriptor[qualifiedNames.getQualifiedNamesCount()];
|
||||
this.classResolver = classResolver;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Name getName(int index) {
|
||||
String name = simpleNames.getNames(index);
|
||||
return Name.identifier(name);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ClassDescriptor getClassDescriptor(int fqNameIndex) {
|
||||
if (classDescriptors[fqNameIndex] != null) {
|
||||
return classDescriptors[fqNameIndex];
|
||||
}
|
||||
|
||||
ProtoBuf.QualifiedNameTable.QualifiedName fqNameProto = qualifiedNames.getQualifiedNames(fqNameIndex);
|
||||
assert fqNameProto.getKind() == ProtoBuf.QualifiedNameTable.QualifiedName.Kind.CLASS : "Not a class fqName: " + getFqName(fqNameIndex);
|
||||
|
||||
if (fqNameProto.hasParentQualifiedName()) {
|
||||
int parentFqNameIndex = fqNameProto.getParentQualifiedName();
|
||||
ProtoBuf.QualifiedNameTable.QualifiedName parentFqNameProto = qualifiedNames.getQualifiedNames(parentFqNameIndex);
|
||||
switch (fqNameProto.getKind()) {
|
||||
case CLASS:
|
||||
return classResolver.findClass(getFqName(fqNameIndex));
|
||||
case PACKAGE:
|
||||
Name name = getName(fqNameProto.getShortName());
|
||||
ClassDescriptor outerClass = getClassDescriptor(parentFqNameIndex);
|
||||
if (outerClass == null) return null;
|
||||
|
||||
return (ClassDescriptor) outerClass.getUnsubstitutedInnerClassesScope().getClassifier(name);
|
||||
}
|
||||
throw new IllegalStateException("Unknown kind: " + fqNameProto);
|
||||
}
|
||||
else {
|
||||
FqName fqName = FqName.topLevel(getName(fqNameProto.getShortName()));
|
||||
return classResolver.findClass(fqName);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FqName getFqName(int index) {
|
||||
ProtoBuf.QualifiedNameTable.QualifiedName fqNameProto = qualifiedNames.getQualifiedNames(index);
|
||||
StringBuilder sb = renderFqName(new StringBuilder(), fqNameProto);
|
||||
return new FqName(sb.toString());
|
||||
}
|
||||
|
||||
private StringBuilder renderFqName(StringBuilder sb, ProtoBuf.QualifiedNameTable.QualifiedName fqNameProto) {
|
||||
if (fqNameProto.hasParentQualifiedName()) {
|
||||
ProtoBuf.QualifiedNameTable.QualifiedName parentProto = qualifiedNames.getQualifiedNames(fqNameProto.getParentQualifiedName());
|
||||
renderFqName(sb, parentProto);
|
||||
sb.append(".");
|
||||
}
|
||||
sb.append(simpleNames.getNames(fqNameProto.getShortName()));
|
||||
return sb;
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class NameSerializationUtil {
|
||||
@NotNull
|
||||
public static NameResolver deserializeNameResolver(@NotNull InputStream in, @NotNull ClassResolver classResolver)
|
||||
throws IOException {
|
||||
ProtoBuf.SimpleNameTable simpleNames = ProtoBuf.SimpleNameTable.parseDelimitedFrom(in);
|
||||
ProtoBuf.QualifiedNameTable qualifiedNames = ProtoBuf.QualifiedNameTable.parseDelimitedFrom(in);
|
||||
return new NameResolver(simpleNames, qualifiedNames, classResolver);
|
||||
}
|
||||
|
||||
public static void serializeNameTable(@NotNull OutputStream out, @NotNull NameTable nameTable) throws IOException {
|
||||
ProtoBuf.SimpleNameTable.Builder simpleNames = ProtoBuf.SimpleNameTable.newBuilder();
|
||||
for (String simpleName : nameTable.getSimpleNames()) {
|
||||
simpleNames.addNames(simpleName);
|
||||
}
|
||||
simpleNames.build().writeDelimitedTo(out);
|
||||
|
||||
ProtoBuf.QualifiedNameTable.Builder qualifiedNames = ProtoBuf.QualifiedNameTable.newBuilder();
|
||||
for (ProtoBuf.QualifiedNameTable.QualifiedName.Builder qName : nameTable.getFqNames()) {
|
||||
qualifiedNames.addQualifiedNames(qName);
|
||||
}
|
||||
qualifiedNames.build().writeDelimitedTo(out);
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorParent;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.descriptors.serialization.ProtoBuf.QualifiedNameTable.QualifiedName;
|
||||
|
||||
public class NameTable {
|
||||
public static final TObjectHashingStrategy<QualifiedName.Builder> QUALIFIED_NAME_BUILDER_HASHING =
|
||||
new TObjectHashingStrategy<ProtoBuf.QualifiedNameTable.QualifiedName.Builder>() {
|
||||
@Override
|
||||
public int computeHashCode(QualifiedName.Builder object) {
|
||||
int result = 13;
|
||||
result = 31 * result + object.getParentQualifiedName();
|
||||
result = 31 * result + object.getShortName();
|
||||
result = 31 * result + object.getKind().hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(
|
||||
QualifiedName.Builder o1, QualifiedName.Builder o2
|
||||
) {
|
||||
return o1.getParentQualifiedName() == o2.getParentQualifiedName()
|
||||
&& o1.getShortName() == o2.getShortName()
|
||||
&& o1.getKind() == o2.getKind();
|
||||
}
|
||||
};
|
||||
|
||||
private final Interner<String> simpleNames = new Interner<String>();
|
||||
private final Interner<QualifiedName.Builder> qualifiedNames = new Interner<QualifiedName.Builder>(QUALIFIED_NAME_BUILDER_HASHING);
|
||||
|
||||
@NotNull
|
||||
public List<String> getSimpleNames() {
|
||||
return simpleNames.getAllInternedObjects();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<QualifiedName.Builder> getFqNames() {
|
||||
return qualifiedNames.getAllInternedObjects();
|
||||
}
|
||||
|
||||
public int getSimpleNameIndex(@NotNull Name name) {
|
||||
return simpleNames.intern(name.asString());
|
||||
}
|
||||
|
||||
public int getFqNameIndex(@NotNull ClassDescriptor classDescriptor) {
|
||||
QualifiedName.Builder builder = QualifiedName.newBuilder();
|
||||
builder.setKind(QualifiedName.Kind.CLASS);
|
||||
builder.setShortName(getSimpleNameIndex(classDescriptor.getName()));
|
||||
|
||||
DeclarationDescriptor containingDeclaration = classDescriptor.getContainingDeclaration();
|
||||
if (containingDeclaration instanceof NamespaceDescriptor) {
|
||||
NamespaceDescriptor namespaceDescriptor = (NamespaceDescriptor) containingDeclaration;
|
||||
builder.setParentQualifiedName(getFqNameIndex(namespaceDescriptor));
|
||||
}
|
||||
else {
|
||||
ClassDescriptor outerClass = (ClassDescriptor) containingDeclaration;
|
||||
builder.setParentQualifiedName(getFqNameIndex(outerClass));
|
||||
}
|
||||
|
||||
return qualifiedNames.intern(builder);
|
||||
}
|
||||
|
||||
public int getFqNameIndex(@NotNull NamespaceDescriptor namespaceDescriptor) {
|
||||
QualifiedName.Builder builder = QualifiedName.newBuilder();
|
||||
//default: builder.setKind(QualifiedNameTable.QualifiedName.Kind.PACKAGE);
|
||||
builder.setShortName(getSimpleNameIndex(namespaceDescriptor.getName()));
|
||||
|
||||
NamespaceDescriptorParent containingDeclaration = namespaceDescriptor.getContainingDeclaration();
|
||||
if (containingDeclaration instanceof NamespaceDescriptor) {
|
||||
NamespaceDescriptor parentNamespace = (NamespaceDescriptor) containingDeclaration;
|
||||
if (!DescriptorUtils.isRootNamespace(parentNamespace)) {
|
||||
builder.setParentQualifiedName(getFqNameIndex(parentNamespace));
|
||||
}
|
||||
}
|
||||
else {
|
||||
builder.clearParentQualifiedName();
|
||||
}
|
||||
|
||||
return qualifiedNames.intern(builder);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user