add support for compile time constant serialization
This commit is contained in:
+5
-3
@@ -31,6 +31,8 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.Flags
|
||||
import org.jetbrains.kotlin.serialization.deserialization.AnnotationAndConstantLoader
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationContext
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
|
||||
public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||
storageManager: StorageManager,
|
||||
@@ -130,11 +132,11 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
|
||||
container: ProtoContainer,
|
||||
proto: ProtoBuf.Callable,
|
||||
nameResolver: NameResolver,
|
||||
kind: AnnotatedCallableKind
|
||||
expectedType: JetType
|
||||
): C? {
|
||||
val signature = getCallableSignature(proto, nameResolver, kind) ?: return null
|
||||
val signature = getCallableSignature(proto, nameResolver, AnnotatedCallableKind.PROPERTY) ?: return null
|
||||
|
||||
val kotlinClass = findClassWithAnnotationsAndInitializers(container, proto, nameResolver, kind)
|
||||
val kotlinClass = findClassWithAnnotationsAndInitializers(container, proto, nameResolver, AnnotatedCallableKind.PROPERTY)
|
||||
if (kotlinClass == null) {
|
||||
errorReporter.reportLoadingError("Kotlin class for loading property constant is not found: ${container.getFqName(nameResolver)}", null)
|
||||
return null
|
||||
|
||||
+4
-3
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
|
||||
class BuiltInsAnnotationAndConstantLoader(
|
||||
module: ModuleDescriptor
|
||||
@@ -61,9 +62,9 @@ class BuiltInsAnnotationAndConstantLoader(
|
||||
container: ProtoContainer,
|
||||
proto: ProtoBuf.Callable,
|
||||
nameResolver: NameResolver,
|
||||
kind: AnnotatedCallableKind
|
||||
expectedType: JetType
|
||||
): CompileTimeConstant<*>? {
|
||||
// TODO: support deserialization of compile time constants in built-ins when needed
|
||||
throw UnsupportedOperationException()
|
||||
val value = proto.getExtension(BuiltInsProtoBuf.compileTimeValue)
|
||||
return deserializer.resolveValue(expectedType, value, nameResolver)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ extend Class {
|
||||
|
||||
extend Callable {
|
||||
repeated Annotation callable_annotation = 150;
|
||||
optional Annotation.Argument.Value compile_time_value = 151;
|
||||
}
|
||||
|
||||
extend Callable.ValueParameter {
|
||||
|
||||
+16
@@ -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>
|
||||
|
||||
+2
-1
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
+10
-10
@@ -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
|
||||
|
||||
+1
-1
@@ -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())
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user