Fix ambiguity on reference inside blocks of special functions
#KT-37058 Fixed
This commit is contained in:
@@ -14,12 +14,12 @@ import org.jetbrains.kotlin.extensions.internal.CandidateInterceptor
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.referenceExpression
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.NEW_INFERENCE_CATCH_EXCEPTION_PARAMETER
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
||||
import org.jetbrains.kotlin.resolve.calls.KotlinCallResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.SPECIAL_FUNCTION_NAMES
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isBinaryRemOperator
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.*
|
||||
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceResolver
|
||||
@@ -92,7 +92,7 @@ class PSICallResolver(
|
||||
val refinedName = refineNameForRemOperator(isBinaryRemOperator, name)
|
||||
|
||||
val kotlinCallKind = resolutionKind.toKotlinCallKind()
|
||||
val kotlinCall = toKotlinCall(context, kotlinCallKind, context.call, refinedName, tracingStrategy)
|
||||
val kotlinCall = toKotlinCall(context, kotlinCallKind, context.call, refinedName, tracingStrategy, isSpecialFunction = false)
|
||||
val scopeTower = ASTScopeTower(context)
|
||||
val resolutionCallbacks = createResolutionCallbacks(context)
|
||||
|
||||
@@ -125,8 +125,10 @@ class PSICallResolver(
|
||||
): OverloadResolutionResults<D> {
|
||||
val dispatchReceiver = resolutionCandidates.firstNotNullResult { it.dispatchReceiver }
|
||||
|
||||
val kotlinCall =
|
||||
toKotlinCall(context, KotlinCallKind.FUNCTION, context.call, givenCandidatesName, tracingStrategy, dispatchReceiver)
|
||||
val isSpecialFunction = resolutionCandidates.any { it.descriptor.name in SPECIAL_FUNCTION_NAMES }
|
||||
val kotlinCall = toKotlinCall(
|
||||
context, KotlinCallKind.FUNCTION, context.call, givenCandidatesName, tracingStrategy, isSpecialFunction, dispatchReceiver
|
||||
)
|
||||
val scopeTower = ASTScopeTower(context)
|
||||
val resolutionCallbacks = createResolutionCallbacks(context)
|
||||
|
||||
@@ -163,7 +165,9 @@ class PSICallResolver(
|
||||
expectedType: UnwrappedType?
|
||||
): CallResolutionResult {
|
||||
val deprecatedName = OperatorConventions.REM_TO_MOD_OPERATION_NAMES[remOperatorName]!!
|
||||
val callWithDeprecatedName = toKotlinCall(context, kotlinCallKind, context.call, deprecatedName, tracingStrategy)
|
||||
val callWithDeprecatedName = toKotlinCall(
|
||||
context, kotlinCallKind, context.call, deprecatedName, tracingStrategy, isSpecialFunction = false
|
||||
)
|
||||
return kotlinCallResolver.resolveCall(
|
||||
scopeTower, resolutionCallbacks, callWithDeprecatedName, expectedType, context.collectAllCandidates
|
||||
) {
|
||||
@@ -558,7 +562,8 @@ class PSICallResolver(
|
||||
oldCall: Call,
|
||||
name: Name,
|
||||
tracingStrategy: TracingStrategy,
|
||||
forcedExplicitReceiver: Receiver? = null
|
||||
isSpecialFunction: Boolean,
|
||||
forcedExplicitReceiver: Receiver? = null,
|
||||
): PSIKotlinCallImpl {
|
||||
val resolvedExplicitReceiver = resolveReceiver(
|
||||
context, forcedExplicitReceiver ?: oldCall.explicitReceiver, oldCall.isSafeCall(), isForImplicitInvoke = false
|
||||
@@ -574,7 +579,7 @@ class PSICallResolver(
|
||||
val argumentsInParenthesis = if (extraArgumentsNumber == 0) allValueArguments else allValueArguments.dropLast(extraArgumentsNumber)
|
||||
|
||||
val externalLambdaArguments = oldCall.functionLiteralArguments
|
||||
val resolvedArgumentsInParenthesis = resolveArgumentsInParenthesis(context, argumentsInParenthesis)
|
||||
val resolvedArgumentsInParenthesis = resolveArgumentsInParenthesis(context, argumentsInParenthesis, isSpecialFunction)
|
||||
|
||||
val externalArgument = if (oldCall.callType == Call.CallType.ARRAY_SET_METHOD) {
|
||||
assert(externalLambdaArguments.isEmpty()) {
|
||||
@@ -608,7 +613,8 @@ class PSICallResolver(
|
||||
else
|
||||
context.dataFlowInfoForArguments.resultInfo
|
||||
|
||||
val resolvedExternalArgument = externalArgument?.let { resolveValueArgument(context, dataFlowInfoAfterArgumentsInParenthesis, it) }
|
||||
val resolvedExternalArgument =
|
||||
externalArgument?.let { resolveValueArgument(context, dataFlowInfoAfterArgumentsInParenthesis, it, isSpecialFunction) }
|
||||
val resultDataFlowInfo = resolvedExternalArgument?.dataFlowInfoAfterThisArgument ?: dataFlowInfoAfterArgumentsInParenthesis
|
||||
|
||||
resolvedArgumentsInParenthesis.forEach { it.setResultDataFlowInfoIfRelevant(resultDataFlowInfo) }
|
||||
@@ -690,11 +696,17 @@ class PSICallResolver(
|
||||
|
||||
private fun resolveArgumentsInParenthesis(
|
||||
context: BasicCallResolutionContext,
|
||||
arguments: List<ValueArgument>
|
||||
arguments: List<ValueArgument>,
|
||||
isSpecialFunction: Boolean
|
||||
): List<KotlinCallArgument> {
|
||||
val dataFlowInfoForArguments = context.dataFlowInfoForArguments
|
||||
return arguments.map { argument ->
|
||||
resolveValueArgument(context, dataFlowInfoForArguments.getInfo(argument), argument).also { resolvedArgument ->
|
||||
resolveValueArgument(
|
||||
context,
|
||||
dataFlowInfoForArguments.getInfo(argument),
|
||||
argument,
|
||||
isSpecialFunction
|
||||
).also { resolvedArgument ->
|
||||
dataFlowInfoForArguments.updateInfo(argument, resolvedArgument.dataFlowInfoAfterThisArgument)
|
||||
}
|
||||
}
|
||||
@@ -703,7 +715,8 @@ class PSICallResolver(
|
||||
private fun resolveValueArgument(
|
||||
outerCallContext: BasicCallResolutionContext,
|
||||
startDataFlowInfo: DataFlowInfo,
|
||||
valueArgument: ValueArgument
|
||||
valueArgument: ValueArgument,
|
||||
isSpecialFunction: Boolean
|
||||
): PSIKotlinCallArgument {
|
||||
val builtIns = outerCallContext.scope.ownerDescriptor.builtIns
|
||||
|
||||
@@ -728,8 +741,17 @@ class PSICallResolver(
|
||||
}
|
||||
|
||||
val context = outerCallContext.replaceContextDependency(ContextDependency.DEPENDENT)
|
||||
.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceDataFlowInfo(startDataFlowInfo)
|
||||
.expandContextForCatchClause(ktExpression)
|
||||
.replaceDataFlowInfo(startDataFlowInfo)
|
||||
.expandContextForCatchClause(ktExpression).let {
|
||||
if (isSpecialFunction &&
|
||||
argumentExpression is KtBlockExpression &&
|
||||
ArgumentTypeResolver.getCallableReferenceExpressionIfAny(argumentExpression, it) != null
|
||||
) {
|
||||
it
|
||||
} else {
|
||||
it.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)
|
||||
}
|
||||
}
|
||||
|
||||
if (ktExpression is KtCallableReferenceExpression) {
|
||||
return createCallableReferenceKotlinCallArgument(
|
||||
|
||||
Reference in New Issue
Block a user