add support for compile time constant serialization

This commit is contained in:
Michael Nedzelsky
2015-01-29 18:39:54 +03:00
parent d45a1f3e44
commit df8fed096c
12 changed files with 187 additions and 24 deletions
+1
View File
@@ -32,6 +32,7 @@ extend Class {
extend Callable {
repeated Annotation callable_annotation = 150;
optional Annotation.Argument.Value compile_time_value = 151;
}
extend Callable.ValueParameter {
@@ -10,6 +10,7 @@ public final class BuiltInsProtoBuf {
registry.add(org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf.className);
registry.add(org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf.classAnnotation);
registry.add(org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf.callableAnnotation);
registry.add(org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf.compileTimeValue);
registry.add(org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf.parameterAnnotation);
}
public static final int CLASS_NAME_FIELD_NUMBER = 150;
@@ -57,6 +58,21 @@ public final class BuiltInsProtoBuf {
150,
com.google.protobuf.WireFormat.FieldType.MESSAGE,
false);
public static final int COMPILE_TIME_VALUE_FIELD_NUMBER = 151;
/**
* <code>extend .org.jetbrains.kotlin.serialization.Callable { ... }</code>
*/
public static final
com.google.protobuf.GeneratedMessageLite.GeneratedExtension<
org.jetbrains.kotlin.serialization.ProtoBuf.Callable,
org.jetbrains.kotlin.serialization.ProtoBuf.Annotation.Argument.Value> compileTimeValue = com.google.protobuf.GeneratedMessageLite
.newSingularGeneratedExtension(
org.jetbrains.kotlin.serialization.ProtoBuf.Callable.getDefaultInstance(),
org.jetbrains.kotlin.serialization.ProtoBuf.Annotation.Argument.Value.getDefaultInstance(),
org.jetbrains.kotlin.serialization.ProtoBuf.Annotation.Argument.Value.getDefaultInstance(),
null,
151,
com.google.protobuf.WireFormat.FieldType.MESSAGE);
public static final int PARAMETER_ANNOTATION_FIELD_NUMBER = 150;
/**
* <code>extend .org.jetbrains.kotlin.serialization.Callable.ValueParameter { ... }</code>
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.serialization.deserialization;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.serialization.ProtoBuf;
import org.jetbrains.kotlin.types.JetType;
import java.util.List;
@@ -51,6 +52,6 @@ public interface AnnotationAndConstantLoader<A, C> {
@NotNull ProtoContainer container,
@NotNull ProtoBuf.Callable proto,
@NotNull NameResolver nameResolver,
@NotNull AnnotatedCallableKind kind
@NotNull JetType expectedType
);
}
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
public class AnnotationDeserializer(private val module: ModuleDescriptor) {
private val builtIns: KotlinBuiltIns
@@ -62,7 +63,7 @@ public class AnnotationDeserializer(private val module: ModuleDescriptor) {
return Pair(parameter, resolveValue(parameter.getType(), proto.getValue(), nameResolver))
}
private fun resolveValue(
public fun resolveValue(
expectedType: JetType,
value: Value,
nameResolver: NameResolver
@@ -90,9 +91,7 @@ public class AnnotationDeserializer(private val module: ModuleDescriptor) {
AnnotationValue(deserializeAnnotation(value.getAnnotation(), nameResolver))
}
Type.ARRAY -> {
if (!KotlinBuiltIns.isArray(expectedType) &&
!KotlinBuiltIns.isPrimitiveArray(expectedType)) return ErrorValue.create("Unexpected argument value")
val expectedIsArray = KotlinBuiltIns.isArray(expectedType) || KotlinBuiltIns.isPrimitiveArray(expectedType)
val arrayElements = value.getArrayElementList()
val actualArrayType =
@@ -102,13 +101,13 @@ public class AnnotationDeserializer(private val module: ModuleDescriptor) {
builtIns.getArrayType(Variance.INVARIANT, actualElementType)
}
else {
// In the case of empty array, no element has the element type, so we fall back to the expected type.
// In the case of empty array, no element has the element type, so we fall back to the expected type, if any.
// This is not very accurate when annotation class has been changed without recompiling clients,
// but should not in fact matter because the value is empty anyway
expectedType
if (expectedIsArray) expectedType else builtIns.getArrayType(Variance.INVARIANT, builtIns.getAnyType())
}
val expectedElementType = builtIns.getArrayElementType(expectedType)
val expectedElementType = builtIns.getArrayElementType(if (expectedIsArray) expectedType else actualArrayType)
ArrayValue(
arrayElements.map { resolveValue(expectedElementType, it, nameResolver) },
@@ -119,12 +118,13 @@ public class AnnotationDeserializer(private val module: ModuleDescriptor) {
else -> error("Unsupported annotation argument type: ${value.getType()} (expected $expectedType)")
}
if (result.getType(builtIns) != expectedType) {
if (result.getType(builtIns) isSubtypeOf expectedType) {
return result
}
else {
// This means that an annotation class has been changed incompatibly without recompiling clients
return ErrorValue.create("Unexpected argument value")
}
return result
}
// NOTE: see analogous code in BinaryClassAnnotationAndConstantLoaderImpl
@@ -113,7 +113,7 @@ public class MemberDeserializer(private val c: DeserializationContext) {
property.setCompileTimeInitializer(
c.storageManager.createNullableLazyValue {
val container = c.containingDeclaration.asProtoContainer()
c.components.annotationAndConstantLoader.loadPropertyConstant(container, proto, c.nameResolver, AnnotatedCallableKind.PROPERTY)
c.components.annotationAndConstantLoader.loadPropertyConstant(container, proto, c.nameResolver, property.getReturnType())
}
)
}