[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
|
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.BodyResolveComponents
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.scope
|
import org.jetbrains.kotlin.fir.resolve.scope
|
||||||
@@ -27,13 +30,51 @@ class FirTowerResolver(
|
|||||||
): CandidateCollector {
|
): CandidateCollector {
|
||||||
val candidateFactoriesAndCollectors = buildCandidateFactoriesAndCollectors(info, collector)
|
val candidateFactoriesAndCollectors = buildCandidateFactoriesAndCollectors(info, collector)
|
||||||
|
|
||||||
val towerResolverSession = FirTowerResolverSession(components, manager, candidateFactoriesAndCollectors, info)
|
enqueueResolutionTasks(components, manager, candidateFactoriesAndCollectors, info)
|
||||||
towerResolverSession.runResolution(info)
|
|
||||||
|
|
||||||
manager.runTasks()
|
manager.runTasks()
|
||||||
return collector
|
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(
|
fun runResolverForDelegatingConstructor(
|
||||||
info: CallInfo,
|
info: CallInfo,
|
||||||
constructedType: ConeClassLikeType
|
constructedType: ConeClassLikeType
|
||||||
@@ -79,26 +120,10 @@ class FirTowerResolver(
|
|||||||
else
|
else
|
||||||
null
|
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(
|
return CandidateFactoriesAndCollectors(
|
||||||
candidateFactory,
|
candidateFactory,
|
||||||
collector,
|
collector,
|
||||||
stubReceiverCandidateFactory,
|
stubReceiverCandidateFactory
|
||||||
invokeReceiverCandidateFactory,
|
|
||||||
invokeReceiverCollector,
|
|
||||||
invokeBuiltinExtensionReceiverCandidateFactory
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-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 InvokeExtension : TowerGroupKind(60)
|
||||||
|
|
||||||
|
object QualifierValue : TowerGroupKind(70)
|
||||||
|
|
||||||
object Last : TowerGroupKind(Integer.MAX_VALUE)
|
object Last : TowerGroupKind(Integer.MAX_VALUE)
|
||||||
|
|
||||||
override fun compareTo(other: TowerGroupKind): Int {
|
override fun compareTo(other: TowerGroupKind): Int {
|
||||||
@@ -64,6 +66,8 @@ private constructor(
|
|||||||
|
|
||||||
val Classifier = kindOf(TowerGroupKind.Classifier)
|
val Classifier = kindOf(TowerGroupKind.Classifier)
|
||||||
|
|
||||||
|
val QualifierValue = kindOf(TowerGroupKind.QualifierValue)
|
||||||
|
|
||||||
val Member = kindOf(TowerGroupKind.Member)
|
val Member = kindOf(TowerGroupKind.Member)
|
||||||
|
|
||||||
fun Local(depth: Int) = kindOf(TowerGroupKind.Local(depth))
|
fun Local(depth: Int) = kindOf(TowerGroupKind.Local(depth))
|
||||||
@@ -87,6 +91,8 @@ private constructor(
|
|||||||
|
|
||||||
val InvokeExtension get() = kindOf(TowerGroupKind.InvokeExtension)
|
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()`
|
// 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'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
|
// 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()
|
result = 31 * result + invokeResolvePriority.hashCode()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "TowerGroup(kinds=${kinds.contentToString()}, invokeResolvePriority=$invokeResolvePriority)"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class 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
|
// Callable references
|
||||||
val stubReceiverCandidateFactory: CandidateFactory?,
|
val stubReceiverCandidateFactory: CandidateFactory?,
|
||||||
|
|
||||||
// invoke receivers
|
|
||||||
val invokeReceiverCandidateFactory: CandidateFactory?,
|
|
||||||
val invokeReceiverCollector: CandidateCollector?,
|
|
||||||
|
|
||||||
// invokeExtensionReceivers
|
|
||||||
val invokeBuiltinExtensionReceiverCandidateFactory: CandidateFactory?
|
|
||||||
)
|
)
|
||||||
|
|
||||||
typealias EnqueueTasksForInvokeReceiverCandidates = () -> Unit
|
|
||||||
|
|
||||||
internal class TowerLevelHandler {
|
internal class TowerLevelHandler {
|
||||||
|
|
||||||
@@ -42,61 +34,34 @@ internal class TowerLevelHandler {
|
|||||||
private var processResult = ProcessorAction.NONE
|
private var processResult = ProcessorAction.NONE
|
||||||
|
|
||||||
fun handleLevel(
|
fun handleLevel(
|
||||||
|
collector: CandidateCollector,
|
||||||
|
candidateFactory: CandidateFactory,
|
||||||
|
stubReceiverCandidateFactory: CandidateFactory? = null,
|
||||||
info: CallInfo,
|
info: CallInfo,
|
||||||
explicitReceiverKind: ExplicitReceiverKind,
|
explicitReceiverKind: ExplicitReceiverKind,
|
||||||
group: TowerGroup,
|
group: TowerGroup,
|
||||||
candidateFactoriesAndCollectors: CandidateFactoriesAndCollectors,
|
towerLevel: SessionBasedTowerLevel
|
||||||
towerLevel: SessionBasedTowerLevel,
|
|
||||||
invokeResolveMode: InvokeResolveMode?,
|
|
||||||
candidateFactory: CandidateFactory,
|
|
||||||
enqueueResolverTasksForInvokeReceiverCandidates: EnqueueTasksForInvokeReceiverCandidates
|
|
||||||
): ProcessorAction {
|
): ProcessorAction {
|
||||||
val resultCollector = candidateFactoriesAndCollectors.resultCollector
|
processResult = ProcessorAction.NONE
|
||||||
val processor =
|
val processor =
|
||||||
TowerScopeLevelProcessor(
|
TowerScopeLevelProcessor(
|
||||||
info.explicitReceiver,
|
info.explicitReceiver,
|
||||||
explicitReceiverKind,
|
explicitReceiverKind,
|
||||||
resultCollector,
|
collector,
|
||||||
candidateFactory,
|
candidateFactory,
|
||||||
group
|
group
|
||||||
)
|
)
|
||||||
|
|
||||||
when (info.callKind) {
|
when (info.callKind) {
|
||||||
CallKind.VariableAccess -> {
|
CallKind.VariableAccess -> {
|
||||||
towerLevel.processProperties(info.name, processor)
|
towerLevel.processProperties(info.name, processor)
|
||||||
|
|
||||||
if (!resultCollector.isSuccess()) {
|
if (!collector.isSuccess()) {
|
||||||
towerLevel.processObjectsAsVariables(info.name, processor)
|
towerLevel.processObjectsAsVariables(info.name, processor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CallKind.Function -> {
|
CallKind.Function -> {
|
||||||
val invokeBuiltinExtensionMode =
|
towerLevel.processFunctions(info.name, processor)
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
CallKind.CallableReference -> {
|
CallKind.CallableReference -> {
|
||||||
val stubReceiver = info.stubReceiver
|
val stubReceiver = info.stubReceiver
|
||||||
@@ -109,13 +74,13 @@ internal class TowerLevelHandler {
|
|||||||
} else {
|
} else {
|
||||||
ExplicitReceiverKind.EXTENSION_RECEIVER
|
ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||||
},
|
},
|
||||||
resultCollector,
|
collector,
|
||||||
candidateFactoriesAndCollectors.stubReceiverCandidateFactory!!, group
|
stubReceiverCandidateFactory!!, group
|
||||||
)
|
)
|
||||||
val towerLevelWithStubReceiver = towerLevel.replaceReceiverValue(stubReceiverValue)
|
val towerLevelWithStubReceiver = towerLevel.replaceReceiverValue(stubReceiverValue)
|
||||||
towerLevelWithStubReceiver.processFunctionsAndProperties(info.name, stubProcessor)
|
towerLevelWithStubReceiver.processFunctionsAndProperties(info.name, stubProcessor)
|
||||||
// NB: we don't perform this for implicit Unit
|
// 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)
|
towerLevel.processFunctionsAndProperties(info.name, processor)
|
||||||
}
|
}
|
||||||
} else {
|
} 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("")
|
I.invoke("")
|
||||||
<!DEBUG_INFO_CALL("fqName: Case4.Companion.invoke; typeCall: operator function")!>invoke("")<!>
|
<!DEBUG_INFO_CALL("fqName: Case4.Companion.invoke; typeCall: operator function")!>invoke("")<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>invoke("")<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>invoke("")<!>
|
||||||
<!DEBUG_INFO_CALL("fqName: fqName is unknown; typeCall: unresolved")!><!UNRESOLVED_REFERENCE!>I<!>("")<!>
|
<!DEBUG_INFO_CALL("fqName: I.Companion.invoke; typeCall: variable&invoke")!>I("")<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: I")!><!UNRESOLVED_REFERENCE!>I<!>("")<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>I("")<!>
|
||||||
<!DEBUG_INFO_CALL("fqName: Case4.Companion.invoke; typeCall: variable&invoke")!>Case4("")<!>
|
<!DEBUG_INFO_CALL("fqName: Case4.Companion.invoke; typeCall: variable&invoke")!>Case4("")<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>Case4("")<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>Case4("")<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@ class Case3() : I {
|
|||||||
|
|
||||||
fun case() {
|
fun case() {
|
||||||
I.<!AMBIGUITY!>invoke<!>(<!UNRESOLVED_REFERENCE!>::x<!>)
|
I.<!AMBIGUITY!>invoke<!>(<!UNRESOLVED_REFERENCE!>::x<!>)
|
||||||
<!UNRESOLVED_REFERENCE!>I<!>(<!UNRESOLVED_REFERENCE!>::x<!>)
|
<!AMBIGUITY!>I<!>(<!UNRESOLVED_REFERENCE!>::x<!>)
|
||||||
<!AMBIGUITY!>Case3<!>(<!UNRESOLVED_REFERENCE!>::x<!>)
|
<!AMBIGUITY!>Case3<!>(<!UNRESOLVED_REFERENCE!>::x<!>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -66,13 +66,13 @@ class Case3() : I {
|
|||||||
I.invoke(::y)
|
I.invoke(::y)
|
||||||
I.invoke(::y)
|
I.invoke(::y)
|
||||||
|
|
||||||
<!UNRESOLVED_REFERENCE!>I<!>(<!DEBUG_INFO_EXPRESSION_TYPE("Type is unknown"), UNRESOLVED_REFERENCE!>::x<!>)
|
I(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KProperty0<kotlin.String>")!>::x<!>)
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: I")!><!UNRESOLVED_REFERENCE!>I<!>(<!UNRESOLVED_REFERENCE!>::x<!>)<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!>I(::x)<!>
|
||||||
<!DEBUG_INFO_CALL("fqName: fqName is unknown; typeCall: unresolved")!><!UNRESOLVED_REFERENCE!>I<!>(<!UNRESOLVED_REFERENCE!>::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<!>)
|
I(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction0<kotlin.String>")!>::y<!>)
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: I")!><!UNRESOLVED_REFERENCE!>I<!>(<!UNRESOLVED_REFERENCE!>::y<!>)<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!>I(::y)<!>
|
||||||
<!DEBUG_INFO_CALL("fqName: fqName is unknown; typeCall: unresolved")!><!UNRESOLVED_REFERENCE!>I<!>(<!UNRESOLVED_REFERENCE!>::y<!>)<!>
|
<!DEBUG_INFO_CALL("fqName: I.Companion.invoke; typeCall: variable&invoke")!>I(::y)<!>
|
||||||
|
|
||||||
Case3(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KProperty0<kotlin.String>")!>::x<!>)
|
Case3(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KProperty0<kotlin.String>")!>::x<!>)
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>Case3(::x)<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>Case3(::x)<!>
|
||||||
|
|||||||
Reference in New Issue
Block a user