Extract interface out of StringTable

Rework SerializerExtension interface: don't pass StringTable to each method
every time, create it in each extension's constructor instead and expose to
DescriptorSerializer with an interface method
This commit is contained in:
Alexander Udalov
2015-09-16 22:32:32 +03:00
parent e749bc262d
commit da68c4d9ee
10 changed files with 268 additions and 275 deletions
@@ -23,24 +23,22 @@ import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.serialization.ProtoBuf.Annotation.Argument.Value
import org.jetbrains.kotlin.serialization.ProtoBuf.Annotation.Argument.Value.Type
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.JetType
public class AnnotationSerializer() {
public fun serializeAnnotation(annotation: AnnotationDescriptor, stringTable: StringTable): ProtoBuf.Annotation {
public class AnnotationSerializer(private val stringTable: StringTable) {
public fun serializeAnnotation(annotation: AnnotationDescriptor): ProtoBuf.Annotation {
return with(ProtoBuf.Annotation.newBuilder()) {
val annotationClass = annotation.getType().getConstructor().getDeclarationDescriptor() as? ClassDescriptor
?: error("Annotation type is not a class: ${annotation.getType()}")
val annotationClass = annotation.type.constructor.declarationDescriptor as? ClassDescriptor
?: error("Annotation type is not a class: ${annotation.type}")
if (ErrorUtils.isError(annotationClass)) {
error("Unresolved annotation type: ${annotation.getType()}")
error("Unresolved annotation type: ${annotation.type}")
}
setId(stringTable.getFqNameIndex(annotationClass))
for ((parameter, value) in annotation.getAllValueArguments()) {
for ((parameter, value) in annotation.allValueArguments) {
val argument = ProtoBuf.Annotation.Argument.newBuilder()
argument.setNameId(stringTable.getSimpleNameIndex(parameter.getName()))
argument.setValue(valueProto(value, parameter.getType(), stringTable))
argument.setNameId(stringTable.getStringIndex(parameter.name.asString()))
argument.setValue(valueProto(value))
addArgument(argument)
}
@@ -48,17 +46,17 @@ public class AnnotationSerializer() {
}
}
fun valueProto(constant: ConstantValue<*>, type: JetType, nameTable: StringTable): Value.Builder = with(Value.newBuilder()) {
fun valueProto(constant: ConstantValue<*>): Value.Builder = with(Value.newBuilder()) {
constant.accept(object : AnnotationArgumentVisitor<Unit, Unit> {
override fun visitAnnotationValue(value: AnnotationValue, data: Unit) {
setType(Type.ANNOTATION)
setAnnotation(serializeAnnotation(value.value, nameTable))
setAnnotation(serializeAnnotation(value.value))
}
override fun visitArrayValue(value: ArrayValue, data: Unit) {
setType(Type.ARRAY)
for (element in value.value) {
addArrayElement(valueProto(element, value.elementType, nameTable).build())
addArrayElement(valueProto(element).build())
}
}
@@ -85,8 +83,8 @@ public class AnnotationSerializer() {
override fun visitEnumValue(value: EnumValue, data: Unit) {
setType(Type.ENUM)
val enumEntry = value.value
setClassId(nameTable.getFqNameIndex(enumEntry.getContainingDeclaration() as ClassDescriptor))
setEnumValueId(nameTable.getSimpleNameIndex(enumEntry.getName()))
setClassId(stringTable.getFqNameIndex(enumEntry.containingDeclaration as ClassDescriptor))
setEnumValueId(stringTable.getStringIndex(enumEntry.name.asString()))
}
override fun visitErrorValue(value: ErrorValue, data: Unit) {
@@ -124,7 +122,7 @@ public class AnnotationSerializer() {
override fun visitStringValue(value: StringValue, data: Unit) {
setType(Type.STRING)
setStringValue(nameTable.getStringIndex(value.value))
setStringValue(stringTable.getStringIndex(value.value))
}
}, Unit)
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.DescriptorFactory;
import org.jetbrains.kotlin.resolve.MemberComparator;
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
@@ -33,7 +34,6 @@ import org.jetbrains.kotlin.utils.UtilsPackage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -44,12 +44,10 @@ import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.
public class DescriptorSerializer {
private final StringTable stringTable;
private final Interner<TypeParameterDescriptor> typeParameters;
private final SerializerExtension extension;
private DescriptorSerializer(StringTable stringTable, Interner<TypeParameterDescriptor> typeParameters, SerializerExtension extension) {
this.stringTable = stringTable;
private DescriptorSerializer(Interner<TypeParameterDescriptor> typeParameters, SerializerExtension extension) {
this.typeParameters = typeParameters;
this.extension = extension;
}
@@ -58,7 +56,7 @@ public class DescriptorSerializer {
public byte[] serialize(@NotNull MessageLite message) {
try {
ByteArrayOutputStream result = new ByteArrayOutputStream();
serializeStringTable(result);
getStringTable().serializeTo(result);
message.writeTo(result);
return result.toByteArray();
}
@@ -67,14 +65,9 @@ public class DescriptorSerializer {
}
}
public void serializeStringTable(@NotNull OutputStream out) throws IOException {
stringTable.serializeSimpleNames().writeDelimitedTo(out);
stringTable.serializeQualifiedNames().writeDelimitedTo(out);
}
@NotNull
public static DescriptorSerializer createTopLevel(@NotNull SerializerExtension extension) {
return new DescriptorSerializer(new StringTable(extension), new Interner<TypeParameterDescriptor>(), extension);
return new DescriptorSerializer(new Interner<TypeParameterDescriptor>(), extension);
}
@NotNull
@@ -95,13 +88,14 @@ public class DescriptorSerializer {
return serializer;
}
@NotNull
private DescriptorSerializer createChildSerializer() {
return new DescriptorSerializer(stringTable, new Interner<TypeParameterDescriptor>(typeParameters), extension);
return new DescriptorSerializer(new Interner<TypeParameterDescriptor>(typeParameters), extension);
}
@NotNull
public StringTable getStringTable() {
return stringTable;
return extension.getStringTable();
}
@NotNull
@@ -150,7 +144,7 @@ public class DescriptorSerializer {
}
for (DeclarationDescriptor descriptor : sort(classDescriptor.getUnsubstitutedInnerClassesScope().getAllDescriptors())) {
int name = stringTable.getSimpleNameIndex(descriptor.getName());
int name = getSimpleNameIndex(descriptor.getName());
if (isEnumEntry(descriptor)) {
builder.addEnumEntry(name);
}
@@ -161,10 +155,10 @@ public class DescriptorSerializer {
ClassDescriptor companionObjectDescriptor = classDescriptor.getCompanionObjectDescriptor();
if (companionObjectDescriptor != null) {
builder.setCompanionObjectName(stringTable.getSimpleNameIndex(companionObjectDescriptor.getName()));
builder.setCompanionObjectName(getSimpleNameIndex(companionObjectDescriptor.getName()));
}
extension.serializeClass(classDescriptor, builder, stringTable);
extension.serializeClass(classDescriptor, builder);
return builder;
}
@@ -253,7 +247,7 @@ public class DescriptorSerializer {
builder.setReceiverType(local.type(receiverParameter.getType()));
}
builder.setName(stringTable.getSimpleNameIndex(descriptor.getName()));
builder.setName(getSimpleNameIndex(descriptor.getName()));
for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) {
builder.addValueParameter(local.valueParameter(valueParameterDescriptor));
@@ -262,7 +256,7 @@ public class DescriptorSerializer {
//noinspection ConstantConditions
builder.setReturnType(local.type(descriptor.getReturnType()));
extension.serializeCallable(descriptor, builder, stringTable);
extension.serializeCallable(descriptor, builder);
return builder;
}
@@ -294,7 +288,7 @@ public class DescriptorSerializer {
builder.setFlags(Flags.getValueParameterFlags(hasAnnotations(descriptor), descriptor.declaresDefaultValue()));
builder.setName(stringTable.getSimpleNameIndex(descriptor.getName()));
builder.setName(getSimpleNameIndex(descriptor.getName()));
builder.setType(type(descriptor.getType()));
@@ -303,7 +297,7 @@ public class DescriptorSerializer {
builder.setVarargElementType(type(varargElementType));
}
extension.serializeValueParameter(descriptor, builder, stringTable);
extension.serializeValueParameter(descriptor, builder);
return builder;
}
@@ -313,7 +307,7 @@ public class DescriptorSerializer {
builder.setId(getTypeParameterId(typeParameter));
builder.setName(stringTable.getSimpleNameIndex(typeParameter.getName()));
builder.setName(getSimpleNameIndex(typeParameter.getName()));
// to avoid storing a default
if (typeParameter.isReified()) {
@@ -353,7 +347,7 @@ public class DescriptorSerializer {
Flexibility flexibility = TypesPackage.flexibility(type);
return type(flexibility.getLowerBound())
.setFlexibleTypeCapabilitiesId(stringTable.getStringIndex(flexibility.getExtraCapabilities().getId()))
.setFlexibleTypeCapabilitiesId(getStringTable().getStringIndex(flexibility.getExtraCapabilities().getId()))
.setFlexibleUpperBound(type(flexibility.getUpperBound()));
}
@@ -376,7 +370,7 @@ public class DescriptorSerializer {
builder.setNullable(true);
}
extension.serializeType(type, builder, stringTable);
extension.serializeType(type, builder);
return builder;
}
@@ -410,7 +404,7 @@ public class DescriptorSerializer {
public ProtoBuf.Package.Builder packageProtoWithoutDescriptors() {
ProtoBuf.Package.Builder builder = ProtoBuf.Package.newBuilder();
extension.serializePackage(Collections.<PackageFragmentDescriptor>emptyList(), builder, stringTable);
extension.serializePackage(Collections.<PackageFragmentDescriptor>emptyList(), builder);
return builder;
}
@@ -432,7 +426,7 @@ public class DescriptorSerializer {
}
}
extension.serializePackage(fragments, builder, stringTable);
extension.serializePackage(fragments, builder);
return builder;
}
@@ -464,7 +458,11 @@ public class DescriptorSerializer {
}
private int getClassId(@NotNull ClassDescriptor descriptor) {
return stringTable.getFqNameIndex(descriptor);
return getStringTable().getFqNameIndex(descriptor);
}
private int getSimpleNameIndex(@NotNull Name name) {
return getStringTable().getStringIndex(name.asString());
}
private int getTypeParameterId(@NotNull TypeParameterDescriptor descriptor) {
@@ -26,39 +26,25 @@ import org.jetbrains.kotlin.types.JetType;
import java.util.Collection;
public abstract class SerializerExtension {
public void serializeClass(
@NotNull ClassDescriptor descriptor,
@NotNull ProtoBuf.Class.Builder proto,
@NotNull StringTable stringTable
) {
@NotNull
public abstract StringTable getStringTable();
public void serializeClass(@NotNull ClassDescriptor descriptor, @NotNull ProtoBuf.Class.Builder proto) {
}
public void serializePackage(
@NotNull Collection<PackageFragmentDescriptor> packageFragments,
@NotNull ProtoBuf.Package.Builder proto,
@NotNull StringTable stringTable
) {
public void serializePackage(@NotNull Collection<PackageFragmentDescriptor> packageFragments, @NotNull ProtoBuf.Package.Builder proto) {
}
public void serializeCallable(
@NotNull CallableMemberDescriptor callable,
@NotNull ProtoBuf.Callable.Builder proto,
@NotNull StringTable stringTable
) {
public void serializeCallable(@NotNull CallableMemberDescriptor callable, @NotNull ProtoBuf.Callable.Builder proto) {
}
public void serializeValueParameter(
@NotNull ValueParameterDescriptor descriptor,
@NotNull ProtoBuf.Callable.ValueParameter.Builder proto,
@NotNull StringTable stringTable
@NotNull ProtoBuf.Callable.ValueParameter.Builder proto
) {
}
public void serializeType(
@NotNull JetType type,
@NotNull ProtoBuf.Type.Builder proto,
@NotNull StringTable stringTable
) {
public void serializeType(@NotNull JetType type, @NotNull ProtoBuf.Type.Builder proto) {
}
@NotNull
@@ -17,128 +17,17 @@
package org.jetbrains.kotlin.serialization;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.ClassOrPackageFragmentDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.types.ErrorUtils;
import org.jetbrains.kotlin.utils.Interner;
import static org.jetbrains.kotlin.serialization.ProtoBuf.QualifiedNameTable.QualifiedName;
import java.io.OutputStream;
public class StringTable {
private static final class FqNameProto {
public final QualifiedName.Builder fqName;
public interface StringTable {
int getStringIndex(@NotNull String string);
public FqNameProto(@NotNull QualifiedName.Builder fqName) {
this.fqName = fqName;
}
int getFqNameIndex(@NotNull ClassOrPackageFragmentDescriptor descriptor);
@Override
public int hashCode() {
int result = 13;
result = 31 * result + fqName.getParentQualifiedName();
result = 31 * result + fqName.getShortName();
result = 31 * result + fqName.getKind().hashCode();
return result;
}
int getFqNameIndex(@NotNull FqName fqName);
@Override
public boolean equals(Object obj) {
if (obj == null || getClass() != obj.getClass()) return false;
QualifiedName.Builder other = ((FqNameProto) obj).fqName;
return fqName.getParentQualifiedName() == other.getParentQualifiedName()
&& fqName.getShortName() == other.getShortName()
&& fqName.getKind() == other.getKind();
}
}
private final Interner<String> strings = new Interner<String>();
private final Interner<FqNameProto> qualifiedNames = new Interner<FqNameProto>();
private final SerializerExtension extension;
public StringTable(@NotNull SerializerExtension extension) {
this.extension = extension;
}
public int getSimpleNameIndex(@NotNull Name name) {
return getStringIndex(name.asString());
}
public int getStringIndex(@NotNull String string) {
return strings.intern(string);
}
public int getFqNameIndex(@NotNull ClassOrPackageFragmentDescriptor descriptor) {
if (ErrorUtils.isError(descriptor)) {
throw new IllegalStateException("Cannot get FQ name of error class: " + descriptor);
}
QualifiedName.Builder builder = QualifiedName.newBuilder();
if (descriptor instanceof ClassDescriptor) {
builder.setKind(QualifiedName.Kind.CLASS);
}
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
int shortName;
if (containingDeclaration instanceof PackageFragmentDescriptor) {
shortName = getSimpleNameIndex(descriptor.getName());
PackageFragmentDescriptor fragment = (PackageFragmentDescriptor) containingDeclaration;
if (!fragment.getFqName().isRoot()) {
builder.setParentQualifiedName(getFqNameIndex(fragment.getFqName()));
}
}
else if (containingDeclaration instanceof ClassDescriptor) {
shortName = getSimpleNameIndex(descriptor.getName());
ClassDescriptor outerClass = (ClassDescriptor) containingDeclaration;
builder.setParentQualifiedName(getFqNameIndex(outerClass));
}
else {
if (descriptor instanceof ClassDescriptor) {
builder.setKind(QualifiedName.Kind.LOCAL);
shortName = getStringIndex(extension.getLocalClassName((ClassDescriptor) descriptor));
}
else {
throw new IllegalStateException("Package container should be a package: " + descriptor);
}
}
builder.setShortName(shortName);
return qualifiedNames.intern(new FqNameProto(builder));
}
public int getFqNameIndex(@NotNull FqName fqName) {
int result = -1;
for (Name segment : fqName.pathSegments()) {
QualifiedName.Builder builder = QualifiedName.newBuilder();
builder.setShortName(getSimpleNameIndex(segment));
if (result != -1) {
builder.setParentQualifiedName(result);
}
result = qualifiedNames.intern(new FqNameProto(builder));
}
return result;
}
@NotNull
public ProtoBuf.StringTable serializeSimpleNames() {
ProtoBuf.StringTable.Builder builder = ProtoBuf.StringTable.newBuilder();
for (String simpleName : strings.getAllInternedObjects()) {
builder.addString(simpleName);
}
return builder.build();
}
@NotNull
public ProtoBuf.QualifiedNameTable serializeQualifiedNames() {
ProtoBuf.QualifiedNameTable.Builder builder = ProtoBuf.QualifiedNameTable.newBuilder();
for (FqNameProto fqName : qualifiedNames.getAllInternedObjects()) {
builder.addQualifiedName(fqName.fqName);
}
return builder.build();
}
void serializeTo(@NotNull OutputStream output);
}
@@ -0,0 +1,153 @@
/*
* Copyright 2010-2015 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.kotlin.serialization;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.ClassOrPackageFragmentDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.types.ErrorUtils;
import org.jetbrains.kotlin.utils.Interner;
import org.jetbrains.kotlin.utils.UtilsPackage;
import java.io.IOException;
import java.io.OutputStream;
import static org.jetbrains.kotlin.serialization.ProtoBuf.QualifiedNameTable.QualifiedName;
public class StringTableImpl implements StringTable {
private static final class FqNameProto {
public final QualifiedName.Builder fqName;
public FqNameProto(@NotNull QualifiedName.Builder fqName) {
this.fqName = fqName;
}
@Override
public int hashCode() {
int result = 13;
result = 31 * result + fqName.getParentQualifiedName();
result = 31 * result + fqName.getShortName();
result = 31 * result + fqName.getKind().hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
if (obj == null || getClass() != obj.getClass()) return false;
QualifiedName.Builder other = ((FqNameProto) obj).fqName;
return fqName.getParentQualifiedName() == other.getParentQualifiedName()
&& fqName.getShortName() == other.getShortName()
&& fqName.getKind() == other.getKind();
}
}
private final Interner<String> strings = new Interner<String>();
private final Interner<FqNameProto> qualifiedNames = new Interner<FqNameProto>();
private final SerializerExtension extension;
public StringTableImpl(@NotNull SerializerExtension extension) {
this.extension = extension;
}
public int getSimpleNameIndex(@NotNull Name name) {
return getStringIndex(name.asString());
}
@Override
public int getStringIndex(@NotNull String string) {
return strings.intern(string);
}
@Override
public int getFqNameIndex(@NotNull ClassOrPackageFragmentDescriptor descriptor) {
if (ErrorUtils.isError(descriptor)) {
throw new IllegalStateException("Cannot get FQ name of error class: " + descriptor);
}
QualifiedName.Builder builder = QualifiedName.newBuilder();
if (descriptor instanceof ClassDescriptor) {
builder.setKind(QualifiedName.Kind.CLASS);
}
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
int shortName;
if (containingDeclaration instanceof PackageFragmentDescriptor) {
shortName = getSimpleNameIndex(descriptor.getName());
PackageFragmentDescriptor fragment = (PackageFragmentDescriptor) containingDeclaration;
if (!fragment.getFqName().isRoot()) {
builder.setParentQualifiedName(getFqNameIndex(fragment.getFqName()));
}
}
else if (containingDeclaration instanceof ClassDescriptor) {
shortName = getSimpleNameIndex(descriptor.getName());
ClassDescriptor outerClass = (ClassDescriptor) containingDeclaration;
builder.setParentQualifiedName(getFqNameIndex(outerClass));
}
else {
if (descriptor instanceof ClassDescriptor) {
builder.setKind(QualifiedName.Kind.LOCAL);
shortName = getStringIndex(extension.getLocalClassName((ClassDescriptor) descriptor));
}
else {
throw new IllegalStateException("Package container should be a package: " + descriptor);
}
}
builder.setShortName(shortName);
return qualifiedNames.intern(new FqNameProto(builder));
}
@Override
public int getFqNameIndex(@NotNull FqName fqName) {
int result = -1;
for (Name segment : fqName.pathSegments()) {
QualifiedName.Builder builder = QualifiedName.newBuilder();
builder.setShortName(getSimpleNameIndex(segment));
if (result != -1) {
builder.setParentQualifiedName(result);
}
result = qualifiedNames.intern(new FqNameProto(builder));
}
return result;
}
@Override
public void serializeTo(@NotNull OutputStream output) {
try {
ProtoBuf.StringTable.Builder stringTable = ProtoBuf.StringTable.newBuilder();
for (String simpleName : strings.getAllInternedObjects()) {
stringTable.addString(simpleName);
}
stringTable.build().writeDelimitedTo(output);
ProtoBuf.QualifiedNameTable.Builder qualifiedNameTable = ProtoBuf.QualifiedNameTable.newBuilder();
for (FqNameProto fqName : qualifiedNames.getAllInternedObjects()) {
qualifiedNameTable.addQualifiedName(fqName.fqName);
}
qualifiedNameTable.build().writeDelimitedTo(output);
}
catch (IOException e) {
throw UtilsPackage.rethrow(e);
}
}
}