[FIR] Reuse empty scopes

This commit is contained in:
Simon Ogorodnik
2021-01-18 18:07:32 +03:00
parent 67267518f0
commit e22711d17f
3 changed files with 33 additions and 22 deletions
@@ -47,6 +47,9 @@ internal class TowerDataElementsForName(
towerDataElement.implicitReceiver?.let { receiver -> IndexedValue(index, receiver) } towerDataElement.implicitReceiver?.let { receiver -> IndexedValue(index, receiver) }
} }
} }
val emptyScopes = mutableSetOf<FirScope>()
val implicitReceiverValuesWithEmptyScopes = mutableSetOf<ImplicitReceiverValue<*>>()
} }
internal abstract class FirBaseTowerResolveTask( internal abstract class FirBaseTowerResolveTask(
@@ -137,8 +140,7 @@ internal abstract class FirBaseTowerResolveTask(
towerLevel towerLevel
) )
if (collector.isSuccess()) onSuccessfulLevel(finalGroup) if (collector.isSuccess()) onSuccessfulLevel(finalGroup)
return result == ProcessorAction.NONE return result == ProcessResult.SCOPE_EMPTY
} }
} }
@@ -22,7 +22,7 @@ internal class CandidateFactoriesAndCollectors(
internal class TowerLevelHandler { internal class TowerLevelHandler {
// Try to avoid adding additional state here // Try to avoid adding additional state here
private var processResult = ProcessorAction.NONE private var processResult = ProcessResult.SCOPE_EMPTY
fun handleLevel( fun handleLevel(
collector: CandidateCollector, collector: CandidateCollector,
@@ -31,8 +31,8 @@ internal class TowerLevelHandler {
explicitReceiverKind: ExplicitReceiverKind, explicitReceiverKind: ExplicitReceiverKind,
group: TowerGroup, group: TowerGroup,
towerLevel: SessionBasedTowerLevel towerLevel: SessionBasedTowerLevel
): ProcessorAction { ): ProcessResult {
processResult = ProcessorAction.NONE processResult = ProcessResult.SCOPE_EMPTY
val processor = val processor =
TowerScopeLevelProcessor( TowerScopeLevelProcessor(
info, info,
@@ -29,6 +29,15 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
enum class ProcessResult {
FOUND, SCOPE_EMPTY;
operator fun plus(other: ProcessResult): ProcessResult {
if (this == FOUND || other == FOUND) return FOUND
return this
}
}
abstract class TowerScopeLevel { abstract class TowerScopeLevel {
sealed class Token<out T : AbstractFirBasedSymbol<*>> { sealed class Token<out T : AbstractFirBasedSymbol<*>> {
@@ -37,11 +46,11 @@ abstract class TowerScopeLevel {
object Objects : Token<AbstractFirBasedSymbol<*>>() object Objects : Token<AbstractFirBasedSymbol<*>>()
} }
abstract fun processFunctionsByName(name: Name, processor: TowerScopeLevelProcessor<FirFunctionSymbol<*>>): ProcessorAction abstract fun processFunctionsByName(name: Name, processor: TowerScopeLevelProcessor<FirFunctionSymbol<*>>): ProcessResult
abstract fun processPropertiesByName(name: Name, processor: TowerScopeLevelProcessor<FirVariableSymbol<*>>): ProcessorAction abstract fun processPropertiesByName(name: Name, processor: TowerScopeLevelProcessor<FirVariableSymbol<*>>): ProcessResult
abstract fun processObjectsByName(name: Name, processor: TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>): ProcessorAction abstract fun processObjectsByName(name: Name, processor: TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>): ProcessResult
interface TowerScopeLevelProcessor<in T : AbstractFirBasedSymbol<*>> { interface TowerScopeLevelProcessor<in T : AbstractFirBasedSymbol<*>> {
fun consumeCandidate( fun consumeCandidate(
@@ -79,9 +88,9 @@ class MemberScopeTowerLevel(
private fun <T : AbstractFirBasedSymbol<*>> processMembers( private fun <T : AbstractFirBasedSymbol<*>> processMembers(
output: TowerScopeLevelProcessor<T>, output: TowerScopeLevelProcessor<T>,
processScopeMembers: FirScope.(processor: (T) -> Unit) -> Unit processScopeMembers: FirScope.(processor: (T) -> Unit) -> Unit
): ProcessorAction { ): ProcessResult {
var empty = true var empty = true
val scope = dispatchReceiverValue.scope(session, scopeSession) ?: return ProcessorAction.NONE val scope = dispatchReceiverValue.scope(session, scopeSession) ?: return ProcessResult.SCOPE_EMPTY
scope.processScopeMembers { candidate -> scope.processScopeMembers { candidate ->
empty = false empty = false
if (candidate is FirCallableSymbol<*> && if (candidate is FirCallableSymbol<*> &&
@@ -118,16 +127,16 @@ class MemberScopeTowerLevel(
output.consumeCandidate(symbol, dispatchReceiverValue, null, scope) output.consumeCandidate(symbol, dispatchReceiverValue, null, scope)
} }
} }
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT return if (empty) ProcessResult.SCOPE_EMPTY else ProcessResult.FOUND
} }
override fun processFunctionsByName( override fun processFunctionsByName(
name: Name, name: Name,
processor: TowerScopeLevelProcessor<FirFunctionSymbol<*>> processor: TowerScopeLevelProcessor<FirFunctionSymbol<*>>
): ProcessorAction { ): ProcessResult {
val isInvoke = name == OperatorNameConventions.INVOKE val isInvoke = name == OperatorNameConventions.INVOKE
if (implicitExtensionInvokeMode && !isInvoke) { if (implicitExtensionInvokeMode && !isInvoke) {
return ProcessorAction.NEXT return ProcessResult.FOUND
} }
return processMembers(processor) { consumer -> return processMembers(processor) { consumer ->
this.processFunctionsAndConstructorsByName( this.processFunctionsAndConstructorsByName(
@@ -145,7 +154,7 @@ class MemberScopeTowerLevel(
override fun processPropertiesByName( override fun processPropertiesByName(
name: Name, name: Name,
processor: TowerScopeLevelProcessor<FirVariableSymbol<*>> processor: TowerScopeLevelProcessor<FirVariableSymbol<*>>
): ProcessorAction { ): ProcessResult {
return processMembers(processor) { consumer -> return processMembers(processor) { consumer ->
this.processPropertiesByName(name) { this.processPropertiesByName(name) {
// WARNING, DO NOT CAST FUNCTIONAL TYPE ITSELF // WARNING, DO NOT CAST FUNCTIONAL TYPE ITSELF
@@ -158,8 +167,8 @@ class MemberScopeTowerLevel(
override fun processObjectsByName( override fun processObjectsByName(
name: Name, name: Name,
processor: TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>> processor: TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>
): ProcessorAction { ): ProcessResult {
return ProcessorAction.NEXT return ProcessResult.FOUND
} }
override fun replaceReceiverValue(receiverValue: ReceiverValue): SessionBasedTowerLevel { override fun replaceReceiverValue(receiverValue: ReceiverValue): SessionBasedTowerLevel {
@@ -262,7 +271,7 @@ class ScopeTowerLevel(
override fun processFunctionsByName( override fun processFunctionsByName(
name: Name, name: Name,
processor: TowerScopeLevelProcessor<FirFunctionSymbol<*>> processor: TowerScopeLevelProcessor<FirFunctionSymbol<*>>
): ProcessorAction { ): ProcessResult {
var empty = true var empty = true
scope.processFunctionsAndConstructorsByName( scope.processFunctionsAndConstructorsByName(
name, name,
@@ -273,25 +282,25 @@ class ScopeTowerLevel(
empty = false empty = false
consumeCallableCandidate(candidate, processor) consumeCallableCandidate(candidate, processor)
} }
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT return if (empty) ProcessResult.SCOPE_EMPTY else ProcessResult.FOUND
} }
override fun processPropertiesByName( override fun processPropertiesByName(
name: Name, name: Name,
processor: TowerScopeLevelProcessor<FirVariableSymbol<*>> processor: TowerScopeLevelProcessor<FirVariableSymbol<*>>
): ProcessorAction { ): ProcessResult {
var empty = true var empty = true
scope.processPropertiesByName(name) { candidate -> scope.processPropertiesByName(name) { candidate ->
empty = false empty = false
consumeCallableCandidate(candidate, processor) consumeCallableCandidate(candidate, processor)
} }
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT return if (empty) ProcessResult.SCOPE_EMPTY else ProcessResult.FOUND
} }
override fun processObjectsByName( override fun processObjectsByName(
name: Name, name: Name,
processor: TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>> processor: TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>
): ProcessorAction { ): ProcessResult {
var empty = true var empty = true
scope.processClassifiersByName(name) { scope.processClassifiersByName(name) {
empty = false empty = false
@@ -301,7 +310,7 @@ class ScopeTowerLevel(
scope = scope scope = scope
) )
} }
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT return if (empty) ProcessResult.SCOPE_EMPTY else ProcessResult.FOUND
} }
} }