Refactor: get rid of static ConstantExpressionEvaluator.evaluate function
Move ArgumentTypeResolver.getLastElementDeparenthesized to JetPsiUtil
This commit is contained in:
@@ -41,6 +41,8 @@ import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.name.SpecialNames;
|
||||
import org.jetbrains.kotlin.parsing.JetExpressionParsing;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.ResolvePackage;
|
||||
import org.jetbrains.kotlin.resolve.StatementFilter;
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -875,4 +877,24 @@ public class JetPsiUtil {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetExpression getLastElementDeparenthesized(
|
||||
@Nullable JetExpression expression,
|
||||
@NotNull StatementFilter statementFilter
|
||||
) {
|
||||
JetExpression deparenthesizedExpression = JetPsiUtil.deparenthesize(expression, false);
|
||||
if (deparenthesizedExpression instanceof JetBlockExpression) {
|
||||
JetBlockExpression blockExpression = (JetBlockExpression) deparenthesizedExpression;
|
||||
// todo
|
||||
// This case is a temporary hack for 'if' branches.
|
||||
// The right way to implement this logic is to interpret 'if' branches as function literals with explicitly-typed signatures
|
||||
// (no arguments and no receiver) and therefore analyze them straight away (not in the 'complete' phase).
|
||||
JetExpression lastStatementInABlock = ResolvePackage.getLastStatementInABlock(statementFilter, blockExpression);
|
||||
if (lastStatementInABlock != null) {
|
||||
return getLastElementDeparenthesized(lastStatementInABlock, statementFilter);
|
||||
}
|
||||
}
|
||||
return deparenthesizedExpression;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryPac
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.psi.JetPsiUtil.getLastElementDeparenthesized;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getRecordedTypeInfo;
|
||||
import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
|
||||
import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
|
||||
@@ -68,19 +69,22 @@ public class ArgumentTypeResolver {
|
||||
@NotNull private final ExpressionTypingServices expressionTypingServices;
|
||||
@NotNull private final KotlinBuiltIns builtIns;
|
||||
@NotNull private final ReflectionTypes reflectionTypes;
|
||||
@NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator;
|
||||
|
||||
public ArgumentTypeResolver(
|
||||
@NotNull TypeResolver typeResolver,
|
||||
@NotNull CallResolver callResolver,
|
||||
@NotNull ExpressionTypingServices expressionTypingServices,
|
||||
@NotNull KotlinBuiltIns builtIns,
|
||||
@NotNull ReflectionTypes reflectionTypes
|
||||
@NotNull ReflectionTypes reflectionTypes,
|
||||
@NotNull ConstantExpressionEvaluator constantExpressionEvaluator
|
||||
) {
|
||||
this.typeResolver = typeResolver;
|
||||
this.callResolver = callResolver;
|
||||
this.expressionTypingServices = expressionTypingServices;
|
||||
this.builtIns = builtIns;
|
||||
this.reflectionTypes = reflectionTypes;
|
||||
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
||||
}
|
||||
|
||||
public static boolean isSubtypeOfForArgumentType(
|
||||
@@ -171,26 +175,6 @@ public class ArgumentTypeResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetExpression getLastElementDeparenthesized(
|
||||
@Nullable JetExpression expression,
|
||||
@NotNull StatementFilter statementFilter
|
||||
) {
|
||||
JetExpression deparenthesizedExpression = JetPsiUtil.deparenthesize(expression, false);
|
||||
if (deparenthesizedExpression instanceof JetBlockExpression) {
|
||||
JetBlockExpression blockExpression = (JetBlockExpression) deparenthesizedExpression;
|
||||
// todo
|
||||
// This case is a temporary hack for 'if' branches.
|
||||
// The right way to implement this logic is to interpret 'if' branches as function literals with explicitly-typed signatures
|
||||
// (no arguments and no receiver) and therefore analyze them straight away (not in the 'complete' phase).
|
||||
JetExpression lastStatementInABlock = ResolvePackage.getLastStatementInABlock(statementFilter, blockExpression);
|
||||
if (lastStatementInABlock != null) {
|
||||
return getLastElementDeparenthesized(lastStatementInABlock, statementFilter);
|
||||
}
|
||||
}
|
||||
return deparenthesizedExpression;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetCallableReferenceExpression getCallableReferenceExpressionIfAny(
|
||||
@NotNull JetExpression expression,
|
||||
@@ -356,7 +340,7 @@ public class ArgumentTypeResolver {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetType updateResultArgumentTypeIfNotDenotable(
|
||||
public JetType updateResultArgumentTypeIfNotDenotable(
|
||||
@NotNull ResolutionContext context,
|
||||
@NotNull JetExpression expression
|
||||
) {
|
||||
@@ -365,30 +349,10 @@ public class ArgumentTypeResolver {
|
||||
if (type.getConstructor() instanceof IntegerValueTypeConstructor) {
|
||||
IntegerValueTypeConstructor constructor = (IntegerValueTypeConstructor) type.getConstructor();
|
||||
JetType primitiveType = TypeUtils.getPrimitiveNumberType(constructor, context.expectedType);
|
||||
updateNumberType(primitiveType, expression, context.statementFilter, context.trace);
|
||||
constantExpressionEvaluator.updateNumberType(primitiveType, expression, context.statementFilter, context.trace);
|
||||
return primitiveType;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public static void updateNumberType(
|
||||
@NotNull JetType numberType,
|
||||
@Nullable JetExpression expression,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
@NotNull BindingTrace trace
|
||||
) {
|
||||
if (expression == null) return;
|
||||
BindingContextUtils.updateRecordedType(numberType, expression, trace, false);
|
||||
|
||||
if (!(expression instanceof JetConstantExpression)) {
|
||||
JetExpression deparenthesized = getLastElementDeparenthesized(expression, statementFilter);
|
||||
if (deparenthesized != expression) {
|
||||
updateNumberType(numberType, deparenthesized, statementFilter, trace);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ConstantExpressionEvaluator.evaluate(expression, trace, numberType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,9 @@ import org.jetbrains.kotlin.resolve.calls.context.CallCandidateResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.FROM_COMPLETER
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.TYPE_BOUND_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||
@@ -235,7 +237,7 @@ public class CallCompleter(
|
||||
if (valueArgument.isExternal()) return
|
||||
|
||||
val expression = valueArgument.getArgumentExpression() ?: return
|
||||
val deparenthesized = ArgumentTypeResolver.getLastElementDeparenthesized(expression, context.statementFilter) ?: return
|
||||
val deparenthesized = JetPsiUtil.getLastElementDeparenthesized(expression, context.statementFilter) ?: return
|
||||
|
||||
val recordedType = expression.let { context.trace.getType(it) }
|
||||
var updatedType: JetType? = recordedType
|
||||
@@ -249,7 +251,7 @@ public class CallCompleter(
|
||||
// For the cases like 'foo(1)' the type of '1' depends on expected type (it can be Int, Byte, etc.),
|
||||
// so while the expected type is not known, it's IntegerValueType(1), and should be updated when the expected type is known.
|
||||
if (recordedType != null && !recordedType.getConstructor().isDenotable()) {
|
||||
updatedType = ArgumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, expression)
|
||||
updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, expression)
|
||||
}
|
||||
|
||||
updatedType = updateRecordedTypeForArgument(updatedType, recordedType, expression, context.trace)
|
||||
|
||||
+1
-4
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.FunctionDescriptorUtil
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver.getLastElementDeparenthesized
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.*
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS
|
||||
@@ -34,10 +33,8 @@ import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.OTHER_ERROR
|
||||
@@ -184,7 +181,7 @@ class GenericCandidateResolver(
|
||||
argumentExpression: JetExpression?,
|
||||
context: ResolutionContext<*>
|
||||
): JetType? {
|
||||
val deparenthesizedArgument = getLastElementDeparenthesized(argumentExpression, context.statementFilter)
|
||||
val deparenthesizedArgument = JetPsiUtil.getLastElementDeparenthesized(argumentExpression, context.statementFilter)
|
||||
if (deparenthesizedArgument == null || type == null) return type
|
||||
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(deparenthesizedArgument, type, context)
|
||||
|
||||
+25
-9
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
|
||||
@@ -48,6 +47,25 @@ public class ConstantExpressionEvaluator(
|
||||
internal val constantValueFactory: ConstantValueFactory,
|
||||
internal val builtIns: KotlinBuiltIns
|
||||
) {
|
||||
public fun updateNumberType(
|
||||
numberType: JetType,
|
||||
expression: JetExpression?,
|
||||
statementFilter: StatementFilter,
|
||||
trace: BindingTrace
|
||||
) {
|
||||
if (expression == null) return
|
||||
BindingContextUtils.updateRecordedType(numberType, expression, trace, false)
|
||||
|
||||
if (expression !is JetConstantExpression) {
|
||||
val deparenthesized = JetPsiUtil.getLastElementDeparenthesized(expression, statementFilter)
|
||||
if (deparenthesized !== expression) {
|
||||
updateNumberType(numberType, deparenthesized, statementFilter, trace)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
evaluateExpression(expression, trace, numberType)
|
||||
}
|
||||
|
||||
internal fun resolveAnnotationArguments(
|
||||
resolvedCall: ResolvedCall<*>,
|
||||
@@ -160,10 +178,10 @@ public class ConstantExpressionEvaluator(
|
||||
val constants = ArrayList<CompileTimeConstant<*>>()
|
||||
for (argument in resolvedValueArgument.getArguments()) {
|
||||
val argumentExpression = argument.getArgumentExpression() ?: continue
|
||||
val constant = ConstantExpressionEvaluator.evaluate(argumentExpression, trace, expectedType)
|
||||
val constant = evaluateExpression(argumentExpression, trace, expectedType)
|
||||
if (constant is IntegerValueTypeConstant) {
|
||||
val defaultType = constant.getType(expectedType)
|
||||
ArgumentTypeResolver.updateNumberType(defaultType, argumentExpression, StatementFilter.NONE, trace)
|
||||
updateNumberType(defaultType, argumentExpression, StatementFilter.NONE, trace)
|
||||
}
|
||||
if (constant != null) {
|
||||
constants.add(constant)
|
||||
@@ -184,17 +202,15 @@ public class ConstantExpressionEvaluator(
|
||||
}
|
||||
|
||||
companion object {
|
||||
platformStatic public fun evaluate(expression: JetExpression, trace: BindingTrace, expectedType: JetType? = TypeUtils.NO_EXPECTED_TYPE): CompileTimeConstant<*>? {
|
||||
val builtIns = KotlinBuiltIns.getInstance()
|
||||
return ConstantExpressionEvaluator(ConstantValueFactory(builtIns), builtIns).evaluateExpression(expression, trace, expectedType)
|
||||
}
|
||||
|
||||
platformStatic public fun evaluateToConstantValue(
|
||||
expression: JetExpression,
|
||||
trace: BindingTrace,
|
||||
expectedType: JetType
|
||||
): ConstantValue<*>? {
|
||||
return evaluate(expression, trace, expectedType)?.toConstantValue(expectedType)
|
||||
val builtIns = KotlinBuiltIns.getInstance()
|
||||
return ConstantExpressionEvaluator(ConstantValueFactory(builtIns), builtIns).
|
||||
evaluateExpression(expression, trace, expectedType)?.
|
||||
toConstantValue(expectedType)
|
||||
}
|
||||
|
||||
platformStatic public fun getConstant(expression: JetExpression, bindingContext: BindingContext): CompileTimeConstant<*>? {
|
||||
|
||||
@@ -50,9 +50,14 @@ import static org.jetbrains.kotlin.types.TypeUtils.*;
|
||||
public class DataFlowAnalyzer {
|
||||
|
||||
private final Iterable<? extends AdditionalTypeChecker> additionalTypeCheckers;
|
||||
private final ConstantExpressionEvaluator constantExpressionEvaluator;
|
||||
|
||||
public DataFlowAnalyzer(@NotNull Iterable<? extends AdditionalTypeChecker> additionalTypeCheckers) {
|
||||
public DataFlowAnalyzer(
|
||||
@NotNull Iterable<? extends AdditionalTypeChecker> additionalTypeCheckers,
|
||||
@NotNull ConstantExpressionEvaluator constantExpressionEvaluator
|
||||
) {
|
||||
this.additionalTypeCheckers = additionalTypeCheckers;
|
||||
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -293,7 +298,7 @@ public class DataFlowAnalyzer {
|
||||
IntegerValueTypeConstant integerValueTypeConstant = (IntegerValueTypeConstant) value;
|
||||
if (context.contextDependency == INDEPENDENT) {
|
||||
expressionType = integerValueTypeConstant.getType(context.expectedType);
|
||||
ArgumentTypeResolver.updateNumberType(expressionType, expression, context.statementFilter, context.trace);
|
||||
constantExpressionEvaluator.updateNumberType(expressionType, expression, context.statementFilter, context.trace);
|
||||
}
|
||||
else {
|
||||
expressionType = integerValueTypeConstant.getUnknownIntegerType();
|
||||
|
||||
+4
-1
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.resolve.constants.evaluate
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.psi.JetProperty
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -24,6 +25,7 @@ import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.annotation.AbstractAnnotationDescriptorResolveTest
|
||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
|
||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.JetTestUtils
|
||||
@@ -64,7 +66,8 @@ public abstract class AbstractEvaluateExpressionTest : AbstractAnnotationDescrip
|
||||
|
||||
private fun evaluateInitializer(context: BindingContext, property: VariableDescriptor): CompileTimeConstant<*>? {
|
||||
val propertyDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(property) as JetProperty
|
||||
val compileTimeConstant = ConstantExpressionEvaluator.evaluate(
|
||||
val builtIns = KotlinBuiltIns.getInstance()
|
||||
val compileTimeConstant = ConstantExpressionEvaluator(ConstantValueFactory(builtIns), builtIns).evaluateExpression(
|
||||
propertyDeclaration.getInitializer()!!,
|
||||
DelegatingBindingTrace(context, "trace for evaluating compile time constant"),
|
||||
property.getType()
|
||||
|
||||
Reference in New Issue
Block a user