FIR: Move constructor processing from scopes to tower resolvers

This commit is contained in:
Denis Zharkov
2019-09-16 09:39:08 +03:00
parent 08a8a9fa61
commit fb4b6b8290
7 changed files with 116 additions and 111 deletions
@@ -5,7 +5,8 @@
package org.jetbrains.kotlin.fir.types
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.model.*
@@ -191,4 +192,4 @@ class ConeIntersectionType(
fun ConeIntersectionType.mapTypes(func: (ConeKotlinType) -> ConeKotlinType): ConeIntersectionType {
return ConeIntersectionType(intersectedTypes.map(func))
}
}
@@ -52,7 +52,7 @@ class QualifiedReceiverTowerDataConsumer<T : AbstractFirBasedSymbol<*>>(
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
if (kind != TowerDataKind.EMPTY) return ProcessorAction.NEXT
return QualifiedReceiverTowerLevel(session).processElementsByName(
return QualifiedReceiverTowerLevel(session, candidateFactory.bodyResolveComponents).processElementsByName(
token,
name,
explicitReceiver,
@@ -13,8 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.impl.FirImportImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedImportImpl
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorWithJump
import org.jetbrains.kotlin.fir.scopes.FirPosition
import org.jetbrains.kotlin.fir.scopes.FirScope
@@ -25,9 +24,13 @@ import org.jetbrains.kotlin.fir.scopes.processClassifiersByNameWithAction
import org.jetbrains.kotlin.fir.service
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeAbbreviatedType
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
interface TowerScopeLevel {
@@ -184,7 +187,7 @@ class ScopeTowerLevel(
ProcessorAction.NEXT
}
}
TowerScopeLevel.Token.Functions -> scope.processFunctionsByName(name) { candidate ->
TowerScopeLevel.Token.Functions -> scope.processFunctionsAndConstructorsByName(name, session, ScopeSession()) { candidate ->
if (candidate.hasConsistentReceivers(extensionReceiver)) {
processor.consumeCandidate(
candidate as T, dispatchReceiverValue = candidate.dispatchReceiverValue(),
@@ -207,7 +210,10 @@ class ScopeTowerLevel(
/**
* Handles only statics and top-levels, DOES NOT handle objects/companions members
*/
class QualifiedReceiverTowerLevel(session: FirSession) : SessionBasedTowerLevel(session) {
class QualifiedReceiverTowerLevel(
session: FirSession,
private val bodyResolveComponents: BodyResolveComponents
) : SessionBasedTowerLevel(session) {
override fun <T : AbstractFirBasedSymbol<*>> processElementsByName(
token: TowerScopeLevel.Token<T>,
name: Name,
@@ -222,23 +228,29 @@ class QualifiedReceiverTowerLevel(session: FirSession) : SessionBasedTowerLevel(
qualifiedReceiver.packageFqName,
qualifiedReceiver.relativeClassFqName
)
), session, ScopeSession()
), session, bodyResolveComponents.scopeSession
)
@Suppress("UNCHECKED_CAST")
return if (token == TowerScopeLevel.Token.Objects) {
scope.processClassifiersByNameWithAction(name, FirPosition.OTHER) {
val processorForCallables: (FirCallableSymbol<*>) -> ProcessorAction = {
val fir = it.fir
if (fir is FirCallableMemberDeclaration<*> && fir.isStatic || it.callableId.classId == null) {
@Suppress("UNCHECKED_CAST")
processor.consumeCandidate(it as T, null, null)
} else {
ProcessorAction.NEXT
}
}
return when (token) {
TowerScopeLevel.Token.Objects -> scope.processClassifiersByNameWithAction(name, FirPosition.OTHER) {
@Suppress("UNCHECKED_CAST")
processor.consumeCandidate(it as T, null, null)
}
} else {
scope.processCallables(name, token.cast()) {
val fir = it.fir
if (fir is FirCallableMemberDeclaration<*> && fir.isStatic || it.callableId.classId == null) {
processor.consumeCandidate(it as T, null, null)
} else {
ProcessorAction.NEXT
}
TowerScopeLevel.Token.Functions -> {
scope.processFunctionsAndConstructorsByName(name, session, bodyResolveComponents.scopeSession, processorForCallables)
}
TowerScopeLevel.Token.Properties -> scope.processPropertiesByName(name, processorForCallables)
}
}
}
@@ -253,4 +265,82 @@ fun FirCallableDeclaration<*>.dispatchReceiverValue(session: FirSession): ClassD
return ClassDispatchReceiverValue(regularClass.symbol)
}
private fun FirCallableSymbol<*>.hasExtensionReceiver(): Boolean = this.fir.receiverTypeRef != null
private fun FirCallableSymbol<*>.hasExtensionReceiver(): Boolean = this.fir.receiverTypeRef != null
private fun FirScope.processFunctionsAndConstructorsByName(
name: Name,
session: FirSession,
scopeSession: ScopeSession,
processor: (FirCallableSymbol<*>) -> ProcessorAction
): ProcessorAction {
val matchedClassSymbol = getFirstClassifierOrNull(name) as? FirClassLikeSymbol<*>
if (processConstructors(
matchedClassSymbol,
processor,
session,
scopeSession,
name
).stop()
) {
return ProcessorAction.STOP
}
return processFunctionsByName(name, processor)
}
private fun FirScope.getFirstClassifierOrNull(name: Name): FirClassifierSymbol<*>? {
var result: FirClassifierSymbol<*>? = null
processClassifiersByNameWithAction(name, FirPosition.OTHER) {
result = it
ProcessorAction.STOP
}
return result
}
private fun finalExpansionName(symbol: FirTypeAliasSymbol, session: FirSession): Name? {
return when (val expandedType = symbol.fir.expandedTypeRef.coneTypeUnsafe<ConeClassLikeType>()) {
is ConeAbbreviatedType ->
expandedType.abbreviationLookupTag.toSymbol(session)?.safeAs<FirTypeAliasSymbol>()?.let {
finalExpansionName(it, session)
}
else -> expandedType.lookupTag.classId.shortClassName
}
}
private fun processConstructors(
matchedSymbol: FirClassLikeSymbol<*>?,
processor: (FirFunctionSymbol<*>) -> ProcessorAction,
session: FirSession,
scopeSession: ScopeSession,
name: Name
): ProcessorAction {
try {
if (matchedSymbol != null) {
val scope = when (matchedSymbol) {
is FirTypeAliasSymbol -> matchedSymbol.fir.buildUseSiteScope(session, scopeSession)
is FirClassSymbol -> matchedSymbol.fir.buildUseSiteScope(session, scopeSession)
}
val constructorName = when (matchedSymbol) {
is FirTypeAliasSymbol -> finalExpansionName(matchedSymbol, session) ?: return ProcessorAction.NEXT
is FirClassSymbol -> name
}
//TODO: why don't we use declared member scope at this point?
if (scope != null && scope.processFunctionsByName(
constructorName,
processor
) == ProcessorAction.STOP
) {
return ProcessorAction.STOP
}
}
return ProcessorAction.NEXT
} catch (e: Throwable) {
throw RuntimeException("While processing constructors", e)
}
}
@@ -8,18 +8,7 @@ package org.jetbrains.kotlin.fir.scopes
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.buildUseSiteScope
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.types.ConeAbbreviatedType
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun MutableList<FirScope>.addImportingScopes(file: FirFile, session: FirSession, scopeSession: ScopeSession) {
this += listOf(
@@ -39,48 +28,3 @@ fun FirCompositeScope.addImportingScopes(file: FirFile, session: FirSession, sco
scopes.addImportingScopes(file, session, scopeSession)
}
private fun finalExpansionName(symbol: FirTypeAliasSymbol, session: FirSession): Name? {
return when (val expandedType = symbol.fir.expandedTypeRef.coneTypeUnsafe<ConeClassLikeType>()) {
is ConeAbbreviatedType ->
expandedType.abbreviationLookupTag.toSymbol(session)?.safeAs<FirTypeAliasSymbol>()?.let {
finalExpansionName(it, session)
}
else -> expandedType.lookupTag.classId.shortClassName
}
}
fun processConstructors(
matchedSymbol: FirClassLikeSymbol<*>?,
processor: (FirFunctionSymbol<*>) -> ProcessorAction,
session: FirSession,
scopeSession: ScopeSession,
name: Name
): ProcessorAction {
try {
if (matchedSymbol != null) {
val scope = when (matchedSymbol) {
is FirTypeAliasSymbol -> matchedSymbol.fir.buildUseSiteScope(session, scopeSession)
is FirClassSymbol -> matchedSymbol.fir.buildUseSiteScope(session, scopeSession)
}
val constructorName = when (matchedSymbol) {
is FirTypeAliasSymbol -> finalExpansionName(matchedSymbol, session) ?: return ProcessorAction.NEXT
is FirClassSymbol -> name
}
//TODO: why don't we use declared member scope at this point?
if (scope != null && scope.processFunctionsByName(
constructorName,
processor
) == ProcessorAction.STOP
) {
return ProcessorAction.STOP
}
}
return ProcessorAction.NEXT
} catch (e: Throwable) {
throw RuntimeException("While processing constructors", e)
}
}
@@ -13,8 +13,7 @@ import org.jetbrains.kotlin.fir.resolve.calls.TowerScopeLevel
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.processConstructors
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
@@ -69,19 +68,6 @@ abstract class FirAbstractImportingScope(
return ProcessorAction.STOP
}
} else if (name.isSpecial || name.identifier.isNotEmpty()) {
val matchedClass = provider.getClassLikeSymbolByFqName(ClassId(import.packageFqName, name))
if (processConstructors(
matchedClass,
processor,
session,
scopeSession,
name
).stop()
) {
return ProcessorAction.STOP
}
val symbols = provider.getTopLevelCallableSymbols(callableId.packageName, callableId.callableName)
for (symbol in symbols) {
@@ -114,4 +100,4 @@ abstract class FirAbstractImportingScope(
) { if (it is FirVariableSymbol<*>) processor(it) else ProcessorAction.NEXT }
}
}
}
@@ -7,38 +7,22 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NEXT
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.STOP
import org.jetbrains.kotlin.fir.scopes.processConstructors
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
class FirTopLevelDeclaredMemberScope(
file: FirFile,
session: FirSession,
private val scopeSession: ScopeSession,
lookupInFir: Boolean = true
) : FirAbstractProviderBasedScope(session, lookupInFir) {
private val packageFqName = file.packageFqName
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
val matchedClass = provider.getClassLikeSymbolByFqName(ClassId(packageFqName, name))
if (processConstructors(
matchedClass,
processor,
session,
scopeSession,
name
).stop()
) {
return STOP
}
val symbols = provider.getTopLevelCallableSymbols(packageFqName, name)
for (symbol in symbols) {
if (symbol is FirFunctionSymbol<*> && !processor(symbol)) {
@@ -10,8 +10,8 @@ import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.*
import org.jetbrains.kotlin.fir.resolve.transformers.FirDesignatedBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.runResolve
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.FirTopLevelDeclaredMemberScope
import org.jetbrains.kotlin.fir.symbols.CallableId
@@ -39,7 +39,7 @@ private fun FirFile.findCallableMember(
packageFqName: FqName, klassFqName: FqName?, declName: Name
): FirCallableDeclaration<*> {
val memberScope =
if (klassFqName == null) FirTopLevelDeclaredMemberScope(this, session, ScopeSession())
if (klassFqName == null) FirTopLevelDeclaredMemberScope(this, session)
else provider.getClassDeclaredMemberScope(ClassId(packageFqName, klassFqName, false))!!
var result: FirCallableDeclaration<*>? = null
val processor = { symbol: FirCallableSymbol<*> ->