FIR: Extract LevelHandler and CallResolutionContext from TowerManager
This commit is contained in:
@@ -265,7 +265,7 @@ class FirCallResolver(
|
||||
implicitReceiverStack.receiversAsReversed(),
|
||||
info,
|
||||
collector = CandidateCollector(this, resolutionStageRunner),
|
||||
manager = TowerResolveManager(towerResolver),
|
||||
manager = TowerResolveManager(),
|
||||
)
|
||||
val bestCandidates = result.bestCandidates()
|
||||
val noSuccessfulCandidates = result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED
|
||||
|
||||
+37
-16
@@ -42,7 +42,7 @@ class FirTowerResolver(
|
||||
|
||||
private val session: FirSession get() = components.session
|
||||
private val collector = CandidateCollector(components, resolutionStageRunner)
|
||||
private val manager = TowerResolveManager(this)
|
||||
private val manager = TowerResolveManager()
|
||||
private lateinit var implicitReceivers: List<ImplicitReceiver>
|
||||
private lateinit var implicitReceiversUsableAsValues: List<ImplicitReceiver>
|
||||
|
||||
@@ -546,21 +546,7 @@ class FirTowerResolver(
|
||||
): CandidateCollector {
|
||||
// TODO: add flag receiver / non-receiver position
|
||||
prepareImplicitReceivers(implicitReceiverValues)
|
||||
val candidateFactory = CandidateFactory(components, info)
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
manager.callResolutionContext = buildCallResolutionContext(info, collector)
|
||||
|
||||
when (val receiver = info.explicitReceiver) {
|
||||
is FirResolvedQualifier -> manager.enqueueResolverTask { runResolverForQualifierReceiver(info, receiver, manager) }
|
||||
@@ -579,6 +565,41 @@ class FirTowerResolver(
|
||||
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() {
|
||||
collector.newDataSet()
|
||||
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
|
||||
|
||||
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
|
||||
import java.util.*
|
||||
import kotlin.coroutines.*
|
||||
|
||||
class TowerResolveManager internal constructor(private val towerResolver: FirTowerResolver) {
|
||||
class TowerResolveManager internal constructor() {
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun isSuccess() = callResolutionContext.resultCollector.isSuccess()
|
||||
|
||||
fun reset() {
|
||||
queue.clear()
|
||||
}
|
||||
|
||||
|
||||
private suspend fun suspendResolverTask(group: TowerGroup) = suspendCoroutine<Unit> { queue += SuspendedResolverTask(it, group) }
|
||||
|
||||
private suspend fun requestGroup(requested: TowerGroup) {
|
||||
@@ -316,16 +46,15 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow
|
||||
): ProcessorAction {
|
||||
requestGroup(group)
|
||||
|
||||
val result = with(LevelHandler(callInfo, explicitReceiverKind, group)) {
|
||||
val result = with(LevelHandler(callInfo, explicitReceiverKind, group, callResolutionContext, this)) {
|
||||
towerLevel.handleLevel(invokeResolveMode)
|
||||
}
|
||||
|
||||
if (resultCollector.isSuccess()) stopResolverTask()
|
||||
if (isSuccess()) stopResolverTask()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
suspend fun processLevelForPropertyWithInvoke(
|
||||
towerLevel: SessionBasedTowerLevel,
|
||||
callInfo: CallInfo,
|
||||
@@ -364,7 +93,7 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow
|
||||
fun runTasks() {
|
||||
while (queue.isNotEmpty()) {
|
||||
queue.poll().continuation.resume(Unit)
|
||||
if (resultCollector.isSuccess()) return
|
||||
if (isSuccess()) return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user