Cleanup ConstantExpressionEvaluator

This commit is contained in:
Dmitriy Novozhilov
2021-04-08 10:30:02 +03:00
committed by TeamCityServer
parent bee2a69e21
commit 1cff17bb58
@@ -83,7 +83,7 @@ class ConstantExpressionEvaluator(
for ((parameterDescriptor, resolvedArgument) in resolvedCall.valueArguments.entries) { for ((parameterDescriptor, resolvedArgument) in resolvedCall.valueArguments.entries) {
val value = getAnnotationArgumentValue(trace, parameterDescriptor, resolvedArgument) val value = getAnnotationArgumentValue(trace, parameterDescriptor, resolvedArgument)
if (value != null) { if (value != null) {
arguments.put(parameterDescriptor.name, value) arguments[parameterDescriptor.name] = value
} }
} }
return arguments return arguments
@@ -125,7 +125,7 @@ class ConstantExpressionEvaluator(
trace: BindingTrace, trace: BindingTrace,
useDeprecationWarning: Boolean useDeprecationWarning: Boolean
) { ) {
val constant = ConstantExpressionEvaluator.getConstant(argumentExpression, trace.bindingContext) val constant = getConstant(argumentExpression, trace.bindingContext)
if (constant != null && constant.canBeUsedInAnnotations) { if (constant != null && constant.canBeUsedInAnnotations) {
checkInnerPartsOfCompileTimeConstant(constant, trace, argumentExpression, useDeprecationWarning) checkInnerPartsOfCompileTimeConstant(constant, trace, argumentExpression, useDeprecationWarning)
return return
@@ -375,7 +375,8 @@ private class ConstantExpressionEvaluatorVisitor(
) : KtVisitor<CompileTimeConstant<*>?, KotlinType>() { ) : KtVisitor<CompileTimeConstant<*>?, KotlinType>() {
private val languageVersionSettings = constantExpressionEvaluator.languageVersionSettings private val languageVersionSettings = constantExpressionEvaluator.languageVersionSettings
private val builtIns = constantExpressionEvaluator.module.builtIns private val builtIns = constantExpressionEvaluator.module.builtIns
private val defaultValueForDontCreateIntegerLiteralType = languageVersionSettings.supportsFeature(LanguageFeature.ApproximateIntegerLiteralTypesInReceiverPosition) private val defaultValueForDontCreateIntegerLiteralType =
languageVersionSettings.supportsFeature(LanguageFeature.ApproximateIntegerLiteralTypesInReceiverPosition)
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)
@@ -404,6 +405,7 @@ private class ConstantExpressionEvaluatorVisitor(
}.wrap(compileTimeConstant.parameters) }.wrap(compileTimeConstant.parameters)
} }
@Suppress("RedundantNullableReturnType")
fun evaluate(entry: KtStringTemplateEntry): TypedCompileTimeConstant<String>? { fun evaluate(entry: KtStringTemplateEntry): TypedCompileTimeConstant<String>? {
return entry.accept(this, null) return entry.accept(this, null)
} }
@@ -435,11 +437,11 @@ private class ConstantExpressionEvaluatorVisitor(
val nodeElementType = expression.node.elementType val nodeElementType = expression.node.elementType
if (nodeElementType == KtNodeTypes.NULL) return NullValue().wrap() if (nodeElementType == KtNodeTypes.NULL) return NullValue().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)
KtNodeTypes.BOOLEAN_CONSTANT -> parseBoolean(text) KtNodeTypes.BOOLEAN_CONSTANT -> parseBoolean(text)
KtNodeTypes.CHARACTER_CONSTANT -> CompileTimeConstantChecker.parseChar(expression) KtNodeTypes.CHARACTER_CONSTANT -> CompileTimeConstantChecker.parseChar(expression)
else -> throw IllegalArgumentException("Unsupported constant: " + expression) else -> throw IllegalArgumentException("Unsupported constant: $expression")
} ?: return null } ?: return null
if (result is Double) { if (result is Double) {
@@ -633,6 +635,7 @@ private class ConstantExpressionEvaluatorVisitor(
val usesVariableAsConstant = usesVariableAsConstant(argumentForReceiver.expression) val usesVariableAsConstant = usesVariableAsConstant(argumentForReceiver.expression)
val usesNonConstValAsConstant = usesNonConstValAsConstant(argumentForReceiver.expression) val usesNonConstValAsConstant = usesNonConstValAsConstant(argumentForReceiver.expression)
val isNumberConversionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS val isNumberConversionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS
val dontCreateILT = !isUnaryPlusMinus && !hasIntegerLiteralType(receiverExpression)
return createConstant( return createConstant(
result, result,
expectedType, expectedType,
@@ -644,7 +647,7 @@ private class ConstantExpressionEvaluatorVisitor(
usesVariableAsConstant, usesVariableAsConstant,
usesNonConstValAsConstant, usesNonConstValAsConstant,
isConvertableConstVal = false, isConvertableConstVal = false,
dontCreateILT = !isUnaryPlusMinus && defaultValueForDontCreateIntegerLiteralType && !hasIntegerLiteralType(receiverExpression) dontCreateILT = defaultValueForDontCreateIntegerLiteralType && dontCreateILT
) )
) )
} else if (argumentsEntrySet.size == 1) { } else if (argumentsEntrySet.size == 1) {
@@ -665,9 +668,12 @@ private class ConstantExpressionEvaluatorVisitor(
} }
} }
val result = val result = evaluateBinaryAndCheck(
evaluateBinaryAndCheck(argumentForReceiver, argumentForParameter, resultingDescriptorName.asString(), callExpression) argumentForReceiver,
?: return null argumentForParameter,
resultingDescriptorName.asString(),
callExpression
) ?: return null
val areArgumentsPure = isPureConstant(argumentForReceiver.expression) && isPureConstant(argumentForParameter.expression) val areArgumentsPure = isPureConstant(argumentForReceiver.expression) && isPureConstant(argumentForParameter.expression)
val canBeUsedInAnnotation = val canBeUsedInAnnotation =
@@ -715,7 +721,7 @@ private class ConstantExpressionEvaluatorVisitor(
private fun evaluateUnaryAndCheck(receiver: OperationArgument, name: String, callExpression: KtExpression): Any? { private fun evaluateUnaryAndCheck(receiver: OperationArgument, name: String, callExpression: KtExpression): Any? {
return evaluateUnaryAndCheck(name, receiver.ctcType, receiver.value) { return evaluateUnaryAndCheck(name, receiver.ctcType, receiver.value) {
trace.report(Errors.INTEGER_OVERFLOW.on(callExpression.getStrictParentOfType<KtExpression>() ?: callExpression)) trace.report(Errors.INTEGER_OVERFLOW.on(callExpression.getStrictParentOfType() ?: callExpression))
} }
} }
@@ -726,7 +732,7 @@ private class ConstantExpressionEvaluatorVisitor(
callExpression: KtExpression callExpression: KtExpression
): Any? { ): Any? {
return evaluateBinaryAndCheck(name, receiver.ctcType, receiver.value, parameter.ctcType, parameter.value) { return evaluateBinaryAndCheck(name, receiver.ctcType, receiver.value, parameter.ctcType, parameter.value) {
trace.report(Errors.INTEGER_OVERFLOW.on(callExpression.getStrictParentOfType<KtExpression>() ?: callExpression)) trace.report(Errors.INTEGER_OVERFLOW.on(callExpression.getStrictParentOfType() ?: callExpression))
} }
} }
@@ -787,7 +793,8 @@ private class ConstantExpressionEvaluatorVisitor(
return false return false
} }
if (DescriptorUtils.isObject(descriptor.containingDeclaration) || if (DescriptorUtils.isObject(descriptor.containingDeclaration) ||
DescriptorUtils.isStaticDeclaration(descriptor)) { DescriptorUtils.isStaticDeclaration(descriptor)
) {
return descriptor.type.canBeUsedForConstVal() return descriptor.type.canBeUsedForConstVal()
} }
return false return false
@@ -1088,8 +1095,7 @@ private class ConstantExpressionEvaluatorVisitor(
private fun createCompileTimeConstantForEquals(result: Any?, operationReference: KtExpression): ConstantValue<*>? { private fun createCompileTimeConstantForEquals(result: Any?, operationReference: KtExpression): 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 value: Boolean = when (val operationToken = (operationReference as KtSimpleNameExpression).getReferencedNameElementType()) {
val value: Boolean = when (operationToken) {
KtTokens.EQEQ -> result KtTokens.EQEQ -> result
KtTokens.EXCLEQ -> !result KtTokens.EXCLEQ -> !result
KtTokens.IDENTIFIER -> { KtTokens.IDENTIFIER -> {
@@ -1106,8 +1112,7 @@ private fun createCompileTimeConstantForEquals(result: Any?, operationReference:
private fun createCompileTimeConstantForCompareTo(result: Any?, operationReference: KtExpression): ConstantValue<*>? { private fun createCompileTimeConstantForCompareTo(result: Any?, operationReference: KtExpression): 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() return when (val operationToken = (operationReference as KtSimpleNameExpression).getReferencedNameElementType()) {
return when (operationToken) {
KtTokens.LT -> BooleanValue(result < 0) KtTokens.LT -> BooleanValue(result < 0)
KtTokens.LTEQ -> BooleanValue(result <= 0) KtTokens.LTEQ -> BooleanValue(result <= 0)
KtTokens.GT -> BooleanValue(result > 0) KtTokens.GT -> BooleanValue(result > 0)