Extract module 'deserialization' out of 'serialization'
'deserialization' stays in core because it's needed both in compiler and reflection, but 'serialization' is used only in the compiler
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="protobuf-java" level="project" />
|
||||
<orderEntry type="library" name="javax.inject" level="project" />
|
||||
<orderEntry type="module" module-name="descriptors" />
|
||||
<orderEntry type="module" module-name="deserialization" exported="" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
</component>
|
||||
</module>
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor
|
||||
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.JetType
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
|
||||
public object AnnotationSerializer {
|
||||
public fun serializeAnnotation(annotation: AnnotationDescriptor, stringTable: StringTable): ProtoBuf.Annotation {
|
||||
return with(ProtoBuf.Annotation.newBuilder()) {
|
||||
val annotationClass = annotation.getType().getConstructor().getDeclarationDescriptor() as? ClassDescriptor
|
||||
?: error("Annotation type is not a class: ${annotation.getType()}")
|
||||
|
||||
setId(stringTable.getFqNameIndex(annotationClass))
|
||||
|
||||
for ((parameter, value) in annotation.getAllValueArguments()) {
|
||||
val argument = ProtoBuf.Annotation.Argument.newBuilder()
|
||||
argument.setNameId(stringTable.getSimpleNameIndex(parameter.getName()))
|
||||
argument.setValue(valueProto(value, parameter.getType(), stringTable))
|
||||
addArgument(argument)
|
||||
}
|
||||
|
||||
build()
|
||||
}
|
||||
}
|
||||
|
||||
fun valueProto(constant: CompileTimeConstant<*>, type: JetType, nameTable: StringTable): Value.Builder = with(Value.newBuilder()) {
|
||||
constant.accept(object : AnnotationArgumentVisitor<Unit, Unit> {
|
||||
override fun visitAnnotationValue(value: AnnotationValue, data: Unit) {
|
||||
setType(Type.ANNOTATION)
|
||||
setAnnotation(serializeAnnotation(value.getValue(), nameTable))
|
||||
}
|
||||
|
||||
override fun visitArrayValue(value: ArrayValue, data: Unit) {
|
||||
setType(Type.ARRAY)
|
||||
for (element in value.getValue()) {
|
||||
addArrayElement(valueProto(element, KotlinBuiltIns.getInstance().getArrayElementType(type), nameTable).build())
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitBooleanValue(value: BooleanValue, data: Unit) {
|
||||
setType(Type.BOOLEAN)
|
||||
setIntValue(if (value.getValue()) 1 else 0)
|
||||
}
|
||||
|
||||
override fun visitByteValue(value: ByteValue, data: Unit) {
|
||||
setType(Type.BYTE)
|
||||
setIntValue(value.getValue().toLong())
|
||||
}
|
||||
|
||||
override fun visitCharValue(value: CharValue, data: Unit) {
|
||||
setType(Type.CHAR)
|
||||
setIntValue(value.getValue().toLong())
|
||||
}
|
||||
|
||||
override fun visitDoubleValue(value: DoubleValue, data: Unit) {
|
||||
setType(Type.DOUBLE)
|
||||
setDoubleValue(value.getValue())
|
||||
}
|
||||
|
||||
override fun visitEnumValue(value: EnumValue, data: Unit) {
|
||||
setType(Type.ENUM)
|
||||
val enumEntry = value.getValue()
|
||||
setClassId(nameTable.getFqNameIndex(enumEntry.getContainingDeclaration() as ClassDescriptor))
|
||||
setEnumValueId(nameTable.getSimpleNameIndex(enumEntry.getName()))
|
||||
}
|
||||
|
||||
override fun visitErrorValue(value: ErrorValue, data: Unit) {
|
||||
throw UnsupportedOperationException("Error value: $value")
|
||||
}
|
||||
|
||||
override fun visitFloatValue(value: FloatValue, data: Unit) {
|
||||
setType(Type.FLOAT)
|
||||
setFloatValue(value.getValue())
|
||||
}
|
||||
|
||||
override fun visitIntValue(value: IntValue, data: Unit) {
|
||||
setType(Type.INT)
|
||||
setIntValue(value.getValue().toLong())
|
||||
}
|
||||
|
||||
override fun visitJavaClassValue(value: JavaClassValue, data: Unit) {
|
||||
// TODO: support class literals
|
||||
throw UnsupportedOperationException("Class literal annotation arguments are not yet supported: $value")
|
||||
}
|
||||
|
||||
override fun visitLongValue(value: LongValue, data: Unit) {
|
||||
setType(Type.LONG)
|
||||
setIntValue(value.getValue())
|
||||
}
|
||||
|
||||
override fun visitNullValue(value: NullValue, data: Unit) {
|
||||
throw UnsupportedOperationException("Null should not appear in annotation arguments")
|
||||
}
|
||||
|
||||
override fun visitNumberTypeValue(constant: IntegerValueTypeConstant, data: Unit) {
|
||||
// TODO: IntegerValueTypeConstant should not occur in annotation arguments
|
||||
val number = constant.getValue(type)
|
||||
val specificConstant = with(KotlinBuiltIns.getInstance()) {
|
||||
when (type) {
|
||||
getLongType() -> LongValue(number.toLong(), true, true, true)
|
||||
getIntType() -> IntValue(number.toInt(), true, true, true)
|
||||
getShortType() -> ShortValue(number.toShort(), true, true, true)
|
||||
getByteType() -> ByteValue(number.toByte(), true, true, true)
|
||||
else -> throw IllegalStateException("Integer constant $constant has non-integer type $type")
|
||||
}
|
||||
}
|
||||
|
||||
specificConstant.accept(this, data)
|
||||
}
|
||||
|
||||
override fun visitShortValue(value: ShortValue, data: Unit) {
|
||||
setType(Type.SHORT)
|
||||
setIntValue(value.getValue().toLong())
|
||||
}
|
||||
|
||||
override fun visitStringValue(value: StringValue, data: Unit) {
|
||||
setType(Type.STRING)
|
||||
setStringValue(nameTable.getStringIndex(value.getValue()))
|
||||
}
|
||||
}, Unit)
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
+442
@@ -0,0 +1,442 @@
|
||||
/*
|
||||
* 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 kotlin.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.resolve.DescriptorFactory;
|
||||
import org.jetbrains.kotlin.resolve.MemberComparator;
|
||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.kotlin.resolve.constants.NullValue;
|
||||
import org.jetbrains.kotlin.types.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry;
|
||||
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getSecondaryConstructors;
|
||||
|
||||
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;
|
||||
this.typeParameters = typeParameters;
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DescriptorSerializer createTopLevel(@NotNull SerializerExtension extension) {
|
||||
return new DescriptorSerializer(new StringTable(extension), new Interner<TypeParameterDescriptor>(), extension);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DescriptorSerializer create(@NotNull ClassDescriptor descriptor, @NotNull SerializerExtension extension) {
|
||||
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||
DescriptorSerializer parentSerializer =
|
||||
container instanceof ClassDescriptor
|
||||
? create((ClassDescriptor) container, extension)
|
||||
: createTopLevel(extension);
|
||||
|
||||
// Calculate type parameter ids for the outer class beforehand, as it would've had happened if we were always
|
||||
// serializing outer classes before nested classes.
|
||||
// Otherwise our interner can get wrong ids because we may serialize classes in any order.
|
||||
DescriptorSerializer serializer = parentSerializer.createChildSerializer();
|
||||
for (TypeParameterDescriptor typeParameter : descriptor.getTypeConstructor().getParameters()) {
|
||||
serializer.typeParameters.intern(typeParameter);
|
||||
}
|
||||
return serializer;
|
||||
}
|
||||
|
||||
private DescriptorSerializer createChildSerializer() {
|
||||
return new DescriptorSerializer(stringTable, new Interner<TypeParameterDescriptor>(typeParameters), extension);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StringTable getStringTable() {
|
||||
return stringTable;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ProtoBuf.Class.Builder classProto(@NotNull ClassDescriptor classDescriptor) {
|
||||
ProtoBuf.Class.Builder builder = ProtoBuf.Class.newBuilder();
|
||||
|
||||
int flags = Flags.getClassFlags(hasAnnotations(classDescriptor), classDescriptor.getVisibility(), classDescriptor.getModality(),
|
||||
classDescriptor.getKind(), classDescriptor.isInner(), classDescriptor.isCompanionObject());
|
||||
builder.setFlags(flags);
|
||||
|
||||
builder.setFqName(getClassId(classDescriptor));
|
||||
|
||||
for (TypeParameterDescriptor typeParameterDescriptor : classDescriptor.getTypeConstructor().getParameters()) {
|
||||
builder.addTypeParameter(typeParameter(typeParameterDescriptor));
|
||||
}
|
||||
|
||||
if (!KotlinBuiltIns.isSpecialClassWithNoSupertypes(classDescriptor)) {
|
||||
// Special classes (Any, Nothing) have no supertypes
|
||||
for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
|
||||
builder.addSupertype(type(supertype));
|
||||
}
|
||||
}
|
||||
|
||||
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||
if (primaryConstructor != null) {
|
||||
if (DescriptorFactory.isDefaultPrimaryConstructor(primaryConstructor)) {
|
||||
builder.setPrimaryConstructor(ProtoBuf.Class.PrimaryConstructor.getDefaultInstance());
|
||||
}
|
||||
else {
|
||||
ProtoBuf.Class.PrimaryConstructor.Builder constructorBuilder = ProtoBuf.Class.PrimaryConstructor.newBuilder();
|
||||
constructorBuilder.setData(callableProto(primaryConstructor));
|
||||
builder.setPrimaryConstructor(constructorBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
for (ConstructorDescriptor constructorDescriptor : getSecondaryConstructors(classDescriptor)) {
|
||||
builder.addSecondaryConstructor(callableProto(constructorDescriptor));
|
||||
}
|
||||
|
||||
for (DeclarationDescriptor descriptor : sort(classDescriptor.getDefaultType().getMemberScope().getAllDescriptors())) {
|
||||
if (descriptor instanceof CallableMemberDescriptor) {
|
||||
CallableMemberDescriptor member = (CallableMemberDescriptor) descriptor;
|
||||
if (member.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) continue;
|
||||
builder.addMember(callableProto(member));
|
||||
}
|
||||
}
|
||||
|
||||
for (DeclarationDescriptor descriptor : sort(classDescriptor.getUnsubstitutedInnerClassesScope().getAllDescriptors())) {
|
||||
int name = stringTable.getSimpleNameIndex(descriptor.getName());
|
||||
if (isEnumEntry(descriptor)) {
|
||||
builder.addEnumEntry(name);
|
||||
}
|
||||
else {
|
||||
builder.addNestedClassName(name);
|
||||
}
|
||||
}
|
||||
|
||||
ClassDescriptor companionObjectDescriptor = classDescriptor.getCompanionObjectDescriptor();
|
||||
if (companionObjectDescriptor != null) {
|
||||
builder.setCompanionObjectName(stringTable.getSimpleNameIndex(companionObjectDescriptor.getName()));
|
||||
}
|
||||
|
||||
extension.serializeClass(classDescriptor, builder, stringTable);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ProtoBuf.Callable.Builder callableProto(@NotNull CallableMemberDescriptor descriptor) {
|
||||
ProtoBuf.Callable.Builder builder = ProtoBuf.Callable.newBuilder();
|
||||
|
||||
DescriptorSerializer local = createChildSerializer();
|
||||
|
||||
boolean hasGetter = false;
|
||||
boolean hasSetter = false;
|
||||
boolean hasConstant = false;
|
||||
if (descriptor instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
|
||||
int propertyFlags = Flags.getAccessorFlags(
|
||||
hasAnnotations(propertyDescriptor),
|
||||
propertyDescriptor.getVisibility(),
|
||||
propertyDescriptor.getModality(),
|
||||
false
|
||||
);
|
||||
|
||||
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
|
||||
if (getter != null) {
|
||||
hasGetter = true;
|
||||
int accessorFlags = getAccessorFlags(getter);
|
||||
if (accessorFlags != propertyFlags) {
|
||||
builder.setGetterFlags(accessorFlags);
|
||||
}
|
||||
}
|
||||
|
||||
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
|
||||
if (setter != null) {
|
||||
hasSetter = true;
|
||||
int accessorFlags = getAccessorFlags(setter);
|
||||
if (accessorFlags != propertyFlags) {
|
||||
builder.setSetterFlags(accessorFlags);
|
||||
}
|
||||
|
||||
if (!setter.isDefault()) {
|
||||
for (ValueParameterDescriptor valueParameterDescriptor : setter.getValueParameters()) {
|
||||
builder.addValueParameter(local.valueParameter(valueParameterDescriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CompileTimeConstant<?> compileTimeConstant = propertyDescriptor.getCompileTimeInitializer();
|
||||
hasConstant = !(compileTimeConstant == null || compileTimeConstant instanceof NullValue);
|
||||
}
|
||||
|
||||
builder.setFlags(Flags.getCallableFlags(
|
||||
hasAnnotations(descriptor),
|
||||
descriptor.getVisibility(),
|
||||
descriptor.getModality(),
|
||||
descriptor.getKind(),
|
||||
callableKind(descriptor),
|
||||
hasGetter,
|
||||
hasSetter,
|
||||
hasConstant
|
||||
));
|
||||
|
||||
for (TypeParameterDescriptor typeParameterDescriptor : descriptor.getTypeParameters()) {
|
||||
builder.addTypeParameter(local.typeParameter(typeParameterDescriptor));
|
||||
}
|
||||
|
||||
ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter();
|
||||
if (receiverParameter != null) {
|
||||
builder.setReceiverType(local.type(receiverParameter.getType()));
|
||||
}
|
||||
|
||||
builder.setName(stringTable.getSimpleNameIndex(descriptor.getName()));
|
||||
|
||||
for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) {
|
||||
builder.addValueParameter(local.valueParameter(valueParameterDescriptor));
|
||||
}
|
||||
|
||||
//noinspection ConstantConditions
|
||||
builder.setReturnType(local.type(descriptor.getReturnType()));
|
||||
|
||||
extension.serializeCallable(descriptor, builder, stringTable);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static int getAccessorFlags(@NotNull PropertyAccessorDescriptor accessor) {
|
||||
return Flags.getAccessorFlags(
|
||||
hasAnnotations(accessor),
|
||||
accessor.getVisibility(),
|
||||
accessor.getModality(),
|
||||
!accessor.isDefault()
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static ProtoBuf.Callable.CallableKind callableKind(@NotNull CallableMemberDescriptor descriptor) {
|
||||
if (descriptor instanceof PropertyDescriptor) {
|
||||
return ((PropertyDescriptor) descriptor).isVar() ? ProtoBuf.Callable.CallableKind.VAR : ProtoBuf.Callable.CallableKind.VAL;
|
||||
}
|
||||
if (descriptor instanceof ConstructorDescriptor) {
|
||||
return ProtoBuf.Callable.CallableKind.CONSTRUCTOR;
|
||||
}
|
||||
assert descriptor instanceof FunctionDescriptor : "Unknown descriptor class: " + descriptor.getClass();
|
||||
return ProtoBuf.Callable.CallableKind.FUN;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ProtoBuf.Callable.ValueParameter.Builder valueParameter(@NotNull ValueParameterDescriptor descriptor) {
|
||||
ProtoBuf.Callable.ValueParameter.Builder builder = ProtoBuf.Callable.ValueParameter.newBuilder();
|
||||
|
||||
builder.setFlags(Flags.getValueParameterFlags(hasAnnotations(descriptor), descriptor.declaresDefaultValue()));
|
||||
|
||||
builder.setName(stringTable.getSimpleNameIndex(descriptor.getName()));
|
||||
|
||||
builder.setType(type(descriptor.getType()));
|
||||
|
||||
JetType varargElementType = descriptor.getVarargElementType();
|
||||
if (varargElementType != null) {
|
||||
builder.setVarargElementType(type(varargElementType));
|
||||
}
|
||||
|
||||
extension.serializeValueParameter(descriptor, builder, stringTable);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private ProtoBuf.TypeParameter.Builder typeParameter(TypeParameterDescriptor typeParameter) {
|
||||
ProtoBuf.TypeParameter.Builder builder = ProtoBuf.TypeParameter.newBuilder();
|
||||
|
||||
builder.setId(getTypeParameterId(typeParameter));
|
||||
|
||||
builder.setName(stringTable.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.addUpperBound(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) {
|
||||
assert !type.isError() : "Can't serialize error types: " + type; // TODO
|
||||
|
||||
if (TypesPackage.isFlexible(type)) return flexibleType(type);
|
||||
|
||||
ProtoBuf.Type.Builder builder = ProtoBuf.Type.newBuilder();
|
||||
|
||||
builder.setConstructor(typeConstructor(type.getConstructor()));
|
||||
|
||||
for (TypeProjection projection : type.getArguments()) {
|
||||
builder.addArgument(typeArgument(projection));
|
||||
}
|
||||
|
||||
// to avoid storing a default
|
||||
if (type.isMarkedNullable()) {
|
||||
builder.setNullable(true);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private ProtoBuf.Type.Builder flexibleType(@NotNull JetType type) {
|
||||
Flexibility flexibility = TypesPackage.flexibility(type);
|
||||
|
||||
ProtoBuf.Type.Builder builder = type(flexibility.getLowerBound());
|
||||
|
||||
builder.setFlexibleTypeCapabilitiesId(stringTable.getStringIndex(flexibility.getExtraCapabilities().getId()));
|
||||
|
||||
builder.setFlexibleUpperBound(type(flexibility.getUpperBound()));
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ProtoBuf.Type.Argument.Builder typeArgument(@NotNull TypeProjection typeProjection) {
|
||||
ProtoBuf.Type.Argument.Builder builder = ProtoBuf.Type.Argument.newBuilder();
|
||||
|
||||
if (typeProjection.isStarProjection()) {
|
||||
builder.setProjection(ProtoBuf.Type.Argument.Projection.STAR);
|
||||
}
|
||||
else {
|
||||
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
|
||||
public ProtoBuf.Package.Builder packageProto(@NotNull Collection<PackageFragmentDescriptor> fragments) {
|
||||
return packageProto(fragments, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ProtoBuf.Package.Builder packageProto(@NotNull Collection<PackageFragmentDescriptor> fragments, @Nullable Function1<DeclarationDescriptor, Boolean> skip) {
|
||||
ProtoBuf.Package.Builder builder = ProtoBuf.Package.newBuilder();
|
||||
|
||||
Collection<DeclarationDescriptor> members = new ArrayList<DeclarationDescriptor>();
|
||||
for (PackageFragmentDescriptor fragment : fragments) {
|
||||
members.addAll(fragment.getMemberScope().getAllDescriptors());
|
||||
}
|
||||
|
||||
for (DeclarationDescriptor declaration : sort(members)) {
|
||||
if (skip != null && skip.invoke(declaration)) continue;
|
||||
|
||||
if (declaration instanceof PropertyDescriptor || declaration instanceof FunctionDescriptor) {
|
||||
builder.addMember(callableProto((CallableMemberDescriptor) declaration));
|
||||
}
|
||||
}
|
||||
|
||||
extension.serializePackage(fragments, builder, stringTable);
|
||||
|
||||
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 stringTable.getFqNameIndex(descriptor);
|
||||
}
|
||||
|
||||
private int getTypeParameterId(@NotNull TypeParameterDescriptor descriptor) {
|
||||
return typeParameters.intern(descriptor);
|
||||
}
|
||||
|
||||
private static boolean hasAnnotations(Annotated descriptor) {
|
||||
return !descriptor.getAnnotations().isEmpty();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends DeclarationDescriptor> List<T> sort(@NotNull Collection<T> descriptors) {
|
||||
List<T> result = new ArrayList<T>(descriptors);
|
||||
//NOTE: the exact comparator does matter here
|
||||
Collections.sort(result, MemberComparator.INSTANCE);
|
||||
return result;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 kotlin.Function1;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class Interner<T> {
|
||||
private final Interner<T> parent;
|
||||
private final int firstIndex;
|
||||
private final Map<T, Integer> interned = new HashMap<T, Integer>();
|
||||
|
||||
public Interner(Interner<T> parent) {
|
||||
this.parent = parent;
|
||||
this.firstIndex = parent != null ? parent.interned.size() + parent.firstIndex : 0;
|
||||
}
|
||||
|
||||
public Interner() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Integer find(@NotNull T obj) {
|
||||
assert parent == null || parent.interned.size() + parent.firstIndex == firstIndex :
|
||||
"Parent changed in parallel with child: indexes will be wrong";
|
||||
if (parent != null) {
|
||||
Integer index = parent.find(obj);
|
||||
if (index != null) return index;
|
||||
}
|
||||
return interned.get(obj);
|
||||
}
|
||||
|
||||
public int intern(@NotNull T obj) {
|
||||
Integer index = find(obj);
|
||||
if (index != null) return index;
|
||||
|
||||
index = firstIndex + interned.size();
|
||||
interned.put(obj, index);
|
||||
return index;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<T> getAllInternedObjects() {
|
||||
return KotlinPackage.toSortedListBy(interned.keySet(), new Function1<T, Integer>() {
|
||||
@Override
|
||||
public Integer invoke(T key) {
|
||||
return interned.get(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.serialization.deserialization.NameResolver;
|
||||
import org.jetbrains.kotlin.utils.UtilsPackage;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class SerializationUtil {
|
||||
private SerializationUtil() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static byte[] serializeClassData(@NotNull ClassData classData) {
|
||||
try {
|
||||
ByteArrayOutputStream result = new ByteArrayOutputStream();
|
||||
serializeNameResolver(result, classData.getNameResolver());
|
||||
classData.getClassProto().writeTo(result);
|
||||
return result.toByteArray();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw UtilsPackage.rethrow(e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static byte[] serializePackageData(@NotNull PackageData packageData) {
|
||||
try {
|
||||
ByteArrayOutputStream result = new ByteArrayOutputStream();
|
||||
serializeNameResolver(result, packageData.getNameResolver());
|
||||
packageData.getPackageProto().writeTo(result);
|
||||
return result.toByteArray();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw UtilsPackage.rethrow(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void serializeNameResolver(@NotNull OutputStream out, @NotNull NameResolver nameResolver) {
|
||||
serializeStringTable(out, nameResolver.getStringTable(), nameResolver.getQualifiedNameTable());
|
||||
}
|
||||
|
||||
public static void serializeStringTable(
|
||||
@NotNull OutputStream out,
|
||||
@NotNull ProtoBuf.StringTable stringTable,
|
||||
@NotNull ProtoBuf.QualifiedNameTable qualifiedNameTable
|
||||
) {
|
||||
try {
|
||||
stringTable.writeDelimitedTo(out);
|
||||
qualifiedNameTable.writeDelimitedTo(out);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw UtilsPackage.rethrow(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.CallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class SerializerExtension {
|
||||
public void serializeClass(
|
||||
@NotNull ClassDescriptor descriptor,
|
||||
@NotNull ProtoBuf.Class.Builder proto,
|
||||
@NotNull StringTable stringTable
|
||||
) {
|
||||
}
|
||||
|
||||
public void serializePackage(
|
||||
@NotNull Collection<PackageFragmentDescriptor> packageFragments,
|
||||
@NotNull ProtoBuf.Package.Builder proto,
|
||||
@NotNull StringTable stringTable
|
||||
) {
|
||||
}
|
||||
|
||||
public void serializeCallable(
|
||||
@NotNull CallableMemberDescriptor callable,
|
||||
@NotNull ProtoBuf.Callable.Builder proto,
|
||||
@NotNull StringTable stringTable
|
||||
) {
|
||||
}
|
||||
|
||||
public void serializeValueParameter(
|
||||
@NotNull ValueParameterDescriptor descriptor,
|
||||
@NotNull ProtoBuf.Callable.ValueParameter.Builder proto,
|
||||
@NotNull StringTable stringTable
|
||||
) {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getLocalClassName(@NotNull ClassDescriptor descriptor) {
|
||||
throw new UnsupportedOperationException("Local classes are unsupported: " + descriptor);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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 static org.jetbrains.kotlin.serialization.ProtoBuf.QualifiedNameTable.QualifiedName;
|
||||
|
||||
public class 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 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) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.builtins
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.constants.NullValue
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.serialization.AnnotationSerializer
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.SerializerExtension
|
||||
import org.jetbrains.kotlin.serialization.StringTable
|
||||
|
||||
public object BuiltInsSerializerExtension : SerializerExtension() {
|
||||
override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder, stringTable: StringTable) {
|
||||
for (annotation in descriptor.getAnnotations()) {
|
||||
proto.addExtension(BuiltInsProtoBuf.classAnnotation, AnnotationSerializer.serializeAnnotation(annotation, stringTable))
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializePackage(
|
||||
packageFragments: Collection<PackageFragmentDescriptor>,
|
||||
proto: ProtoBuf.Package.Builder,
|
||||
stringTable: StringTable
|
||||
) {
|
||||
val classes = packageFragments.flatMap {
|
||||
it.getMemberScope().getDescriptors(DescriptorKindFilter.CLASSIFIERS).filterIsInstance<ClassDescriptor>()
|
||||
}
|
||||
|
||||
for (descriptor in DescriptorSerializer.sort(classes)) {
|
||||
proto.addExtension(BuiltInsProtoBuf.className, stringTable.getSimpleNameIndex(descriptor.getName()))
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeCallable(
|
||||
callable: CallableMemberDescriptor,
|
||||
proto: ProtoBuf.Callable.Builder,
|
||||
stringTable: StringTable
|
||||
) {
|
||||
for (annotation in callable.getAnnotations()) {
|
||||
proto.addExtension(BuiltInsProtoBuf.callableAnnotation, AnnotationSerializer.serializeAnnotation(annotation, stringTable))
|
||||
}
|
||||
val compileTimeConstant = (callable as? PropertyDescriptor)?.getCompileTimeInitializer()
|
||||
if (compileTimeConstant != null && compileTimeConstant !is NullValue) {
|
||||
val type = compileTimeConstant.getType(KotlinBuiltIns.getInstance())
|
||||
proto.setExtension(BuiltInsProtoBuf.compileTimeValue, AnnotationSerializer.valueProto(compileTimeConstant, type, stringTable).build())
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeValueParameter(
|
||||
descriptor: ValueParameterDescriptor,
|
||||
proto: ProtoBuf.Callable.ValueParameter.Builder,
|
||||
stringTable: StringTable
|
||||
) {
|
||||
for (annotation in descriptor.getAnnotations()) {
|
||||
proto.addExtension(BuiltInsProtoBuf.parameterAnnotation, AnnotationSerializer.serializeAnnotation(annotation, stringTable))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user