Don't enter twice local scopes w/out particular name in FIR tower resolver
This commit is contained in:
@@ -7,8 +7,11 @@ package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.TowerDataKind.EMPTY
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.TowerDataKind.TOWER_LEVEL
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NONE
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||
|
||||
enum class TowerDataKind {
|
||||
@@ -29,6 +32,7 @@ class CallResolver(
|
||||
private fun processImplicitReceiver(
|
||||
towerDataConsumer: TowerDataConsumer,
|
||||
implicitReceiverValue: ImplicitReceiverValue<*>,
|
||||
nonEmptyLocalScopes: List<FirLocalScope>,
|
||||
oldGroup: Int
|
||||
): Int {
|
||||
var group = oldGroup
|
||||
@@ -39,7 +43,7 @@ class CallResolver(
|
||||
// fun test(b: Bar) { b.baz() }
|
||||
// }
|
||||
towerDataConsumer.consume(
|
||||
TowerDataKind.TOWER_LEVEL,
|
||||
TOWER_LEVEL,
|
||||
MemberScopeTowerLevel(session, implicitReceiverValue, scopeSession = components.scopeSession),
|
||||
group++
|
||||
)
|
||||
@@ -50,7 +54,7 @@ class CallResolver(
|
||||
// fun test() { bar() }
|
||||
// }
|
||||
towerDataConsumer.consume(
|
||||
TowerDataKind.TOWER_LEVEL,
|
||||
TOWER_LEVEL,
|
||||
MemberScopeTowerLevel(session, implicitReceiverValue, implicitReceiverValue, components.scopeSession),
|
||||
group++
|
||||
)
|
||||
@@ -62,9 +66,9 @@ class CallResolver(
|
||||
// bar()
|
||||
// }
|
||||
// }
|
||||
for (scope in localScopes) {
|
||||
for (scope in nonEmptyLocalScopes) {
|
||||
towerDataConsumer.consume(
|
||||
TowerDataKind.TOWER_LEVEL,
|
||||
TOWER_LEVEL,
|
||||
ScopeTowerLevel(session, components, scope, implicitExtensionReceiver = implicitReceiverValue),
|
||||
group++
|
||||
)
|
||||
@@ -83,7 +87,7 @@ class CallResolver(
|
||||
// }
|
||||
// }
|
||||
towerDataConsumer.consume(
|
||||
TowerDataKind.TOWER_LEVEL,
|
||||
TOWER_LEVEL,
|
||||
ScopeTowerLevel(session, components, implicitScope, implicitExtensionReceiver = implicitReceiverValue),
|
||||
group++
|
||||
)
|
||||
@@ -97,7 +101,7 @@ class CallResolver(
|
||||
// fun test() { foo() }
|
||||
// }
|
||||
towerDataConsumer.consume(
|
||||
TowerDataKind.TOWER_LEVEL,
|
||||
TOWER_LEVEL,
|
||||
ScopeTowerLevel(session, components, implicitCompanionScope, implicitExtensionReceiver = implicitReceiverValue),
|
||||
group++
|
||||
)
|
||||
@@ -119,7 +123,7 @@ class CallResolver(
|
||||
// with(a) { with(b) { foo() } }
|
||||
// }
|
||||
towerDataConsumer.consume(
|
||||
TowerDataKind.TOWER_LEVEL,
|
||||
TOWER_LEVEL,
|
||||
MemberScopeTowerLevel(
|
||||
session, scopeSession = components.scopeSession,
|
||||
dispatchReceiver = implicitDispatchReceiverValue,
|
||||
@@ -137,7 +141,7 @@ class CallResolver(
|
||||
// }
|
||||
for (scope in topLevelScopes) {
|
||||
towerDataConsumer.consume(
|
||||
TowerDataKind.TOWER_LEVEL,
|
||||
TOWER_LEVEL,
|
||||
ScopeTowerLevel(session, components, scope, implicitExtensionReceiver = implicitReceiverValue),
|
||||
group++
|
||||
)
|
||||
@@ -147,7 +151,7 @@ class CallResolver(
|
||||
}
|
||||
|
||||
val collector by lazy { CandidateCollector(components, resolutionStageRunner) }
|
||||
lateinit var towerDataConsumer: TowerDataConsumer
|
||||
private lateinit var towerDataConsumer: TowerDataConsumer
|
||||
private lateinit var implicitReceiverValues: List<ImplicitReceiverValue<*>>
|
||||
|
||||
fun runTowerResolver(consumer: TowerDataConsumer, implicitReceiverValues: List<ImplicitReceiverValue<*>>): CandidateCollector {
|
||||
@@ -158,12 +162,15 @@ class CallResolver(
|
||||
// Member of explicit receiver' type (this stage does nothing without explicit receiver)
|
||||
// class Foo(val x: Int)
|
||||
// fun test(f: Foo) { f.x }
|
||||
towerDataConsumer.consume(TowerDataKind.EMPTY, TowerScopeLevel.Empty, group++)
|
||||
towerDataConsumer.consume(EMPTY, TowerScopeLevel.Empty, group++)
|
||||
|
||||
// Member of local scope
|
||||
// fun test(x: Int) = x
|
||||
val nonEmptyLocalScopes = mutableListOf<FirLocalScope>()
|
||||
for (scope in localScopes) {
|
||||
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, components, scope), group++)
|
||||
if (towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, scope), group++) != NONE) {
|
||||
nonEmptyLocalScopes += scope
|
||||
}
|
||||
}
|
||||
|
||||
var blockDispatchReceivers = false
|
||||
@@ -172,7 +179,7 @@ class CallResolver(
|
||||
for (implicitReceiverValue in implicitReceiverValues) {
|
||||
if (!blockDispatchReceivers || implicitReceiverValue !is ImplicitDispatchReceiverValue) {
|
||||
// Direct use of implicit receiver (see inside)
|
||||
group = processImplicitReceiver(towerDataConsumer, implicitReceiverValue, group)
|
||||
group = processImplicitReceiver(towerDataConsumer, implicitReceiverValue, nonEmptyLocalScopes, group)
|
||||
}
|
||||
val implicitScope = implicitReceiverValue.implicitScope
|
||||
if (implicitScope != null) {
|
||||
@@ -181,7 +188,7 @@ class CallResolver(
|
||||
// val x = 0
|
||||
// class Nested { val y = x }
|
||||
// }
|
||||
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, components, implicitScope), group++)
|
||||
towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, implicitScope), group++)
|
||||
}
|
||||
if (implicitReceiverValue is ImplicitDispatchReceiverValue) {
|
||||
val implicitCompanionScope = implicitReceiverValue.implicitCompanionScope
|
||||
@@ -191,7 +198,7 @@ class CallResolver(
|
||||
// companion object { val x = 0 }
|
||||
// class Nested { val y = x }
|
||||
// }
|
||||
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, components, implicitCompanionScope), group++)
|
||||
towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, implicitCompanionScope), group++)
|
||||
}
|
||||
if (!implicitReceiverValue.boundSymbol.fir.isInner) {
|
||||
blockDispatchReceivers = true
|
||||
@@ -203,7 +210,7 @@ class CallResolver(
|
||||
// val x = 0
|
||||
// fun test() { x }
|
||||
for (scope in topLevelScopes) {
|
||||
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, components, scope), group++)
|
||||
towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, scope), group++)
|
||||
}
|
||||
|
||||
return collector
|
||||
|
||||
+13
-9
@@ -92,13 +92,15 @@ class PrioritizedTowerDataConsumer(
|
||||
group: Int
|
||||
): ProcessorAction {
|
||||
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
|
||||
var empty = true
|
||||
for ((index, consumer) in consumers.withIndex()) {
|
||||
val action = consumer.consume(kind, towerScopeLevel, group * consumers.size + index)
|
||||
if (action.stop()) {
|
||||
return ProcessorAction.STOP
|
||||
when (action) {
|
||||
ProcessorAction.STOP -> return action
|
||||
ProcessorAction.NEXT -> empty = false
|
||||
}
|
||||
}
|
||||
return ProcessorAction.NEXT
|
||||
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,16 +125,18 @@ class AccumulatingTowerDataConsumer(
|
||||
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
|
||||
accumulatedTowerData += TowerData(kind, towerScopeLevel, group)
|
||||
|
||||
if (initialConsumer.consume(kind, towerScopeLevel, group).stop()) {
|
||||
return ProcessorAction.STOP
|
||||
var empty = true
|
||||
when (val action = initialConsumer.consume(kind, towerScopeLevel, group)) {
|
||||
ProcessorAction.STOP -> return action
|
||||
ProcessorAction.NEXT -> empty = false
|
||||
}
|
||||
for (consumer in additionalConsumers) {
|
||||
val action = consumer.consume(kind, towerScopeLevel, group)
|
||||
if (action.stop()) {
|
||||
return ProcessorAction.STOP
|
||||
when (val action = consumer.consume(kind, towerScopeLevel, group)) {
|
||||
ProcessorAction.STOP -> return action
|
||||
ProcessorAction.NEXT -> empty = false
|
||||
}
|
||||
}
|
||||
return ProcessorAction.NEXT
|
||||
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
|
||||
}
|
||||
|
||||
fun addConsumer(consumer: TowerDataConsumer): ProcessorAction {
|
||||
|
||||
+2
-4
@@ -50,10 +50,8 @@ abstract class FirAbstractSimpleImportingScope(
|
||||
token: TowerScopeLevel.Token<T>,
|
||||
processor: (FirCallableSymbol<*>) -> ProcessorAction
|
||||
): ProcessorAction {
|
||||
|
||||
|
||||
val imports = simpleImports[name] ?: return ProcessorAction.NEXT
|
||||
if (imports.isEmpty()) return ProcessorAction.NEXT
|
||||
val imports = simpleImports[name] ?: return ProcessorAction.NONE
|
||||
if (imports.isEmpty()) return ProcessorAction.NONE
|
||||
|
||||
for (import in imports) {
|
||||
if (processCallables(import, import.importedName!!, token, processor).stop()) {
|
||||
|
||||
+3
@@ -50,6 +50,9 @@ abstract class FirAbstractStarImportingScope(
|
||||
token: TowerScopeLevel.Token<T>,
|
||||
processor: (FirCallableSymbol<*>) -> ProcessorAction
|
||||
): ProcessorAction {
|
||||
if (starImports.isEmpty()) {
|
||||
return ProcessorAction.NONE
|
||||
}
|
||||
for (import in starImports) {
|
||||
if (processCallables(import, name, token, processor).stop()) {
|
||||
return ProcessorAction.STOP
|
||||
|
||||
@@ -39,7 +39,7 @@ class FirLocalScope : FirScope() {
|
||||
if (prop != null) {
|
||||
return processor(prop)
|
||||
}
|
||||
return ProcessorAction.NEXT
|
||||
return ProcessorAction.NONE
|
||||
}
|
||||
|
||||
override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||
@@ -47,6 +47,6 @@ class FirLocalScope : FirScope() {
|
||||
if (prop != null) {
|
||||
return processor(prop)
|
||||
}
|
||||
return ProcessorAction.NEXT
|
||||
return ProcessorAction.NONE
|
||||
}
|
||||
}
|
||||
@@ -54,15 +54,17 @@ enum class FirPosition(val allowTypeParameters: Boolean = true) {
|
||||
|
||||
enum class ProcessorAction {
|
||||
STOP,
|
||||
NEXT;
|
||||
NEXT,
|
||||
NONE;
|
||||
|
||||
operator fun not(): Boolean {
|
||||
return when (this) {
|
||||
STOP -> true
|
||||
NEXT -> false
|
||||
NONE -> false
|
||||
}
|
||||
}
|
||||
|
||||
fun stop() = this == STOP
|
||||
fun next() = this == NEXT
|
||||
fun next() = this != STOP
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user