Simplify code in callable reference resolution
This commit is contained in:
+23
-42
@@ -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 <D : CallableDescriptor> ResolveArgumentsMode.acceptResolution(results: OverloadResolutionResults<D>, 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<CallableDescriptor> {
|
||||
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<CallableDescriptor>? {
|
||||
val reference = callableReferenceExpression.callableReference
|
||||
|
||||
fun resolveWithReceiver(traceTitle: String, receiver: Receiver?): OverloadResolutionResults<CallableDescriptor> {
|
||||
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<CallableDescriptor>? {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -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(::<caret>foo)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -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(::<caret>foo)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -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(::<caret>foo)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user