FIR: Extract LevelHandler and CallResolutionContext from TowerManager
This commit is contained in:
@@ -265,7 +265,7 @@ class FirCallResolver(
|
|||||||
implicitReceiverStack.receiversAsReversed(),
|
implicitReceiverStack.receiversAsReversed(),
|
||||||
info,
|
info,
|
||||||
collector = CandidateCollector(this, resolutionStageRunner),
|
collector = CandidateCollector(this, resolutionStageRunner),
|
||||||
manager = TowerResolveManager(towerResolver),
|
manager = TowerResolveManager(),
|
||||||
)
|
)
|
||||||
val bestCandidates = result.bestCandidates()
|
val bestCandidates = result.bestCandidates()
|
||||||
val noSuccessfulCandidates = result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED
|
val noSuccessfulCandidates = result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED
|
||||||
|
|||||||
+37
-16
@@ -42,7 +42,7 @@ class FirTowerResolver(
|
|||||||
|
|
||||||
private val session: FirSession get() = components.session
|
private val session: FirSession get() = components.session
|
||||||
private val collector = CandidateCollector(components, resolutionStageRunner)
|
private val collector = CandidateCollector(components, resolutionStageRunner)
|
||||||
private val manager = TowerResolveManager(this)
|
private val manager = TowerResolveManager()
|
||||||
private lateinit var implicitReceivers: List<ImplicitReceiver>
|
private lateinit var implicitReceivers: List<ImplicitReceiver>
|
||||||
private lateinit var implicitReceiversUsableAsValues: List<ImplicitReceiver>
|
private lateinit var implicitReceiversUsableAsValues: List<ImplicitReceiver>
|
||||||
|
|
||||||
@@ -546,21 +546,7 @@ class FirTowerResolver(
|
|||||||
): CandidateCollector {
|
): CandidateCollector {
|
||||||
// TODO: add flag receiver / non-receiver position
|
// TODO: add flag receiver / non-receiver position
|
||||||
prepareImplicitReceivers(implicitReceiverValues)
|
prepareImplicitReceivers(implicitReceiverValues)
|
||||||
val candidateFactory = CandidateFactory(components, info)
|
manager.callResolutionContext = buildCallResolutionContext(info, collector)
|
||||||
manager.candidateFactory = candidateFactory
|
|
||||||
if (info.callKind == CallKind.CallableReference && info.stubReceiver != null) {
|
|
||||||
manager.stubReceiverCandidateFactory = candidateFactory.replaceCallInfo(info.replaceExplicitReceiver(info.stubReceiver))
|
|
||||||
}
|
|
||||||
manager.resultCollector = collector
|
|
||||||
if (info.callKind == CallKind.Function) {
|
|
||||||
manager.invokeReceiverCollector = CandidateCollector(components, components.resolutionStageRunner)
|
|
||||||
manager.invokeReceiverCandidateFactory = CandidateFactory(components, info.replaceWithVariableAccess())
|
|
||||||
if (info.explicitReceiver != null) {
|
|
||||||
with(manager.invokeReceiverCandidateFactory) {
|
|
||||||
manager.invokeBuiltinExtensionReceiverCandidateFactory = replaceCallInfo(callInfo.replaceExplicitReceiver(null))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
when (val receiver = info.explicitReceiver) {
|
when (val receiver = info.explicitReceiver) {
|
||||||
is FirResolvedQualifier -> manager.enqueueResolverTask { runResolverForQualifierReceiver(info, receiver, manager) }
|
is FirResolvedQualifier -> manager.enqueueResolverTask { runResolverForQualifierReceiver(info, receiver, manager) }
|
||||||
@@ -579,6 +565,41 @@ class FirTowerResolver(
|
|||||||
return collector
|
return collector
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun buildCallResolutionContext(
|
||||||
|
info: CallInfo,
|
||||||
|
collector: CandidateCollector
|
||||||
|
): CallResolutionContext {
|
||||||
|
val candidateFactory = CandidateFactory(components, info)
|
||||||
|
val stubReceiverCandidateFactory =
|
||||||
|
if (info.callKind == CallKind.CallableReference && info.stubReceiver != null)
|
||||||
|
candidateFactory.replaceCallInfo(info.replaceExplicitReceiver(info.stubReceiver))
|
||||||
|
else
|
||||||
|
null
|
||||||
|
|
||||||
|
var invokeReceiverCollector: CandidateCollector? = null
|
||||||
|
var invokeReceiverCandidateFactory: CandidateFactory? = null
|
||||||
|
var invokeBuiltinExtensionReceiverCandidateFactory: CandidateFactory? = null
|
||||||
|
if (info.callKind == CallKind.Function) {
|
||||||
|
invokeReceiverCollector = CandidateCollector(components, components.resolutionStageRunner)
|
||||||
|
invokeReceiverCandidateFactory = CandidateFactory(components, info.replaceWithVariableAccess())
|
||||||
|
if (info.explicitReceiver != null) {
|
||||||
|
with(invokeReceiverCandidateFactory) {
|
||||||
|
invokeBuiltinExtensionReceiverCandidateFactory = replaceCallInfo(callInfo.replaceExplicitReceiver(null))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CallResolutionContext(
|
||||||
|
candidateFactory,
|
||||||
|
collector,
|
||||||
|
invokeReceiverCandidateFactory,
|
||||||
|
invokeBuiltinExtensionReceiverCandidateFactory,
|
||||||
|
stubReceiverCandidateFactory,
|
||||||
|
invokeReceiverCollector,
|
||||||
|
this
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
collector.newDataSet()
|
collector.newDataSet()
|
||||||
manager.reset()
|
manager.reset()
|
||||||
|
|||||||
@@ -0,0 +1,290 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.resolve.calls
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessExpressionBuilder
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.constructType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||||
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
|
internal class CallResolutionContext(
|
||||||
|
val candidateFactory: CandidateFactory,
|
||||||
|
val resultCollector: CandidateCollector,
|
||||||
|
val invokeReceiverCandidateFactory: CandidateFactory?,
|
||||||
|
val invokeBuiltinExtensionReceiverCandidateFactory: CandidateFactory?,
|
||||||
|
val stubReceiverCandidateFactory: CandidateFactory?,
|
||||||
|
val invokeReceiverCollector: CandidateCollector?,
|
||||||
|
val towerResolver: FirTowerResolver
|
||||||
|
) {
|
||||||
|
// TODO: Get rid of the property, storing state here looks like a hack
|
||||||
|
internal lateinit var invokeOnGivenReceiverCandidateFactory: CandidateFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class LevelHandler(
|
||||||
|
private val info: CallInfo,
|
||||||
|
private val explicitReceiverKind: ExplicitReceiverKind,
|
||||||
|
private val group: TowerGroup,
|
||||||
|
private val callResolutionContext: CallResolutionContext,
|
||||||
|
private val manager: TowerResolveManager
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val resultCollector: CandidateCollector get() = callResolutionContext.resultCollector
|
||||||
|
private val towerResolver: FirTowerResolver get() = callResolutionContext.towerResolver
|
||||||
|
|
||||||
|
private fun enqueueResolverTask(group: TowerGroup = TowerGroup.Start, task: suspend () -> Unit) =
|
||||||
|
manager.enqueueResolverTask(group, task)
|
||||||
|
|
||||||
|
private fun createExplicitReceiverForInvoke(candidate: Candidate): FirQualifiedAccessExpressionBuilder {
|
||||||
|
val (name, typeRef) = when (val symbol = candidate.symbol) {
|
||||||
|
is FirCallableSymbol<*> -> {
|
||||||
|
symbol.callableId.callableName to towerResolver.typeCalculator.tryCalculateReturnType(symbol.firUnsafe())
|
||||||
|
}
|
||||||
|
is FirRegularClassSymbol -> {
|
||||||
|
symbol.classId.shortClassName to buildResolvedTypeRef {
|
||||||
|
type = symbol.constructType(emptyArray(), isNullable = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> throw AssertionError()
|
||||||
|
}
|
||||||
|
return FirQualifiedAccessExpressionBuilder().apply {
|
||||||
|
calleeReference = FirNamedReferenceWithCandidate(
|
||||||
|
null,
|
||||||
|
name,
|
||||||
|
candidate
|
||||||
|
)
|
||||||
|
dispatchReceiver = candidate.dispatchReceiverExpression()
|
||||||
|
this.typeRef = typeRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun SessionBasedTowerLevel.handleLevel(invokeResolveMode: InvokeResolveMode? = null): ProcessorAction {
|
||||||
|
var result = ProcessorAction.NONE
|
||||||
|
val processor =
|
||||||
|
TowerScopeLevelProcessor(
|
||||||
|
info.explicitReceiver,
|
||||||
|
explicitReceiverKind,
|
||||||
|
resultCollector,
|
||||||
|
// TODO: performance?
|
||||||
|
if (invokeResolveMode == InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER) {
|
||||||
|
callResolutionContext.invokeOnGivenReceiverCandidateFactory
|
||||||
|
} else callResolutionContext.candidateFactory,
|
||||||
|
group
|
||||||
|
)
|
||||||
|
when (info.callKind) {
|
||||||
|
CallKind.VariableAccess -> {
|
||||||
|
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor)
|
||||||
|
// TODO: more accurate condition, or process properties/object in some other way
|
||||||
|
if (!resultCollector.isSuccess() &&
|
||||||
|
(this !is ScopeTowerLevel || this.extensionReceiver == null)
|
||||||
|
) {
|
||||||
|
result += processElementsByName(TowerScopeLevel.Token.Objects, info.name, processor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CallKind.Function -> {
|
||||||
|
val invokeBuiltinExtensionMode =
|
||||||
|
invokeResolveMode == InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
|
||||||
|
if (!invokeBuiltinExtensionMode) {
|
||||||
|
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor)
|
||||||
|
}
|
||||||
|
if (invokeResolveMode == InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER ||
|
||||||
|
resultCollector.isSuccess()
|
||||||
|
) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
val invokeReceiverProcessor = TowerScopeLevelProcessor(
|
||||||
|
info.explicitReceiver,
|
||||||
|
explicitReceiverKind,
|
||||||
|
callResolutionContext.invokeReceiverCollector!!,
|
||||||
|
if (invokeBuiltinExtensionMode) callResolutionContext.invokeBuiltinExtensionReceiverCandidateFactory!!
|
||||||
|
else callResolutionContext.invokeReceiverCandidateFactory!!,
|
||||||
|
group
|
||||||
|
)
|
||||||
|
callResolutionContext.invokeReceiverCollector.newDataSet()
|
||||||
|
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, invokeReceiverProcessor)
|
||||||
|
if (this !is ScopeTowerLevel || this.extensionReceiver == null) {
|
||||||
|
result += processElementsByName(TowerScopeLevel.Token.Objects, info.name, invokeReceiverProcessor)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callResolutionContext.invokeReceiverCollector.isSuccess()) {
|
||||||
|
processInvokeReceiversCandidates(invokeBuiltinExtensionMode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CallKind.CallableReference -> {
|
||||||
|
val stubReceiver = info.stubReceiver
|
||||||
|
if (stubReceiver != null) {
|
||||||
|
val stubReceiverValue = ExpressionReceiverValue(stubReceiver)
|
||||||
|
val stubProcessor = TowerScopeLevelProcessor(
|
||||||
|
info.explicitReceiver,
|
||||||
|
if (this is MemberScopeTowerLevel && dispatchReceiver is AbstractExplicitReceiver<*>) {
|
||||||
|
ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||||
|
} else {
|
||||||
|
ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||||
|
},
|
||||||
|
resultCollector,
|
||||||
|
callResolutionContext.stubReceiverCandidateFactory!!, group
|
||||||
|
)
|
||||||
|
val towerLevelWithStubReceiver = replaceReceiverValue(stubReceiverValue)
|
||||||
|
with(towerLevelWithStubReceiver) {
|
||||||
|
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, stubProcessor)
|
||||||
|
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, stubProcessor)
|
||||||
|
}
|
||||||
|
// NB: we don't perform this for implicit Unit
|
||||||
|
if (!resultCollector.isSuccess() && info.explicitReceiver?.typeRef !is FirImplicitBuiltinTypeRef) {
|
||||||
|
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor)
|
||||||
|
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor)
|
||||||
|
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processInvokeReceiversCandidates(invokeBuiltinExtensionMode: Boolean) {
|
||||||
|
for (invokeReceiverCandidate in callResolutionContext.invokeReceiverCollector!!.bestCandidates()) {
|
||||||
|
val symbol = invokeReceiverCandidate.symbol
|
||||||
|
if (symbol !is FirCallableSymbol<*> && symbol !is FirRegularClassSymbol) continue
|
||||||
|
|
||||||
|
val isExtensionFunctionType =
|
||||||
|
(symbol as? FirCallableSymbol<*>)?.fir?.returnTypeRef?.isExtensionFunctionType(towerResolver.components.session) == true
|
||||||
|
|
||||||
|
if (invokeBuiltinExtensionMode && !isExtensionFunctionType) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val extensionReceiverExpression = invokeReceiverCandidate.extensionReceiverExpression()
|
||||||
|
val useImplicitReceiverAsBuiltinInvokeArgument =
|
||||||
|
!invokeBuiltinExtensionMode && isExtensionFunctionType &&
|
||||||
|
invokeReceiverCandidate.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
||||||
|
|
||||||
|
val invokeReceiverExpression = createExplicitReceiverForInvoke(invokeReceiverCandidate).let {
|
||||||
|
if (!invokeBuiltinExtensionMode) {
|
||||||
|
it.extensionReceiver = extensionReceiverExpression
|
||||||
|
// NB: this should fix problem in DFA (KT-36014)
|
||||||
|
it.explicitReceiver = info.explicitReceiver
|
||||||
|
it.safe = info.isSafeCall
|
||||||
|
}
|
||||||
|
towerResolver.components.transformQualifiedAccessUsingSmartcastInfo(it.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
val invokeFunctionInfo =
|
||||||
|
info.copy(explicitReceiver = invokeReceiverExpression, name = OperatorNameConventions.INVOKE).let {
|
||||||
|
when {
|
||||||
|
invokeBuiltinExtensionMode -> it.withReceiverAsArgument(info.explicitReceiver!!)
|
||||||
|
else -> it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val explicitReceiver = ExpressionReceiverValue(invokeReceiverExpression)
|
||||||
|
callResolutionContext.invokeOnGivenReceiverCandidateFactory = CandidateFactory(towerResolver.components, invokeFunctionInfo)
|
||||||
|
when {
|
||||||
|
invokeBuiltinExtensionMode -> {
|
||||||
|
enqueueResolverTask {
|
||||||
|
towerResolver.runResolverForBuiltinInvokeExtensionWithExplicitArgument(
|
||||||
|
invokeFunctionInfo, explicitReceiver, manager
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
useImplicitReceiverAsBuiltinInvokeArgument -> {
|
||||||
|
enqueueResolverTask {
|
||||||
|
towerResolver.runResolverForBuiltinInvokeExtensionWithImplicitArgument(
|
||||||
|
invokeFunctionInfo, explicitReceiver, manager
|
||||||
|
)
|
||||||
|
}
|
||||||
|
enqueueResolverTask {
|
||||||
|
towerResolver.runResolverForInvoke(
|
||||||
|
invokeFunctionInfo, explicitReceiver, manager
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
enqueueResolverTask {
|
||||||
|
towerResolver.runResolverForInvoke(
|
||||||
|
invokeFunctionInfo, explicitReceiver, manager
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TowerScopeLevelProcessor(
|
||||||
|
val explicitReceiver: FirExpression?,
|
||||||
|
val explicitReceiverKind: ExplicitReceiverKind,
|
||||||
|
val resultCollector: CandidateCollector,
|
||||||
|
val candidateFactory: CandidateFactory,
|
||||||
|
val group: TowerGroup
|
||||||
|
) : TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>> {
|
||||||
|
override fun consumeCandidate(
|
||||||
|
symbol: AbstractFirBasedSymbol<*>,
|
||||||
|
dispatchReceiverValue: ReceiverValue?,
|
||||||
|
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
|
||||||
|
builtInExtensionFunctionReceiverValue: ReceiverValue?
|
||||||
|
) {
|
||||||
|
// Check explicit extension receiver for default package members
|
||||||
|
if (symbol is FirNamedFunctionSymbol && dispatchReceiverValue == null &&
|
||||||
|
(implicitExtensionReceiverValue == null) != (explicitReceiver == null) &&
|
||||||
|
explicitReceiver !is FirResolvedQualifier &&
|
||||||
|
symbol.callableId.packageName.startsWith(defaultPackage)
|
||||||
|
) {
|
||||||
|
val extensionReceiverType = explicitReceiver?.typeRef?.coneTypeSafe()
|
||||||
|
?: implicitExtensionReceiverValue?.type as? ConeClassLikeType
|
||||||
|
if (extensionReceiverType != null) {
|
||||||
|
val declarationReceiverTypeRef =
|
||||||
|
(symbol as? FirCallableSymbol<*>)?.fir?.receiverTypeRef as? FirResolvedTypeRef
|
||||||
|
val declarationReceiverType = declarationReceiverTypeRef?.type
|
||||||
|
if (declarationReceiverType is ConeClassLikeType) {
|
||||||
|
if (!AbstractTypeChecker.isSubtypeOf(
|
||||||
|
candidateFactory.bodyResolveComponents.inferenceComponents.ctx,
|
||||||
|
extensionReceiverType,
|
||||||
|
declarationReceiverType.lookupTag.constructClassType(
|
||||||
|
declarationReceiverType.typeArguments.map { ConeStarProjection }.toTypedArray(),
|
||||||
|
isNullable = true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ---
|
||||||
|
resultCollector.consumeCandidate(
|
||||||
|
group, candidateFactory.createCandidate(
|
||||||
|
symbol,
|
||||||
|
explicitReceiverKind,
|
||||||
|
dispatchReceiverValue,
|
||||||
|
implicitExtensionReceiverValue,
|
||||||
|
builtInExtensionFunctionReceiverValue
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val defaultPackage = Name.identifier("kotlin")
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-278
@@ -5,294 +5,24 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.calls
|
package org.jetbrains.kotlin.fir.resolve.calls
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessExpressionBuilder
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.constructType
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
|
||||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
|
||||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
|
|
||||||
class TowerResolveManager internal constructor(private val towerResolver: FirTowerResolver) {
|
class TowerResolveManager internal constructor() {
|
||||||
|
|
||||||
private val queue = PriorityQueue<SuspendedResolverTask>()
|
private val queue = PriorityQueue<SuspendedResolverTask>()
|
||||||
|
|
||||||
lateinit var candidateFactory: CandidateFactory
|
// TODO: Get rid of the property (it should be passed in a different way)
|
||||||
|
internal lateinit var callResolutionContext: CallResolutionContext
|
||||||
|
|
||||||
lateinit var invokeOnGivenReceiverCandidateFactory: CandidateFactory
|
private fun isSuccess() = callResolutionContext.resultCollector.isSuccess()
|
||||||
|
|
||||||
lateinit var invokeReceiverCandidateFactory: CandidateFactory
|
|
||||||
|
|
||||||
lateinit var invokeBuiltinExtensionReceiverCandidateFactory: CandidateFactory
|
|
||||||
|
|
||||||
lateinit var stubReceiverCandidateFactory: CandidateFactory
|
|
||||||
|
|
||||||
lateinit var resultCollector: CandidateCollector
|
|
||||||
|
|
||||||
lateinit var invokeReceiverCollector: CandidateCollector
|
|
||||||
|
|
||||||
private class TowerScopeLevelProcessor(
|
|
||||||
val explicitReceiver: FirExpression?,
|
|
||||||
val explicitReceiverKind: ExplicitReceiverKind,
|
|
||||||
val resultCollector: CandidateCollector,
|
|
||||||
val candidateFactory: CandidateFactory,
|
|
||||||
val group: TowerGroup
|
|
||||||
) : TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>> {
|
|
||||||
override fun consumeCandidate(
|
|
||||||
symbol: AbstractFirBasedSymbol<*>,
|
|
||||||
dispatchReceiverValue: ReceiverValue?,
|
|
||||||
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
|
|
||||||
builtInExtensionFunctionReceiverValue: ReceiverValue?
|
|
||||||
) {
|
|
||||||
// Check explicit extension receiver for default package members
|
|
||||||
if (symbol is FirNamedFunctionSymbol && dispatchReceiverValue == null &&
|
|
||||||
(implicitExtensionReceiverValue == null) != (explicitReceiver == null) &&
|
|
||||||
explicitReceiver !is FirResolvedQualifier &&
|
|
||||||
symbol.callableId.packageName.startsWith(defaultPackage)
|
|
||||||
) {
|
|
||||||
val extensionReceiverType = explicitReceiver?.typeRef?.coneTypeSafe()
|
|
||||||
?: implicitExtensionReceiverValue?.type as? ConeClassLikeType
|
|
||||||
if (extensionReceiverType != null) {
|
|
||||||
val declarationReceiverTypeRef =
|
|
||||||
(symbol as? FirCallableSymbol<*>)?.fir?.receiverTypeRef as? FirResolvedTypeRef
|
|
||||||
val declarationReceiverType = declarationReceiverTypeRef?.type
|
|
||||||
if (declarationReceiverType is ConeClassLikeType) {
|
|
||||||
if (!AbstractTypeChecker.isSubtypeOf(
|
|
||||||
candidateFactory.bodyResolveComponents.inferenceComponents.ctx,
|
|
||||||
extensionReceiverType,
|
|
||||||
declarationReceiverType.lookupTag.constructClassType(
|
|
||||||
declarationReceiverType.typeArguments.map { ConeStarProjection }.toTypedArray(),
|
|
||||||
isNullable = true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ---
|
|
||||||
resultCollector.consumeCandidate(
|
|
||||||
group, candidateFactory.createCandidate(
|
|
||||||
symbol,
|
|
||||||
explicitReceiverKind,
|
|
||||||
dispatchReceiverValue,
|
|
||||||
implicitExtensionReceiverValue,
|
|
||||||
builtInExtensionFunctionReceiverValue
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val defaultPackage = Name.identifier("kotlin")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private inner class LevelHandler(
|
|
||||||
val info: CallInfo,
|
|
||||||
val explicitReceiverKind: ExplicitReceiverKind,
|
|
||||||
val group: TowerGroup
|
|
||||||
) {
|
|
||||||
private fun createExplicitReceiverForInvoke(candidate: Candidate): FirQualifiedAccessExpressionBuilder {
|
|
||||||
val (name, typeRef) = when (val symbol = candidate.symbol) {
|
|
||||||
is FirCallableSymbol<*> -> {
|
|
||||||
symbol.callableId.callableName to towerResolver.typeCalculator.tryCalculateReturnType(symbol.firUnsafe())
|
|
||||||
}
|
|
||||||
is FirRegularClassSymbol -> {
|
|
||||||
symbol.classId.shortClassName to buildResolvedTypeRef {
|
|
||||||
type = symbol.constructType(emptyArray(), isNullable = false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> throw AssertionError()
|
|
||||||
}
|
|
||||||
return FirQualifiedAccessExpressionBuilder().apply {
|
|
||||||
calleeReference = FirNamedReferenceWithCandidate(
|
|
||||||
null,
|
|
||||||
name,
|
|
||||||
candidate
|
|
||||||
)
|
|
||||||
dispatchReceiver = candidate.dispatchReceiverExpression()
|
|
||||||
this.typeRef = typeRef
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun SessionBasedTowerLevel.handleLevel(invokeResolveMode: InvokeResolveMode? = null): ProcessorAction {
|
|
||||||
var result = ProcessorAction.NONE
|
|
||||||
val processor =
|
|
||||||
TowerScopeLevelProcessor(
|
|
||||||
info.explicitReceiver,
|
|
||||||
explicitReceiverKind,
|
|
||||||
resultCollector,
|
|
||||||
// TODO: performance?
|
|
||||||
if (invokeResolveMode == InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER) {
|
|
||||||
invokeOnGivenReceiverCandidateFactory
|
|
||||||
} else candidateFactory,
|
|
||||||
group
|
|
||||||
)
|
|
||||||
when (info.callKind) {
|
|
||||||
CallKind.VariableAccess -> {
|
|
||||||
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor)
|
|
||||||
// TODO: more accurate condition, or process properties/object in some other way
|
|
||||||
if (!resultCollector.isSuccess() &&
|
|
||||||
(this !is ScopeTowerLevel || this.extensionReceiver == null)
|
|
||||||
) {
|
|
||||||
result += processElementsByName(TowerScopeLevel.Token.Objects, info.name, processor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CallKind.Function -> {
|
|
||||||
val invokeBuiltinExtensionMode =
|
|
||||||
invokeResolveMode == InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
|
|
||||||
if (!invokeBuiltinExtensionMode) {
|
|
||||||
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor)
|
|
||||||
}
|
|
||||||
if (invokeResolveMode == InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER ||
|
|
||||||
resultCollector.isSuccess()
|
|
||||||
) {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
val invokeReceiverProcessor = TowerScopeLevelProcessor(
|
|
||||||
info.explicitReceiver,
|
|
||||||
explicitReceiverKind,
|
|
||||||
invokeReceiverCollector,
|
|
||||||
if (invokeBuiltinExtensionMode) invokeBuiltinExtensionReceiverCandidateFactory
|
|
||||||
else invokeReceiverCandidateFactory,
|
|
||||||
group
|
|
||||||
)
|
|
||||||
invokeReceiverCollector.newDataSet()
|
|
||||||
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, invokeReceiverProcessor)
|
|
||||||
if (this !is ScopeTowerLevel || this.extensionReceiver == null) {
|
|
||||||
result += processElementsByName(TowerScopeLevel.Token.Objects, info.name, invokeReceiverProcessor)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (invokeReceiverCollector.isSuccess()) {
|
|
||||||
processInvokeReceiversCandidates(invokeBuiltinExtensionMode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CallKind.CallableReference -> {
|
|
||||||
val stubReceiver = info.stubReceiver
|
|
||||||
if (stubReceiver != null) {
|
|
||||||
val stubReceiverValue = ExpressionReceiverValue(stubReceiver)
|
|
||||||
val stubProcessor = TowerScopeLevelProcessor(
|
|
||||||
info.explicitReceiver,
|
|
||||||
if (this is MemberScopeTowerLevel && dispatchReceiver is AbstractExplicitReceiver<*>) {
|
|
||||||
ExplicitReceiverKind.DISPATCH_RECEIVER
|
|
||||||
} else {
|
|
||||||
ExplicitReceiverKind.EXTENSION_RECEIVER
|
|
||||||
},
|
|
||||||
resultCollector,
|
|
||||||
stubReceiverCandidateFactory, group
|
|
||||||
)
|
|
||||||
val towerLevelWithStubReceiver = replaceReceiverValue(stubReceiverValue)
|
|
||||||
with(towerLevelWithStubReceiver) {
|
|
||||||
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, stubProcessor)
|
|
||||||
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, stubProcessor)
|
|
||||||
}
|
|
||||||
// NB: we don't perform this for implicit Unit
|
|
||||||
if (!resultCollector.isSuccess() && info.explicitReceiver?.typeRef !is FirImplicitBuiltinTypeRef) {
|
|
||||||
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor)
|
|
||||||
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor)
|
|
||||||
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processInvokeReceiversCandidates(invokeBuiltinExtensionMode: Boolean) {
|
|
||||||
for (invokeReceiverCandidate in invokeReceiverCollector.bestCandidates()) {
|
|
||||||
val symbol = invokeReceiverCandidate.symbol
|
|
||||||
if (symbol !is FirCallableSymbol<*> && symbol !is FirRegularClassSymbol) continue
|
|
||||||
|
|
||||||
val isExtensionFunctionType =
|
|
||||||
(symbol as? FirCallableSymbol<*>)?.fir?.returnTypeRef?.isExtensionFunctionType(towerResolver.components.session) == true
|
|
||||||
|
|
||||||
if (invokeBuiltinExtensionMode && !isExtensionFunctionType) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
val extensionReceiverExpression = invokeReceiverCandidate.extensionReceiverExpression()
|
|
||||||
val useImplicitReceiverAsBuiltinInvokeArgument =
|
|
||||||
!invokeBuiltinExtensionMode && isExtensionFunctionType &&
|
|
||||||
invokeReceiverCandidate.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
|
||||||
|
|
||||||
val invokeReceiverExpression = createExplicitReceiverForInvoke(invokeReceiverCandidate).let {
|
|
||||||
if (!invokeBuiltinExtensionMode) {
|
|
||||||
it.extensionReceiver = extensionReceiverExpression
|
|
||||||
// NB: this should fix problem in DFA (KT-36014)
|
|
||||||
it.explicitReceiver = info.explicitReceiver
|
|
||||||
it.safe = info.isSafeCall
|
|
||||||
}
|
|
||||||
towerResolver.components.transformQualifiedAccessUsingSmartcastInfo(it.build())
|
|
||||||
}
|
|
||||||
|
|
||||||
val invokeFunctionInfo =
|
|
||||||
info.copy(explicitReceiver = invokeReceiverExpression, name = OperatorNameConventions.INVOKE).let {
|
|
||||||
when {
|
|
||||||
invokeBuiltinExtensionMode -> it.withReceiverAsArgument(info.explicitReceiver!!)
|
|
||||||
else -> it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val explicitReceiver = ExpressionReceiverValue(invokeReceiverExpression)
|
|
||||||
invokeOnGivenReceiverCandidateFactory = CandidateFactory(towerResolver.components, invokeFunctionInfo)
|
|
||||||
when {
|
|
||||||
invokeBuiltinExtensionMode -> {
|
|
||||||
enqueueResolverTask {
|
|
||||||
towerResolver.runResolverForBuiltinInvokeExtensionWithExplicitArgument(
|
|
||||||
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
useImplicitReceiverAsBuiltinInvokeArgument -> {
|
|
||||||
enqueueResolverTask {
|
|
||||||
towerResolver.runResolverForBuiltinInvokeExtensionWithImplicitArgument(
|
|
||||||
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
|
|
||||||
)
|
|
||||||
}
|
|
||||||
enqueueResolverTask {
|
|
||||||
towerResolver.runResolverForInvoke(
|
|
||||||
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
enqueueResolverTask {
|
|
||||||
towerResolver.runResolverForInvoke(
|
|
||||||
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
queue.clear()
|
queue.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private suspend fun suspendResolverTask(group: TowerGroup) = suspendCoroutine<Unit> { queue += SuspendedResolverTask(it, group) }
|
private suspend fun suspendResolverTask(group: TowerGroup) = suspendCoroutine<Unit> { queue += SuspendedResolverTask(it, group) }
|
||||||
|
|
||||||
private suspend fun requestGroup(requested: TowerGroup) {
|
private suspend fun requestGroup(requested: TowerGroup) {
|
||||||
@@ -316,16 +46,15 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow
|
|||||||
): ProcessorAction {
|
): ProcessorAction {
|
||||||
requestGroup(group)
|
requestGroup(group)
|
||||||
|
|
||||||
val result = with(LevelHandler(callInfo, explicitReceiverKind, group)) {
|
val result = with(LevelHandler(callInfo, explicitReceiverKind, group, callResolutionContext, this)) {
|
||||||
towerLevel.handleLevel(invokeResolveMode)
|
towerLevel.handleLevel(invokeResolveMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resultCollector.isSuccess()) stopResolverTask()
|
if (isSuccess()) stopResolverTask()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
suspend fun processLevelForPropertyWithInvoke(
|
suspend fun processLevelForPropertyWithInvoke(
|
||||||
towerLevel: SessionBasedTowerLevel,
|
towerLevel: SessionBasedTowerLevel,
|
||||||
callInfo: CallInfo,
|
callInfo: CallInfo,
|
||||||
@@ -364,7 +93,7 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow
|
|||||||
fun runTasks() {
|
fun runTasks() {
|
||||||
while (queue.isNotEmpty()) {
|
while (queue.isNotEmpty()) {
|
||||||
queue.poll().continuation.resume(Unit)
|
queue.poll().continuation.resume(Unit)
|
||||||
if (resultCollector.isSuccess()) return
|
if (isSuccess()) return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user