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.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors.CALLABLE_REFERENCE_LHS_NOT_A_CLASS
|
import org.jetbrains.kotlin.diagnostics.Errors.CALLABLE_REFERENCE_LHS_NOT_A_CLASS
|
||||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
|
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.DoubleColonLHS
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
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(
|
fun resolvePossiblyAmbiguousCallableReference(
|
||||||
callableReferenceExpression: KtCallableReferenceExpression,
|
callableReferenceExpression: KtCallableReferenceExpression,
|
||||||
lhs: DoubleColonLHS?,
|
lhs: DoubleColonLHS?,
|
||||||
@@ -80,15 +48,28 @@ fun resolvePossiblyAmbiguousCallableReference(
|
|||||||
): OverloadResolutionResults<CallableDescriptor>? {
|
): OverloadResolutionResults<CallableDescriptor>? {
|
||||||
val reference = callableReferenceExpression.callableReference
|
val reference = callableReferenceExpression.callableReference
|
||||||
|
|
||||||
fun resolveWithReceiver(traceTitle: String, receiver: Receiver?): OverloadResolutionResults<CallableDescriptor> {
|
fun resolveWithReceiver(traceTitle: String?, receiver: Receiver?): OverloadResolutionResults<CallableDescriptor>? {
|
||||||
val temporaryTraceAndCache = TemporaryTraceAndCache.create(context, traceTitle, reference)
|
val call = CallMaker.makeCall(reference, receiver, null, reference, emptyList())
|
||||||
val newContext = context.replaceTraceAndCache(temporaryTraceAndCache)
|
val temporaryTrace = TemporaryTraceAndCache.create(context, traceTitle, reference)
|
||||||
val results = resolvePossiblyAmbiguousCallableReference(reference, receiver, newContext, resolutionMode, callResolver)
|
val newContext =
|
||||||
resolutionMode.acceptResolution(results, temporaryTraceAndCache)
|
if (resolutionMode == ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS)
|
||||||
return results
|
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) {
|
when (lhs) {
|
||||||
is DoubleColonLHS.Type -> {
|
is DoubleColonLHS.Type -> {
|
||||||
@@ -101,17 +82,17 @@ fun resolvePossiblyAmbiguousCallableReference(
|
|||||||
val qualifier = context.trace.get(BindingContext.QUALIFIER, callableReferenceExpression.receiverExpression!!)
|
val qualifier = context.trace.get(BindingContext.QUALIFIER, callableReferenceExpression.receiverExpression!!)
|
||||||
if (qualifier is ClassQualifier) {
|
if (qualifier is ClassQualifier) {
|
||||||
val possibleStatic = resolveWithReceiver("resolve unbound callable reference in static scope", qualifier)
|
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))
|
val possibleWithReceiver = resolveWithReceiver("resolve unbound callable reference with receiver", TransientReceiver(lhsType))
|
||||||
if (possibleWithReceiver.isSomething()) return possibleWithReceiver
|
if (possibleWithReceiver != null) return possibleWithReceiver
|
||||||
}
|
}
|
||||||
is DoubleColonLHS.Expression -> {
|
is DoubleColonLHS.Expression -> {
|
||||||
val result = resolveWithReceiver("resolve bound callable reference", ExpressionReceiver.create(
|
val result = resolveWithReceiver("resolve bound callable reference", ExpressionReceiver.create(
|
||||||
callableReferenceExpression.receiverExpression!!, lhsType, context.trace.bindingContext
|
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"
|
// "Create local variable 'foo'" "false"
|
||||||
// ACTION: Rename reference
|
// ACTION: Rename reference
|
||||||
// ACTION: Add 'f =' to argument
|
|
||||||
// ACTION: Create function 'foo'
|
// ACTION: Create function 'foo'
|
||||||
// ERROR: Unresolved reference: foo
|
// ERROR: Unresolved reference: foo
|
||||||
fun test(f: (Int) -> Int) {}
|
fun test(f: (Int) -> Int) {}
|
||||||
|
|
||||||
fun refer() {
|
fun refer() {
|
||||||
val v = test(::<caret>foo)
|
val v = test(::<caret>foo)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -1,10 +1,9 @@
|
|||||||
// "Create parameter 'foo'" "false"
|
// "Create parameter 'foo'" "false"
|
||||||
// ACTION: Rename reference
|
// ACTION: Rename reference
|
||||||
// ACTION: Add 'f =' to argument
|
|
||||||
// ACTION: Create function 'foo'
|
// ACTION: Create function 'foo'
|
||||||
// ERROR: Unresolved reference: foo
|
// ERROR: Unresolved reference: foo
|
||||||
fun test(f: (Int) -> Int) {}
|
fun test(f: (Int) -> Int) {}
|
||||||
|
|
||||||
fun refer() {
|
fun refer() {
|
||||||
val v = test(::<caret>foo)
|
val v = test(::<caret>foo)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -1,10 +1,9 @@
|
|||||||
// "Create property 'foo'" "false"
|
// "Create property 'foo'" "false"
|
||||||
// ACTION: Rename reference
|
// ACTION: Rename reference
|
||||||
// ACTION: Add 'f =' to argument
|
|
||||||
// ACTION: Create function 'foo'
|
// ACTION: Create function 'foo'
|
||||||
// ERROR: Unresolved reference: foo
|
// ERROR: Unresolved reference: foo
|
||||||
fun test(f: (Int) -> Int) {}
|
fun test(f: (Int) -> Int) {}
|
||||||
|
|
||||||
fun refer() {
|
fun refer() {
|
||||||
val v = test(::<caret>foo)
|
val v = test(::<caret>foo)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user