[NI] Add hacks for property delegation resolution.
This commit is contained in:
committed by
Mikhail Zarechenskiy
parent
af138e7403
commit
b9e9243e9d
@@ -27,8 +27,12 @@ import org.jetbrains.kotlin.diagnostics.Errors.*
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext.*
|
import org.jetbrains.kotlin.resolve.BindingContext.*
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.USE_NEW_INFERENCE
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.checkers.OperatorCallChecker
|
import org.jetbrains.kotlin.resolve.calls.checkers.OperatorCallChecker
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.FROM_COMPLETER
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.FROM_COMPLETER
|
||||||
@@ -47,6 +51,7 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
|||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.createFakeExpressionOfType
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.createFakeExpressionOfType
|
||||||
import org.jetbrains.kotlin.types.expressions.FakeCallResolver
|
import org.jetbrains.kotlin.types.expressions.FakeCallResolver
|
||||||
|
import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
//TODO: check for 'operator' modifier!
|
//TODO: check for 'operator' modifier!
|
||||||
@@ -310,8 +315,16 @@ class DelegatedPropertyResolver(
|
|||||||
initializerScope: LexicalScope,
|
initializerScope: LexicalScope,
|
||||||
dataFlowInfo: DataFlowInfo
|
dataFlowInfo: DataFlowInfo
|
||||||
): OverloadResolutionResults<FunctionDescriptor> {
|
): OverloadResolutionResults<FunctionDescriptor> {
|
||||||
val expectedType = TypeUtils.NO_EXPECTED_TYPE
|
val context = ExpressionTypingContext.newContext(trace, initializerScope, dataFlowInfo, NO_EXPECTED_TYPE)
|
||||||
val context = ExpressionTypingContext.newContext(trace, initializerScope, dataFlowInfo, expectedType)
|
return getProvideDelegateMethod(propertyDescriptor, delegateExpression, delegateExpressionType, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getProvideDelegateMethod(
|
||||||
|
propertyDescriptor: VariableDescriptorWithAccessors,
|
||||||
|
delegateExpression: KtExpression,
|
||||||
|
delegateExpressionType: KotlinType,
|
||||||
|
context: ExpressionTypingContext
|
||||||
|
): OverloadResolutionResults<FunctionDescriptor> {
|
||||||
val propertyHasReceiver = propertyDescriptor.dispatchReceiverParameter != null
|
val propertyHasReceiver = propertyDescriptor.dispatchReceiverParameter != null
|
||||||
val arguments = KtPsiFactory(delegateExpression, markGenerated = false).run {
|
val arguments = KtPsiFactory(delegateExpression, markGenerated = false).run {
|
||||||
listOf(
|
listOf(
|
||||||
@@ -320,11 +333,11 @@ class DelegatedPropertyResolver(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
val functionName = OperatorNameConventions.PROVIDE_DELEGATE
|
val functionName = OperatorNameConventions.PROVIDE_DELEGATE
|
||||||
val receiver = ExpressionReceiver.create(delegateExpression, delegateExpressionType, trace.bindingContext)
|
val receiver = ExpressionReceiver.create(delegateExpression, delegateExpressionType, context.trace.bindingContext)
|
||||||
|
|
||||||
val (provideDelegateCall, provideDelegateResults) =
|
val (provideDelegateCall, provideDelegateResults) =
|
||||||
fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments, functionName, delegateExpression)
|
fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments, functionName, delegateExpression)
|
||||||
trace.record(BindingContext.PROVIDE_DELEGATE_CALL, propertyDescriptor, provideDelegateCall)
|
context.trace.record(BindingContext.PROVIDE_DELEGATE_CALL, propertyDescriptor, provideDelegateCall)
|
||||||
|
|
||||||
return provideDelegateResults
|
return provideDelegateResults
|
||||||
}
|
}
|
||||||
@@ -362,7 +375,8 @@ class DelegatedPropertyResolver(
|
|||||||
traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, it, completer)
|
traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, it, completer)
|
||||||
}
|
}
|
||||||
|
|
||||||
val delegateType = expressionTypingServices.safeGetType(scopeForDelegate, delegateExpression, NO_EXPECTED_TYPE, dataFlowInfo, traceToResolveDelegatedProperty)
|
val expectedTypeByNewInference = completer.resolveViaNewInference(delegateExpression, variableDescriptor, scopeForDelegate, trace, dataFlowInfo)
|
||||||
|
val delegateType = expressionTypingServices.safeGetType(scopeForDelegate, delegateExpression, expectedTypeByNewInference ?: NO_EXPECTED_TYPE, dataFlowInfo, traceToResolveDelegatedProperty)
|
||||||
|
|
||||||
traceToResolveDelegatedProperty.commit({ slice, _ -> slice !== CONSTRAINT_SYSTEM_COMPLETER }, true)
|
traceToResolveDelegatedProperty.commit({ slice, _ -> slice !== CONSTRAINT_SYSTEM_COMPLETER }, true)
|
||||||
|
|
||||||
@@ -479,5 +493,45 @@ class DelegatedPropertyResolver(
|
|||||||
FROM_COMPLETER.position()
|
FROM_COMPLETER.position()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun resolveViaNewInference(
|
||||||
|
delegateExpression: KtExpression,
|
||||||
|
variableDescriptor: VariableDescriptorWithAccessors,
|
||||||
|
scopeForDelegate: LexicalScope,
|
||||||
|
trace: BindingTrace,
|
||||||
|
dataFlowInfo: DataFlowInfo
|
||||||
|
): KotlinType? {
|
||||||
|
if (!USE_NEW_INFERENCE) return null
|
||||||
|
|
||||||
|
val traceToResolveConventionMethods = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods")
|
||||||
|
|
||||||
|
val delegateType = expressionTypingServices.getTypeInfo(scopeForDelegate, delegateExpression, NO_EXPECTED_TYPE, dataFlowInfo,
|
||||||
|
traceToResolveConventionMethods, false, delegateExpression, ContextDependency.DEPENDENT)
|
||||||
|
|
||||||
|
val contextForProvideDelegate = ExpressionTypingContext.newContext(traceToResolveConventionMethods, scopeForDelegate, delegateType.dataFlowInfo,
|
||||||
|
NO_EXPECTED_TYPE, ContextDependency.DEPENDENT, StatementFilter.NONE)
|
||||||
|
|
||||||
|
val provideDelegateResults = getProvideDelegateMethod(
|
||||||
|
variableDescriptor, delegateExpression, delegateType.type ?: return null, contextForProvideDelegate
|
||||||
|
)
|
||||||
|
|
||||||
|
var typeInfoForGetValueReceiver = delegateType
|
||||||
|
if (conventionMethodFound(provideDelegateResults)) {
|
||||||
|
val provideDelegateDescriptor = provideDelegateResults.resultingDescriptor
|
||||||
|
if (provideDelegateDescriptor.isOperator) {
|
||||||
|
typeInfoForGetValueReceiver = KotlinTypeInfo(provideDelegateDescriptor.returnType,
|
||||||
|
provideDelegateResults.resultingCall.dataFlowInfoForArguments.resultInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getGetSetValueMethod(
|
||||||
|
variableDescriptor, delegateExpression, typeInfoForGetValueReceiver.type ?: return null,
|
||||||
|
traceToResolveConventionMethods, scopeForDelegate, typeInfoForGetValueReceiver.dataFlowInfo,
|
||||||
|
isGet = true, isComplete = true
|
||||||
|
)
|
||||||
|
|
||||||
|
val call = delegateExpression.getCall(traceToResolveConventionMethods.bindingContext)
|
||||||
|
return call.getResolvedCall(traceToResolveConventionMethods.bindingContext)?.resultingDescriptor?.returnType
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -426,7 +426,7 @@ class StubOnlyResolvedCall<D : CallableDescriptor>(val candidate: SimpleKotlinRe
|
|||||||
override fun getStatus() = ResolutionStatus.UNKNOWN_STATUS
|
override fun getStatus() = ResolutionStatus.UNKNOWN_STATUS
|
||||||
|
|
||||||
override fun getCandidateDescriptor(): D = candidate.candidateDescriptor as D
|
override fun getCandidateDescriptor(): D = candidate.candidateDescriptor as D
|
||||||
override fun getResultingDescriptor(): D = candidateDescriptor
|
override fun getResultingDescriptor(): D = candidate.descriptorWithFreshTypes as D
|
||||||
override fun getExtensionReceiver() = candidate.extensionReceiver?.receiver?.receiverValue
|
override fun getExtensionReceiver() = candidate.extensionReceiver?.receiver?.receiverValue
|
||||||
override fun getDispatchReceiver() = candidate.dispatchReceiverArgument?.receiver?.receiverValue
|
override fun getDispatchReceiver() = candidate.dispatchReceiverArgument?.receiver?.receiverValue
|
||||||
override fun getExplicitReceiverKind() = candidate.explicitReceiverKind
|
override fun getExplicitReceiverKind() = candidate.explicitReceiverKind
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.resolve.TypeResolver
|
|||||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.KotlinCallResolver
|
import org.jetbrains.kotlin.resolve.calls.KotlinCallResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.createLookupLocation
|
import org.jetbrains.kotlin.resolve.calls.callUtil.createLookupLocation
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.ArgumentsToParametersMapper
|
import org.jetbrains.kotlin.resolve.calls.components.ArgumentsToParametersMapper
|
||||||
@@ -50,6 +51,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
|||||||
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallableDescriptors
|
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallableDescriptors
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate
|
import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
|
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
@@ -378,7 +380,22 @@ class PSICallResolver(
|
|||||||
is QualifierReceiver -> QualifierReceiverKotlinCallArgument(oldReceiver) // todo report warning if isSafeCall
|
is QualifierReceiver -> QualifierReceiverKotlinCallArgument(oldReceiver) // todo report warning if isSafeCall
|
||||||
is ReceiverValue -> {
|
is ReceiverValue -> {
|
||||||
val detailedReceiver = context.transformToReceiverWithSmartCastInfo(oldReceiver)
|
val detailedReceiver = context.transformToReceiverWithSmartCastInfo(oldReceiver)
|
||||||
ReceiverExpressionKotlinCallArgument(detailedReceiver, isSafeCall)
|
|
||||||
|
var subCallArgument: ReceiverKotlinCallArgument? = null
|
||||||
|
if (oldReceiver is ExpressionReceiver) {
|
||||||
|
val ktExpression = KtPsiUtil.getLastElementDeparenthesized(oldReceiver.expression, context.statementFilter)
|
||||||
|
|
||||||
|
val onlyResolvedCall = ktExpression?.getCall(context.trace.bindingContext)?.let {
|
||||||
|
context.trace.get(BindingContext.ONLY_RESOLVED_CALL, it)
|
||||||
|
}
|
||||||
|
if (onlyResolvedCall != null) {
|
||||||
|
subCallArgument = SubKotlinCallArgumentImpl(CallMaker.makeExternalValueArgument(oldReceiver.expression),
|
||||||
|
context.dataFlowInfo, context.dataFlowInfo, detailedReceiver, onlyResolvedCall)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
subCallArgument ?: ReceiverExpressionKotlinCallArgument(detailedReceiver, isSafeCall)
|
||||||
}
|
}
|
||||||
else -> error("Incorrect receiver: $oldReceiver")
|
else -> error("Incorrect receiver: $oldReceiver")
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCall
|
import org.jetbrains.kotlin.resolve.calls.model.KotlinCall
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor
|
import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor
|
||||||
|
|
||||||
@@ -41,9 +42,11 @@ class TypeVariableTypeConstructor(private val builtIns: KotlinBuiltIns, val debu
|
|||||||
sealed class NewTypeVariable(builtIns: KotlinBuiltIns, name: String) {
|
sealed class NewTypeVariable(builtIns: KotlinBuiltIns, name: String) {
|
||||||
val freshTypeConstructor: TypeConstructor = TypeVariableTypeConstructor(builtIns, name)
|
val freshTypeConstructor: TypeConstructor = TypeVariableTypeConstructor(builtIns, name)
|
||||||
|
|
||||||
|
// member scope is used if we have receiver with type TypeVariable(T)
|
||||||
|
// todo add to member scope methods from supertypes for type variable
|
||||||
val defaultType: SimpleType = KotlinTypeFactory.simpleType(
|
val defaultType: SimpleType = KotlinTypeFactory.simpleType(
|
||||||
Annotations.EMPTY, freshTypeConstructor, arguments = emptyList(),
|
Annotations.EMPTY, freshTypeConstructor, arguments = emptyList(),
|
||||||
nullable = false, memberScope = ErrorUtils.createErrorScope("Type variable", true))
|
nullable = false, memberScope = builtIns.any.unsubstitutedMemberScope)
|
||||||
|
|
||||||
override fun toString() = freshTypeConstructor.toString()
|
override fun toString() = freshTypeConstructor.toString()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user