Merge CallableReferencesResolutionUtils.kt into DoubleColonExpressionResolver
This commit is contained in:
-130
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.callableReferences
|
||||
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
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.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
|
||||
fun resolvePossiblyAmbiguousCallableReference(
|
||||
callableReferenceExpression: KtCallableReferenceExpression,
|
||||
lhs: DoubleColonLHS?,
|
||||
context: ResolutionContext<*>,
|
||||
resolutionMode: ResolveArgumentsMode,
|
||||
callResolver: CallResolver
|
||||
): OverloadResolutionResults<CallableDescriptor>? {
|
||||
val reference = callableReferenceExpression.callableReference
|
||||
|
||||
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 resolveWithReceiver("resolve callable reference with empty LHS", null)
|
||||
|
||||
when (lhs) {
|
||||
is DoubleColonLHS.Type -> {
|
||||
val classifier = lhsType.constructor.declarationDescriptor
|
||||
if (classifier !is ClassDescriptor) {
|
||||
context.trace.report(CALLABLE_REFERENCE_LHS_NOT_A_CLASS.on(callableReferenceExpression))
|
||||
return null
|
||||
}
|
||||
|
||||
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 != null) return possibleStatic
|
||||
}
|
||||
|
||||
val possibleWithReceiver = resolveWithReceiver("resolve unbound callable reference with receiver", TransientReceiver(lhsType))
|
||||
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 != null) return result
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun createKCallableTypeForReference(
|
||||
descriptor: CallableDescriptor,
|
||||
lhs: DoubleColonLHS?,
|
||||
reflectionTypes: ReflectionTypes,
|
||||
scopeOwnerDescriptor: DeclarationDescriptor
|
||||
): KotlinType? {
|
||||
val receiverType =
|
||||
if (descriptor.extensionReceiverParameter != null || descriptor.dispatchReceiverParameter != null)
|
||||
(lhs as? DoubleColonLHS.Type)?.type
|
||||
else null
|
||||
|
||||
return when (descriptor) {
|
||||
is FunctionDescriptor -> {
|
||||
val returnType = descriptor.returnType ?: return null
|
||||
val valueParametersTypes = ExpressionTypingUtils.getValueParametersTypes(descriptor.valueParameters)
|
||||
return reflectionTypes.getKFunctionType(Annotations.EMPTY, receiverType, valueParametersTypes, returnType)
|
||||
}
|
||||
is PropertyDescriptor -> {
|
||||
val mutable = descriptor.isVar && run {
|
||||
val setter = descriptor.setter
|
||||
// TODO: support private-to-this
|
||||
setter == null || Visibilities.isVisible(null, setter, scopeOwnerDescriptor)
|
||||
}
|
||||
reflectionTypes.getKPropertyType(Annotations.EMPTY, receiverType, descriptor.type, mutable)
|
||||
}
|
||||
is VariableDescriptor -> null
|
||||
else -> throw UnsupportedOperationException("Callable reference resolved to an unsupported descriptor: $descriptor")
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.FunctionTypeResolveUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.TypeResolver;
|
||||
import org.jetbrains.kotlin.resolve.callableReferences.CallableReferencesResolutionUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
|
||||
@@ -261,7 +260,7 @@ public class ArgumentTypeResolver {
|
||||
OverloadResolutionResultsUtil.getResultingCall(overloadResolutionResults, context.contextDependency);
|
||||
if (resolvedCall == null) return null;
|
||||
|
||||
return CallableReferencesResolutionUtilsKt.createKCallableTypeForReference(
|
||||
return DoubleColonExpressionResolver.Companion.createKCallableTypeForReference(
|
||||
resolvedCall.getResultingDescriptor(), lhs, reflectionTypes, context.scope.getOwnerDescriptor()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.callableReferences.createKCallableTypeForReference
|
||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer.CallForImplicitInvoke
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS
|
||||
@@ -52,6 +51,7 @@ import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.TypeUtils.noExpectedType
|
||||
import org.jetbrains.kotlin.types.checker.ErrorTypesAreEqualToAnything
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver
|
||||
import java.util.*
|
||||
|
||||
class CandidateResolver(
|
||||
@@ -157,7 +157,7 @@ class CandidateResolver(
|
||||
private fun <D : CallableDescriptor> CallCandidateResolutionContext<D>.checkExpectedCallableType()
|
||||
= check {
|
||||
if (!noExpectedType(expectedType)) {
|
||||
val candidateKCallableType = createKCallableTypeForReference(
|
||||
val candidateKCallableType = DoubleColonExpressionResolver.createKCallableTypeForReference(
|
||||
candidateCall.candidateDescriptor,
|
||||
(call.callElement.parent as? KtCallableReferenceExpression)?.receiverExpression?.let {
|
||||
trace.bindingContext.get(BindingContext.DOUBLE_COLON_LHS, it)
|
||||
|
||||
+111
-3
@@ -30,17 +30,22 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.callableReferences.createKCallableTypeForReference
|
||||
import org.jetbrains.kotlin.resolve.callableReferences.resolvePossiblyAmbiguousCallableReference
|
||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
|
||||
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -425,8 +430,111 @@ class DoubleColonExpressionResolver(
|
||||
else resolveDoubleColonLHS(expression, context)
|
||||
|
||||
val resolutionResults =
|
||||
resolvePossiblyAmbiguousCallableReference(expression, lhsResult, context, resolveArgumentsMode, callResolver)
|
||||
resolveCallableReferenceRHS(expression, lhsResult, context, resolveArgumentsMode)
|
||||
|
||||
return lhsResult to resolutionResults
|
||||
}
|
||||
|
||||
private fun tryResolveRHSWithReceiver(
|
||||
traceTitle: String,
|
||||
receiver: Receiver?,
|
||||
reference: KtSimpleNameExpression,
|
||||
outerContext: ResolutionContext<*>,
|
||||
resolutionMode: ResolveArgumentsMode
|
||||
): OverloadResolutionResults<CallableDescriptor>? {
|
||||
val call = CallMaker.makeCall(reference, receiver, null, reference, emptyList())
|
||||
val temporaryTrace = TemporaryTraceAndCache.create(outerContext, traceTitle, reference)
|
||||
val newContext =
|
||||
if (resolutionMode == ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS)
|
||||
outerContext.replaceTraceAndCache(temporaryTrace).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)
|
||||
else
|
||||
outerContext.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
|
||||
}
|
||||
|
||||
private fun resolveCallableReferenceRHS(
|
||||
expression: KtCallableReferenceExpression,
|
||||
lhs: DoubleColonLHS?,
|
||||
c: ResolutionContext<*>,
|
||||
mode: ResolveArgumentsMode
|
||||
): OverloadResolutionResults<CallableDescriptor>? {
|
||||
val reference = expression.callableReference
|
||||
|
||||
val lhsType = lhs?.type ?:
|
||||
return tryResolveRHSWithReceiver("resolve callable reference with empty LHS", null, reference, c, mode)
|
||||
|
||||
when (lhs) {
|
||||
is DoubleColonLHS.Type -> {
|
||||
val classifier = lhsType.constructor.declarationDescriptor
|
||||
if (classifier !is ClassDescriptor) {
|
||||
c.trace.report(CALLABLE_REFERENCE_LHS_NOT_A_CLASS.on(expression))
|
||||
return null
|
||||
}
|
||||
|
||||
val qualifier = c.trace.get(BindingContext.QUALIFIER, expression.receiverExpression!!)
|
||||
if (qualifier is ClassQualifier) {
|
||||
val possibleStatic = tryResolveRHSWithReceiver(
|
||||
"resolve unbound callable reference in static scope", qualifier, reference, c, mode
|
||||
)
|
||||
if (possibleStatic != null) return possibleStatic
|
||||
}
|
||||
|
||||
val possibleWithReceiver = tryResolveRHSWithReceiver(
|
||||
"resolve unbound callable reference with receiver", TransientReceiver(lhsType), reference, c, mode
|
||||
)
|
||||
if (possibleWithReceiver != null) return possibleWithReceiver
|
||||
}
|
||||
is DoubleColonLHS.Expression -> {
|
||||
val expressionReceiver = ExpressionReceiver.create(expression.receiverExpression!!, lhsType, c.trace.bindingContext)
|
||||
val result = tryResolveRHSWithReceiver(
|
||||
"resolve bound callable reference", expressionReceiver, reference, c, mode
|
||||
)
|
||||
if (result != null) return result
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun createKCallableTypeForReference(
|
||||
descriptor: CallableDescriptor,
|
||||
lhs: DoubleColonLHS?,
|
||||
reflectionTypes: ReflectionTypes,
|
||||
scopeOwnerDescriptor: DeclarationDescriptor
|
||||
): KotlinType? {
|
||||
val receiverType =
|
||||
if (descriptor.extensionReceiverParameter != null || descriptor.dispatchReceiverParameter != null)
|
||||
(lhs as? DoubleColonLHS.Type)?.type
|
||||
else null
|
||||
|
||||
return when (descriptor) {
|
||||
is FunctionDescriptor -> {
|
||||
val returnType = descriptor.returnType ?: return null
|
||||
val valueParametersTypes = ExpressionTypingUtils.getValueParametersTypes(descriptor.valueParameters)
|
||||
return reflectionTypes.getKFunctionType(Annotations.EMPTY, receiverType, valueParametersTypes, returnType)
|
||||
}
|
||||
is PropertyDescriptor -> {
|
||||
val mutable = descriptor.isVar && run {
|
||||
val setter = descriptor.setter
|
||||
// TODO: support private-to-this
|
||||
setter == null || Visibilities.isVisible(null, setter, scopeOwnerDescriptor)
|
||||
}
|
||||
reflectionTypes.getKPropertyType(Annotations.EMPTY, receiverType, descriptor.type, mutable)
|
||||
}
|
||||
is VariableDescriptor -> null
|
||||
else -> throw UnsupportedOperationException("Callable reference resolved to an unsupported descriptor: $descriptor")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.util.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.PossiblyBareType
|
||||
import org.jetbrains.kotlin.resolve.callableReferences.createKCallableTypeForReference
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeNullability
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
@@ -252,7 +252,7 @@ private fun MutableCollection<LookupElement>.addLookupElementsForNullable(factor
|
||||
fun CallableDescriptor.callableReferenceType(resolutionFacade: ResolutionFacade, lhs: DoubleColonLHS?): FuzzyType? {
|
||||
if (!CallType.CALLABLE_REFERENCE.descriptorKindFilter.accepts(this)) return null // not supported by callable references
|
||||
|
||||
return createKCallableTypeForReference(
|
||||
return DoubleColonExpressionResolver.createKCallableTypeForReference(
|
||||
this,
|
||||
lhs,
|
||||
resolutionFacade.getFrontendService(ReflectionTypes::class.java),
|
||||
|
||||
Reference in New Issue
Block a user