From 4dbd4a56d5a0fe732093c515787554a3f5a4a7f5 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Fri, 22 May 2020 13:08:19 +0300 Subject: [PATCH] Compose: adapt new API for intercepting candidates in call resolvers Most part is made by @lelandrichardson --- .../internal/CandidateInterceptor.kt | 71 ++++++++++++------ .../internal/NonStableExtensionPoints.kt | 65 +++++++++++++--- .../calls/tower/NewResolutionOldInference.kt | 20 ++++- .../resolve/calls/tower/PSICallResolver.kt | 43 +++++++++-- .../resolve/calls/tower/ImplicitScopeTower.kt | 15 +++- .../kotlin/resolve/calls/tower/TowerLevels.kt | 74 +++++++++++++++---- 6 files changed, 229 insertions(+), 59 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/extensions/internal/CandidateInterceptor.kt b/compiler/frontend/src/org/jetbrains/kotlin/extensions/internal/CandidateInterceptor.kt index 00acaa14832..dc8c6a35352 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/extensions/internal/CandidateInterceptor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/extensions/internal/CandidateInterceptor.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.extensions.internal import com.intellij.openapi.project.Project import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.name.Name @@ -18,7 +19,9 @@ import org.jetbrains.kotlin.resolve.calls.model.CallResolutionResult import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower import org.jetbrains.kotlin.resolve.calls.tower.NewResolutionOldInference +import org.jetbrains.kotlin.resolve.calls.tower.PSICallResolver import org.jetbrains.kotlin.resolve.scopes.ResolutionScope +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo @OptIn(InternalNonStableExtensionPoints::class) class CandidateInterceptor(project: Project) { @@ -28,7 +31,7 @@ class CandidateInterceptor(project: Project) { candidates: Collection, context: BasicCallResolutionContext, candidateResolver: CandidateResolver, - callResolver: CallResolver?, + callResolver: CallResolver, name: Name, kind: NewResolutionOldInference.ResolutionKind, tracing: TracingStrategy @@ -36,34 +39,58 @@ class CandidateInterceptor(project: Project) { extension.interceptCandidates(it, context, candidateResolver, callResolver, name, kind, tracing) } - fun interceptResolvedCandidates( - callResolutionResult: CallResolutionResult, - context: BasicCallResolutionContext, - callResolver: KotlinCallResolver, - name: Name, - kind: NewResolutionOldInference.ResolutionKind, - tracing: TracingStrategy - ): CallResolutionResult { - var resolutionResult = callResolutionResult - for (extension in extensions) { - resolutionResult = extension.interceptCandidates( - resolutionResult, context, callResolver, name, kind, tracing - ) - } - - return resolutionResult - } - - fun interceptCandidates( + fun interceptFunctionCandidates( candidates: Collection, scopeTower: ImplicitScopeTower, resolutionContext: BasicCallResolutionContext, resolutionScope: ResolutionScope, - callResolver: CallResolver?, + callResolver: CallResolver, name: Name, location: LookupLocation ): Collection = extensions.fold(candidates) { it, extension -> - extension.interceptCandidates(it, scopeTower, resolutionContext, resolutionScope, callResolver, name, location) + extension.interceptFunctionCandidates(it, scopeTower, resolutionContext, resolutionScope, callResolver, name, location) + } + + fun interceptFunctionCandidates( + candidates: Collection, + scopeTower: ImplicitScopeTower, + resolutionContext: BasicCallResolutionContext, + resolutionScope: ResolutionScope, + callResolver: PSICallResolver, + name: Name, + location: LookupLocation, + dispatchReceiver: ReceiverValueWithSmartCastInfo?, + extensionReceiver: ReceiverValueWithSmartCastInfo? + ): Collection = extensions.fold(candidates) { it, extension -> + extension.interceptFunctionCandidates( + it, scopeTower, resolutionContext, resolutionScope, callResolver, name, location, dispatchReceiver, extensionReceiver + ) + } + + fun interceptVariableCandidates( + candidates: Collection, + scopeTower: ImplicitScopeTower, + resolutionContext: BasicCallResolutionContext, + resolutionScope: ResolutionScope, + callResolver: CallResolver, + name: Name, + location: LookupLocation + ): Collection = extensions.fold(candidates) { it, extension -> + extension.interceptVariableCandidates(it, scopeTower, resolutionContext, resolutionScope, callResolver, name, location) + } + + fun interceptVariableCandidates( + candidates: Collection, + scopeTower: ImplicitScopeTower, + resolutionContext: BasicCallResolutionContext, + resolutionScope: ResolutionScope, + callResolver: PSICallResolver, + name: Name, + location: LookupLocation, + dispatchReceiver: ReceiverValueWithSmartCastInfo?, + extensionReceiver: ReceiverValueWithSmartCastInfo? + ): Collection = extensions.fold(candidates) { it, extension -> + extension.interceptVariableCandidates(it, scopeTower, resolutionContext, resolutionScope, callResolver, name, location, dispatchReceiver, extensionReceiver) } companion object : ProjectExtensionDescriptor( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/extensions/internal/NonStableExtensionPoints.kt b/compiler/frontend/src/org/jetbrains/kotlin/extensions/internal/NonStableExtensionPoints.kt index 81231351025..565daab4ee0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/extensions/internal/NonStableExtensionPoints.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/extensions/internal/NonStableExtensionPoints.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.extensions.internal import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.name.Name @@ -13,13 +14,13 @@ import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtLambdaExpression import org.jetbrains.kotlin.resolve.calls.CallResolver import org.jetbrains.kotlin.resolve.calls.CandidateResolver -import org.jetbrains.kotlin.resolve.calls.KotlinCallResolver import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext -import org.jetbrains.kotlin.resolve.calls.model.CallResolutionResult import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower import org.jetbrains.kotlin.resolve.calls.tower.NewResolutionOldInference +import org.jetbrains.kotlin.resolve.calls.tower.PSICallResolver import org.jetbrains.kotlin.resolve.scopes.ResolutionScope +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext @@ -51,26 +52,68 @@ interface TypeResolutionInterceptorExtension { @InternalNonStableExtensionPoints interface CallResolutionInterceptorExtension { + @JvmDefault fun interceptCandidates( candidates: Collection, context: BasicCallResolutionContext, candidateResolver: CandidateResolver, - callResolver: CallResolver?, + callResolver: CallResolver, name: Name, kind: NewResolutionOldInference.ResolutionKind, tracing: TracingStrategy ): Collection = candidates @JvmDefault - fun interceptCandidates( - callResolutionResult: CallResolutionResult, - context: BasicCallResolutionContext, - callResolver: KotlinCallResolver, + fun interceptFunctionCandidates( + candidates: Collection, + scopeTower: ImplicitScopeTower, + resolutionContext: BasicCallResolutionContext, + resolutionScope: ResolutionScope, + callResolver: CallResolver, name: Name, - kind: NewResolutionOldInference.ResolutionKind, - tracing: TracingStrategy - ): CallResolutionResult = callResolutionResult + location: LookupLocation + ): Collection = candidates + @JvmDefault + fun interceptFunctionCandidates( + candidates: Collection, + scopeTower: ImplicitScopeTower, + resolutionContext: BasicCallResolutionContext, + resolutionScope: ResolutionScope, + callResolver: PSICallResolver, + name: Name, + location: LookupLocation, + dispatchReceiver: ReceiverValueWithSmartCastInfo?, + extensionReceiver: ReceiverValueWithSmartCastInfo? + ): Collection = candidates + + @JvmDefault + fun interceptVariableCandidates( + candidates: Collection, + scopeTower: ImplicitScopeTower, + resolutionContext: BasicCallResolutionContext, + resolutionScope: ResolutionScope, + callResolver: CallResolver, + name: Name, + location: LookupLocation + ): Collection = candidates + + @JvmDefault + fun interceptVariableCandidates( + candidates: Collection, + scopeTower: ImplicitScopeTower, + resolutionContext: BasicCallResolutionContext, + resolutionScope: ResolutionScope, + callResolver: PSICallResolver, + name: Name, + location: LookupLocation, + dispatchReceiver: ReceiverValueWithSmartCastInfo?, + extensionReceiver: ReceiverValueWithSmartCastInfo? + ): Collection = candidates + + @Suppress("DeprecatedCallableAddReplaceWith") + @Deprecated("Please use dedicated interceptVariableCandidates and interceptFunctionCandidates instead") + @JvmDefault fun interceptCandidates( candidates: Collection, scopeTower: ImplicitScopeTower, @@ -80,4 +123,4 @@ interface CallResolutionInterceptorExtension { name: Name, location: LookupLocation ): Collection = candidates -} +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt index b5a58d3b607..578ad57381c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt @@ -379,13 +379,27 @@ class NewResolutionOldInference( override val isNewInferenceEnabled: Boolean get() = resolutionContext.languageVersionSettings.supportsFeature(LanguageFeature.NewInference) - override fun interceptCandidates( + + override fun interceptFunctionCandidates( resolutionScope: ResolutionScope, name: Name, initialResults: Collection, - location: LookupLocation + location: LookupLocation, + dispatchReceiver: ReceiverValueWithSmartCastInfo?, + extensionReceiver: ReceiverValueWithSmartCastInfo? ): Collection { - return candidateInterceptor.interceptCandidates(initialResults, this, resolutionContext, resolutionScope, callResolver, name, location) + return candidateInterceptor.interceptFunctionCandidates(initialResults, this, resolutionContext, resolutionScope, callResolver, name, location) + } + + override fun interceptVariableCandidates( + resolutionScope: ResolutionScope, + name: Name, + initialResults: Collection, + location: LookupLocation, + dispatchReceiver: ReceiverValueWithSmartCastInfo?, + extensionReceiver: ReceiverValueWithSmartCastInfo? + ): Collection { + return candidateInterceptor.interceptVariableCandidates(initialResults, this, resolutionContext, resolutionScope, callResolver, name, location) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index e3e0c8ac86e..b8a87f497cf 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -110,10 +110,6 @@ class PSICallResolver( return OverloadResolutionResultsImpl.nameNotFound() } - result = candidateInterceptor.interceptResolvedCandidates( - result, context, kotlinCallResolver, name, resolutionKind, tracingStrategy - ) - val overloadResolutionResults = convertToOverloadResolutionResults(context, result, tracingStrategy) return overloadResolutionResults.also { clearCacheForApproximationResults() @@ -407,13 +403,46 @@ class PSICallResolver( } } - override fun interceptCandidates( + override fun interceptFunctionCandidates( resolutionScope: ResolutionScope, name: Name, initialResults: Collection, - location: LookupLocation + location: LookupLocation, + dispatchReceiver: ReceiverValueWithSmartCastInfo?, + extensionReceiver: ReceiverValueWithSmartCastInfo? ): Collection { - return candidateInterceptor.interceptCandidates(initialResults, this, context, resolutionScope, null, name, location) + return candidateInterceptor.interceptFunctionCandidates( + initialResults, + this, + context, + resolutionScope, + this@PSICallResolver, + name, + location, + dispatchReceiver, + extensionReceiver + ) + } + + override fun interceptVariableCandidates( + resolutionScope: ResolutionScope, + name: Name, + initialResults: Collection, + location: LookupLocation, + dispatchReceiver: ReceiverValueWithSmartCastInfo?, + extensionReceiver: ReceiverValueWithSmartCastInfo? + ): Collection { + return candidateInterceptor.interceptVariableCandidates( + initialResults, + this, + context, + resolutionScope, + this@PSICallResolver, + name, + location, + dispatchReceiver, + extensionReceiver + ) } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt index 029ea406cdb..576ab7c0eb9 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt @@ -44,12 +44,23 @@ interface ImplicitScopeTower { val typeApproximator: TypeApproximator - fun interceptCandidates( + fun interceptFunctionCandidates( resolutionScope: ResolutionScope, name: Name, initialResults: Collection, - location: LookupLocation + location: LookupLocation, + dispatchReceiver: ReceiverValueWithSmartCastInfo?, + extensionReceiver: ReceiverValueWithSmartCastInfo? ): Collection + + fun interceptVariableCandidates( + resolutionScope: ResolutionScope, + name: Name, + initialResults: Collection, + location: LookupLocation, + dispatchReceiver: ReceiverValueWithSmartCastInfo?, + extensionReceiver: ReceiverValueWithSmartCastInfo? + ): Collection } interface ScopeTowerLevel { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt index 4031c6fd2e2..80817debabe 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt @@ -163,7 +163,7 @@ internal class MemberScopeTowerLevel( name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo? ): Collection { - return collectMembers { getContributedVariables(name, location) } + return collectMembers { getContributedVariablesAndIntercept(name, location, dispatchReceiver, extensionReceiver, scopeTower) } } override fun getObjects( @@ -178,8 +178,10 @@ internal class MemberScopeTowerLevel( extensionReceiver: ReceiverValueWithSmartCastInfo? ): Collection { return collectMembers { - getContributedFunctions(name, location) + it.getInnerConstructors(name, location) + - syntheticScopes.collectSyntheticMemberFunctions(listOfNotNull(it), name, location) + getContributedFunctionsAndIntercept(name, location, dispatchReceiver, extensionReceiver, scopeTower) + it.getInnerConstructors( + name, + location + ) + syntheticScopes.collectSyntheticMemberFunctions(listOfNotNull(it), name, location) } } @@ -193,9 +195,15 @@ internal class MemberScopeTowerLevel( internal class QualifierScopeTowerLevel(scopeTower: ImplicitScopeTower, val qualifier: QualifierReceiver) : AbstractScopeTowerLevel(scopeTower) { override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope - .getContributedVariables(name, location).map { - createCandidateDescriptor(it, dispatchReceiver = null) - } + .getContributedVariablesAndIntercept( + name, + location, + qualifier.classValueReceiverWithSmartCastInfo, + extensionReceiver, + scopeTower + ).map { + createCandidateDescriptor(it, dispatchReceiver = null) + } override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope .getContributedObjectVariables(name, location).map { @@ -206,10 +214,12 @@ internal class QualifierScopeTowerLevel(scopeTower: ImplicitScopeTower, val qual .getContributedFunctionsAndConstructors( name, location, + qualifier.classValueReceiverWithSmartCastInfo, + extensionReceiver, scopeTower ).map { - createCandidateDescriptor(it, dispatchReceiver = null) - } + createCandidateDescriptor(it, dispatchReceiver = null) + } override fun recordLookup(name: Name) {} } @@ -228,7 +238,13 @@ internal open class ScopeBasedTowerLevel protected constructor( override fun getVariables( name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo? - ): Collection = resolutionScope.getContributedVariables(name, location).map { + ): Collection = resolutionScope.getContributedVariablesAndIntercept( + name, + location, + null, + extensionReceiver, + scopeTower + ).map { createCandidateDescriptor( it, dispatchReceiver = null, @@ -254,7 +270,7 @@ internal open class ScopeBasedTowerLevel protected constructor( ): Collection { val result: ArrayList = ArrayList() - resolutionScope.getContributedFunctionsAndConstructors(name, location, scopeTower).mapTo(result) { + resolutionScope.getContributedFunctionsAndConstructors(name, location, null, extensionReceiver, scopeTower).mapTo(result) { createCandidateDescriptor( it, dispatchReceiver = null, @@ -338,8 +354,8 @@ internal class HidesMembersTowerLevel(scopeTower: ImplicitScopeTower) : Abstract return scopeTower.lexicalScope.collectCandidates(name, location).filter { it.extensionReceiverParameter != null && it.hasHidesMembersAnnotation() }.map { - createCandidateDescriptor(it, dispatchReceiver = null) - } + createCandidateDescriptor(it, dispatchReceiver = null) + } } override fun recordLookup(name: Name) {} @@ -362,6 +378,8 @@ private fun KotlinType?.getInnerConstructors(name: Name, location: LookupLocatio private fun ResolutionScope.getContributedFunctionsAndConstructors( name: Name, location: LookupLocation, + dispatchReceiver: ReceiverValueWithSmartCastInfo?, + extensionReceiver: ReceiverValueWithSmartCastInfo?, scopeTower: ImplicitScopeTower ): Collection { val result = ArrayList(getContributedFunctions(name, location)) @@ -373,7 +391,32 @@ private fun ResolutionScope.getContributedFunctionsAndConstructors( result.addAll(scopeTower.syntheticScopes.collectSyntheticStaticFunctions(this, name, location)) result.addAll(scopeTower.syntheticScopes.collectSyntheticConstructors(this, name, location)) - return scopeTower.interceptCandidates(this, name, result, location) + return scopeTower.interceptFunctionCandidates(this, name, result, location, dispatchReceiver, extensionReceiver) +} + + +private fun ResolutionScope.getContributedVariablesAndIntercept( + name: Name, + location: LookupLocation, + dispatchReceiver: ReceiverValueWithSmartCastInfo?, + extensionReceiver: ReceiverValueWithSmartCastInfo?, + scopeTower: ImplicitScopeTower +): Collection { + val result = getContributedVariables(name, location) + + return scopeTower.interceptVariableCandidates(this, name, result, location, dispatchReceiver, extensionReceiver) +} + +private fun ResolutionScope.getContributedFunctionsAndIntercept( + name: Name, + location: LookupLocation, + dispatchReceiver: ReceiverValueWithSmartCastInfo?, + extensionReceiver: ReceiverValueWithSmartCastInfo?, + scopeTower: ImplicitScopeTower +): Collection { + val result = getContributedFunctions(name, location) + + return scopeTower.interceptFunctionCandidates(this, name, result, location, dispatchReceiver, extensionReceiver) } private fun getConstructorsOfClassifier(classifier: ClassifierDescriptor?): List { @@ -391,7 +434,10 @@ private fun ResolutionScope.getContributedObjectVariables(name: Name, location: return listOfNotNull(objectDescriptor) } -private fun ResolutionScope.getContributedObjectVariablesIncludeDeprecated(name: Name, location: LookupLocation): Collection> { +private fun ResolutionScope.getContributedObjectVariablesIncludeDeprecated( + name: Name, + location: LookupLocation +): Collection> { val (classifier, isOwnerDeprecated) = getContributedClassifierIncludeDeprecated(name, location) ?: return emptyList() val objectDescriptor = getFakeDescriptorForObject(classifier) ?: return emptyList() return listOf(DescriptorWithDeprecation(objectDescriptor, isOwnerDeprecated))