Refactor ConstantValue implementations
Remove KotlinBuiltIns and take a ModuleDescriptor instance in getType instead. This will allow to create constant values in contexts where there's no module or built-ins accessible (such as, deserialization of module annotations during indexing of .kotlin_module files in IDE). Note that some values (KClassValue, EnumValue, AnnotationValue) still take module-dependent objects (KotlinType, ClassDescriptor and AnnotationDescriptor respectively). This is to be refactored later
This commit is contained in:
@@ -370,8 +370,9 @@ public abstract class AnnotationCodegen {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visitEnumValue(EnumValue value, Void data) {
|
public Void visitEnumValue(EnumValue value, Void data) {
|
||||||
String propertyName = value.getValue().getName().asString();
|
String enumClassInternalName = AsmUtil.asmTypeByClassId(value.getEnumClassId()).getDescriptor();
|
||||||
annotationVisitor.visitEnum(name, typeMapper.mapType(value.getType()).getDescriptor(), propertyName);
|
String enumEntryName = value.getEnumEntryName().asString();
|
||||||
|
annotationVisitor.visitEnum(name, enumClassInternalName, enumEntryName);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-4
@@ -20,21 +20,19 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|||||||
import org.jetbrains.kotlin.load.java.structure.JavaField
|
import org.jetbrains.kotlin.load.java.structure.JavaField
|
||||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||||
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
|
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
|
||||||
|
|
||||||
class JavaPropertyInitializerEvaluatorImpl : JavaPropertyInitializerEvaluator {
|
class JavaPropertyInitializerEvaluatorImpl : JavaPropertyInitializerEvaluator {
|
||||||
override fun getInitializerConstant(field: JavaField, descriptor: PropertyDescriptor): ConstantValue<*>? {
|
override fun getInitializerConstant(field: JavaField, descriptor: PropertyDescriptor): ConstantValue<*>? {
|
||||||
val evaluated = field.initializerValue ?: return null
|
val evaluated = field.initializerValue ?: return null
|
||||||
|
|
||||||
val factory = ConstantValueFactory(descriptor.builtIns)
|
|
||||||
return when (evaluated) {
|
return when (evaluated) {
|
||||||
//Note: evaluated expression may be of class that does not match field type in some cases
|
//Note: evaluated expression may be of class that does not match field type in some cases
|
||||||
// tested for Int, left other checks just in case
|
// tested for Int, left other checks just in case
|
||||||
is Byte, is Short, is Int, is Long -> {
|
is Byte, is Short, is Int, is Long -> {
|
||||||
factory.createIntegerConstantValue((evaluated as Number).toLong(), descriptor.type)
|
ConstantValueFactory.createIntegerConstantValue((evaluated as Number).toLong(), descriptor.type)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
factory.createConstantValue(evaluated)
|
ConstantValueFactory.createConstantValue(evaluated)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-2
@@ -18,10 +18,13 @@ package org.jetbrains.kotlin.script
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||||
import org.jetbrains.kotlin.psi.KtUserType
|
import org.jetbrains.kotlin.psi.KtUserType
|
||||||
import org.jetbrains.kotlin.resolve.BindingTraceContext
|
import org.jetbrains.kotlin.resolve.BindingTraceContext
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||||
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KParameter
|
import kotlin.reflect.KParameter
|
||||||
@@ -33,10 +36,11 @@ internal fun String?.orAnonymous(kind: String = ""): String =
|
|||||||
this ?: "<anonymous" + (if (kind.isNotBlank()) " $kind" else "") + ">"
|
this ?: "<anonymous" + (if (kind.isNotBlank()) " $kind" else "") + ">"
|
||||||
|
|
||||||
internal fun constructAnnotation(psi: KtAnnotationEntry, targetClass: KClass<out Annotation>): Annotation {
|
internal fun constructAnnotation(psi: KtAnnotationEntry, targetClass: KClass<out Annotation>): Annotation {
|
||||||
|
val module = ModuleDescriptorImpl(Name.special("<script-annotations-preprocessing>"), LockBasedStorageManager(), DefaultBuiltIns.Instance)
|
||||||
|
val evaluator = ConstantExpressionEvaluator(module, LanguageVersionSettingsImpl.DEFAULT)
|
||||||
|
val trace = BindingTraceContext()
|
||||||
|
|
||||||
val valueArguments = psi.valueArguments.map { arg ->
|
val valueArguments = psi.valueArguments.map { arg ->
|
||||||
val evaluator = ConstantExpressionEvaluator(DefaultBuiltIns.Instance, LanguageVersionSettingsImpl.DEFAULT)
|
|
||||||
val trace = BindingTraceContext()
|
|
||||||
val result = evaluator.evaluateToConstantValue(arg.getArgumentExpression()!!, trace, TypeUtils.NO_EXPECTED_TYPE)
|
val result = evaluator.evaluateToConstantValue(arg.getArgumentExpression()!!, trace, TypeUtils.NO_EXPECTED_TYPE)
|
||||||
// TODO: consider inspecting `trace` to find diagnostics reported during the computation (such as division by zero, integer overflow, invalid annotation parameters etc.)
|
// TODO: consider inspecting `trace` to find diagnostics reported during the computation (such as division by zero, integer overflow, invalid annotation parameters etc.)
|
||||||
val argName = arg.getArgumentName()?.asName?.toString()
|
val argName = arg.getArgumentName()?.asName?.toString()
|
||||||
|
|||||||
+3
-3
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
|||||||
import org.jetbrains.kotlin.resolve.calls.tower.*
|
import org.jetbrains.kotlin.resolve.calls.tower.*
|
||||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstantChecker
|
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstantChecker
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
@@ -242,9 +242,9 @@ class DiagnosticReporterByTrackingStrategy(
|
|||||||
|
|
||||||
private fun reportConstantTypeMismatch(constraintError: NewConstraintError, expression: KtExpression): Boolean {
|
private fun reportConstantTypeMismatch(constraintError: NewConstraintError, expression: KtExpression): Boolean {
|
||||||
if (expression is KtConstantExpression) {
|
if (expression is KtConstantExpression) {
|
||||||
val builtIns = context.scope.ownerDescriptor.builtIns
|
val module = context.scope.ownerDescriptor.module
|
||||||
val constantValue = constantExpressionEvaluator.evaluateToConstantValue(expression, trace, context.expectedType)
|
val constantValue = constantExpressionEvaluator.evaluateToConstantValue(expression, trace, context.expectedType)
|
||||||
val hasConstantTypeError = CompileTimeConstantChecker(context, builtIns, true)
|
val hasConstantTypeError = CompileTimeConstantChecker(context, module, true)
|
||||||
.checkConstantExpressionType(constantValue, expression, constraintError.upperType)
|
.checkConstantExpressionType(constantValue, expression, constraintError.upperType)
|
||||||
if (hasConstantTypeError) return true
|
if (hasConstantTypeError) return true
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-9
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.KtNodeTypes;
|
import org.jetbrains.kotlin.KtNodeTypes;
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtilsKt;
|
import org.jetbrains.kotlin.diagnostics.DiagnosticUtilsKt;
|
||||||
@@ -42,20 +43,22 @@ public class CompileTimeConstantChecker {
|
|||||||
private static final Set<DiagnosticFactory<?>> errorsThatDependOnExpectedType =
|
private static final Set<DiagnosticFactory<?>> errorsThatDependOnExpectedType =
|
||||||
Sets.newHashSet(CONSTANT_EXPECTED_TYPE_MISMATCH, NULL_FOR_NONNULL_TYPE);
|
Sets.newHashSet(CONSTANT_EXPECTED_TYPE_MISMATCH, NULL_FOR_NONNULL_TYPE);
|
||||||
|
|
||||||
private final KotlinBuiltIns builtIns;
|
|
||||||
private final BindingTrace trace;
|
|
||||||
private final boolean checkOnlyErrorsThatDependOnExpectedType;
|
|
||||||
private final ResolutionContext<?> context;
|
private final ResolutionContext<?> context;
|
||||||
|
private final ModuleDescriptor module;
|
||||||
|
private final KotlinBuiltIns builtIns;
|
||||||
|
private final boolean checkOnlyErrorsThatDependOnExpectedType;
|
||||||
|
private final BindingTrace trace;
|
||||||
|
|
||||||
public CompileTimeConstantChecker(
|
public CompileTimeConstantChecker(
|
||||||
@NotNull ResolutionContext<?> context,
|
@NotNull ResolutionContext<?> context,
|
||||||
@NotNull KotlinBuiltIns builtIns,
|
@NotNull ModuleDescriptor module,
|
||||||
boolean checkOnlyErrorsThatDependOnExpectedType
|
boolean checkOnlyErrorsThatDependOnExpectedType
|
||||||
) {
|
) {
|
||||||
this.checkOnlyErrorsThatDependOnExpectedType = checkOnlyErrorsThatDependOnExpectedType;
|
|
||||||
this.builtIns = builtIns;
|
|
||||||
this.trace = context.trace;
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
this.module = module;
|
||||||
|
this.builtIns = module.getBuiltIns();
|
||||||
|
this.checkOnlyErrorsThatDependOnExpectedType = checkOnlyErrorsThatDependOnExpectedType;
|
||||||
|
this.trace = context.trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return true if there is an error
|
// return true if there is an error
|
||||||
@@ -98,7 +101,7 @@ public class CompileTimeConstantChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!noExpectedTypeOrError(expectedType)) {
|
if (!noExpectedTypeOrError(expectedType)) {
|
||||||
KotlinType valueType = value.getType();
|
KotlinType valueType = value.getType(module);
|
||||||
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) {
|
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) {
|
||||||
return reportConstantExpectedTypeMismatch(expression, "integer", expectedType, null);
|
return reportConstantExpectedTypeMismatch(expression, "integer", expectedType, null);
|
||||||
}
|
}
|
||||||
@@ -115,7 +118,7 @@ public class CompileTimeConstantChecker {
|
|||||||
return reportError(FLOAT_LITERAL_OUT_OF_RANGE.on(expression));
|
return reportError(FLOAT_LITERAL_OUT_OF_RANGE.on(expression));
|
||||||
}
|
}
|
||||||
if (!noExpectedTypeOrError(expectedType)) {
|
if (!noExpectedTypeOrError(expectedType)) {
|
||||||
KotlinType valueType = value.getType();
|
KotlinType valueType = value.getType(module);
|
||||||
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) {
|
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) {
|
||||||
return reportConstantExpectedTypeMismatch(expression, "floating-point", expectedType, null);
|
return reportConstantExpectedTypeMismatch(expression, "floating-point", expectedType, null);
|
||||||
}
|
}
|
||||||
|
|||||||
+41
-54
@@ -51,11 +51,9 @@ import java.math.BigInteger
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class ConstantExpressionEvaluator(
|
class ConstantExpressionEvaluator(
|
||||||
internal val builtIns: KotlinBuiltIns,
|
internal val module: ModuleDescriptor,
|
||||||
internal val languageVersionSettings: LanguageVersionSettings
|
internal val languageVersionSettings: LanguageVersionSettings
|
||||||
) {
|
) {
|
||||||
internal val constantValueFactory = ConstantValueFactory(builtIns)
|
|
||||||
|
|
||||||
fun updateNumberType(
|
fun updateNumberType(
|
||||||
numberType: KotlinType,
|
numberType: KotlinType,
|
||||||
expression: KtExpression?,
|
expression: KtExpression?,
|
||||||
@@ -106,7 +104,7 @@ class ConstantExpressionEvaluator(
|
|||||||
|
|
||||||
if (parameterDescriptor.declaresDefaultValue() && compileTimeConstants.isEmpty()) return null
|
if (parameterDescriptor.declaresDefaultValue() && compileTimeConstants.isEmpty()) return null
|
||||||
|
|
||||||
return constantValueFactory.createArrayValue(constants, parameterDescriptor.type)
|
return ConstantValueFactory.createArrayValue(constants, parameterDescriptor.type)
|
||||||
} else {
|
} else {
|
||||||
// we should actually get only one element, but just in case of getting many, we take the last one
|
// we should actually get only one element, but just in case of getting many, we take the last one
|
||||||
return constants.lastOrNull()
|
return constants.lastOrNull()
|
||||||
@@ -116,7 +114,7 @@ class ConstantExpressionEvaluator(
|
|||||||
private fun isArrayPassedInNamedForm(constants: List<ConstantValue<Any?>>, resolvedArgument: ResolvedValueArgument): Boolean {
|
private fun isArrayPassedInNamedForm(constants: List<ConstantValue<Any?>>, resolvedArgument: ResolvedValueArgument): Boolean {
|
||||||
val constant = constants.singleOrNull() ?: return false
|
val constant = constants.singleOrNull() ?: return false
|
||||||
val argument = resolvedArgument.arguments.singleOrNull() ?: return false
|
val argument = resolvedArgument.arguments.singleOrNull() ?: return false
|
||||||
return KotlinBuiltIns.isArrayOrPrimitiveArray(constant.type) && argument.isNamed()
|
return constant is ArrayValue && argument.isNamed()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkCompileTimeConstant(
|
private fun checkCompileTimeConstant(
|
||||||
@@ -205,7 +203,7 @@ class ConstantExpressionEvaluator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val returnType = resolvedCall.resultingDescriptor.returnType ?: return null
|
val returnType = resolvedCall.resultingDescriptor.returnType ?: return null
|
||||||
val componentType = builtIns.getArrayElementType(returnType)
|
val componentType = module.builtIns.getArrayElementType(returnType)
|
||||||
|
|
||||||
val result = arrayListOf<KtExpression>()
|
val result = arrayListOf<KtExpression>()
|
||||||
for ((_, resolvedValueArgument) in resolvedCall.valueArguments) {
|
for ((_, resolvedValueArgument) in resolvedCall.valueArguments) {
|
||||||
@@ -289,8 +287,7 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
private val constantExpressionEvaluator: ConstantExpressionEvaluator,
|
private val constantExpressionEvaluator: ConstantExpressionEvaluator,
|
||||||
private val trace: BindingTrace
|
private val trace: BindingTrace
|
||||||
) : KtVisitor<CompileTimeConstant<*>?, KotlinType>() {
|
) : KtVisitor<CompileTimeConstant<*>?, KotlinType>() {
|
||||||
|
private val builtIns = constantExpressionEvaluator.module.builtIns
|
||||||
private val factory = constantExpressionEvaluator.constantValueFactory
|
|
||||||
|
|
||||||
fun evaluate(expression: KtExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
fun evaluate(expression: KtExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
||||||
val recordedCompileTimeConstant = ConstantExpressionEvaluator.getPossiblyErrorConstant(expression, trace.bindingContext)
|
val recordedCompileTimeConstant = ConstantExpressionEvaluator.getPossiblyErrorConstant(expression, trace.bindingContext)
|
||||||
@@ -314,8 +311,8 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
}
|
}
|
||||||
return when (constantValue) {
|
return when (constantValue) {
|
||||||
is ErrorValue, is EnumValue -> return null
|
is ErrorValue, is EnumValue -> return null
|
||||||
is NullValue -> factory.createStringValue("null")
|
is NullValue -> ConstantValueFactory.createStringValue("null")
|
||||||
else -> factory.createStringValue(constantValue.value.toString())
|
else -> ConstantValueFactory.createStringValue(constantValue.value.toString())
|
||||||
}.wrap(compileTimeConstant.parameters)
|
}.wrap(compileTimeConstant.parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,23 +326,26 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
): TypedCompileTimeConstant<String>? {
|
): TypedCompileTimeConstant<String>? {
|
||||||
val expression = entry.expression ?: return null
|
val expression = entry.expression ?: return null
|
||||||
|
|
||||||
return evaluate(expression, constantExpressionEvaluator.builtIns.stringType)?.let {
|
return evaluate(expression, builtIns.stringType)?.let {
|
||||||
createStringConstant(it)
|
createStringConstant(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitLiteralStringTemplateEntry(entry: KtLiteralStringTemplateEntry, data: Nothing?) =
|
override fun visitLiteralStringTemplateEntry(
|
||||||
factory.createStringValue(entry.text).wrap()
|
entry: KtLiteralStringTemplateEntry,
|
||||||
|
data: Nothing?
|
||||||
|
): TypedCompileTimeConstant<String> =
|
||||||
|
ConstantValueFactory.createStringValue(entry.text).wrap()
|
||||||
|
|
||||||
override fun visitEscapeStringTemplateEntry(entry: KtEscapeStringTemplateEntry, data: Nothing?) =
|
override fun visitEscapeStringTemplateEntry(entry: KtEscapeStringTemplateEntry, data: Nothing?): TypedCompileTimeConstant<String> =
|
||||||
factory.createStringValue(entry.unescapedValue).wrap()
|
ConstantValueFactory.createStringValue(entry.unescapedValue).wrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitConstantExpression(expression: KtConstantExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
override fun visitConstantExpression(expression: KtConstantExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
||||||
val text = expression.text ?: return null
|
val text = expression.text ?: return null
|
||||||
|
|
||||||
val nodeElementType = expression.node.elementType
|
val nodeElementType = expression.node.elementType
|
||||||
if (nodeElementType == KtNodeTypes.NULL) return factory.createNullValue().wrap()
|
if (nodeElementType == KtNodeTypes.NULL) return ConstantValueFactory.createNullValue().wrap()
|
||||||
|
|
||||||
val result: Any? = when (nodeElementType) {
|
val result: Any? = when (nodeElementType) {
|
||||||
KtNodeTypes.INTEGER_CONSTANT, KtNodeTypes.FLOAT_CONSTANT -> parseNumericLiteral(text, nodeElementType)
|
KtNodeTypes.INTEGER_CONSTANT, KtNodeTypes.FLOAT_CONSTANT -> parseNumericLiteral(text, nodeElementType)
|
||||||
@@ -461,7 +461,7 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
|
|
||||||
val operationToken = expression.operationToken
|
val operationToken = expression.operationToken
|
||||||
if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationToken)) {
|
if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationToken)) {
|
||||||
val booleanType = constantExpressionEvaluator.builtIns.booleanType
|
val booleanType = builtIns.booleanType
|
||||||
val leftConstant = evaluate(leftExpression, booleanType) ?: return null
|
val leftConstant = evaluate(leftExpression, booleanType) ?: return null
|
||||||
|
|
||||||
val rightExpression = expression.right ?: return null
|
val rightExpression = expression.right ?: return null
|
||||||
@@ -545,7 +545,7 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
|
|
||||||
if ((isIntegerType(argumentForReceiver.value) && isIntegerType(argumentForParameter.value)) ||
|
if ((isIntegerType(argumentForReceiver.value) && isIntegerType(argumentForParameter.value)) ||
|
||||||
!constantExpressionEvaluator.languageVersionSettings.supportsFeature(LanguageFeature.DivisionByZeroInConstantExpressions)) {
|
!constantExpressionEvaluator.languageVersionSettings.supportsFeature(LanguageFeature.DivisionByZeroInConstantExpressions)) {
|
||||||
return factory.createErrorValue("Division by zero").wrap()
|
return ConstantValueFactory.createErrorValue("Division by zero").wrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,10 +563,8 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
val parameters =
|
val parameters =
|
||||||
CompileTimeConstant.Parameters(canBeUsedInAnnotation, areArgumentsPure, usesVariableAsConstant, usesNonConstValAsConstant)
|
CompileTimeConstant.Parameters(canBeUsedInAnnotation, areArgumentsPure, usesVariableAsConstant, usesNonConstValAsConstant)
|
||||||
return when (resultingDescriptorName) {
|
return when (resultingDescriptorName) {
|
||||||
OperatorNameConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression, factory)?.wrap(
|
OperatorNameConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression)?.wrap(parameters)
|
||||||
parameters
|
OperatorNameConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression)?.wrap(parameters)
|
||||||
)
|
|
||||||
OperatorNameConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression, factory)?.wrap(parameters)
|
|
||||||
else -> {
|
else -> {
|
||||||
createConstant(result, expectedType, parameters)
|
createConstant(result, expectedType, parameters)
|
||||||
}
|
}
|
||||||
@@ -664,7 +662,7 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
||||||
val enumDescriptor = trace.bindingContext.get(BindingContext.REFERENCE_TARGET, expression)
|
val enumDescriptor = trace.bindingContext.get(BindingContext.REFERENCE_TARGET, expression)
|
||||||
if (enumDescriptor != null && DescriptorUtils.isEnumEntry(enumDescriptor)) {
|
if (enumDescriptor != null && DescriptorUtils.isEnumEntry(enumDescriptor)) {
|
||||||
return factory.createEnumValue(enumDescriptor as ClassDescriptor).wrap()
|
return ConstantValueFactory.createEnumValue(enumDescriptor as ClassDescriptor).wrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
val resolvedCall = expression.getResolvedCall(trace.bindingContext)
|
val resolvedCall = expression.getResolvedCall(trace.bindingContext)
|
||||||
@@ -764,14 +762,14 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
call: ResolvedCall<*>
|
call: ResolvedCall<*>
|
||||||
): TypedCompileTimeConstant<List<ConstantValue<*>>>? {
|
): TypedCompileTimeConstant<List<ConstantValue<*>>>? {
|
||||||
val returnType = call.resultingDescriptor.returnType ?: return null
|
val returnType = call.resultingDescriptor.returnType ?: return null
|
||||||
val componentType = constantExpressionEvaluator.builtIns.getArrayElementType(returnType)
|
val componentType = builtIns.getArrayElementType(returnType)
|
||||||
|
|
||||||
val arguments = call.valueArguments.values.flatMap { resolveArguments(it.arguments, componentType) }
|
val arguments = call.valueArguments.values.flatMap { resolveArguments(it.arguments, componentType) }
|
||||||
|
|
||||||
// not evaluated arguments are not constants: function-calls, properties with custom getter...
|
// not evaluated arguments are not constants: function-calls, properties with custom getter...
|
||||||
val evaluatedArguments = arguments.filterNotNull()
|
val evaluatedArguments = arguments.filterNotNull()
|
||||||
|
|
||||||
return factory.createArrayValue(evaluatedArguments.map { it.toConstantValue(componentType) }, returnType)
|
return ConstantValueFactory.createArrayValue(evaluatedArguments.map { it.toConstantValue(componentType) }, returnType)
|
||||||
.wrap(
|
.wrap(
|
||||||
usesVariableAsConstant = evaluatedArguments.any { it.usesVariableAsConstant },
|
usesVariableAsConstant = evaluatedArguments.any { it.usesVariableAsConstant },
|
||||||
usesNonConstValAsConstant = arguments.any { it == null || it.usesNonConstValAsConstant }
|
usesNonConstValAsConstant = arguments.any { it == null || it.usesNonConstValAsConstant }
|
||||||
@@ -781,7 +779,7 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
override fun visitClassLiteralExpression(expression: KtClassLiteralExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
override fun visitClassLiteralExpression(expression: KtClassLiteralExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
||||||
val type = trace.getType(expression)!!
|
val type = trace.getType(expression)!!
|
||||||
if (type.isError) return null
|
if (type.isError) return null
|
||||||
return factory.createKClassValue(type).wrap()
|
return ConstantValueFactory.createKClassValue(type).wrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveArguments(valueArguments: List<ValueArgument>, expectedType: KotlinType): List<CompileTimeConstant<*>?> {
|
private fun resolveArguments(valueArguments: List<ValueArgument>, expectedType: KotlinType): List<CompileTimeConstant<*>?> {
|
||||||
@@ -823,10 +821,8 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
return createOperationArgument(argumentExpression, parameter.type, argumentCompileTimeType)
|
return createOperationArgument(argumentExpression, parameter.type, argumentCompileTimeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getCompileTimeType(c: KotlinType): CompileTimeType<out Any>? =
|
||||||
private fun getCompileTimeType(c: KotlinType): CompileTimeType<out Any>? {
|
when (TypeUtils.makeNotNullable(c)) {
|
||||||
val builtIns = constantExpressionEvaluator.builtIns
|
|
||||||
return when (TypeUtils.makeNotNullable(c)) {
|
|
||||||
builtIns.intType -> INT
|
builtIns.intType -> INT
|
||||||
builtIns.byteType -> BYTE
|
builtIns.byteType -> BYTE
|
||||||
builtIns.shortType -> SHORT
|
builtIns.shortType -> SHORT
|
||||||
@@ -839,7 +835,6 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
builtIns.anyType -> ANY
|
builtIns.anyType -> ANY
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun createOperationArgument(
|
private fun createOperationArgument(
|
||||||
expression: KtExpression,
|
expression: KtExpression,
|
||||||
@@ -860,7 +855,7 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
return if (parameters.isPure) {
|
return if (parameters.isPure) {
|
||||||
return createCompileTimeConstant(value, parameters, expectedType ?: TypeUtils.NO_EXPECTED_TYPE)
|
return createCompileTimeConstant(value, parameters, expectedType ?: TypeUtils.NO_EXPECTED_TYPE)
|
||||||
} else {
|
} else {
|
||||||
factory.createConstantValue(value)?.wrap(parameters)
|
ConstantValueFactory.createConstantValue(value)?.wrap(parameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -871,7 +866,7 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
): CompileTimeConstant<*>? {
|
): CompileTimeConstant<*>? {
|
||||||
return when (value) {
|
return when (value) {
|
||||||
is Byte, is Short, is Int, is Long -> createIntegerCompileTimeConstant((value as Number).toLong(), parameters, expectedType)
|
is Byte, is Short, is Int, is Long -> createIntegerCompileTimeConstant((value as Number).toLong(), parameters, expectedType)
|
||||||
else -> factory.createConstantValue(value)?.wrap(parameters)
|
else -> ConstantValueFactory.createConstantValue(value)?.wrap(parameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -881,20 +876,20 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
expectedType: KotlinType
|
expectedType: KotlinType
|
||||||
): CompileTimeConstant<*>? {
|
): CompileTimeConstant<*>? {
|
||||||
if (TypeUtils.noExpectedType(expectedType) || expectedType.isError) {
|
if (TypeUtils.noExpectedType(expectedType) || expectedType.isError) {
|
||||||
return IntegerValueTypeConstant(value, constantExpressionEvaluator.builtIns, parameters)
|
return IntegerValueTypeConstant(value, builtIns, parameters)
|
||||||
}
|
}
|
||||||
val integerValue = factory.createIntegerConstantValue(value, expectedType)
|
val integerValue = ConstantValueFactory.createIntegerConstantValue(value, expectedType)
|
||||||
if (integerValue != null) {
|
if (integerValue != null) {
|
||||||
return integerValue.wrap(parameters)
|
return integerValue.wrap(parameters)
|
||||||
}
|
}
|
||||||
return when (value) {
|
return when (value) {
|
||||||
value.toInt().toLong() -> factory.createIntValue(value.toInt())
|
value.toInt().toLong() -> ConstantValueFactory.createIntValue(value.toInt())
|
||||||
else -> factory.createLongValue(value)
|
else -> ConstantValueFactory.createLongValue(value)
|
||||||
}.wrap(parameters)
|
}.wrap(parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> ConstantValue<T>.wrap(parameters: CompileTimeConstant.Parameters): TypedCompileTimeConstant<T> =
|
private fun <T> ConstantValue<T>.wrap(parameters: CompileTimeConstant.Parameters): TypedCompileTimeConstant<T> =
|
||||||
TypedCompileTimeConstant(this, parameters)
|
TypedCompileTimeConstant(this, constantExpressionEvaluator.module, parameters)
|
||||||
|
|
||||||
private fun <T> ConstantValue<T>.wrap(
|
private fun <T> ConstantValue<T>.wrap(
|
||||||
canBeUsedInAnnotation: Boolean = this !is NullValue,
|
canBeUsedInAnnotation: Boolean = this !is NullValue,
|
||||||
@@ -962,11 +957,7 @@ private fun parseBoolean(text: String): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun createCompileTimeConstantForEquals(
|
private fun createCompileTimeConstantForEquals(result: Any?, operationReference: KtExpression): ConstantValue<*>? {
|
||||||
result: Any?,
|
|
||||||
operationReference: KtExpression,
|
|
||||||
factory: ConstantValueFactory
|
|
||||||
): ConstantValue<*>? {
|
|
||||||
if (result is Boolean) {
|
if (result is Boolean) {
|
||||||
assert(operationReference is KtSimpleNameExpression) { "This method should be called only for equals operations" }
|
assert(operationReference is KtSimpleNameExpression) { "This method should be called only for equals operations" }
|
||||||
val operationToken = (operationReference as KtSimpleNameExpression).getReferencedNameElementType()
|
val operationToken = (operationReference as KtSimpleNameExpression).getReferencedNameElementType()
|
||||||
@@ -979,27 +970,23 @@ private fun createCompileTimeConstantForEquals(
|
|||||||
}
|
}
|
||||||
else -> throw IllegalStateException("Unknown equals operation token: $operationToken ${operationReference.text}")
|
else -> throw IllegalStateException("Unknown equals operation token: $operationToken ${operationReference.text}")
|
||||||
}
|
}
|
||||||
return factory.createBooleanValue(value)
|
return ConstantValueFactory.createBooleanValue(value)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createCompileTimeConstantForCompareTo(
|
private fun createCompileTimeConstantForCompareTo(result: Any?, operationReference: KtExpression): ConstantValue<*>? {
|
||||||
result: Any?,
|
|
||||||
operationReference: KtExpression,
|
|
||||||
factory: ConstantValueFactory
|
|
||||||
): ConstantValue<*>? {
|
|
||||||
if (result is Int) {
|
if (result is Int) {
|
||||||
assert(operationReference is KtSimpleNameExpression) { "This method should be called only for compareTo operations" }
|
assert(operationReference is KtSimpleNameExpression) { "This method should be called only for compareTo operations" }
|
||||||
val operationToken = (operationReference as KtSimpleNameExpression).getReferencedNameElementType()
|
val operationToken = (operationReference as KtSimpleNameExpression).getReferencedNameElementType()
|
||||||
return when (operationToken) {
|
return when (operationToken) {
|
||||||
KtTokens.LT -> factory.createBooleanValue(result < 0)
|
KtTokens.LT -> ConstantValueFactory.createBooleanValue(result < 0)
|
||||||
KtTokens.LTEQ -> factory.createBooleanValue(result <= 0)
|
KtTokens.LTEQ -> ConstantValueFactory.createBooleanValue(result <= 0)
|
||||||
KtTokens.GT -> factory.createBooleanValue(result > 0)
|
KtTokens.GT -> ConstantValueFactory.createBooleanValue(result > 0)
|
||||||
KtTokens.GTEQ -> factory.createBooleanValue(result >= 0)
|
KtTokens.GTEQ -> ConstantValueFactory.createBooleanValue(result >= 0)
|
||||||
KtTokens.IDENTIFIER -> {
|
KtTokens.IDENTIFIER -> {
|
||||||
assert(operationReference.getReferencedNameAsName() == OperatorNameConventions.COMPARE_TO) { "This method should be called only for compareTo operations" }
|
assert(operationReference.getReferencedNameAsName() == OperatorNameConventions.COMPARE_TO) { "This method should be called only for compareTo operations" }
|
||||||
return factory.createIntValue(result)
|
return ConstantValueFactory.createIntValue(result)
|
||||||
}
|
}
|
||||||
else -> throw IllegalStateException("Unknown compareTo operation token: $operationToken")
|
else -> throw IllegalStateException("Unknown compareTo operation token: $operationToken")
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-3
@@ -208,13 +208,15 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!(compileTimeConstant instanceof IntegerValueTypeConstant)) {
|
if (!(compileTimeConstant instanceof IntegerValueTypeConstant)) {
|
||||||
CompileTimeConstantChecker constantChecker = new CompileTimeConstantChecker(context, components.builtIns, false);
|
CompileTimeConstantChecker constantChecker = new CompileTimeConstantChecker(context, components.moduleDescriptor, false);
|
||||||
ConstantValue constantValue =
|
ConstantValue constantValue =
|
||||||
compileTimeConstant != null ? ((TypedCompileTimeConstant) compileTimeConstant).getConstantValue() : null;
|
compileTimeConstant != null ? ((TypedCompileTimeConstant) compileTimeConstant).getConstantValue() : null;
|
||||||
boolean hasError = constantChecker.checkConstantExpressionType(constantValue, expression, context.expectedType);
|
boolean hasError = constantChecker.checkConstantExpressionType(constantValue, expression, context.expectedType);
|
||||||
if (hasError) {
|
if (hasError) {
|
||||||
return TypeInfoFactoryKt.createTypeInfo(constantValue != null ? constantValue.getType() : getDefaultType(elementType),
|
return TypeInfoFactoryKt.createTypeInfo(
|
||||||
context);
|
constantValue != null ? constantValue.getType(components.moduleDescriptor) : getDefaultType(elementType),
|
||||||
|
context
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,11 +53,10 @@ import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEP
|
|||||||
import static org.jetbrains.kotlin.types.TypeUtils.*;
|
import static org.jetbrains.kotlin.types.TypeUtils.*;
|
||||||
|
|
||||||
public class DataFlowAnalyzer {
|
public class DataFlowAnalyzer {
|
||||||
|
|
||||||
private final Iterable<AdditionalTypeChecker> additionalTypeCheckers;
|
private final Iterable<AdditionalTypeChecker> additionalTypeCheckers;
|
||||||
private final ConstantExpressionEvaluator constantExpressionEvaluator;
|
private final ConstantExpressionEvaluator constantExpressionEvaluator;
|
||||||
|
private final ModuleDescriptor module;
|
||||||
private final KotlinBuiltIns builtIns;
|
private final KotlinBuiltIns builtIns;
|
||||||
private final SmartCastManager smartCastManager;
|
|
||||||
private final ExpressionTypingFacade facade;
|
private final ExpressionTypingFacade facade;
|
||||||
private final LanguageVersionSettings languageVersionSettings;
|
private final LanguageVersionSettings languageVersionSettings;
|
||||||
private final EffectSystem effectSystem;
|
private final EffectSystem effectSystem;
|
||||||
@@ -65,16 +64,16 @@ public class DataFlowAnalyzer {
|
|||||||
public DataFlowAnalyzer(
|
public DataFlowAnalyzer(
|
||||||
@NotNull Iterable<AdditionalTypeChecker> additionalTypeCheckers,
|
@NotNull Iterable<AdditionalTypeChecker> additionalTypeCheckers,
|
||||||
@NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
|
@NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
|
||||||
|
@NotNull ModuleDescriptor module,
|
||||||
@NotNull KotlinBuiltIns builtIns,
|
@NotNull KotlinBuiltIns builtIns,
|
||||||
@NotNull SmartCastManager smartCastManager,
|
|
||||||
@NotNull ExpressionTypingFacade facade,
|
@NotNull ExpressionTypingFacade facade,
|
||||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||||
@NotNull EffectSystem effectSystem
|
@NotNull EffectSystem effectSystem
|
||||||
) {
|
) {
|
||||||
this.additionalTypeCheckers = additionalTypeCheckers;
|
this.additionalTypeCheckers = additionalTypeCheckers;
|
||||||
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
||||||
|
this.module = module;
|
||||||
this.builtIns = builtIns;
|
this.builtIns = builtIns;
|
||||||
this.smartCastManager = smartCastManager;
|
|
||||||
this.facade = facade;
|
this.facade = facade;
|
||||||
this.languageVersionSettings = languageVersionSettings;
|
this.languageVersionSettings = languageVersionSettings;
|
||||||
this.effectSystem = effectSystem;
|
this.effectSystem = effectSystem;
|
||||||
@@ -285,7 +284,7 @@ public class DataFlowAnalyzer {
|
|||||||
|
|
||||||
if (expression instanceof KtConstantExpression && reportErrorForTypeMismatch) {
|
if (expression instanceof KtConstantExpression && reportErrorForTypeMismatch) {
|
||||||
ConstantValue<?> constantValue = constantExpressionEvaluator.evaluateToConstantValue(expression, c.trace, c.expectedType);
|
ConstantValue<?> constantValue = constantExpressionEvaluator.evaluateToConstantValue(expression, c.trace, c.expectedType);
|
||||||
boolean error = new CompileTimeConstantChecker(c, builtIns, true)
|
boolean error = new CompileTimeConstantChecker(c, module, true)
|
||||||
.checkConstantExpressionType(constantValue, (KtConstantExpression) expression, c.expectedType);
|
.checkConstantExpressionType(constantValue, (KtConstantExpression) expression, c.expectedType);
|
||||||
hasError.set(error);
|
hasError.set(error);
|
||||||
return expressionType;
|
return expressionType;
|
||||||
|
|||||||
+7
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings;
|
|||||||
import org.jetbrains.kotlin.context.GlobalContext;
|
import org.jetbrains.kotlin.context.GlobalContext;
|
||||||
import org.jetbrains.kotlin.contracts.EffectSystem;
|
import org.jetbrains.kotlin.contracts.EffectSystem;
|
||||||
import org.jetbrains.kotlin.contracts.parsing.ContractParsingServices;
|
import org.jetbrains.kotlin.contracts.parsing.ContractParsingServices;
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||||
import org.jetbrains.kotlin.incremental.components.LookupTracker;
|
import org.jetbrains.kotlin.incremental.components.LookupTracker;
|
||||||
import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap;
|
import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap;
|
||||||
import org.jetbrains.kotlin.resolve.*;
|
import org.jetbrains.kotlin.resolve.*;
|
||||||
@@ -36,6 +37,7 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
public class ExpressionTypingComponents {
|
public class ExpressionTypingComponents {
|
||||||
/*package*/ GlobalContext globalContext;
|
/*package*/ GlobalContext globalContext;
|
||||||
|
/*package*/ ModuleDescriptor moduleDescriptor;
|
||||||
/*package*/ ExpressionTypingServices expressionTypingServices;
|
/*package*/ ExpressionTypingServices expressionTypingServices;
|
||||||
/*package*/ CallResolver callResolver;
|
/*package*/ CallResolver callResolver;
|
||||||
/*package*/ PlatformToKotlinClassMap platformToKotlinClassMap;
|
/*package*/ PlatformToKotlinClassMap platformToKotlinClassMap;
|
||||||
@@ -74,6 +76,11 @@ public class ExpressionTypingComponents {
|
|||||||
this.globalContext = globalContext;
|
this.globalContext = globalContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public void setModuleDescriptor(@NotNull ModuleDescriptor moduleDescriptor) {
|
||||||
|
this.moduleDescriptor = moduleDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
|
public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
|
||||||
this.expressionTypingServices = expressionTypingServices;
|
this.expressionTypingServices = expressionTypingServices;
|
||||||
|
|||||||
+2
-2
@@ -207,7 +207,7 @@ class StatementGenerator(
|
|||||||
|
|
||||||
fun generateConstantExpression(expression: KtExpression, constant: CompileTimeConstant<*>): IrExpression {
|
fun generateConstantExpression(expression: KtExpression, constant: CompileTimeConstant<*>): IrExpression {
|
||||||
val constantValue = constant.toConstantValue(getInferredTypeWithImplicitCastsOrFail(expression))
|
val constantValue = constant.toConstantValue(getInferredTypeWithImplicitCastsOrFail(expression))
|
||||||
val constantType = constantValue.type
|
val constantType = constantValue.getType(context.moduleDescriptor)
|
||||||
|
|
||||||
return when (constantValue) {
|
return when (constantValue) {
|
||||||
is StringValue ->
|
is StringValue ->
|
||||||
@@ -231,7 +231,7 @@ class StatementGenerator(
|
|||||||
is ShortValue ->
|
is ShortValue ->
|
||||||
IrConstImpl.short(expression.startOffset, expression.endOffset, constantType, constantValue.value)
|
IrConstImpl.short(expression.startOffset, expression.endOffset, constantType, constantValue.value)
|
||||||
else ->
|
else ->
|
||||||
TODO("handle other literal types: ${constantValue.type}")
|
TODO("handle other literal types: $constantType")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
|||||||
import org.jetbrains.kotlin.resolve.annotation.AbstractAnnotationDescriptorResolveTest
|
import org.jetbrains.kotlin.resolve.annotation.AbstractAnnotationDescriptorResolveTest
|
||||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
||||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -65,12 +65,11 @@ abstract class AbstractCompileTimeConstantEvaluatorTest : AbstractAnnotationDesc
|
|||||||
|
|
||||||
private fun evaluateInitializer(context: BindingContext, property: VariableDescriptor): CompileTimeConstant<*>? {
|
private fun evaluateInitializer(context: BindingContext, property: VariableDescriptor): CompileTimeConstant<*>? {
|
||||||
val propertyDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(property) as KtProperty
|
val propertyDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(property) as KtProperty
|
||||||
val compileTimeConstant = ConstantExpressionEvaluator(property.builtIns, LanguageVersionSettingsImpl.DEFAULT).evaluateExpression(
|
return ConstantExpressionEvaluator(property.module, LanguageVersionSettingsImpl.DEFAULT).evaluateExpression(
|
||||||
propertyDeclaration.initializer!!,
|
propertyDeclaration.initializer!!,
|
||||||
DelegatingBindingTrace(context, "trace for evaluating compile time constant"),
|
DelegatingBindingTrace(context, "trace for evaluating compile time constant"),
|
||||||
property.type
|
property.type
|
||||||
)
|
)
|
||||||
return compileTimeConstant
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doTest(path: String, getValueToTest: (VariableDescriptor, BindingContext) -> String) {
|
private fun doTest(path: String, getValueToTest: (VariableDescriptor, BindingContext) -> String) {
|
||||||
|
|||||||
+2
-3
@@ -114,8 +114,7 @@ class JavaDeprecatedAnnotationDescriptor(
|
|||||||
c: LazyJavaResolverContext
|
c: LazyJavaResolverContext
|
||||||
): JavaAnnotationDescriptor(c, annotation, KotlinBuiltIns.FQ_NAMES.deprecated) {
|
): JavaAnnotationDescriptor(c, annotation, KotlinBuiltIns.FQ_NAMES.deprecated) {
|
||||||
override val allValueArguments: Map<Name, ConstantValue<*>> by c.storageManager.createLazyValue {
|
override val allValueArguments: Map<Name, ConstantValue<*>> by c.storageManager.createLazyValue {
|
||||||
mapOf(JavaAnnotationMapper.DEPRECATED_ANNOTATION_MESSAGE to
|
mapOf(JavaAnnotationMapper.DEPRECATED_ANNOTATION_MESSAGE to ConstantValueFactory.createStringValue("Deprecated in Java"))
|
||||||
ConstantValueFactory(c.module.builtIns).createStringValue("Deprecated in Java"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +169,7 @@ object JavaAnnotationTargetMapper {
|
|||||||
JavaAnnotationMapper.TARGET_ANNOTATION_ALLOWED_TARGETS,
|
JavaAnnotationMapper.TARGET_ANNOTATION_ALLOWED_TARGETS,
|
||||||
builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.target)
|
builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.target)
|
||||||
)
|
)
|
||||||
return ArrayValue(kotlinTargets, parameterDescriptor?.type ?: ErrorUtils.createErrorType("Error: AnnotationTarget[]"), builtIns)
|
return ArrayValue(kotlinTargets) { parameterDescriptor?.type ?: ErrorUtils.createErrorType("Error: AnnotationTarget[]") }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val retentionNameList = mapOf(
|
private val retentionNameList = mapOf(
|
||||||
|
|||||||
+7
-9
@@ -57,8 +57,6 @@ class LazyJavaAnnotationDescriptor(
|
|||||||
|
|
||||||
override val source = c.components.sourceElementFactory.source(javaAnnotation)
|
override val source = c.components.sourceElementFactory.source(javaAnnotation)
|
||||||
|
|
||||||
private val factory = ConstantValueFactory(c.module.builtIns)
|
|
||||||
|
|
||||||
override val allValueArguments by c.storageManager.createLazyValue {
|
override val allValueArguments by c.storageManager.createLazyValue {
|
||||||
javaAnnotation.arguments.mapNotNull { arg ->
|
javaAnnotation.arguments.mapNotNull { arg ->
|
||||||
val name = arg.name ?: DEFAULT_ANNOTATION_MEMBER_NAME
|
val name = arg.name ?: DEFAULT_ANNOTATION_MEMBER_NAME
|
||||||
@@ -68,7 +66,7 @@ class LazyJavaAnnotationDescriptor(
|
|||||||
|
|
||||||
private fun resolveAnnotationArgument(argument: JavaAnnotationArgument?): ConstantValue<*>? {
|
private fun resolveAnnotationArgument(argument: JavaAnnotationArgument?): ConstantValue<*>? {
|
||||||
return when (argument) {
|
return when (argument) {
|
||||||
is JavaLiteralAnnotationArgument -> factory.createConstantValue(argument.value)
|
is JavaLiteralAnnotationArgument -> ConstantValueFactory.createConstantValue(argument.value)
|
||||||
is JavaEnumValueAnnotationArgument -> resolveFromEnumValue(argument.resolve(), argument.entryName)
|
is JavaEnumValueAnnotationArgument -> resolveFromEnumValue(argument.resolve(), argument.entryName)
|
||||||
is JavaArrayAnnotationArgument -> resolveFromArray(argument.name ?: DEFAULT_ANNOTATION_MEMBER_NAME, argument.getElements())
|
is JavaArrayAnnotationArgument -> resolveFromArray(argument.name ?: DEFAULT_ANNOTATION_MEMBER_NAME, argument.getElements())
|
||||||
is JavaAnnotationAsAnnotationArgument -> resolveFromAnnotation(argument.getAnnotation())
|
is JavaAnnotationAsAnnotationArgument -> resolveFromAnnotation(argument.getAnnotation())
|
||||||
@@ -78,7 +76,7 @@ class LazyJavaAnnotationDescriptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveFromAnnotation(javaAnnotation: JavaAnnotation): ConstantValue<*> {
|
private fun resolveFromAnnotation(javaAnnotation: JavaAnnotation): ConstantValue<*> {
|
||||||
return factory.createAnnotationValue(LazyJavaAnnotationDescriptor(c, javaAnnotation))
|
return ConstantValueFactory.createAnnotationValue(LazyJavaAnnotationDescriptor(c, javaAnnotation))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveFromArray(argumentName: Name, elements: List<JavaAnnotationArgument>): ConstantValue<*>? {
|
private fun resolveFromArray(argumentName: Name, elements: List<JavaAnnotationArgument>): ConstantValue<*>? {
|
||||||
@@ -93,16 +91,16 @@ class LazyJavaAnnotationDescriptor(
|
|||||||
)
|
)
|
||||||
|
|
||||||
val values = elements.map {
|
val values = elements.map {
|
||||||
argument -> resolveAnnotationArgument(argument) ?: factory.createNullValue()
|
argument -> resolveAnnotationArgument(argument) ?: ConstantValueFactory.createNullValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
return factory.createArrayValue(values, arrayType)
|
return ConstantValueFactory.createArrayValue(values, arrayType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveFromEnumValue(element: JavaField?, entryName: Name?): ConstantValue<*>? {
|
private fun resolveFromEnumValue(element: JavaField?, entryName: Name?): ConstantValue<*>? {
|
||||||
if (element == null || !element.isEnumEntry) {
|
if (element == null || !element.isEnumEntry) {
|
||||||
if (entryName == null) return null
|
if (entryName == null) return null
|
||||||
return factory.createEnumValue(ErrorUtils.createErrorClassWithExactName(entryName))
|
return ConstantValueFactory.createEnumValue(ErrorUtils.createErrorClassWithExactName(entryName))
|
||||||
}
|
}
|
||||||
|
|
||||||
val containingJavaClass = element.containingClass
|
val containingJavaClass = element.containingClass
|
||||||
@@ -112,7 +110,7 @@ class LazyJavaAnnotationDescriptor(
|
|||||||
val classifier = enumClass.unsubstitutedInnerClassesScope.getContributedClassifier(element.name, NoLookupLocation.FROM_JAVA_LOADER)
|
val classifier = enumClass.unsubstitutedInnerClassesScope.getContributedClassifier(element.name, NoLookupLocation.FROM_JAVA_LOADER)
|
||||||
as? ClassDescriptor ?: return null
|
as? ClassDescriptor ?: return null
|
||||||
|
|
||||||
return factory.createEnumValue(classifier)
|
return ConstantValueFactory.createEnumValue(classifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveFromJavaClassObjectType(javaType: JavaType): ConstantValue<*>? {
|
private fun resolveFromJavaClassObjectType(javaType: JavaType): ConstantValue<*>? {
|
||||||
@@ -128,7 +126,7 @@ class LazyJavaAnnotationDescriptor(
|
|||||||
|
|
||||||
val javaClassObjectType = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, jlClass, arguments)
|
val javaClassObjectType = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, jlClass, arguments)
|
||||||
|
|
||||||
return factory.createKClassValue(javaClassObjectType)
|
return ConstantValueFactory.createKClassValue(javaClassObjectType)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
|||||||
+6
-7
@@ -45,7 +45,6 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
|
|||||||
storageManager, kotlinClassFinder
|
storageManager, kotlinClassFinder
|
||||||
) {
|
) {
|
||||||
private val annotationDeserializer = AnnotationDeserializer(module, notFoundClasses)
|
private val annotationDeserializer = AnnotationDeserializer(module, notFoundClasses)
|
||||||
private val factory = ConstantValueFactory(module.builtIns)
|
|
||||||
|
|
||||||
override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationDescriptor =
|
override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationDescriptor =
|
||||||
annotationDeserializer.deserializeAnnotation(proto, nameResolver)
|
annotationDeserializer.deserializeAnnotation(proto, nameResolver)
|
||||||
@@ -65,7 +64,7 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
|
|||||||
initializer
|
initializer
|
||||||
}
|
}
|
||||||
|
|
||||||
return factory.createConstantValue(normalizedValue)
|
return ConstantValueFactory.createConstantValue(normalizedValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadPropertyAnnotations(
|
override fun loadPropertyAnnotations(
|
||||||
@@ -116,7 +115,7 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
|
|||||||
override fun visitEnd() {
|
override fun visitEnd() {
|
||||||
val parameter = DescriptorResolverUtils.getAnnotationParameterByName(name, annotationClass)
|
val parameter = DescriptorResolverUtils.getAnnotationParameterByName(name, annotationClass)
|
||||||
if (parameter != null) {
|
if (parameter != null) {
|
||||||
arguments[name] = factory.createArrayValue(elements.compact(), parameter.type)
|
arguments[name] = ConstantValueFactory.createArrayValue(elements.compact(), parameter.type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,10 +138,10 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
|
|||||||
if (enumClass.kind == ClassKind.ENUM_CLASS) {
|
if (enumClass.kind == ClassKind.ENUM_CLASS) {
|
||||||
val classifier = enumClass.unsubstitutedInnerClassesScope.getContributedClassifier(name, NoLookupLocation.FROM_JAVA_LOADER)
|
val classifier = enumClass.unsubstitutedInnerClassesScope.getContributedClassifier(name, NoLookupLocation.FROM_JAVA_LOADER)
|
||||||
if (classifier is ClassDescriptor) {
|
if (classifier is ClassDescriptor) {
|
||||||
return factory.createEnumValue(classifier)
|
return ConstantValueFactory.createEnumValue(classifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return factory.createErrorValue("Unresolved enum entry: $enumClassId.$name")
|
return ConstantValueFactory.createErrorValue("Unresolved enum entry: $enumClassId.$name")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitEnd() {
|
override fun visitEnd() {
|
||||||
@@ -150,8 +149,8 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createConstant(name: Name?, value: Any?): ConstantValue<*> {
|
private fun createConstant(name: Name?, value: Any?): ConstantValue<*> {
|
||||||
return factory.createConstantValue(value) ?:
|
return ConstantValueFactory.createConstantValue(value) ?:
|
||||||
factory.createErrorValue("Unsupported annotation argument: $name")
|
ConstantValueFactory.createErrorValue("Unsupported annotation argument: $name")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ fun getFunctionTypeArgumentProjections(
|
|||||||
val parameterNameAnnotation = BuiltInAnnotationDescriptor(
|
val parameterNameAnnotation = BuiltInAnnotationDescriptor(
|
||||||
builtIns,
|
builtIns,
|
||||||
KotlinBuiltIns.FQ_NAMES.parameterName,
|
KotlinBuiltIns.FQ_NAMES.parameterName,
|
||||||
mapOf(Name.identifier("name") to ConstantValueFactory(builtIns).createStringValue(name.asString()))
|
mapOf(Name.identifier("name") to ConstantValueFactory.createStringValue(name.asString()))
|
||||||
)
|
)
|
||||||
type.replaceAnnotations(AnnotationsImpl(type.annotations + parameterNameAnnotation))
|
type.replaceAnnotations(AnnotationsImpl(type.annotations + parameterNameAnnotation))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,8 +39,10 @@ fun KotlinBuiltIns.createDeprecatedAnnotation(
|
|||||||
this,
|
this,
|
||||||
KotlinBuiltIns.FQ_NAMES.replaceWith,
|
KotlinBuiltIns.FQ_NAMES.replaceWith,
|
||||||
mapOf(
|
mapOf(
|
||||||
REPLACE_WITH_EXPRESSION_NAME to StringValue(replaceWith, this),
|
REPLACE_WITH_EXPRESSION_NAME to StringValue(replaceWith),
|
||||||
REPLACE_WITH_IMPORTS_NAME to ArrayValue(emptyList(), getArrayType(Variance.INVARIANT, stringType), this)
|
REPLACE_WITH_IMPORTS_NAME to ArrayValue(emptyList()) { module ->
|
||||||
|
module.builtIns.getArrayType(Variance.INVARIANT, stringType)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -48,7 +50,7 @@ fun KotlinBuiltIns.createDeprecatedAnnotation(
|
|||||||
this,
|
this,
|
||||||
KotlinBuiltIns.FQ_NAMES.deprecated,
|
KotlinBuiltIns.FQ_NAMES.deprecated,
|
||||||
mapOf(
|
mapOf(
|
||||||
DEPRECATED_MESSAGE_NAME to StringValue(message, this),
|
DEPRECATED_MESSAGE_NAME to StringValue(message),
|
||||||
DEPRECATED_REPLACE_WITH_NAME to AnnotationValue(replaceWithAnnotation),
|
DEPRECATED_REPLACE_WITH_NAME to AnnotationValue(replaceWithAnnotation),
|
||||||
DEPRECATED_LEVEL_NAME to EnumValue(getDeprecationLevelEnumEntry(level) ?: error("Deprecation level $level not found"))
|
DEPRECATED_LEVEL_NAME to EnumValue(getDeprecationLevelEnumEntry(level) ?: error("Deprecation level $level not found"))
|
||||||
)
|
)
|
||||||
|
|||||||
+15
-18
@@ -17,8 +17,12 @@
|
|||||||
package org.jetbrains.kotlin.resolve.constants
|
package org.jetbrains.kotlin.resolve.constants
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
|
||||||
interface CompileTimeConstant<out T> {
|
interface CompileTimeConstant<out T> {
|
||||||
val isError: Boolean
|
val isError: Boolean
|
||||||
@@ -48,12 +52,13 @@ interface CompileTimeConstant<out T> {
|
|||||||
|
|
||||||
class TypedCompileTimeConstant<out T>(
|
class TypedCompileTimeConstant<out T>(
|
||||||
val constantValue: ConstantValue<T>,
|
val constantValue: ConstantValue<T>,
|
||||||
|
module: ModuleDescriptor,
|
||||||
override val parameters: CompileTimeConstant.Parameters
|
override val parameters: CompileTimeConstant.Parameters
|
||||||
) : CompileTimeConstant<T> {
|
) : CompileTimeConstant<T> {
|
||||||
override val isError: Boolean
|
override val isError: Boolean
|
||||||
get() = constantValue is ErrorValue
|
get() = constantValue is ErrorValue
|
||||||
|
|
||||||
val type: KotlinType = constantValue.type
|
val type: KotlinType = constantValue.getType(module)
|
||||||
|
|
||||||
override fun toConstantValue(expectedType: KotlinType): ConstantValue<T> = constantValue
|
override fun toConstantValue(expectedType: KotlinType): ConstantValue<T> = constantValue
|
||||||
|
|
||||||
@@ -75,32 +80,24 @@ class TypedCompileTimeConstant<out T>(
|
|||||||
|
|
||||||
class IntegerValueTypeConstant(
|
class IntegerValueTypeConstant(
|
||||||
private val value: Number,
|
private val value: Number,
|
||||||
private val builtIns: KotlinBuiltIns,
|
builtIns: KotlinBuiltIns,
|
||||||
override val parameters: CompileTimeConstant.Parameters
|
override val parameters: CompileTimeConstant.Parameters
|
||||||
) : CompileTimeConstant<Number> {
|
) : CompileTimeConstant<Number> {
|
||||||
private val typeConstructor = IntegerValueTypeConstructor(value.toLong(), builtIns)
|
private val typeConstructor = IntegerValueTypeConstructor(value.toLong(), builtIns)
|
||||||
|
|
||||||
override fun toConstantValue(expectedType: KotlinType): ConstantValue<Number> {
|
override fun toConstantValue(expectedType: KotlinType): ConstantValue<Number> {
|
||||||
val factory = ConstantValueFactory(builtIns)
|
|
||||||
val type = getType(expectedType)
|
val type = getType(expectedType)
|
||||||
return when {
|
return when {
|
||||||
KotlinBuiltIns.isInt(type) -> {
|
KotlinBuiltIns.isInt(type) -> ConstantValueFactory.createIntValue(value.toInt())
|
||||||
factory.createIntValue(value.toInt())
|
KotlinBuiltIns.isByte(type) -> ConstantValueFactory.createByteValue(value.toByte())
|
||||||
}
|
KotlinBuiltIns.isShort(type) -> ConstantValueFactory.createShortValue(value.toShort())
|
||||||
KotlinBuiltIns.isByte(type) -> {
|
else -> ConstantValueFactory.createLongValue(value.toLong())
|
||||||
factory.createByteValue(value.toByte())
|
|
||||||
}
|
|
||||||
KotlinBuiltIns.isShort(type) -> {
|
|
||||||
factory.createShortValue(value.toShort())
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
factory.createLongValue(value.toLong())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val unknownIntegerType = KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(Annotations.EMPTY, typeConstructor, emptyList<TypeProjection>(),
|
val unknownIntegerType = KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
|
||||||
false, ErrorUtils.createErrorScope("Scope for number value type (" + typeConstructor.toString() + ")", true)
|
Annotations.EMPTY, typeConstructor, emptyList(), false,
|
||||||
|
ErrorUtils.createErrorScope("Scope for number value type ($typeConstructor)", true)
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getType(expectedType: KotlinType): KotlinType = TypeUtils.getPrimitiveNumberType(typeConstructor, expectedType)
|
fun getType(expectedType: KotlinType): KotlinType = TypeUtils.getPrimitiveNumberType(typeConstructor, expectedType)
|
||||||
|
|||||||
+18
-20
@@ -19,41 +19,37 @@ package org.jetbrains.kotlin.resolve.constants
|
|||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
|
||||||
class ConstantValueFactory(
|
object ConstantValueFactory {
|
||||||
private val builtins: KotlinBuiltIns
|
fun createLongValue(value: Long) = LongValue(value)
|
||||||
) {
|
|
||||||
fun createLongValue(value: Long) = LongValue(value, builtins)
|
|
||||||
|
|
||||||
fun createIntValue(value: Int) = IntValue(value, builtins)
|
fun createIntValue(value: Int) = IntValue(value)
|
||||||
|
|
||||||
fun createErrorValue(message: String) = ErrorValue.create(message)
|
fun createErrorValue(message: String) = ErrorValue.create(message)
|
||||||
|
|
||||||
fun createShortValue(value: Short) = ShortValue(value, builtins)
|
fun createShortValue(value: Short) = ShortValue(value)
|
||||||
|
|
||||||
fun createByteValue(value: Byte) = ByteValue(value, builtins)
|
fun createByteValue(value: Byte) = ByteValue(value)
|
||||||
|
|
||||||
fun createDoubleValue(value: Double) = DoubleValue(value, builtins)
|
fun createDoubleValue(value: Double) = DoubleValue(value)
|
||||||
|
|
||||||
fun createFloatValue(value: Float) = FloatValue(value, builtins)
|
fun createFloatValue(value: Float) = FloatValue(value)
|
||||||
|
|
||||||
fun createBooleanValue(value: Boolean) = BooleanValue(value, builtins)
|
fun createBooleanValue(value: Boolean) = BooleanValue(value)
|
||||||
|
|
||||||
fun createCharValue(value: Char) = CharValue(value, builtins)
|
fun createCharValue(value: Char) = CharValue(value)
|
||||||
|
|
||||||
fun createStringValue(value: String) = StringValue(value, builtins)
|
fun createStringValue(value: String) = StringValue(value)
|
||||||
|
|
||||||
fun createNullValue() = NullValue(builtins)
|
fun createNullValue() = NullValue()
|
||||||
|
|
||||||
fun createEnumValue(enumEntryClass: ClassDescriptor): EnumValue = EnumValue(enumEntryClass)
|
fun createEnumValue(enumEntryClass: ClassDescriptor): EnumValue = EnumValue(enumEntryClass)
|
||||||
|
|
||||||
fun createArrayValue(
|
fun createArrayValue(value: List<ConstantValue<*>>, type: KotlinType) = createArrayValue(value) { type }
|
||||||
value: List<ConstantValue<*>>,
|
|
||||||
type: KotlinType
|
|
||||||
) = ArrayValue(value, type, builtins)
|
|
||||||
|
|
||||||
fun createAnnotationValue(value: AnnotationDescriptor) = AnnotationValue(value)
|
fun createAnnotationValue(value: AnnotationDescriptor) = AnnotationValue(value)
|
||||||
|
|
||||||
@@ -83,11 +79,14 @@ class ConstantValueFactory(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createArrayValue(value: List<ConstantValue<*>>, computeType: (ModuleDescriptor) -> KotlinType): ArrayValue =
|
||||||
|
ArrayValue(value, computeType)
|
||||||
|
|
||||||
private fun List<*>.arrayToList(): List<ConstantValue<*>> =
|
private fun List<*>.arrayToList(): List<ConstantValue<*>> =
|
||||||
this.toList().mapNotNull { createConstantValue(it) }
|
this.toList().mapNotNull { createConstantValue(it) }
|
||||||
|
|
||||||
private fun PrimitiveType.arrayType(): KotlinType =
|
private fun PrimitiveType.arrayType(): (ModuleDescriptor) -> KotlinType =
|
||||||
builtins.getPrimitiveArrayKotlinType(this)
|
{ module -> module.builtIns.getPrimitiveArrayKotlinType(this) }
|
||||||
|
|
||||||
fun createIntegerConstantValue(
|
fun createIntegerConstantValue(
|
||||||
value: Long,
|
value: Long,
|
||||||
@@ -104,4 +103,3 @@ class ConstantValueFactory(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,14 +18,19 @@ package org.jetbrains.kotlin.resolve.constants
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
abstract class ConstantValue<out T>(open val value: T) {
|
abstract class ConstantValue<out T>(open val value: T) {
|
||||||
abstract val type: KotlinType
|
abstract fun getType(module: ModuleDescriptor): KotlinType
|
||||||
|
|
||||||
abstract fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R
|
abstract fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R
|
||||||
|
|
||||||
@@ -36,8 +41,7 @@ abstract class IntegerValueConstant<out T> protected constructor(value: T) : Con
|
|||||||
|
|
||||||
class AnnotationValue(value: AnnotationDescriptor) : ConstantValue<AnnotationDescriptor>(value) {
|
class AnnotationValue(value: AnnotationDescriptor) : ConstantValue<AnnotationDescriptor>(value) {
|
||||||
|
|
||||||
override val type: KotlinType
|
override fun getType(module: ModuleDescriptor): KotlinType = value.type
|
||||||
get() = value.type
|
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitAnnotationValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitAnnotationValue(this, data)
|
||||||
override fun toString() = value.toString()
|
override fun toString() = value.toString()
|
||||||
@@ -45,12 +49,10 @@ class AnnotationValue(value: AnnotationDescriptor) : ConstantValue<AnnotationDes
|
|||||||
|
|
||||||
class ArrayValue(
|
class ArrayValue(
|
||||||
value: List<ConstantValue<*>>,
|
value: List<ConstantValue<*>>,
|
||||||
override val type: KotlinType,
|
private val computeType: (ModuleDescriptor) -> KotlinType
|
||||||
private val builtIns: KotlinBuiltIns
|
|
||||||
) : ConstantValue<List<ConstantValue<*>>>(value) {
|
) : ConstantValue<List<ConstantValue<*>>>(value) {
|
||||||
|
override fun getType(module: ModuleDescriptor): KotlinType = computeType(module).also { type ->
|
||||||
init {
|
assert(KotlinBuiltIns.isArray(type) || KotlinBuiltIns.isPrimitiveArray(type)) { "Type should be an array, but was $type: $value" }
|
||||||
assert(KotlinBuiltIns.isArray(type) || KotlinBuiltIns.isPrimitiveArray(type)) { "Type should be an array, but was " + type + ": " + value }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitArrayValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitArrayValue(this, data)
|
||||||
@@ -60,33 +62,20 @@ class ArrayValue(
|
|||||||
override fun hashCode() = value.hashCode()
|
override fun hashCode() = value.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
class BooleanValue(
|
class BooleanValue(value: Boolean) : ConstantValue<Boolean>(value) {
|
||||||
value: Boolean,
|
override fun getType(module: ModuleDescriptor) = module.builtIns.booleanType
|
||||||
builtIns: KotlinBuiltIns
|
|
||||||
) : ConstantValue<Boolean>(value) {
|
|
||||||
|
|
||||||
override val type = builtIns.booleanType
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitBooleanValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitBooleanValue(this, data)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ByteValue(
|
class ByteValue(value: Byte) : IntegerValueConstant<Byte>(value) {
|
||||||
value: Byte,
|
override fun getType(module: ModuleDescriptor) = module.builtIns.byteType
|
||||||
builtIns: KotlinBuiltIns
|
|
||||||
) : IntegerValueConstant<Byte>(value) {
|
|
||||||
|
|
||||||
override val type = builtIns.byteType
|
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitByteValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitByteValue(this, data)
|
||||||
override fun toString(): String = "$value.toByte()"
|
override fun toString(): String = "$value.toByte()"
|
||||||
}
|
}
|
||||||
|
|
||||||
class CharValue(
|
class CharValue(value: Char) : IntegerValueConstant<Char>(value) {
|
||||||
value: Char,
|
override fun getType(module: ModuleDescriptor) = module.builtIns.charType
|
||||||
builtIns: KotlinBuiltIns
|
|
||||||
) : IntegerValueConstant<Char>(value) {
|
|
||||||
|
|
||||||
override val type = builtIns.charType
|
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitCharValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitCharValue(this, data)
|
||||||
|
|
||||||
@@ -96,7 +85,7 @@ class CharValue(
|
|||||||
'\b' -> "\\b"
|
'\b' -> "\\b"
|
||||||
'\t' -> "\\t"
|
'\t' -> "\\t"
|
||||||
'\n' -> "\\n"
|
'\n' -> "\\n"
|
||||||
//TODO: KT-8507
|
//TODO: KT-8507
|
||||||
12.toChar() -> "\\f"
|
12.toChar() -> "\\f"
|
||||||
'\r' -> "\\r"
|
'\r' -> "\\r"
|
||||||
else -> if (isPrintableUnicode(c)) Character.toString(c) else "?"
|
else -> if (isPrintableUnicode(c)) Character.toString(c) else "?"
|
||||||
@@ -114,27 +103,26 @@ class CharValue(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DoubleValue(
|
class DoubleValue(value: Double) : ConstantValue<Double>(value) {
|
||||||
value: Double,
|
override fun getType(module: ModuleDescriptor) = module.builtIns.doubleType
|
||||||
builtIns: KotlinBuiltIns
|
|
||||||
) : ConstantValue<Double>(value) {
|
|
||||||
override val type = builtIns.doubleType
|
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitDoubleValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitDoubleValue(this, data)
|
||||||
|
|
||||||
override fun toString() = "$value.toDouble()"
|
override fun toString() = "$value.toDouble()"
|
||||||
}
|
}
|
||||||
|
|
||||||
class EnumValue(
|
class EnumValue(value: ClassDescriptor) : ConstantValue<ClassDescriptor>(value) {
|
||||||
value: ClassDescriptor
|
val enumClassId: ClassId get() = (value.containingDeclaration as ClassDescriptor).classId!!
|
||||||
) : ConstantValue<ClassDescriptor>(value) {
|
|
||||||
|
|
||||||
override val type: KotlinType
|
val enumEntryName: Name get() = value.name
|
||||||
get() = value.classValueType ?: ErrorUtils.createErrorType("Containing class for error-class based enum entry $value")
|
|
||||||
|
override fun getType(module: ModuleDescriptor): KotlinType =
|
||||||
|
value.classValueType
|
||||||
|
?: ErrorUtils.createErrorType("Containing class for error-class based enum entry ${value.fqNameUnsafe}")
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitEnumValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitEnumValue(this, data)
|
||||||
|
|
||||||
override fun toString() = "$type.${value.name}"
|
override fun toString() = "${enumClassId.shortClassName}.$enumEntryName"
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean = this === other || value == (other as? EnumValue)?.value
|
override fun equals(other: Any?): Boolean = this === other || value == (other as? EnumValue)?.value
|
||||||
|
|
||||||
@@ -151,7 +139,7 @@ abstract class ErrorValue : ConstantValue<Unit>(Unit) {
|
|||||||
|
|
||||||
class ErrorValueWithMessage(val message: String) : ErrorValue() {
|
class ErrorValueWithMessage(val message: String) : ErrorValue() {
|
||||||
|
|
||||||
override val type = ErrorUtils.createErrorType(message)
|
override fun getType(module: ModuleDescriptor) = ErrorUtils.createErrorType(message)
|
||||||
|
|
||||||
override fun toString() = message
|
override fun toString() = message
|
||||||
}
|
}
|
||||||
@@ -163,23 +151,16 @@ abstract class ErrorValue : ConstantValue<Unit>(Unit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FloatValue(
|
class FloatValue(value: Float) : ConstantValue<Float>(value) {
|
||||||
value: Float,
|
override fun getType(module: ModuleDescriptor) = module.builtIns.floatType
|
||||||
builtIns: KotlinBuiltIns
|
|
||||||
) : ConstantValue<Float>(value) {
|
|
||||||
override val type = builtIns.floatType
|
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitFloatValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitFloatValue(this, data)
|
||||||
|
|
||||||
override fun toString() = "$value.toFloat()"
|
override fun toString() = "$value.toFloat()"
|
||||||
}
|
}
|
||||||
|
|
||||||
class IntValue(
|
class IntValue(value: Int) : IntegerValueConstant<Int>(value) {
|
||||||
value: Int,
|
override fun getType(module: ModuleDescriptor) = module.builtIns.intType
|
||||||
builtIns: KotlinBuiltIns
|
|
||||||
) : IntegerValueConstant<Int>(value) {
|
|
||||||
|
|
||||||
override val type = builtIns.intType
|
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitIntValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitIntValue(this, data)
|
||||||
|
|
||||||
@@ -188,54 +169,41 @@ class IntValue(
|
|||||||
override fun hashCode() = value
|
override fun hashCode() = value
|
||||||
}
|
}
|
||||||
|
|
||||||
class KClassValue(override val type: KotlinType) :
|
class KClassValue(private val type: KotlinType) : ConstantValue<KotlinType>(type) {
|
||||||
ConstantValue<KotlinType>(type) {
|
override fun getType(module: ModuleDescriptor): KotlinType = type
|
||||||
|
|
||||||
override val value: KotlinType
|
override val value: KotlinType
|
||||||
get() = type.arguments.single().type
|
get() = type.arguments.single().type
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitKClassValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitKClassValue(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
class LongValue(
|
class LongValue(value: Long) : IntegerValueConstant<Long>(value) {
|
||||||
value: Long,
|
override fun getType(module: ModuleDescriptor) = module.builtIns.longType
|
||||||
builtIns: KotlinBuiltIns
|
|
||||||
) : IntegerValueConstant<Long>(value) {
|
|
||||||
|
|
||||||
override val type = builtIns.longType
|
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitLongValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitLongValue(this, data)
|
||||||
|
|
||||||
override fun toString() = "$value.toLong()"
|
override fun toString() = "$value.toLong()"
|
||||||
}
|
}
|
||||||
|
|
||||||
class NullValue(
|
class NullValue : ConstantValue<Void?>(null) {
|
||||||
builtIns: KotlinBuiltIns
|
override fun getType(module: ModuleDescriptor) = module.builtIns.nullableNothingType
|
||||||
) : ConstantValue<Void?>(null) {
|
|
||||||
|
|
||||||
override val type = builtIns.nullableNothingType
|
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitNullValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitNullValue(this, data)
|
||||||
|
|
||||||
override fun toString() = "null"
|
override fun toString() = "null"
|
||||||
}
|
}
|
||||||
|
|
||||||
class ShortValue(
|
class ShortValue(value: Short) : IntegerValueConstant<Short>(value) {
|
||||||
value: Short,
|
override fun getType(module: ModuleDescriptor) = module.builtIns.shortType
|
||||||
builtIns: KotlinBuiltIns
|
|
||||||
) : IntegerValueConstant<Short>(value) {
|
|
||||||
|
|
||||||
override val type = builtIns.shortType
|
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitShortValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitShortValue(this, data)
|
||||||
|
|
||||||
override fun toString() = "$value.toShort()"
|
override fun toString() = "$value.toShort()"
|
||||||
}
|
}
|
||||||
|
|
||||||
class StringValue(
|
class StringValue(value: String) : ConstantValue<String>(value) {
|
||||||
value: String,
|
override fun getType(module: ModuleDescriptor) = module.builtIns.stringType
|
||||||
builtIns: KotlinBuiltIns
|
|
||||||
) : ConstantValue<String>(value) {
|
|
||||||
override val type = builtIns.stringType
|
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitStringValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitStringValue(this, data)
|
||||||
|
|
||||||
|
|||||||
+15
-17
@@ -40,8 +40,6 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
|
|||||||
private val builtIns: KotlinBuiltIns
|
private val builtIns: KotlinBuiltIns
|
||||||
get() = module.builtIns
|
get() = module.builtIns
|
||||||
|
|
||||||
private val factory = ConstantValueFactory(builtIns)
|
|
||||||
|
|
||||||
fun deserializeAnnotation(proto: Annotation, nameResolver: NameResolver): AnnotationDescriptor {
|
fun deserializeAnnotation(proto: Annotation, nameResolver: NameResolver): AnnotationDescriptor {
|
||||||
val annotationClass = resolveClass(nameResolver.getClassId(proto.id))
|
val annotationClass = resolveClass(nameResolver.getClassId(proto.id))
|
||||||
|
|
||||||
@@ -72,16 +70,16 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
|
|||||||
nameResolver: NameResolver
|
nameResolver: NameResolver
|
||||||
): ConstantValue<*> {
|
): ConstantValue<*> {
|
||||||
val result: ConstantValue<*> = when (value.type) {
|
val result: ConstantValue<*> = when (value.type) {
|
||||||
Type.BYTE -> factory.createByteValue(value.intValue.toByte())
|
Type.BYTE -> ConstantValueFactory.createByteValue(value.intValue.toByte())
|
||||||
Type.CHAR -> factory.createCharValue(value.intValue.toChar())
|
Type.CHAR -> ConstantValueFactory.createCharValue(value.intValue.toChar())
|
||||||
Type.SHORT -> factory.createShortValue(value.intValue.toShort())
|
Type.SHORT -> ConstantValueFactory.createShortValue(value.intValue.toShort())
|
||||||
Type.INT -> factory.createIntValue(value.intValue.toInt())
|
Type.INT -> ConstantValueFactory.createIntValue(value.intValue.toInt())
|
||||||
Type.LONG -> factory.createLongValue(value.intValue)
|
Type.LONG -> ConstantValueFactory.createLongValue(value.intValue)
|
||||||
Type.FLOAT -> factory.createFloatValue(value.floatValue)
|
Type.FLOAT -> ConstantValueFactory.createFloatValue(value.floatValue)
|
||||||
Type.DOUBLE -> factory.createDoubleValue(value.doubleValue)
|
Type.DOUBLE -> ConstantValueFactory.createDoubleValue(value.doubleValue)
|
||||||
Type.BOOLEAN -> factory.createBooleanValue(value.intValue != 0L)
|
Type.BOOLEAN -> ConstantValueFactory.createBooleanValue(value.intValue != 0L)
|
||||||
Type.STRING -> {
|
Type.STRING -> {
|
||||||
factory.createStringValue(nameResolver.getString(value.stringValue))
|
ConstantValueFactory.createStringValue(nameResolver.getString(value.stringValue))
|
||||||
}
|
}
|
||||||
Type.CLASS -> {
|
Type.CLASS -> {
|
||||||
resolveClassLiteralValue(nameResolver.getClassId(value.classId))
|
resolveClassLiteralValue(nameResolver.getClassId(value.classId))
|
||||||
@@ -111,7 +109,7 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
|
|||||||
|
|
||||||
val expectedElementType = builtIns.getArrayElementType(if (expectedIsArray) expectedType else actualArrayType)
|
val expectedElementType = builtIns.getArrayElementType(if (expectedIsArray) expectedType else actualArrayType)
|
||||||
|
|
||||||
factory.createArrayValue(
|
ConstantValueFactory.createArrayValue(
|
||||||
arrayElements.map {
|
arrayElements.map {
|
||||||
resolveValue(expectedElementType, it, nameResolver)
|
resolveValue(expectedElementType, it, nameResolver)
|
||||||
},
|
},
|
||||||
@@ -121,12 +119,12 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
|
|||||||
else -> error("Unsupported annotation argument type: ${value.type} (expected $expectedType)")
|
else -> error("Unsupported annotation argument type: ${value.type} (expected $expectedType)")
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (result.type.isSubtypeOf(expectedType)) {
|
return if (result.getType(module).isSubtypeOf(expectedType)) {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// This means that an annotation class has been changed incompatibly without recompiling clients
|
// This means that an annotation class has been changed incompatibly without recompiling clients
|
||||||
factory.createErrorValue("Unexpected argument value")
|
ConstantValueFactory.createErrorValue("Unexpected argument value")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +134,7 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
|
|||||||
val starProjectedType = resolveClass(classId).defaultType.replaceArgumentsWithStarProjections()
|
val starProjectedType = resolveClass(classId).defaultType.replaceArgumentsWithStarProjections()
|
||||||
val kClass = resolveClass(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.kClass.toSafe()))
|
val kClass = resolveClass(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.kClass.toSafe()))
|
||||||
val type = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, kClass, listOf(TypeProjectionImpl(starProjectedType)))
|
val type = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, kClass, listOf(TypeProjectionImpl(starProjectedType)))
|
||||||
return factory.createKClassValue(type)
|
return ConstantValueFactory.createKClassValue(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: see analogous code in BinaryClassAnnotationAndConstantLoaderImpl
|
// NOTE: see analogous code in BinaryClassAnnotationAndConstantLoaderImpl
|
||||||
@@ -145,10 +143,10 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
|
|||||||
if (enumClass.kind == ClassKind.ENUM_CLASS) {
|
if (enumClass.kind == ClassKind.ENUM_CLASS) {
|
||||||
val enumEntry = enumClass.unsubstitutedInnerClassesScope.getContributedClassifier(enumEntryName, NoLookupLocation.FROM_DESERIALIZATION)
|
val enumEntry = enumClass.unsubstitutedInnerClassesScope.getContributedClassifier(enumEntryName, NoLookupLocation.FROM_DESERIALIZATION)
|
||||||
if (enumEntry is ClassDescriptor) {
|
if (enumEntry is ClassDescriptor) {
|
||||||
return factory.createEnumValue(enumEntry)
|
return ConstantValueFactory.createEnumValue(enumEntry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return factory.createErrorValue("Unresolved enum entry: $enumClassId.$enumEntryName")
|
return ConstantValueFactory.createErrorValue("Unresolved enum entry: $enumClassId.$enumEntryName")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveArrayElementType(value: Value, nameResolver: NameResolver): SimpleType =
|
private fun resolveArrayElementType(value: Value, nameResolver: NameResolver): SimpleType =
|
||||||
|
|||||||
+4
-4
@@ -43,8 +43,8 @@ class ExtractableSubstringInfo(
|
|||||||
) {
|
) {
|
||||||
private fun guessLiteralType(literal: String): KotlinType {
|
private fun guessLiteralType(literal: String): KotlinType {
|
||||||
val facade = template.getResolutionFacade()
|
val facade = template.getResolutionFacade()
|
||||||
val builtIns = facade.moduleDescriptor.builtIns
|
val module = facade.moduleDescriptor
|
||||||
val stringType = builtIns.stringType
|
val stringType = module.builtIns.stringType
|
||||||
|
|
||||||
if (startEntry != endEntry || startEntry !is KtLiteralStringTemplateEntry) return stringType
|
if (startEntry != endEntry || startEntry !is KtLiteralStringTemplateEntry) return stringType
|
||||||
|
|
||||||
@@ -56,10 +56,10 @@ class ExtractableSubstringInfo(
|
|||||||
val tempContext = expr.analyzeInContext(scope, template)
|
val tempContext = expr.analyzeInContext(scope, template)
|
||||||
val trace = DelegatingBindingTrace(tempContext, "Evaluate '$literal'")
|
val trace = DelegatingBindingTrace(tempContext, "Evaluate '$literal'")
|
||||||
val languageVersionSettings = facade.getFrontendService(LanguageVersionSettings::class.java)
|
val languageVersionSettings = facade.getFrontendService(LanguageVersionSettings::class.java)
|
||||||
val value = ConstantExpressionEvaluator(builtIns, languageVersionSettings).evaluateExpression(expr, trace)
|
val value = ConstantExpressionEvaluator(module, languageVersionSettings).evaluateExpression(expr, trace)
|
||||||
if (value == null || value.isError) return stringType
|
if (value == null || value.isError) return stringType
|
||||||
|
|
||||||
return value.toConstantValue(TypeUtils.NO_EXPECTED_TYPE).type
|
return value.toConstantValue(TypeUtils.NO_EXPECTED_TYPE).getType(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
val template: KtStringTemplateExpression = startEntry.parent as KtStringTemplateExpression
|
val template: KtStringTemplateExpression = startEntry.parent as KtStringTemplateExpression
|
||||||
|
|||||||
@@ -54,8 +54,9 @@ class KotlinLightConstantExpressionEvaluator : ConstantExpressionEvaluator {
|
|||||||
return when (expressionToCompute) {
|
return when (expressionToCompute) {
|
||||||
is KtExpression -> {
|
is KtExpression -> {
|
||||||
val resolutionFacade = expressionToCompute.getResolutionFacade()
|
val resolutionFacade = expressionToCompute.getResolutionFacade()
|
||||||
val evaluator = FrontendConstantExpressionEvaluator(resolutionFacade.moduleDescriptor.builtIns,
|
val evaluator = FrontendConstantExpressionEvaluator(
|
||||||
expressionToCompute.languageVersionSettings)
|
resolutionFacade.moduleDescriptor, expressionToCompute.languageVersionSettings
|
||||||
|
)
|
||||||
val evaluatorTrace = DelegatingBindingTrace(resolutionFacade.analyze(expressionToCompute), "Evaluating annotation argument")
|
val evaluatorTrace = DelegatingBindingTrace(resolutionFacade.analyze(expressionToCompute), "Evaluating annotation argument")
|
||||||
|
|
||||||
val constant = evaluator.evaluateExpression(expressionToCompute, evaluatorTrace) ?: return null
|
val constant = evaluator.evaluateExpression(expressionToCompute, evaluatorTrace) ?: return null
|
||||||
|
|||||||
Reference in New Issue
Block a user