Don't enter twice local scopes w/out particular name in FIR tower resolver

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