FIR tower levels: inline processElementsByName[AndStoreResult]

This commit is contained in:
Mikhail Glukhikh
2020-12-09 22:01:51 +03:00
parent af4941b222
commit 34d7a7c184
2 changed files with 80 additions and 98 deletions
@@ -53,17 +53,18 @@ internal class TowerLevelHandler {
when (info.callKind) { when (info.callKind) {
CallKind.VariableAccess -> { CallKind.VariableAccess -> {
towerLevel.processProperties(info.name, processor) processResult += towerLevel.processPropertiesByName(info.name, processor)
if (!collector.isSuccess()) { if (!collector.isSuccess() && towerLevel is ScopeTowerLevel && towerLevel.extensionReceiver == null) {
towerLevel.processObjectsAsVariables(info.name, processor) processResult += towerLevel.processObjectsByName(info.name, processor)
} }
} }
CallKind.Function -> { CallKind.Function -> {
towerLevel.processFunctions(info.name, processor) processResult += towerLevel.processFunctionsByName(info.name, processor)
} }
CallKind.CallableReference -> { CallKind.CallableReference -> {
towerLevel.processFunctionsAndProperties(info.name, processor) processResult += towerLevel.processFunctionsByName(info.name, processor)
processResult += towerLevel.processPropertiesByName(info.name, processor)
} }
else -> { else -> {
throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}") throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}")
@@ -71,46 +72,6 @@ internal class TowerLevelHandler {
} }
return processResult return processResult
} }
private fun TowerScopeLevel.processProperties(
name: Name,
processor: TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>
) {
processElementsByNameAndStoreResult(TowerScopeLevel.Token.Properties, name, processor)
}
private fun TowerScopeLevel.processFunctions(
name: Name,
processor: TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>
) {
processElementsByNameAndStoreResult(TowerScopeLevel.Token.Functions, name, processor)
}
private fun TowerScopeLevel.processFunctionsAndProperties(
name: Name, processor: TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>
) {
processFunctions(name, processor)
processProperties(name, processor)
}
private fun TowerScopeLevel.processObjectsAsVariables(
name: Name, processor: TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>
) {
// Skipping objects when extension receiver is bound to the level
if (this is ScopeTowerLevel && this.extensionReceiver != null) return
processElementsByNameAndStoreResult(TowerScopeLevel.Token.Objects, name, processor)
}
private fun <T : AbstractFirBasedSymbol<*>> TowerScopeLevel.processElementsByNameAndStoreResult(
token: TowerScopeLevel.Token<T>,
name: Name,
processor: TowerScopeLevel.TowerScopeLevelProcessor<T>
): ProcessorAction {
return processElementsByName(token, name, processor).also {
processResult += it
}
}
} }
private class TowerScopeLevelProcessor( private class TowerScopeLevelProcessor(
@@ -31,13 +31,13 @@ interface TowerScopeLevel {
object Objects : Token<AbstractFirBasedSymbol<*>>() object Objects : Token<AbstractFirBasedSymbol<*>>()
} }
fun <T : AbstractFirBasedSymbol<*>> processElementsByName( fun processFunctionsByName(name: Name, processor: TowerScopeLevelProcessor<FirFunctionSymbol<*>>): ProcessorAction
token: Token<T>,
name: Name,
processor: TowerScopeLevelProcessor<T>
): ProcessorAction
interface TowerScopeLevelProcessor<T : AbstractFirBasedSymbol<*>> { fun processPropertiesByName(name: Name, processor: TowerScopeLevelProcessor<FirVariableSymbol<*>>): ProcessorAction
fun processObjectsByName(name: Name, processor: TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>): ProcessorAction
interface TowerScopeLevelProcessor<in T : AbstractFirBasedSymbol<*>> {
fun consumeCandidate( fun consumeCandidate(
symbol: T, symbol: T,
dispatchReceiverValue: ReceiverValue?, dispatchReceiverValue: ReceiverValue?,
@@ -115,38 +115,47 @@ class MemberScopeTowerLevel(
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
} }
override fun <T : AbstractFirBasedSymbol<*>> processElementsByName( override fun processFunctionsByName(
token: TowerScopeLevel.Token<T>,
name: Name, name: Name,
processor: TowerScopeLevel.TowerScopeLevelProcessor<T> processor: TowerScopeLevel.TowerScopeLevelProcessor<FirFunctionSymbol<*>>
): ProcessorAction { ): ProcessorAction {
val isInvoke = name == OperatorNameConventions.INVOKE && token == TowerScopeLevel.Token.Functions val isInvoke = name == OperatorNameConventions.INVOKE
if (implicitExtensionInvokeMode && !isInvoke) { if (implicitExtensionInvokeMode && !isInvoke) {
return ProcessorAction.NEXT return ProcessorAction.NEXT
} }
return when (token) { return processMembers(processor) { consumer ->
is TowerScopeLevel.Token.Properties -> processMembers(processor) { consumer -> this.processFunctionsAndConstructorsByName(
this.processPropertiesByName(name) { name, session, bodyResolveComponents,
includeInnerConstructors = true,
processor = {
// WARNING, DO NOT CAST FUNCTIONAL TYPE ITSELF // WARNING, DO NOT CAST FUNCTIONAL TYPE ITSELF
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
consumer(it as T) consumer(it as FirFunctionSymbol<*>)
} }
} )
TowerScopeLevel.Token.Functions -> processMembers(processor) { consumer ->
this.processFunctionsAndConstructorsByName(
name, session, bodyResolveComponents,
includeInnerConstructors = true,
processor = {
// WARNING, DO NOT CAST FUNCTIONAL TYPE ITSELF
@Suppress("UNCHECKED_CAST")
consumer(it as T)
}
)
}
TowerScopeLevel.Token.Objects -> ProcessorAction.NEXT
} }
} }
override fun processPropertiesByName(
name: Name,
processor: TowerScopeLevel.TowerScopeLevelProcessor<FirVariableSymbol<*>>
): ProcessorAction {
return processMembers(processor) { consumer ->
this.processPropertiesByName(name) {
// WARNING, DO NOT CAST FUNCTIONAL TYPE ITSELF
@Suppress("UNCHECKED_CAST")
consumer(it)
}
}
}
override fun processObjectsByName(
name: Name,
processor: TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>
): ProcessorAction {
return ProcessorAction.NEXT
}
override fun replaceReceiverValue(receiverValue: ReceiverValue): SessionBasedTowerLevel { override fun replaceReceiverValue(receiverValue: ReceiverValue): SessionBasedTowerLevel {
return MemberScopeTowerLevel( return MemberScopeTowerLevel(
session, bodyResolveComponents, receiverValue, extensionReceiver, implicitExtensionInvokeMode, scopeSession session, bodyResolveComponents, receiverValue, extensionReceiver, implicitExtensionInvokeMode, scopeSession
@@ -222,35 +231,47 @@ class ScopeTowerLevel(
} }
} }
override fun <T : AbstractFirBasedSymbol<*>> processElementsByName( override fun processFunctionsByName(
token: TowerScopeLevel.Token<T>,
name: Name, name: Name,
processor: TowerScopeLevel.TowerScopeLevelProcessor<T> processor: TowerScopeLevel.TowerScopeLevelProcessor<FirFunctionSymbol<*>>
): ProcessorAction { ): ProcessorAction {
var empty = true var empty = true
@Suppress("UNCHECKED_CAST") scope.processFunctionsAndConstructorsByName(
when (token) { name,
TowerScopeLevel.Token.Properties -> scope.processPropertiesByName(name) { candidate -> session,
empty = false bodyResolveComponents,
consumeCallableCandidate(candidate, processor) includeInnerConstructors = includeInnerConstructors
} ) { candidate ->
TowerScopeLevel.Token.Functions -> scope.processFunctionsAndConstructorsByName( empty = false
name, consumeCallableCandidate(candidate, processor)
session, }
bodyResolveComponents, return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
includeInnerConstructors = includeInnerConstructors }
) { candidate ->
empty = false override fun processPropertiesByName(
consumeCallableCandidate(candidate, processor) name: Name,
} processor: TowerScopeLevel.TowerScopeLevelProcessor<FirVariableSymbol<*>>
TowerScopeLevel.Token.Objects -> scope.processClassifiersByName(name) { ): ProcessorAction {
empty = false var empty = true
processor.consumeCandidate( scope.processPropertiesByName(name) { candidate ->
it as T, dispatchReceiverValue = null, empty = false
extensionReceiverValue = null, consumeCallableCandidate(candidate, processor)
scope = scope }
) return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
} }
override fun processObjectsByName(
name: Name,
processor: TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>
): ProcessorAction {
var empty = true
scope.processClassifiersByName(name) {
empty = false
processor.consumeCandidate(
it, dispatchReceiverValue = null,
extensionReceiverValue = null,
scope = scope
)
} }
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
} }