Compose: adapt new API for intercepting candidates in call resolvers

Most part is made by @lelandrichardson
This commit is contained in:
Mikhail Zarechenskiy
2020-05-22 13:08:19 +03:00
parent 500acf412f
commit 4dbd4a56d5
6 changed files with 229 additions and 59 deletions
@@ -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<NewResolutionOldInference.MyCandidate>,
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<FunctionDescriptor>,
scopeTower: ImplicitScopeTower,
resolutionContext: BasicCallResolutionContext,
resolutionScope: ResolutionScope,
callResolver: CallResolver?,
callResolver: CallResolver,
name: Name,
location: LookupLocation
): Collection<FunctionDescriptor> = 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<FunctionDescriptor>,
scopeTower: ImplicitScopeTower,
resolutionContext: BasicCallResolutionContext,
resolutionScope: ResolutionScope,
callResolver: PSICallResolver,
name: Name,
location: LookupLocation,
dispatchReceiver: ReceiverValueWithSmartCastInfo?,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<FunctionDescriptor> = extensions.fold(candidates) { it, extension ->
extension.interceptFunctionCandidates(
it, scopeTower, resolutionContext, resolutionScope, callResolver, name, location, dispatchReceiver, extensionReceiver
)
}
fun interceptVariableCandidates(
candidates: Collection<VariableDescriptor>,
scopeTower: ImplicitScopeTower,
resolutionContext: BasicCallResolutionContext,
resolutionScope: ResolutionScope,
callResolver: CallResolver,
name: Name,
location: LookupLocation
): Collection<VariableDescriptor> = extensions.fold(candidates) { it, extension ->
extension.interceptVariableCandidates(it, scopeTower, resolutionContext, resolutionScope, callResolver, name, location)
}
fun interceptVariableCandidates(
candidates: Collection<VariableDescriptor>,
scopeTower: ImplicitScopeTower,
resolutionContext: BasicCallResolutionContext,
resolutionScope: ResolutionScope,
callResolver: PSICallResolver,
name: Name,
location: LookupLocation,
dispatchReceiver: ReceiverValueWithSmartCastInfo?,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<VariableDescriptor> = extensions.fold(candidates) { it, extension ->
extension.interceptVariableCandidates(it, scopeTower, resolutionContext, resolutionScope, callResolver, name, location, dispatchReceiver, extensionReceiver)
}
companion object : ProjectExtensionDescriptor<CallResolutionInterceptorExtension>(
@@ -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<NewResolutionOldInference.MyCandidate>,
context: BasicCallResolutionContext,
candidateResolver: CandidateResolver,
callResolver: CallResolver?,
callResolver: CallResolver,
name: Name,
kind: NewResolutionOldInference.ResolutionKind,
tracing: TracingStrategy
): Collection<NewResolutionOldInference.MyCandidate> = candidates
@JvmDefault
fun interceptCandidates(
callResolutionResult: CallResolutionResult,
context: BasicCallResolutionContext,
callResolver: KotlinCallResolver,
fun interceptFunctionCandidates(
candidates: Collection<FunctionDescriptor>,
scopeTower: ImplicitScopeTower,
resolutionContext: BasicCallResolutionContext,
resolutionScope: ResolutionScope,
callResolver: CallResolver,
name: Name,
kind: NewResolutionOldInference.ResolutionKind,
tracing: TracingStrategy
): CallResolutionResult = callResolutionResult
location: LookupLocation
): Collection<FunctionDescriptor> = candidates
@JvmDefault
fun interceptFunctionCandidates(
candidates: Collection<FunctionDescriptor>,
scopeTower: ImplicitScopeTower,
resolutionContext: BasicCallResolutionContext,
resolutionScope: ResolutionScope,
callResolver: PSICallResolver,
name: Name,
location: LookupLocation,
dispatchReceiver: ReceiverValueWithSmartCastInfo?,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<FunctionDescriptor> = candidates
@JvmDefault
fun interceptVariableCandidates(
candidates: Collection<VariableDescriptor>,
scopeTower: ImplicitScopeTower,
resolutionContext: BasicCallResolutionContext,
resolutionScope: ResolutionScope,
callResolver: CallResolver,
name: Name,
location: LookupLocation
): Collection<VariableDescriptor> = candidates
@JvmDefault
fun interceptVariableCandidates(
candidates: Collection<VariableDescriptor>,
scopeTower: ImplicitScopeTower,
resolutionContext: BasicCallResolutionContext,
resolutionScope: ResolutionScope,
callResolver: PSICallResolver,
name: Name,
location: LookupLocation,
dispatchReceiver: ReceiverValueWithSmartCastInfo?,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<VariableDescriptor> = candidates
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("Please use dedicated interceptVariableCandidates and interceptFunctionCandidates instead")
@JvmDefault
fun interceptCandidates(
candidates: Collection<FunctionDescriptor>,
scopeTower: ImplicitScopeTower,
@@ -80,4 +123,4 @@ interface CallResolutionInterceptorExtension {
name: Name,
location: LookupLocation
): Collection<FunctionDescriptor> = candidates
}
}
@@ -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<FunctionDescriptor>,
location: LookupLocation
location: LookupLocation,
dispatchReceiver: ReceiverValueWithSmartCastInfo?,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<FunctionDescriptor> {
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<VariableDescriptor>,
location: LookupLocation,
dispatchReceiver: ReceiverValueWithSmartCastInfo?,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<VariableDescriptor> {
return candidateInterceptor.interceptVariableCandidates(initialResults, this, resolutionContext, resolutionScope, callResolver, name, location)
}
}
@@ -110,10 +110,6 @@ class PSICallResolver(
return OverloadResolutionResultsImpl.nameNotFound()
}
result = candidateInterceptor.interceptResolvedCandidates(
result, context, kotlinCallResolver, name, resolutionKind, tracingStrategy
)
val overloadResolutionResults = convertToOverloadResolutionResults<D>(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<FunctionDescriptor>,
location: LookupLocation
location: LookupLocation,
dispatchReceiver: ReceiverValueWithSmartCastInfo?,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<FunctionDescriptor> {
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<VariableDescriptor>,
location: LookupLocation,
dispatchReceiver: ReceiverValueWithSmartCastInfo?,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<VariableDescriptor> {
return candidateInterceptor.interceptVariableCandidates(
initialResults,
this,
context,
resolutionScope,
this@PSICallResolver,
name,
location,
dispatchReceiver,
extensionReceiver
)
}
}
@@ -44,12 +44,23 @@ interface ImplicitScopeTower {
val typeApproximator: TypeApproximator
fun interceptCandidates(
fun interceptFunctionCandidates(
resolutionScope: ResolutionScope,
name: Name,
initialResults: Collection<FunctionDescriptor>,
location: LookupLocation
location: LookupLocation,
dispatchReceiver: ReceiverValueWithSmartCastInfo?,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<FunctionDescriptor>
fun interceptVariableCandidates(
resolutionScope: ResolutionScope,
name: Name,
initialResults: Collection<VariableDescriptor>,
location: LookupLocation,
dispatchReceiver: ReceiverValueWithSmartCastInfo?,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<VariableDescriptor>
}
interface ScopeTowerLevel {
@@ -163,7 +163,7 @@ internal class MemberScopeTowerLevel(
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> {
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<CandidateWithBoundDispatchReceiver> {
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<CandidateWithBoundDispatchReceiver> = resolutionScope.getContributedVariables(name, location).map {
): Collection<CandidateWithBoundDispatchReceiver> = resolutionScope.getContributedVariablesAndIntercept(
name,
location,
null,
extensionReceiver,
scopeTower
).map {
createCandidateDescriptor(
it,
dispatchReceiver = null,
@@ -254,7 +270,7 @@ internal open class ScopeBasedTowerLevel protected constructor(
): Collection<CandidateWithBoundDispatchReceiver> {
val result: ArrayList<CandidateWithBoundDispatchReceiver> = 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<FunctionDescriptor> {
val result = ArrayList<FunctionDescriptor>(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<VariableDescriptor> {
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<FunctionDescriptor> {
val result = getContributedFunctions(name, location)
return scopeTower.interceptFunctionCandidates(this, name, result, location, dispatchReceiver, extensionReceiver)
}
private fun getConstructorsOfClassifier(classifier: ClassifierDescriptor?): List<ConstructorDescriptor> {
@@ -391,7 +434,10 @@ private fun ResolutionScope.getContributedObjectVariables(name: Name, location:
return listOfNotNull(objectDescriptor)
}
private fun ResolutionScope.getContributedObjectVariablesIncludeDeprecated(name: Name, location: LookupLocation): Collection<DescriptorWithDeprecation<VariableDescriptor>> {
private fun ResolutionScope.getContributedObjectVariablesIncludeDeprecated(
name: Name,
location: LookupLocation
): Collection<DescriptorWithDeprecation<VariableDescriptor>> {
val (classifier, isOwnerDeprecated) = getContributedClassifierIncludeDeprecated(name, location) ?: return emptyList()
val objectDescriptor = getFakeDescriptorForObject(classifier) ?: return emptyList()
return listOf(DescriptorWithDeprecation(objectDescriptor, isOwnerDeprecated))