From 2fcd4e955af86343836b543bce6b5da41b5720ef Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 1 Jul 2016 18:42:11 +0300 Subject: [PATCH] Simplify code in callable reference resolution --- .../CallableReferencesResolutionUtils.kt | 65 +++++++------------ .../localVariable/callableRef.kt | 3 +- .../createVariable/parameter/callableRef.kt | 3 +- .../createVariable/property/callableRef.kt | 3 +- 4 files changed, 26 insertions(+), 48 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt index 49337e3ba5f..9578ad5fee3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt @@ -21,7 +21,6 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.diagnostics.Errors.CALLABLE_REFERENCE_LHS_NOT_A_CLASS import org.jetbrains.kotlin.psi.KtCallableReferenceExpression -import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.CallResolver import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode @@ -40,37 +39,6 @@ import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.expressions.DoubleColonLHS import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils -private fun ResolveArgumentsMode.acceptResolution(results: OverloadResolutionResults, trace: TemporaryTraceAndCache) { - when (this) { - ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS -> - if (results.isSingleResult) trace.commit() - ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS -> - if (results.isSomething()) trace.commit() - } -} - -private fun resolvePossiblyAmbiguousCallableReference( - reference: KtSimpleNameExpression, - receiver: Receiver?, - context: ResolutionContext<*>, - resolutionMode: ResolveArgumentsMode, - callResolver: CallResolver -): OverloadResolutionResults { - val call = CallMaker.makeCall(reference, receiver, null, reference, emptyList()) - val temporaryTrace = TemporaryTraceAndCache.create(context, "resolve callable reference as function", reference) - val newContext = if (resolutionMode == ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS) - context.replaceTraceAndCache(temporaryTrace).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE) - else - context.replaceTraceAndCache(temporaryTrace) - val callResolutionContext = BasicCallResolutionContext.create( - newContext, call, CheckArgumentTypesMode.CHECK_CALLABLE_TYPE) - val resolutionResults = callResolver.resolveCallForMember(reference, callResolutionContext) - resolutionMode.acceptResolution(resolutionResults, temporaryTrace) - return resolutionResults -} - -private fun OverloadResolutionResults<*>.isSomething(): Boolean = !isNothing - fun resolvePossiblyAmbiguousCallableReference( callableReferenceExpression: KtCallableReferenceExpression, lhs: DoubleColonLHS?, @@ -80,15 +48,28 @@ fun resolvePossiblyAmbiguousCallableReference( ): OverloadResolutionResults? { val reference = callableReferenceExpression.callableReference - fun resolveWithReceiver(traceTitle: String, receiver: Receiver?): OverloadResolutionResults { - val temporaryTraceAndCache = TemporaryTraceAndCache.create(context, traceTitle, reference) - val newContext = context.replaceTraceAndCache(temporaryTraceAndCache) - val results = resolvePossiblyAmbiguousCallableReference(reference, receiver, newContext, resolutionMode, callResolver) - resolutionMode.acceptResolution(results, temporaryTraceAndCache) - return results + fun resolveWithReceiver(traceTitle: String?, receiver: Receiver?): OverloadResolutionResults? { + val call = CallMaker.makeCall(reference, receiver, null, reference, emptyList()) + val temporaryTrace = TemporaryTraceAndCache.create(context, traceTitle, reference) + val newContext = + if (resolutionMode == ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS) + context.replaceTraceAndCache(temporaryTrace).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE) + else + context.replaceTraceAndCache(temporaryTrace) + + val resolutionResults = callResolver.resolveCallForMember( + reference, BasicCallResolutionContext.create(newContext, call, CheckArgumentTypesMode.CHECK_CALLABLE_TYPE) + ) + + val shouldCommitTrace = + if (resolutionMode == ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS) resolutionResults.isSingleResult + else !resolutionResults.isNothing + if (shouldCommitTrace) temporaryTrace.commit() + + return if (resolutionResults.isNothing) null else resolutionResults } - val lhsType = lhs?.type ?: return resolvePossiblyAmbiguousCallableReference(reference, null, context, resolutionMode, callResolver) + val lhsType = lhs?.type ?: return resolveWithReceiver("resolve callable reference with empty LHS", null) when (lhs) { is DoubleColonLHS.Type -> { @@ -101,17 +82,17 @@ fun resolvePossiblyAmbiguousCallableReference( val qualifier = context.trace.get(BindingContext.QUALIFIER, callableReferenceExpression.receiverExpression!!) if (qualifier is ClassQualifier) { val possibleStatic = resolveWithReceiver("resolve unbound callable reference in static scope", qualifier) - if (possibleStatic.isSomething()) return possibleStatic + if (possibleStatic != null) return possibleStatic } val possibleWithReceiver = resolveWithReceiver("resolve unbound callable reference with receiver", TransientReceiver(lhsType)) - if (possibleWithReceiver.isSomething()) return possibleWithReceiver + if (possibleWithReceiver != null) return possibleWithReceiver } is DoubleColonLHS.Expression -> { val result = resolveWithReceiver("resolve bound callable reference", ExpressionReceiver.create( callableReferenceExpression.receiverExpression!!, lhsType, context.trace.bindingContext )) - if (result.isSomething()) return result + if (result != null) return result } } diff --git a/idea/testData/quickfix/createFromUsage/createVariable/localVariable/callableRef.kt b/idea/testData/quickfix/createFromUsage/createVariable/localVariable/callableRef.kt index bc906da3a37..7e1bb019349 100644 --- a/idea/testData/quickfix/createFromUsage/createVariable/localVariable/callableRef.kt +++ b/idea/testData/quickfix/createFromUsage/createVariable/localVariable/callableRef.kt @@ -1,10 +1,9 @@ // "Create local variable 'foo'" "false" // ACTION: Rename reference -// ACTION: Add 'f =' to argument // ACTION: Create function 'foo' // ERROR: Unresolved reference: foo fun test(f: (Int) -> Int) {} fun refer() { val v = test(::foo) -} \ No newline at end of file +} diff --git a/idea/testData/quickfix/createFromUsage/createVariable/parameter/callableRef.kt b/idea/testData/quickfix/createFromUsage/createVariable/parameter/callableRef.kt index 5742686eb8d..7b2174d7a02 100644 --- a/idea/testData/quickfix/createFromUsage/createVariable/parameter/callableRef.kt +++ b/idea/testData/quickfix/createFromUsage/createVariable/parameter/callableRef.kt @@ -1,10 +1,9 @@ // "Create parameter 'foo'" "false" // ACTION: Rename reference -// ACTION: Add 'f =' to argument // ACTION: Create function 'foo' // ERROR: Unresolved reference: foo fun test(f: (Int) -> Int) {} fun refer() { val v = test(::foo) -} \ No newline at end of file +} diff --git a/idea/testData/quickfix/createFromUsage/createVariable/property/callableRef.kt b/idea/testData/quickfix/createFromUsage/createVariable/property/callableRef.kt index e0f64a1b08a..5a7ddad8e02 100644 --- a/idea/testData/quickfix/createFromUsage/createVariable/property/callableRef.kt +++ b/idea/testData/quickfix/createFromUsage/createVariable/property/callableRef.kt @@ -1,10 +1,9 @@ // "Create property 'foo'" "false" // ACTION: Rename reference -// ACTION: Add 'f =' to argument // ACTION: Create function 'foo' // ERROR: Unresolved reference: foo fun test(f: (Int) -> Int) {} fun refer() { val v = test(::foo) -} \ No newline at end of file +}