FIR: Extract LevelHandler and CallResolutionContext from TowerManager

This commit is contained in:
Denis Zharkov
2020-03-27 12:05:24 +03:00
parent 08ee76b103
commit 60cbc5fa39
4 changed files with 335 additions and 295 deletions
@@ -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
@@ -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")
}
}
@@ -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
}
}
}