[FIR] Extract invoke processing from TowerLevelHandler
This commit is contained in:
+388
@@ -0,0 +1,388 @@
|
||||
/*
|
||||
* 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.tower
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
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.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
|
||||
import org.jetbrains.kotlin.fir.types.isExtensionFunctionType
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
internal class FirInvokeResolveTowerExtension(
|
||||
private val components: BodyResolveComponents,
|
||||
private val manager: TowerResolveManager,
|
||||
private val candidateFactoriesAndCollectors: CandidateFactoriesAndCollectors
|
||||
) {
|
||||
|
||||
fun enqueueResolveTasksForQualifier(info: CallInfo, receiver: FirResolvedQualifier) {
|
||||
if (info.callKind != CallKind.Function) return
|
||||
enqueueBothInvokeReceiverTasks(
|
||||
info,
|
||||
invokeAction = { task, receiverInfo ->
|
||||
task.runResolverForQualifierReceiver(receiverInfo, receiver)
|
||||
},
|
||||
invokeExtensionAction = { task, receiverInfo ->
|
||||
task.runResolverForNoReceiver(receiverInfo)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun enqueueResolveTasksForNoReceiver(info: CallInfo) {
|
||||
if (info.callKind != CallKind.Function) return
|
||||
val invokeReceiverVariableInfo = info.replaceWithVariableAccess()
|
||||
enqueueInvokeReceiverTask(
|
||||
info,
|
||||
invokeReceiverVariableInfo,
|
||||
invokeBuiltinExtensionMode = false
|
||||
) {
|
||||
it.runResolverForNoReceiver(invokeReceiverVariableInfo)
|
||||
}
|
||||
}
|
||||
|
||||
fun enqueueResolveTasksForExpressionReceiver(info: CallInfo, receiver: FirExpression) {
|
||||
if (info.callKind != CallKind.Function) return
|
||||
enqueueBothInvokeReceiverTasks(
|
||||
info,
|
||||
invokeAction = { task, receiverInfo ->
|
||||
task.runResolverForExpressionReceiver(receiverInfo, receiver)
|
||||
},
|
||||
invokeExtensionAction = { task, receiverInfo ->
|
||||
task.runResolverForNoReceiver(receiverInfo)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private inline fun enqueueBothInvokeReceiverTasks(
|
||||
originalCallInfo: CallInfo,
|
||||
crossinline invokeAction: suspend (FirTowerResolveTask, CallInfo) -> Unit,
|
||||
crossinline invokeExtensionAction: suspend (FirTowerResolveTask, CallInfo) -> Unit
|
||||
) {
|
||||
val invokeReceiverVariableInfo = originalCallInfo.replaceWithVariableAccess()
|
||||
val invokeReceiverVariableWithNoReceiverInfo = invokeReceiverVariableInfo.replaceExplicitReceiver(null)
|
||||
|
||||
val towerDataElementsForName = TowerDataElementsForName(invokeReceiverVariableInfo.name, components.towerDataContext)
|
||||
|
||||
enqueueInvokeReceiverTask(
|
||||
originalCallInfo,
|
||||
invokeReceiverVariableInfo,
|
||||
towerDataElementsForName = towerDataElementsForName,
|
||||
invokeBuiltinExtensionMode = false
|
||||
) {
|
||||
invokeAction(it, invokeReceiverVariableInfo)
|
||||
}
|
||||
enqueueInvokeReceiverTask(
|
||||
originalCallInfo,
|
||||
invokeReceiverVariableWithNoReceiverInfo,
|
||||
towerDataElementsForName = towerDataElementsForName,
|
||||
invokeBuiltinExtensionMode = true
|
||||
) {
|
||||
invokeExtensionAction(it, invokeReceiverVariableWithNoReceiverInfo)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun enqueueInvokeReceiverTask(
|
||||
info: CallInfo,
|
||||
invokeReceiverInfo: CallInfo,
|
||||
towerDataElementsForName: TowerDataElementsForName = TowerDataElementsForName(invokeReceiverInfo.name, components.towerDataContext),
|
||||
invokeBuiltinExtensionMode: Boolean,
|
||||
crossinline task: suspend (FirTowerResolveTask) -> Unit
|
||||
) {
|
||||
val collector = CandidateCollector(components, components.resolutionStageRunner)
|
||||
val invokeReceiverProcessor = InvokeReceiverResolveTask(
|
||||
components,
|
||||
manager,
|
||||
towerDataElementsForName,
|
||||
collector,
|
||||
CandidateFactory(components, invokeReceiverInfo),
|
||||
onSuccessfulLevel = { towerGroup ->
|
||||
enqueueResolverTasksForInvokeReceiverCandidates(
|
||||
invokeBuiltinExtensionMode, info,
|
||||
receiverGroup = towerGroup,
|
||||
collector
|
||||
)
|
||||
collector.newDataSet()
|
||||
}
|
||||
)
|
||||
manager.enqueueResolverTask {
|
||||
task(invokeReceiverProcessor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun enqueueResolverTasksForInvokeReceiverCandidates(
|
||||
extensionInvokeOnActualReceiver: Boolean,
|
||||
info: CallInfo,
|
||||
receiverGroup: TowerGroup,
|
||||
collector: CandidateCollector
|
||||
) {
|
||||
val invokeBuiltinExtensionMode: Boolean = extensionInvokeOnActualReceiver
|
||||
|
||||
for (invokeReceiverCandidate in collector.bestCandidates()) {
|
||||
val symbol = invokeReceiverCandidate.symbol
|
||||
if (symbol !is FirCallableSymbol<*> && symbol !is FirClassLikeSymbol<*>) continue
|
||||
|
||||
val isExtensionFunctionType =
|
||||
(symbol as? FirCallableSymbol<*>)?.fir?.returnTypeRef?.isExtensionFunctionType(components.session) == true
|
||||
|
||||
if (invokeBuiltinExtensionMode && !isExtensionFunctionType) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
val extensionReceiverExpression = invokeReceiverCandidate.extensionReceiverExpression()
|
||||
val useImplicitReceiverAsBuiltinInvokeArgument =
|
||||
!invokeBuiltinExtensionMode && isExtensionFunctionType &&
|
||||
invokeReceiverCandidate.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
||||
|
||||
val invokeReceiverExpression =
|
||||
components.createExplicitReceiverForInvoke(
|
||||
invokeReceiverCandidate, info, invokeBuiltinExtensionMode, extensionReceiverExpression
|
||||
)
|
||||
|
||||
val invokeFunctionInfo =
|
||||
info.copy(
|
||||
explicitReceiver = invokeReceiverExpression, name = OperatorNameConventions.INVOKE,
|
||||
candidateForCommonInvokeReceiver = invokeReceiverCandidate.takeUnless { invokeBuiltinExtensionMode }
|
||||
).let {
|
||||
when {
|
||||
invokeBuiltinExtensionMode -> it.withReceiverAsArgument(info.explicitReceiver!!)
|
||||
else -> it
|
||||
}
|
||||
}
|
||||
|
||||
val explicitReceiver = ExpressionReceiverValue(invokeReceiverExpression)
|
||||
enqueueResolverTasksForInvoke(
|
||||
invokeFunctionInfo,
|
||||
explicitReceiver,
|
||||
invokeBuiltinExtensionMode,
|
||||
useImplicitReceiverAsBuiltinInvokeArgument,
|
||||
receiverGroup
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun enqueueResolverTasksForInvoke(
|
||||
invokeFunctionInfo: CallInfo,
|
||||
explicitReceiver: ExpressionReceiverValue,
|
||||
invokeBuiltinExtensionMode: Boolean,
|
||||
useImplicitReceiverAsBuiltinInvokeArgument: Boolean,
|
||||
receiverGroup: TowerGroup
|
||||
) {
|
||||
val invokeOnGivenReceiverCandidateFactory = CandidateFactory(components, invokeFunctionInfo)
|
||||
val task = InvokeFunctionResolveTask(
|
||||
components,
|
||||
manager,
|
||||
TowerDataElementsForName(invokeFunctionInfo.name, components.towerDataContext),
|
||||
receiverGroup,
|
||||
candidateFactoriesAndCollectors.resultCollector,
|
||||
invokeOnGivenReceiverCandidateFactory,
|
||||
candidateFactoriesAndCollectors.stubReceiverCandidateFactory
|
||||
)
|
||||
if (invokeBuiltinExtensionMode) {
|
||||
manager.enqueueResolverTask {
|
||||
task.runResolverForBuiltinInvokeExtensionWithExplicitArgument(
|
||||
invokeFunctionInfo, explicitReceiver,
|
||||
TowerGroup.EmptyRoot
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (useImplicitReceiverAsBuiltinInvokeArgument) {
|
||||
manager.enqueueResolverTask {
|
||||
task.runResolverForBuiltinInvokeExtensionWithImplicitArgument(
|
||||
invokeFunctionInfo, explicitReceiver,
|
||||
TowerGroup.EmptyRoot
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
manager.enqueueResolverTask {
|
||||
task.runResolverForInvoke(
|
||||
invokeFunctionInfo, explicitReceiver,
|
||||
TowerGroup.EmptyRoot
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun BodyResolveComponents.createExplicitReceiverForInvoke(
|
||||
candidate: Candidate,
|
||||
info: CallInfo,
|
||||
invokeBuiltinExtensionMode: Boolean,
|
||||
extensionReceiverExpression: FirExpression
|
||||
): FirExpression {
|
||||
return when (val symbol = candidate.symbol) {
|
||||
is FirCallableSymbol<*> -> createExplicitReceiverForInvokeByCallable(
|
||||
candidate, info, invokeBuiltinExtensionMode, extensionReceiverExpression, symbol
|
||||
)
|
||||
is FirRegularClassSymbol -> buildResolvedQualifierForClass(symbol, sourceElement = null)
|
||||
is FirTypeAliasSymbol -> {
|
||||
val type = symbol.fir.expandedTypeRef.coneTypeUnsafe<ConeClassLikeType>().fullyExpandedType(session)
|
||||
val expansionRegularClass = type.lookupTag.toSymbol(session)?.fir as? FirRegularClass
|
||||
buildResolvedQualifierForClass(expansionRegularClass!!.symbol, sourceElement = symbol.fir.source)
|
||||
}
|
||||
else -> throw AssertionError()
|
||||
}
|
||||
}
|
||||
|
||||
private fun BodyResolveComponents.createExplicitReceiverForInvokeByCallable(
|
||||
candidate: Candidate,
|
||||
info: CallInfo,
|
||||
invokeBuiltinExtensionMode: Boolean,
|
||||
extensionReceiverExpression: FirExpression,
|
||||
symbol: FirCallableSymbol<*>
|
||||
): FirExpression {
|
||||
return FirQualifiedAccessExpressionBuilder().apply {
|
||||
calleeReference = FirNamedReferenceWithCandidate(
|
||||
null,
|
||||
symbol.callableId.callableName,
|
||||
candidate
|
||||
)
|
||||
dispatchReceiver = candidate.dispatchReceiverExpression()
|
||||
this.typeRef = returnTypeCalculator.tryCalculateReturnType(symbol.firUnsafe())
|
||||
|
||||
if (!invokeBuiltinExtensionMode) {
|
||||
extensionReceiver = extensionReceiverExpression
|
||||
// NB: this should fix problem in DFA (KT-36014)
|
||||
explicitReceiver = info.explicitReceiver
|
||||
}
|
||||
}.build().let(::transformQualifiedAccessUsingSmartcastInfo)
|
||||
}
|
||||
|
||||
private class InvokeReceiverResolveTask(
|
||||
components: BodyResolveComponents,
|
||||
manager: TowerResolveManager,
|
||||
towerDataElementsForName: TowerDataElementsForName,
|
||||
collector: CandidateCollector,
|
||||
candidateFactory: CandidateFactory,
|
||||
private val onSuccessfulLevel: (TowerGroup) -> Unit
|
||||
) : FirTowerResolveTask(
|
||||
components,
|
||||
manager,
|
||||
towerDataElementsForName,
|
||||
collector,
|
||||
candidateFactory,
|
||||
stubReceiverCandidateFactory = null
|
||||
) {
|
||||
override fun interceptTowerGroup(towerGroup: TowerGroup): TowerGroup =
|
||||
towerGroup.InvokeResolvePriority(InvokeResolvePriority.INVOKE_RECEIVER)
|
||||
|
||||
override fun onSuccessfulLevel(towerGroup: TowerGroup) {
|
||||
this.onSuccessfulLevel.invoke(towerGroup)
|
||||
}
|
||||
}
|
||||
|
||||
private class InvokeFunctionResolveTask(
|
||||
components: BodyResolveComponents,
|
||||
manager: TowerResolveManager,
|
||||
towerDataElementsForName: TowerDataElementsForName,
|
||||
private val receiverGroup: TowerGroup,
|
||||
collector: CandidateCollector,
|
||||
candidateFactory: CandidateFactory,
|
||||
stubReceiverCandidateFactory: CandidateFactory? = null
|
||||
) : FirBaseTowerResolveTask(
|
||||
components,
|
||||
manager,
|
||||
towerDataElementsForName,
|
||||
collector,
|
||||
candidateFactory,
|
||||
stubReceiverCandidateFactory
|
||||
) {
|
||||
|
||||
override fun interceptTowerGroup(towerGroup: TowerGroup): TowerGroup =
|
||||
maxOf(towerGroup.InvokeResolvePriority(InvokeResolvePriority.COMMON_INVOKE), receiverGroup)
|
||||
|
||||
suspend fun runResolverForInvoke(
|
||||
info: CallInfo,
|
||||
invokeReceiverValue: ExpressionReceiverValue,
|
||||
parentGroupForInvokeCandidates: TowerGroup
|
||||
) {
|
||||
processLevelForRegularInvoke(
|
||||
invokeReceiverValue.toMemberScopeTowerLevel(),
|
||||
info, parentGroupForInvokeCandidates.Member,
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
)
|
||||
|
||||
enumerateTowerLevels(
|
||||
onScope = { scope, group ->
|
||||
processLevelForRegularInvoke(
|
||||
scope.toScopeTowerLevel(extensionReceiver = invokeReceiverValue),
|
||||
info, group,
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
)
|
||||
},
|
||||
onImplicitReceiver = { receiver, group ->
|
||||
// NB: companions are processed via implicitReceiverValues!
|
||||
processLevelForRegularInvoke(
|
||||
receiver.toMemberScopeTowerLevel(extensionReceiver = invokeReceiverValue),
|
||||
info, group.Member,
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// Here we already know extension receiver for invoke, and it's stated in info as first argument
|
||||
suspend fun runResolverForBuiltinInvokeExtensionWithExplicitArgument(
|
||||
info: CallInfo,
|
||||
invokeReceiverValue: ExpressionReceiverValue,
|
||||
parentGroupForInvokeCandidates: TowerGroup
|
||||
) {
|
||||
processLevel(
|
||||
invokeReceiverValue.toMemberScopeTowerLevel(),
|
||||
info, parentGroupForInvokeCandidates.Member.InvokeResolvePriority(InvokeResolvePriority.INVOKE_EXTENSION),
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
)
|
||||
}
|
||||
|
||||
// Here we don't know extension receiver for invoke, assuming it's one of implicit receivers
|
||||
suspend fun runResolverForBuiltinInvokeExtensionWithImplicitArgument(
|
||||
info: CallInfo,
|
||||
invokeReceiverValue: ExpressionReceiverValue,
|
||||
parentGroupForInvokeCandidates: TowerGroup
|
||||
) {
|
||||
for ((depth, implicitReceiverValue) in towerDataElementsForName.implicitReceivers) {
|
||||
val towerGroup =
|
||||
parentGroupForInvokeCandidates
|
||||
.Implicit(depth)
|
||||
.InvokeExtension
|
||||
.InvokeResolvePriority(InvokeResolvePriority.INVOKE_EXTENSION)
|
||||
|
||||
processLevel(
|
||||
invokeReceiverValue.toMemberScopeTowerLevel(
|
||||
extensionReceiver = implicitReceiverValue,
|
||||
implicitExtensionInvokeMode = true
|
||||
),
|
||||
info, towerGroup,
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processLevelForRegularInvoke(
|
||||
towerLevel: SessionBasedTowerLevel,
|
||||
callInfo: CallInfo,
|
||||
group: TowerGroup,
|
||||
explicitReceiverKind: ExplicitReceiverKind
|
||||
) = processLevel(
|
||||
towerLevel, callInfo,
|
||||
group.InvokeResolvePriority(InvokeResolvePriority.COMMON_INVOKE),
|
||||
explicitReceiverKind
|
||||
)
|
||||
}
|
||||
+417
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
* 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.tower
|
||||
|
||||
import org.jetbrains.kotlin.fir.asReversedFrozen
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.FirTowerDataContext
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirCompositeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
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.descriptorUtil.HIDES_MEMBERS_NAME_LIST
|
||||
import java.util.*
|
||||
|
||||
|
||||
internal class TowerDataElementsForName(
|
||||
name: Name,
|
||||
towerDataContext: FirTowerDataContext
|
||||
) {
|
||||
val nonLocalTowerDataElements = towerDataContext.nonLocalTowerDataElements.asReversedFrozen()
|
||||
|
||||
val reversedFilteredLocalScopes by lazy(LazyThreadSafetyMode.NONE) {
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
buildList {
|
||||
val localScopesBase = towerDataContext.localScopes
|
||||
val lastIndex = localScopesBase.lastIndex
|
||||
for (i in lastIndex downTo 0) {
|
||||
val localScope = localScopesBase[i]
|
||||
if (localScope.mayContainName(name)) {
|
||||
add(IndexedValue(lastIndex - i, localScope))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val implicitReceivers by lazy(LazyThreadSafetyMode.NONE) {
|
||||
nonLocalTowerDataElements.mapIndexedNotNull { index, towerDataElement ->
|
||||
towerDataElement.implicitReceiver?.let { receiver -> IndexedValue(index, receiver) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class FirBaseTowerResolveTask(
|
||||
protected val components: BodyResolveComponents,
|
||||
private val manager: TowerResolveManager,
|
||||
protected val towerDataElementsForName: TowerDataElementsForName,
|
||||
private val collector: CandidateCollector,
|
||||
private val candidateFactory: CandidateFactory,
|
||||
private val stubReceiverCandidateFactory: CandidateFactory? = null
|
||||
) {
|
||||
protected val session get() = components.session
|
||||
|
||||
private val handler: TowerLevelHandler = TowerLevelHandler()
|
||||
|
||||
open fun interceptTowerGroup(towerGroup: TowerGroup) = towerGroup
|
||||
open fun onSuccessfulLevel(towerGroup: TowerGroup) {}
|
||||
|
||||
protected suspend inline fun processLevel(
|
||||
towerLevel: SessionBasedTowerLevel,
|
||||
callInfo: CallInfo,
|
||||
group: TowerGroup,
|
||||
explicitReceiverKind: ExplicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
|
||||
onEmptyLevel: () -> Unit = {}
|
||||
) {
|
||||
if (processLevel(towerLevel, callInfo, group, explicitReceiverKind)) {
|
||||
onEmptyLevel()
|
||||
}
|
||||
}
|
||||
|
||||
protected fun FirScope.toScopeTowerLevel(
|
||||
extensionReceiver: ReceiverValue? = null,
|
||||
extensionsOnly: Boolean = false,
|
||||
includeInnerConstructors: Boolean = true
|
||||
): ScopeTowerLevel = ScopeTowerLevel(
|
||||
session, components, this,
|
||||
extensionReceiver, extensionsOnly, includeInnerConstructors
|
||||
)
|
||||
|
||||
protected fun ReceiverValue.toMemberScopeTowerLevel(
|
||||
extensionReceiver: ReceiverValue? = null,
|
||||
implicitExtensionInvokeMode: Boolean = false
|
||||
) = MemberScopeTowerLevel(
|
||||
session, components, this,
|
||||
extensionReceiver, implicitExtensionInvokeMode,
|
||||
scopeSession = components.scopeSession
|
||||
)
|
||||
|
||||
protected inline fun enumerateTowerLevels(
|
||||
parentGroup: TowerGroup = TowerGroup.EmptyRoot,
|
||||
onScope: (FirScope, TowerGroup) -> Unit,
|
||||
onImplicitReceiver: (ImplicitReceiverValue<*>, TowerGroup) -> Unit,
|
||||
) {
|
||||
for ((index, localScope) in towerDataElementsForName.reversedFilteredLocalScopes) {
|
||||
onScope(localScope, parentGroup.Local(index))
|
||||
}
|
||||
|
||||
for ((depth, lexical) in towerDataElementsForName.nonLocalTowerDataElements.withIndex()) {
|
||||
if (!lexical.isLocal && lexical.scope != null) {
|
||||
onScope(lexical.scope, parentGroup.NonLocal(depth))
|
||||
}
|
||||
|
||||
val receiver = lexical.implicitReceiver
|
||||
|
||||
if (receiver != null && receiver !is InaccessibleImplicitReceiverValue) {
|
||||
onImplicitReceiver(receiver, parentGroup.Implicit(depth))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if level is empty
|
||||
*/
|
||||
private suspend fun processLevel(
|
||||
towerLevel: SessionBasedTowerLevel,
|
||||
callInfo: CallInfo,
|
||||
group: TowerGroup,
|
||||
explicitReceiverKind: ExplicitReceiverKind
|
||||
): Boolean {
|
||||
val finalGroup = interceptTowerGroup(group)
|
||||
manager.requestGroup(finalGroup)
|
||||
|
||||
|
||||
val result = handler.handleLevel(
|
||||
collector,
|
||||
candidateFactory,
|
||||
stubReceiverCandidateFactory,
|
||||
callInfo,
|
||||
explicitReceiverKind,
|
||||
finalGroup,
|
||||
towerLevel
|
||||
)
|
||||
if (collector.isSuccess()) onSuccessfulLevel(finalGroup)
|
||||
return result == ProcessorAction.NONE
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal open class FirTowerResolveTask(
|
||||
components: BodyResolveComponents,
|
||||
manager: TowerResolveManager,
|
||||
towerDataElementsForName: TowerDataElementsForName,
|
||||
collector: CandidateCollector,
|
||||
candidateFactory: CandidateFactory,
|
||||
stubReceiverCandidateFactory: CandidateFactory? = null
|
||||
) : FirBaseTowerResolveTask(
|
||||
components,
|
||||
manager,
|
||||
towerDataElementsForName,
|
||||
collector,
|
||||
candidateFactory,
|
||||
stubReceiverCandidateFactory
|
||||
) {
|
||||
|
||||
suspend fun runResolverForQualifierReceiver(
|
||||
info: CallInfo,
|
||||
resolvedQualifier: FirResolvedQualifier
|
||||
) {
|
||||
val qualifierReceiver = createQualifierReceiver(resolvedQualifier, session, components.scopeSession)
|
||||
|
||||
when {
|
||||
info.isPotentialQualifierPart -> {
|
||||
processClassifierScope(info, qualifierReceiver, prioritized = true)
|
||||
processQualifierScopes(info, qualifierReceiver)
|
||||
}
|
||||
else -> {
|
||||
processQualifierScopes(info, qualifierReceiver)
|
||||
processClassifierScope(info, qualifierReceiver, prioritized = false)
|
||||
}
|
||||
}
|
||||
|
||||
if (resolvedQualifier.symbol != null) {
|
||||
val typeRef = resolvedQualifier.typeRef
|
||||
// NB: yet built-in Unit is used for "no-value" type
|
||||
if (info.callKind == CallKind.CallableReference) {
|
||||
if (info.stubReceiver != null || typeRef !is FirImplicitBuiltinTypeRef) {
|
||||
runResolverForExpressionReceiver(info, resolvedQualifier, parentGroup = TowerGroup.QualifierValue)
|
||||
}
|
||||
} else {
|
||||
if (typeRef !is FirImplicitBuiltinTypeRef) {
|
||||
runResolverForExpressionReceiver(info, resolvedQualifier, parentGroup = TowerGroup.QualifierValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processQualifierScopes(
|
||||
info: CallInfo, qualifierReceiver: QualifierReceiver?
|
||||
) {
|
||||
if (qualifierReceiver == null) return
|
||||
val callableScope = qualifierReceiver.callableScope() ?: return
|
||||
processLevel(
|
||||
callableScope.toScopeTowerLevel(includeInnerConstructors = false),
|
||||
info.noStubReceiver(), TowerGroup.Qualifier
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun processClassifierScope(
|
||||
info: CallInfo, qualifierReceiver: QualifierReceiver?, prioritized: Boolean
|
||||
) {
|
||||
if (qualifierReceiver == null) return
|
||||
if (info.callKind != CallKind.CallableReference &&
|
||||
qualifierReceiver is ClassQualifierReceiver &&
|
||||
qualifierReceiver.classSymbol != qualifierReceiver.originalSymbol
|
||||
) return
|
||||
val scope = qualifierReceiver.classifierScope() ?: return
|
||||
val group = if (prioritized) TowerGroup.ClassifierPrioritized else TowerGroup.Classifier
|
||||
processLevel(
|
||||
scope.toScopeTowerLevel(includeInnerConstructors = false), info.noStubReceiver(),
|
||||
group
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun runResolverForExpressionReceiver(
|
||||
info: CallInfo,
|
||||
receiver: FirExpression,
|
||||
parentGroup: TowerGroup = TowerGroup.EmptyRoot
|
||||
) {
|
||||
val explicitReceiverValue = ExpressionReceiverValue(receiver)
|
||||
|
||||
processExtensionsThatHideMembers(info, explicitReceiverValue, parentGroup)
|
||||
|
||||
// Member scope of expression receiver
|
||||
processLevel(
|
||||
explicitReceiverValue.toMemberScopeTowerLevel(), info, parentGroup.Member, ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
)
|
||||
|
||||
val shouldProcessExplicitReceiverScopeOnly =
|
||||
info.callKind == CallKind.Function && info.explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() != null
|
||||
if (shouldProcessExplicitReceiverScopeOnly) {
|
||||
// Special case (integer literal type)
|
||||
return
|
||||
}
|
||||
|
||||
enumerateTowerLevels(
|
||||
parentGroup = parentGroup,
|
||||
onScope = { scope, group ->
|
||||
processScopeForExplicitReceiver(
|
||||
scope,
|
||||
explicitReceiverValue,
|
||||
info,
|
||||
group
|
||||
)
|
||||
},
|
||||
onImplicitReceiver = { implicitReceiverValue, group ->
|
||||
processCombinationOfReceivers(implicitReceiverValue, explicitReceiverValue, info, group)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun runResolverForNoReceiver(
|
||||
info: CallInfo
|
||||
) {
|
||||
processExtensionsThatHideMembers(info, explicitReceiverValue = null)
|
||||
|
||||
val emptyScopes = mutableSetOf<FirScope>()
|
||||
val implicitReceiverValuesWithEmptyScopes = mutableSetOf<ImplicitReceiverValue<*>>()
|
||||
|
||||
enumerateTowerLevels(
|
||||
onScope = l@{ scope, group ->
|
||||
// NB: this check does not work for variables
|
||||
// because we do not search for objects if we have extension receiver
|
||||
if (info.callKind != CallKind.VariableAccess && scope in emptyScopes) return@l
|
||||
|
||||
processLevel(
|
||||
scope.toScopeTowerLevel(), info, group,
|
||||
onEmptyLevel = {
|
||||
emptyScopes += scope
|
||||
}
|
||||
)
|
||||
},
|
||||
onImplicitReceiver = { receiver, group ->
|
||||
processCandidatesWithGivenImplicitReceiverAsValue(
|
||||
receiver,
|
||||
info,
|
||||
group,
|
||||
implicitReceiverValuesWithEmptyScopes,
|
||||
emptyScopes
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun runResolverForSuperReceiver(
|
||||
info: CallInfo,
|
||||
superTypeRef: FirTypeRef
|
||||
) {
|
||||
val scope = when (superTypeRef) {
|
||||
is FirResolvedTypeRef -> superTypeRef.type.scope(session, components.scopeSession)
|
||||
is FirComposedSuperTypeRef -> FirCompositeScope(
|
||||
superTypeRef.superTypeRefs.mapNotNull { it.type.scope(session, components.scopeSession) }
|
||||
)
|
||||
else -> null
|
||||
} ?: return
|
||||
processLevel(
|
||||
scope.toScopeTowerLevel(),
|
||||
info, TowerGroup.Member, explicitReceiverKind = ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun processExtensionsThatHideMembers(
|
||||
info: CallInfo,
|
||||
explicitReceiverValue: ReceiverValue?,
|
||||
parentGroup: TowerGroup = TowerGroup.EmptyRoot
|
||||
) {
|
||||
val shouldProcessExtensionsBeforeMembers =
|
||||
info.callKind == CallKind.Function && info.name in HIDES_MEMBERS_NAME_LIST
|
||||
|
||||
if (!shouldProcessExtensionsBeforeMembers) return
|
||||
|
||||
val importingScopes = components.fileImportsScope.asReversed()
|
||||
for ((index, topLevelScope) in importingScopes.withIndex()) {
|
||||
if (explicitReceiverValue != null) {
|
||||
processHideMembersLevel(
|
||||
explicitReceiverValue, topLevelScope, info, index, depth = null,
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER, parentGroup
|
||||
)
|
||||
} else {
|
||||
for ((depth, implicitReceiverValue) in towerDataElementsForName.implicitReceivers) {
|
||||
processHideMembersLevel(
|
||||
implicitReceiverValue, topLevelScope, info, index, depth,
|
||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, parentGroup
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processScopeForExplicitReceiver(
|
||||
scope: FirScope,
|
||||
explicitReceiverValue: ExpressionReceiverValue,
|
||||
info: CallInfo,
|
||||
towerGroup: TowerGroup,
|
||||
) {
|
||||
processLevel(
|
||||
scope.toScopeTowerLevel(extensionReceiver = explicitReceiverValue),
|
||||
info, towerGroup, ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
private suspend fun processCombinationOfReceivers(
|
||||
implicitReceiverValue: ImplicitReceiverValue<*>,
|
||||
explicitReceiverValue: ExpressionReceiverValue,
|
||||
info: CallInfo,
|
||||
parentGroup: TowerGroup
|
||||
) {
|
||||
// Member extensions
|
||||
processLevel(
|
||||
implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = explicitReceiverValue),
|
||||
info, parentGroup.Member, ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun processCandidatesWithGivenImplicitReceiverAsValue(
|
||||
receiver: ImplicitReceiverValue<*>,
|
||||
info: CallInfo,
|
||||
parentGroup: TowerGroup,
|
||||
implicitReceiverValuesWithEmptyScopes: MutableSet<ImplicitReceiverValue<*>>,
|
||||
emptyScopes: MutableSet<FirScope>
|
||||
) {
|
||||
processLevel(
|
||||
receiver.toMemberScopeTowerLevel(), info, parentGroup.Member,
|
||||
onEmptyLevel = {
|
||||
implicitReceiverValuesWithEmptyScopes += receiver
|
||||
}
|
||||
)
|
||||
|
||||
enumerateTowerLevels(
|
||||
parentGroup,
|
||||
onScope = l@{ scope, group ->
|
||||
if (scope in emptyScopes) return@l
|
||||
|
||||
processLevel(
|
||||
scope.toScopeTowerLevel(extensionReceiver = receiver),
|
||||
info, group,
|
||||
onEmptyLevel = {
|
||||
emptyScopes += scope
|
||||
}
|
||||
)
|
||||
},
|
||||
onImplicitReceiver = l@{ implicitReceiverValue, group ->
|
||||
if (implicitReceiverValue in implicitReceiverValuesWithEmptyScopes) return@l
|
||||
processLevel(
|
||||
implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = receiver),
|
||||
info, group
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
private suspend fun processHideMembersLevel(
|
||||
receiverValue: ReceiverValue,
|
||||
topLevelScope: FirScope,
|
||||
info: CallInfo,
|
||||
index: Int,
|
||||
depth: Int?,
|
||||
explicitReceiverKind: ExplicitReceiverKind,
|
||||
parentGroup: TowerGroup
|
||||
) = processLevel(
|
||||
topLevelScope.toScopeTowerLevel(
|
||||
extensionReceiver = receiverValue, extensionsOnly = true
|
||||
),
|
||||
info,
|
||||
parentGroup.TopPrioritized(index).let { if (depth != null) it.Implicit(depth) else it },
|
||||
explicitReceiverKind,
|
||||
)
|
||||
}
|
||||
+44
-19
@@ -5,6 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
@@ -27,13 +30,51 @@ class FirTowerResolver(
|
||||
): CandidateCollector {
|
||||
val candidateFactoriesAndCollectors = buildCandidateFactoriesAndCollectors(info, collector)
|
||||
|
||||
val towerResolverSession = FirTowerResolverSession(components, manager, candidateFactoriesAndCollectors, info)
|
||||
towerResolverSession.runResolution(info)
|
||||
enqueueResolutionTasks(components, manager, candidateFactoriesAndCollectors, info)
|
||||
|
||||
manager.runTasks()
|
||||
return collector
|
||||
}
|
||||
|
||||
private fun enqueueResolutionTasks(
|
||||
components: BodyResolveComponents,
|
||||
manager: TowerResolveManager,
|
||||
candidateFactoriesAndCollectors: CandidateFactoriesAndCollectors,
|
||||
info: CallInfo
|
||||
) {
|
||||
val invokeResolveTowerExtension = FirInvokeResolveTowerExtension(components, manager, candidateFactoriesAndCollectors)
|
||||
|
||||
val mainTask = FirTowerResolveTask(
|
||||
components,
|
||||
manager,
|
||||
TowerDataElementsForName(info.name, components.towerDataContext),
|
||||
candidateFactoriesAndCollectors.resultCollector,
|
||||
candidateFactoriesAndCollectors.candidateFactory,
|
||||
candidateFactoriesAndCollectors.stubReceiverCandidateFactory
|
||||
)
|
||||
when (val receiver = info.explicitReceiver) {
|
||||
is FirResolvedQualifier -> {
|
||||
manager.enqueueResolverTask { mainTask.runResolverForQualifierReceiver(info, receiver) }
|
||||
invokeResolveTowerExtension.enqueueResolveTasksForQualifier(info, receiver)
|
||||
}
|
||||
null -> {
|
||||
manager.enqueueResolverTask { mainTask.runResolverForNoReceiver(info) }
|
||||
invokeResolveTowerExtension.enqueueResolveTasksForNoReceiver(info)
|
||||
}
|
||||
else -> {
|
||||
if (receiver is FirQualifiedAccessExpression) {
|
||||
val calleeReference = receiver.calleeReference
|
||||
if (calleeReference is FirSuperReference) {
|
||||
return manager.enqueueResolverTask { mainTask.runResolverForSuperReceiver(info, receiver.typeRef) }
|
||||
}
|
||||
}
|
||||
|
||||
manager.enqueueResolverTask { mainTask.runResolverForExpressionReceiver(info, receiver) }
|
||||
invokeResolveTowerExtension.enqueueResolveTasksForExpressionReceiver(info, receiver)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun runResolverForDelegatingConstructor(
|
||||
info: CallInfo,
|
||||
constructedType: ConeClassLikeType
|
||||
@@ -79,26 +120,10 @@ class FirTowerResolver(
|
||||
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 CandidateFactoriesAndCollectors(
|
||||
candidateFactory,
|
||||
collector,
|
||||
stubReceiverCandidateFactory,
|
||||
invokeReceiverCandidateFactory,
|
||||
invokeReceiverCollector,
|
||||
invokeBuiltinExtensionReceiverCandidateFactory
|
||||
stubReceiverCandidateFactory
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
-664
@@ -1,664 +0,0 @@
|
||||
/*
|
||||
* 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.tower
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.asReversedFrozen
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessExpressionBuilder
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
|
||||
import org.jetbrains.kotlin.fir.scopes.FirCompositeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
class FirTowerResolverSession internal constructor(
|
||||
private val components: BodyResolveComponents,
|
||||
private val manager: TowerResolveManager,
|
||||
private val candidateFactoriesAndCollectors: CandidateFactoriesAndCollectors,
|
||||
private val mainCallInfo: CallInfo,
|
||||
) {
|
||||
private data class ImplicitReceiver(
|
||||
val receiver: ImplicitReceiverValue<*>,
|
||||
val depth: Int
|
||||
)
|
||||
|
||||
private val session: FirSession get() = components.session
|
||||
|
||||
private val localScopes: List<FirScope> by lazy(LazyThreadSafetyMode.NONE) {
|
||||
val localScopesBase = components.towerDataContext.localScopes
|
||||
val result = ArrayList<FirScope>()
|
||||
for (i in localScopesBase.lastIndex downTo 0) {
|
||||
val localScope = localScopesBase[i]
|
||||
if (localScope.mayContainName(mainCallInfo.name)
|
||||
|| (mainCallInfo.callKind == CallKind.Function && localScope.mayContainName(OperatorNameConventions.INVOKE))
|
||||
) {
|
||||
result.add(localScope)
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
private val nonLocalTowerDataElements = components.towerDataContext.nonLocalTowerDataElements.asReversedFrozen()
|
||||
|
||||
private val implicitReceivers: List<ImplicitReceiver> by lazy(LazyThreadSafetyMode.NONE) {
|
||||
nonLocalTowerDataElements.withIndex().mapNotNull { (index, element) ->
|
||||
element.implicitReceiver?.let { ImplicitReceiver(it, index) }
|
||||
}
|
||||
}
|
||||
|
||||
fun runResolution(info: CallInfo) {
|
||||
when (val receiver = info.explicitReceiver) {
|
||||
is FirResolvedQualifier -> manager.enqueueResolverTask { runResolverForQualifierReceiver(info, receiver) }
|
||||
null -> manager.enqueueResolverTask { runResolverForNoReceiver(info) }
|
||||
else -> run {
|
||||
if (receiver is FirQualifiedAccessExpression) {
|
||||
val calleeReference = receiver.calleeReference
|
||||
if (calleeReference is FirSuperReference) {
|
||||
return@run manager.enqueueResolverTask { runResolverForSuperReceiver(info, receiver.typeRef) }
|
||||
}
|
||||
}
|
||||
manager.enqueueResolverTask { runResolverForExpressionReceiver(info, receiver) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processLevel(
|
||||
towerLevel: SessionBasedTowerLevel,
|
||||
callInfo: CallInfo,
|
||||
group: TowerGroup,
|
||||
explicitReceiverKind: ExplicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
|
||||
invokeResolveMode: InvokeResolveMode? = null,
|
||||
candidateFactory: CandidateFactory = candidateFactoriesAndCollectors.candidateFactory,
|
||||
// Non-trivial only for qualifier receiver, because there we should prioritize invokes that were found
|
||||
// at Qualifier scopes above candidates found in QualifierAsExpression receiver
|
||||
useParentGroupForInvokes: Boolean = false
|
||||
): ProcessorAction {
|
||||
manager.requestGroup(group)
|
||||
|
||||
val levelHandler = TowerLevelHandler()
|
||||
|
||||
return levelHandler.handleLevel(
|
||||
callInfo, explicitReceiverKind, group,
|
||||
candidateFactoriesAndCollectors, towerLevel, invokeResolveMode, candidateFactory
|
||||
) {
|
||||
enqueueResolverTasksForInvokeReceiverCandidates(
|
||||
invokeResolveMode, callInfo,
|
||||
parentGroupForInvokeCandidates = if (useParentGroupForInvokes) group else TowerGroup.EmptyRoot
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processLevelForPropertyWithInvokeExtension(
|
||||
towerLevel: SessionBasedTowerLevel,
|
||||
callInfo: CallInfo,
|
||||
group: TowerGroup
|
||||
) {
|
||||
if (callInfo.callKind == CallKind.Function) {
|
||||
processLevel(
|
||||
towerLevel,
|
||||
callInfo,
|
||||
group,
|
||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
|
||||
InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirScope.toScopeTowerLevel(
|
||||
extensionReceiver: ReceiverValue? = null,
|
||||
extensionsOnly: Boolean = false,
|
||||
includeInnerConstructors: Boolean = true
|
||||
): ScopeTowerLevel = ScopeTowerLevel(
|
||||
session, components, this,
|
||||
extensionReceiver, extensionsOnly, includeInnerConstructors
|
||||
)
|
||||
|
||||
private fun ReceiverValue.toMemberScopeTowerLevel(
|
||||
extensionReceiver: ReceiverValue? = null,
|
||||
implicitExtensionInvokeMode: Boolean = false
|
||||
) = MemberScopeTowerLevel(
|
||||
session, components, this,
|
||||
extensionReceiver, implicitExtensionInvokeMode,
|
||||
scopeSession = components.scopeSession
|
||||
)
|
||||
|
||||
private suspend fun processQualifierScopes(
|
||||
info: CallInfo, qualifierReceiver: QualifierReceiver?
|
||||
) {
|
||||
if (qualifierReceiver == null) return
|
||||
val callableScope = qualifierReceiver.callableScope() ?: return
|
||||
processLevel(
|
||||
callableScope.toScopeTowerLevel(includeInnerConstructors = false),
|
||||
info.noStubReceiver(), TowerGroup.Qualifier,
|
||||
useParentGroupForInvokes = true,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun processClassifierScope(
|
||||
info: CallInfo, qualifierReceiver: QualifierReceiver?, prioritized: Boolean
|
||||
) {
|
||||
if (qualifierReceiver == null) return
|
||||
if (info.callKind != CallKind.CallableReference &&
|
||||
qualifierReceiver is ClassQualifierReceiver &&
|
||||
qualifierReceiver.classSymbol != qualifierReceiver.originalSymbol
|
||||
) return
|
||||
val scope = qualifierReceiver.classifierScope() ?: return
|
||||
val group = if (prioritized) TowerGroup.ClassifierPrioritized else TowerGroup.Classifier
|
||||
processLevel(
|
||||
scope.toScopeTowerLevel(includeInnerConstructors = false), info.noStubReceiver(),
|
||||
group,
|
||||
useParentGroupForInvokes = true,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun runResolverForQualifierReceiver(
|
||||
info: CallInfo,
|
||||
resolvedQualifier: FirResolvedQualifier
|
||||
) {
|
||||
val qualifierReceiver = createQualifierReceiver(resolvedQualifier, session, components.scopeSession)
|
||||
|
||||
when {
|
||||
info.isPotentialQualifierPart -> {
|
||||
processClassifierScope(info, qualifierReceiver, prioritized = true)
|
||||
processQualifierScopes(info, qualifierReceiver)
|
||||
}
|
||||
else -> {
|
||||
processQualifierScopes(info, qualifierReceiver)
|
||||
processClassifierScope(info, qualifierReceiver, prioritized = false)
|
||||
}
|
||||
}
|
||||
|
||||
if (resolvedQualifier.symbol != null) {
|
||||
val typeRef = resolvedQualifier.typeRef
|
||||
// NB: yet built-in Unit is used for "no-value" type
|
||||
if (info.callKind == CallKind.CallableReference) {
|
||||
if (info.stubReceiver != null || typeRef !is FirImplicitBuiltinTypeRef) {
|
||||
runResolverForExpressionReceiver(info, resolvedQualifier)
|
||||
}
|
||||
} else {
|
||||
if (typeRef !is FirImplicitBuiltinTypeRef) {
|
||||
runResolverForExpressionReceiver(info, resolvedQualifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun runResolverForNoReceiver(
|
||||
info: CallInfo
|
||||
) {
|
||||
processExtensionsThatHideMembers(info, explicitReceiverValue = null)
|
||||
|
||||
val emptyScopes = mutableSetOf<FirScope>()
|
||||
val implicitReceiverValuesWithEmptyScopes = mutableSetOf<ImplicitReceiverValue<*>>()
|
||||
|
||||
enumerateTowerLevels(
|
||||
onScope = l@{ scope, group ->
|
||||
// NB: this check does not work for variables
|
||||
// because we do not search for objects if we have extension receiver
|
||||
if (info.callKind != CallKind.VariableAccess && scope in emptyScopes) return@l
|
||||
|
||||
processLevel(
|
||||
scope.toScopeTowerLevel(), info, group
|
||||
)
|
||||
},
|
||||
onImplicitReceiver = { receiver, group ->
|
||||
processCandidatesWithGivenImplicitReceiverAsValue(
|
||||
receiver,
|
||||
info,
|
||||
group,
|
||||
implicitReceiverValuesWithEmptyScopes,
|
||||
emptyScopes
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun processExtensionsThatHideMembers(
|
||||
info: CallInfo,
|
||||
explicitReceiverValue: ReceiverValue?
|
||||
) {
|
||||
val shouldProcessExtensionsBeforeMembers =
|
||||
info.callKind == CallKind.Function && info.name in HIDES_MEMBERS_NAME_LIST
|
||||
|
||||
if (!shouldProcessExtensionsBeforeMembers) return
|
||||
|
||||
val importingScopes = components.fileImportsScope.asReversed()
|
||||
for ((index, topLevelScope) in importingScopes.withIndex()) {
|
||||
if (explicitReceiverValue != null) {
|
||||
processHideMembersLevel(
|
||||
explicitReceiverValue, topLevelScope, info, index, depth = null,
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
)
|
||||
} else {
|
||||
for ((implicitReceiverValue, depth) in implicitReceivers) {
|
||||
processHideMembersLevel(
|
||||
implicitReceiverValue, topLevelScope, info, index, depth,
|
||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processHideMembersLevel(
|
||||
receiverValue: ReceiverValue,
|
||||
topLevelScope: FirScope,
|
||||
info: CallInfo,
|
||||
index: Int,
|
||||
depth: Int?,
|
||||
explicitReceiverKind: ExplicitReceiverKind
|
||||
) = processLevel(
|
||||
topLevelScope.toScopeTowerLevel(
|
||||
extensionReceiver = receiverValue, extensionsOnly = true
|
||||
),
|
||||
info,
|
||||
TowerGroup.TopPrioritized(index).let { if (depth != null) it.Implicit(depth) else it },
|
||||
explicitReceiverKind,
|
||||
)
|
||||
|
||||
private suspend fun processCandidatesWithGivenImplicitReceiverAsValue(
|
||||
receiver: ImplicitReceiverValue<*>,
|
||||
info: CallInfo,
|
||||
parentGroup: TowerGroup,
|
||||
implicitReceiverValuesWithEmptyScopes: MutableSet<ImplicitReceiverValue<*>>,
|
||||
emptyScopes: MutableSet<FirScope>
|
||||
) {
|
||||
val implicitResult = processLevel(
|
||||
receiver.toMemberScopeTowerLevel(), info, parentGroup.Member
|
||||
)
|
||||
|
||||
if (implicitResult == ProcessorAction.NONE) {
|
||||
implicitReceiverValuesWithEmptyScopes += receiver
|
||||
}
|
||||
|
||||
enumerateTowerLevels(
|
||||
parentGroup,
|
||||
onScope = l@{ scope, group ->
|
||||
if (scope in emptyScopes) return@l
|
||||
|
||||
val result = processLevel(
|
||||
scope.toScopeTowerLevel(extensionReceiver = receiver),
|
||||
info, group
|
||||
)
|
||||
|
||||
if (result == ProcessorAction.NONE) {
|
||||
emptyScopes += scope
|
||||
}
|
||||
},
|
||||
onImplicitReceiver = l@{ implicitReceiverValue, group ->
|
||||
if (implicitReceiverValue in implicitReceiverValuesWithEmptyScopes) return@l
|
||||
processLevel(
|
||||
implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = receiver),
|
||||
info, group
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
private suspend fun runResolverForExpressionReceiver(
|
||||
info: CallInfo,
|
||||
receiver: FirExpression
|
||||
) {
|
||||
val explicitReceiverValue = ExpressionReceiverValue(receiver)
|
||||
|
||||
processExtensionsThatHideMembers(info, explicitReceiverValue)
|
||||
|
||||
// Member scope of expression receiver
|
||||
processLevel(
|
||||
explicitReceiverValue.toMemberScopeTowerLevel(), info, TowerGroup.Member, ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
)
|
||||
|
||||
val shouldProcessExplicitReceiverScopeOnly =
|
||||
info.callKind == CallKind.Function && info.explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() != null
|
||||
if (shouldProcessExplicitReceiverScopeOnly) {
|
||||
// Special case (integer literal type)
|
||||
return
|
||||
}
|
||||
|
||||
enumerateTowerLevels(
|
||||
onScope = { scope, group ->
|
||||
processScopeForExplicitReceiver(
|
||||
scope,
|
||||
explicitReceiverValue,
|
||||
info,
|
||||
group
|
||||
)
|
||||
},
|
||||
onImplicitReceiver = { implicitReceiverValue, group ->
|
||||
processCombinationOfReceivers(implicitReceiverValue, explicitReceiverValue, info, group)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private inline fun enumerateTowerLevels(
|
||||
parentGroup: TowerGroup = TowerGroup.EmptyRoot,
|
||||
onScope: (FirScope, TowerGroup) -> Unit,
|
||||
onImplicitReceiver: (ImplicitReceiverValue<*>, TowerGroup) -> Unit,
|
||||
) {
|
||||
for ((index, localScope) in localScopes.withIndex()) {
|
||||
onScope(localScope, parentGroup.Local(index))
|
||||
}
|
||||
|
||||
for ((depth, lexical) in nonLocalTowerDataElements.withIndex()) {
|
||||
if (!lexical.isLocal && lexical.scope != null) {
|
||||
onScope(lexical.scope, parentGroup.NonLocal(depth))
|
||||
}
|
||||
|
||||
val receiver = lexical.implicitReceiver
|
||||
|
||||
if (receiver !is InaccessibleImplicitReceiverValue) {
|
||||
receiver?.let { implicitReceiverValue ->
|
||||
onImplicitReceiver(implicitReceiverValue, parentGroup.Implicit(depth))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processScopeForExplicitReceiver(
|
||||
scope: FirScope,
|
||||
explicitReceiverValue: ExpressionReceiverValue,
|
||||
info: CallInfo,
|
||||
towerGroup: TowerGroup,
|
||||
): ProcessorAction {
|
||||
val result = processLevel(
|
||||
scope.toScopeTowerLevel(extensionReceiver = explicitReceiverValue),
|
||||
info, towerGroup, ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
)
|
||||
|
||||
processLevelForPropertyWithInvokeExtension(
|
||||
scope.toScopeTowerLevel(), info, towerGroup
|
||||
)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private suspend fun processCombinationOfReceivers(
|
||||
implicitReceiverValue: ImplicitReceiverValue<*>,
|
||||
explicitReceiverValue: ExpressionReceiverValue,
|
||||
info: CallInfo,
|
||||
parentGroup: TowerGroup
|
||||
) {
|
||||
// Member extensions
|
||||
processLevel(
|
||||
implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = explicitReceiverValue),
|
||||
info, parentGroup.Member, ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
)
|
||||
// properties for invoke on implicit receiver
|
||||
processLevelForPropertyWithInvokeExtension(
|
||||
implicitReceiverValue.toMemberScopeTowerLevel(), info, parentGroup.Member
|
||||
)
|
||||
|
||||
enumerateTowerLevels(
|
||||
onScope = { scope, group ->
|
||||
processLevelForPropertyWithInvokeExtension(
|
||||
scope.toScopeTowerLevel(extensionReceiver = implicitReceiverValue),
|
||||
info, group
|
||||
)
|
||||
},
|
||||
onImplicitReceiver = { receiver, group ->
|
||||
processLevelForPropertyWithInvokeExtension(
|
||||
receiver.toMemberScopeTowerLevel(extensionReceiver = implicitReceiverValue),
|
||||
info, group
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun runResolverForSuperReceiver(
|
||||
info: CallInfo,
|
||||
superTypeRef: FirTypeRef
|
||||
) {
|
||||
val scope = when (superTypeRef) {
|
||||
is FirResolvedTypeRef -> superTypeRef.type.scope(session, components.scopeSession)
|
||||
is FirComposedSuperTypeRef -> FirCompositeScope(
|
||||
superTypeRef.superTypeRefs.mapNotNull { it.type.scope(session, components.scopeSession) }
|
||||
)
|
||||
else -> null
|
||||
} ?: return
|
||||
processLevel(
|
||||
scope.toScopeTowerLevel(),
|
||||
info, TowerGroup.Member, explicitReceiverKind = ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun runResolverForInvoke(
|
||||
info: CallInfo,
|
||||
invokeReceiverValue: ExpressionReceiverValue,
|
||||
invokeOnGivenReceiverCandidateFactory: CandidateFactory,
|
||||
parentGroupForInvokeCandidates: TowerGroup
|
||||
) {
|
||||
processLevelForRegularInvoke(
|
||||
invokeReceiverValue.toMemberScopeTowerLevel(),
|
||||
info, parentGroupForInvokeCandidates.Member,
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER,
|
||||
invokeOnGivenReceiverCandidateFactory
|
||||
)
|
||||
|
||||
enumerateTowerLevels(
|
||||
onScope = { scope, group ->
|
||||
processLevelForRegularInvoke(
|
||||
scope.toScopeTowerLevel(extensionReceiver = invokeReceiverValue),
|
||||
info, group,
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER,
|
||||
invokeOnGivenReceiverCandidateFactory
|
||||
)
|
||||
},
|
||||
onImplicitReceiver = { receiver, group ->
|
||||
// NB: companions are processed via implicitReceiverValues!
|
||||
processLevelForRegularInvoke(
|
||||
receiver.toMemberScopeTowerLevel(extensionReceiver = invokeReceiverValue),
|
||||
info, group.Member,
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER,
|
||||
invokeOnGivenReceiverCandidateFactory
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun processLevelForRegularInvoke(
|
||||
towerLevel: SessionBasedTowerLevel,
|
||||
callInfo: CallInfo,
|
||||
group: TowerGroup,
|
||||
explicitReceiverKind: ExplicitReceiverKind,
|
||||
candidateFactory: CandidateFactory
|
||||
) = processLevel(
|
||||
towerLevel, callInfo,
|
||||
group.InvokeResolvePriority(InvokeResolvePriority.COMMON_INVOKE),
|
||||
explicitReceiverKind, InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER, candidateFactory
|
||||
)
|
||||
|
||||
// Here we already know extension receiver for invoke, and it's stated in info as first argument
|
||||
private suspend fun runResolverForBuiltinInvokeExtensionWithExplicitArgument(
|
||||
info: CallInfo,
|
||||
invokeReceiverValue: ExpressionReceiverValue,
|
||||
invokeOnGivenReceiverCandidateFactory: CandidateFactory,
|
||||
parentGroupForInvokeCandidates: TowerGroup
|
||||
) {
|
||||
processLevel(
|
||||
invokeReceiverValue.toMemberScopeTowerLevel(),
|
||||
info, parentGroupForInvokeCandidates.Member.InvokeResolvePriority(InvokeResolvePriority.INVOKE_EXTENSION),
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER,
|
||||
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER,
|
||||
invokeOnGivenReceiverCandidateFactory
|
||||
)
|
||||
}
|
||||
|
||||
// Here we don't know extension receiver for invoke, assuming it's one of implicit receivers
|
||||
private suspend fun runResolverForBuiltinInvokeExtensionWithImplicitArgument(
|
||||
info: CallInfo,
|
||||
invokeReceiverValue: ExpressionReceiverValue,
|
||||
invokeOnGivenReceiverCandidateFactory: CandidateFactory,
|
||||
parentGroupForInvokeCandidates: TowerGroup
|
||||
) {
|
||||
for ((implicitReceiverValue, depth) in implicitReceivers) {
|
||||
val towerGroup =
|
||||
parentGroupForInvokeCandidates
|
||||
.Implicit(depth)
|
||||
.InvokeExtension
|
||||
.InvokeResolvePriority(InvokeResolvePriority.INVOKE_EXTENSION)
|
||||
|
||||
processLevel(
|
||||
invokeReceiverValue.toMemberScopeTowerLevel(
|
||||
extensionReceiver = implicitReceiverValue,
|
||||
implicitExtensionInvokeMode = true
|
||||
),
|
||||
info, towerGroup,
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER,
|
||||
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER,
|
||||
invokeOnGivenReceiverCandidateFactory
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun enqueueResolverTasksForInvokeReceiverCandidates(
|
||||
invokeResolveMode: InvokeResolveMode?,
|
||||
info: CallInfo,
|
||||
parentGroupForInvokeCandidates: TowerGroup
|
||||
) {
|
||||
val invokeBuiltinExtensionMode = invokeResolveMode == InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
|
||||
|
||||
for (invokeReceiverCandidate in candidateFactoriesAndCollectors.invokeReceiverCollector!!.bestCandidates()) {
|
||||
val returnTypeRef = when (val symbol = invokeReceiverCandidate.symbol) {
|
||||
is FirTypeAliasSymbol -> symbol.fir.expandedTypeRef
|
||||
is FirCallableSymbol<*> -> symbol.fir.returnTypeRef
|
||||
is FirRegularClassSymbol -> null
|
||||
else -> continue
|
||||
}
|
||||
val isExtensionFunctionType = returnTypeRef?.isExtensionFunctionType(components.session) == true
|
||||
|
||||
if (invokeBuiltinExtensionMode && !isExtensionFunctionType) {
|
||||
continue
|
||||
}
|
||||
|
||||
val extensionReceiverExpression = invokeReceiverCandidate.extensionReceiverExpression()
|
||||
val useImplicitReceiverAsBuiltinInvokeArgument =
|
||||
!invokeBuiltinExtensionMode && isExtensionFunctionType &&
|
||||
invokeReceiverCandidate.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
||||
|
||||
val invokeReceiverExpression =
|
||||
components.createExplicitReceiverForInvoke(
|
||||
invokeReceiverCandidate, info, invokeBuiltinExtensionMode, extensionReceiverExpression
|
||||
)
|
||||
|
||||
val invokeFunctionInfo =
|
||||
info.copy(
|
||||
explicitReceiver = invokeReceiverExpression, name = OperatorNameConventions.INVOKE,
|
||||
candidateForCommonInvokeReceiver = invokeReceiverCandidate.takeUnless { invokeBuiltinExtensionMode }
|
||||
).let {
|
||||
when {
|
||||
invokeBuiltinExtensionMode -> it.withReceiverAsArgument(info.explicitReceiver!!)
|
||||
else -> it
|
||||
}
|
||||
}
|
||||
|
||||
val explicitReceiver = ExpressionReceiverValue(invokeReceiverExpression)
|
||||
enqueueResolverTasksForInvoke(
|
||||
invokeFunctionInfo,
|
||||
explicitReceiver,
|
||||
invokeBuiltinExtensionMode,
|
||||
useImplicitReceiverAsBuiltinInvokeArgument,
|
||||
parentGroupForInvokeCandidates
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun enqueueResolverTasksForInvoke(
|
||||
invokeFunctionInfo: CallInfo,
|
||||
explicitReceiver: ExpressionReceiverValue,
|
||||
invokeBuiltinExtensionMode: Boolean,
|
||||
useImplicitReceiverAsBuiltinInvokeArgument: Boolean,
|
||||
parentGroupForInvokeCandidates: TowerGroup
|
||||
) {
|
||||
val invokeOnGivenReceiverCandidateFactory = CandidateFactory(components, invokeFunctionInfo)
|
||||
if (invokeBuiltinExtensionMode) {
|
||||
manager.enqueueResolverTask {
|
||||
runResolverForBuiltinInvokeExtensionWithExplicitArgument(
|
||||
invokeFunctionInfo, explicitReceiver, invokeOnGivenReceiverCandidateFactory,
|
||||
parentGroupForInvokeCandidates
|
||||
)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (useImplicitReceiverAsBuiltinInvokeArgument) {
|
||||
manager.enqueueResolverTask {
|
||||
runResolverForBuiltinInvokeExtensionWithImplicitArgument(
|
||||
invokeFunctionInfo, explicitReceiver, invokeOnGivenReceiverCandidateFactory,
|
||||
parentGroupForInvokeCandidates
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
manager.enqueueResolverTask {
|
||||
runResolverForInvoke(
|
||||
invokeFunctionInfo, explicitReceiver, invokeOnGivenReceiverCandidateFactory,
|
||||
parentGroupForInvokeCandidates
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun BodyResolveComponents.createExplicitReceiverForInvoke(
|
||||
candidate: Candidate,
|
||||
info: CallInfo,
|
||||
invokeBuiltinExtensionMode: Boolean,
|
||||
extensionReceiverExpression: FirExpression
|
||||
): FirExpression {
|
||||
return when (val symbol = candidate.symbol) {
|
||||
is FirCallableSymbol<*> -> createExplicitReceiverForInvokeByCallable(
|
||||
candidate, info, invokeBuiltinExtensionMode, extensionReceiverExpression, symbol
|
||||
)
|
||||
is FirRegularClassSymbol -> buildResolvedQualifierForClass(symbol, sourceElement = null)
|
||||
is FirTypeAliasSymbol -> {
|
||||
val type = symbol.fir.expandedTypeRef.coneTypeUnsafe<ConeClassLikeType>().fullyExpandedType(session)
|
||||
val expansionRegularClass = type.lookupTag.toSymbol(session)?.fir as? FirRegularClass
|
||||
buildResolvedQualifierForClass(expansionRegularClass!!.symbol, sourceElement = symbol.fir.source)
|
||||
}
|
||||
else -> throw AssertionError()
|
||||
}
|
||||
}
|
||||
|
||||
private fun BodyResolveComponents.createExplicitReceiverForInvokeByCallable(
|
||||
candidate: Candidate,
|
||||
info: CallInfo,
|
||||
invokeBuiltinExtensionMode: Boolean,
|
||||
extensionReceiverExpression: FirExpression,
|
||||
symbol: FirCallableSymbol<*>
|
||||
): FirExpression {
|
||||
return FirQualifiedAccessExpressionBuilder().apply {
|
||||
calleeReference = FirNamedReferenceWithCandidate(
|
||||
null,
|
||||
symbol.callableId.callableName,
|
||||
candidate
|
||||
)
|
||||
dispatchReceiver = candidate.dispatchReceiverExpression()
|
||||
this.typeRef = returnTypeCalculator.tryCalculateReturnType(symbol.firUnsafe())
|
||||
|
||||
if (!invokeBuiltinExtensionMode) {
|
||||
extensionReceiver = extensionReceiverExpression
|
||||
// NB: this should fix problem in DFA (KT-36014)
|
||||
explicitReceiver = info.explicitReceiver
|
||||
}
|
||||
}.build().let(::transformQualifiedAccessUsingSmartcastInfo)
|
||||
}
|
||||
+13
-1
@@ -26,6 +26,8 @@ sealed class TowerGroupKind(private val index: Int) : Comparable<TowerGroupKind>
|
||||
|
||||
object InvokeExtension : TowerGroupKind(60)
|
||||
|
||||
object QualifierValue : TowerGroupKind(70)
|
||||
|
||||
object Last : TowerGroupKind(Integer.MAX_VALUE)
|
||||
|
||||
override fun compareTo(other: TowerGroupKind): Int {
|
||||
@@ -64,6 +66,8 @@ private constructor(
|
||||
|
||||
val Classifier = kindOf(TowerGroupKind.Classifier)
|
||||
|
||||
val QualifierValue = kindOf(TowerGroupKind.QualifierValue)
|
||||
|
||||
val Member = kindOf(TowerGroupKind.Member)
|
||||
|
||||
fun Local(depth: Int) = kindOf(TowerGroupKind.Local(depth))
|
||||
@@ -87,6 +91,8 @@ private constructor(
|
||||
|
||||
val InvokeExtension get() = kindOf(TowerGroupKind.InvokeExtension)
|
||||
|
||||
fun TopPrioritized(depth: Int) = kindOf(TowerGroupKind.TopPrioritized(depth))
|
||||
|
||||
// Treating `a.foo()` common calls as more prioritized than `a.foo.invoke()`
|
||||
// It's not the same as TowerGroupKind because it's not about tower levels, but rather a different dimension semantically.
|
||||
// It could be implemented via another TowerGroupKind, but it's not clear what priority should be assigned to the new TowerGroupKind
|
||||
@@ -127,8 +133,14 @@ private constructor(
|
||||
result = 31 * result + invokeResolvePriority.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "TowerGroup(kinds=${kinds.contentToString()}, invokeResolvePriority=$invokeResolvePriority)"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
enum class InvokeResolvePriority {
|
||||
NONE, COMMON_INVOKE, INVOKE_EXTENSION;
|
||||
NONE, INVOKE_RECEIVER, COMMON_INVOKE, INVOKE_EXTENSION;
|
||||
}
|
||||
|
||||
+12
-47
@@ -25,16 +25,8 @@ internal class CandidateFactoriesAndCollectors(
|
||||
|
||||
// Callable references
|
||||
val stubReceiverCandidateFactory: CandidateFactory?,
|
||||
|
||||
// invoke receivers
|
||||
val invokeReceiverCandidateFactory: CandidateFactory?,
|
||||
val invokeReceiverCollector: CandidateCollector?,
|
||||
|
||||
// invokeExtensionReceivers
|
||||
val invokeBuiltinExtensionReceiverCandidateFactory: CandidateFactory?
|
||||
)
|
||||
|
||||
typealias EnqueueTasksForInvokeReceiverCandidates = () -> Unit
|
||||
|
||||
internal class TowerLevelHandler {
|
||||
|
||||
@@ -42,61 +34,34 @@ internal class TowerLevelHandler {
|
||||
private var processResult = ProcessorAction.NONE
|
||||
|
||||
fun handleLevel(
|
||||
collector: CandidateCollector,
|
||||
candidateFactory: CandidateFactory,
|
||||
stubReceiverCandidateFactory: CandidateFactory? = null,
|
||||
info: CallInfo,
|
||||
explicitReceiverKind: ExplicitReceiverKind,
|
||||
group: TowerGroup,
|
||||
candidateFactoriesAndCollectors: CandidateFactoriesAndCollectors,
|
||||
towerLevel: SessionBasedTowerLevel,
|
||||
invokeResolveMode: InvokeResolveMode?,
|
||||
candidateFactory: CandidateFactory,
|
||||
enqueueResolverTasksForInvokeReceiverCandidates: EnqueueTasksForInvokeReceiverCandidates
|
||||
towerLevel: SessionBasedTowerLevel
|
||||
): ProcessorAction {
|
||||
val resultCollector = candidateFactoriesAndCollectors.resultCollector
|
||||
processResult = ProcessorAction.NONE
|
||||
val processor =
|
||||
TowerScopeLevelProcessor(
|
||||
info.explicitReceiver,
|
||||
explicitReceiverKind,
|
||||
resultCollector,
|
||||
collector,
|
||||
candidateFactory,
|
||||
group
|
||||
)
|
||||
|
||||
when (info.callKind) {
|
||||
CallKind.VariableAccess -> {
|
||||
towerLevel.processProperties(info.name, processor)
|
||||
|
||||
if (!resultCollector.isSuccess()) {
|
||||
if (!collector.isSuccess()) {
|
||||
towerLevel.processObjectsAsVariables(info.name, processor)
|
||||
}
|
||||
}
|
||||
CallKind.Function -> {
|
||||
val invokeBuiltinExtensionMode =
|
||||
invokeResolveMode == InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
|
||||
|
||||
if (!invokeBuiltinExtensionMode) {
|
||||
towerLevel.processFunctions(info.name, processor)
|
||||
}
|
||||
|
||||
if (invokeResolveMode == InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER ||
|
||||
resultCollector.isSuccess()
|
||||
) {
|
||||
return processResult
|
||||
}
|
||||
|
||||
val invokeReceiverProcessor = TowerScopeLevelProcessor(
|
||||
info.explicitReceiver,
|
||||
explicitReceiverKind,
|
||||
candidateFactoriesAndCollectors.invokeReceiverCollector!!,
|
||||
if (invokeBuiltinExtensionMode) candidateFactoriesAndCollectors.invokeBuiltinExtensionReceiverCandidateFactory!!
|
||||
else candidateFactoriesAndCollectors.invokeReceiverCandidateFactory!!,
|
||||
group
|
||||
)
|
||||
candidateFactoriesAndCollectors.invokeReceiverCollector.newDataSet()
|
||||
towerLevel.processProperties(info.name, invokeReceiverProcessor)
|
||||
towerLevel.processObjectsAsVariables(info.name, invokeReceiverProcessor)
|
||||
|
||||
if (candidateFactoriesAndCollectors.invokeReceiverCollector.isSuccess()) {
|
||||
enqueueResolverTasksForInvokeReceiverCandidates()
|
||||
}
|
||||
towerLevel.processFunctions(info.name, processor)
|
||||
}
|
||||
CallKind.CallableReference -> {
|
||||
val stubReceiver = info.stubReceiver
|
||||
@@ -109,13 +74,13 @@ internal class TowerLevelHandler {
|
||||
} else {
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
},
|
||||
resultCollector,
|
||||
candidateFactoriesAndCollectors.stubReceiverCandidateFactory!!, group
|
||||
collector,
|
||||
stubReceiverCandidateFactory!!, group
|
||||
)
|
||||
val towerLevelWithStubReceiver = towerLevel.replaceReceiverValue(stubReceiverValue)
|
||||
towerLevelWithStubReceiver.processFunctionsAndProperties(info.name, stubProcessor)
|
||||
// NB: we don't perform this for implicit Unit
|
||||
if (!resultCollector.isSuccess() && info.explicitReceiver?.typeRef !is FirImplicitBuiltinTypeRef) {
|
||||
if (!collector.isSuccess() && info.explicitReceiver?.typeRef !is FirImplicitBuiltinTypeRef) {
|
||||
towerLevel.processFunctionsAndProperties(info.name, processor)
|
||||
}
|
||||
} else {
|
||||
|
||||
-5
@@ -70,8 +70,3 @@ class TowerResolveManager private constructor(private val shouldStopAtTheLevel:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class InvokeResolveMode {
|
||||
IMPLICIT_CALL_ON_GIVEN_RECEIVER,
|
||||
RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
|
||||
}
|
||||
|
||||
+2
-2
@@ -60,8 +60,8 @@ class Case4() : I {
|
||||
I.invoke("")
|
||||
<!DEBUG_INFO_CALL("fqName: Case4.Companion.invoke; typeCall: operator function")!>invoke("")<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>invoke("")<!>
|
||||
<!DEBUG_INFO_CALL("fqName: fqName is unknown; typeCall: unresolved")!><!UNRESOLVED_REFERENCE!>I<!>("")<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: I")!><!UNRESOLVED_REFERENCE!>I<!>("")<!>
|
||||
<!DEBUG_INFO_CALL("fqName: I.Companion.invoke; typeCall: variable&invoke")!>I("")<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>I("")<!>
|
||||
<!DEBUG_INFO_CALL("fqName: Case4.Companion.invoke; typeCall: variable&invoke")!>Case4("")<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>Case4("")<!>
|
||||
}
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ class Case3() : I {
|
||||
|
||||
fun case() {
|
||||
I.<!AMBIGUITY!>invoke<!>(<!UNRESOLVED_REFERENCE!>::x<!>)
|
||||
<!UNRESOLVED_REFERENCE!>I<!>(<!UNRESOLVED_REFERENCE!>::x<!>)
|
||||
<!AMBIGUITY!>I<!>(<!UNRESOLVED_REFERENCE!>::x<!>)
|
||||
<!AMBIGUITY!>Case3<!>(<!UNRESOLVED_REFERENCE!>::x<!>)
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -66,13 +66,13 @@ class Case3() : I {
|
||||
I.invoke(::y)
|
||||
I.invoke(::y)
|
||||
|
||||
<!UNRESOLVED_REFERENCE!>I<!>(<!DEBUG_INFO_EXPRESSION_TYPE("Type is unknown"), UNRESOLVED_REFERENCE!>::x<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: I")!><!UNRESOLVED_REFERENCE!>I<!>(<!UNRESOLVED_REFERENCE!>::x<!>)<!>
|
||||
<!DEBUG_INFO_CALL("fqName: fqName is unknown; typeCall: unresolved")!><!UNRESOLVED_REFERENCE!>I<!>(<!UNRESOLVED_REFERENCE!>::x<!>)<!>
|
||||
I(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KProperty0<kotlin.String>")!>::x<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!>I(::x)<!>
|
||||
<!DEBUG_INFO_CALL("fqName: I.Companion.invoke; typeCall: variable&invoke")!>I(::x)<!>
|
||||
|
||||
<!UNRESOLVED_REFERENCE!>I<!>(<!DEBUG_INFO_EXPRESSION_TYPE("Type is unknown"), UNRESOLVED_REFERENCE!>::y<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: I")!><!UNRESOLVED_REFERENCE!>I<!>(<!UNRESOLVED_REFERENCE!>::y<!>)<!>
|
||||
<!DEBUG_INFO_CALL("fqName: fqName is unknown; typeCall: unresolved")!><!UNRESOLVED_REFERENCE!>I<!>(<!UNRESOLVED_REFERENCE!>::y<!>)<!>
|
||||
I(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction0<kotlin.String>")!>::y<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!>I(::y)<!>
|
||||
<!DEBUG_INFO_CALL("fqName: I.Companion.invoke; typeCall: variable&invoke")!>I(::y)<!>
|
||||
|
||||
Case3(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KProperty0<kotlin.String>")!>::x<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>Case3(::x)<!>
|
||||
|
||||
Reference in New Issue
Block a user