[FIR] Extract QualifierReceiver to a separate file
This commit is contained in:
@@ -6,27 +6,24 @@
|
|||||||
package org.jetbrains.kotlin.fir.resolve.calls
|
package org.jetbrains.kotlin.fir.resolve.calls
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParametersOwner
|
import org.jetbrains.kotlin.fir.declarations.FirTypeParametersOwner
|
||||||
import org.jetbrains.kotlin.fir.declarations.expandedConeType
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirSealedClassImpl
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirThisReceiverExpressionImpl
|
import org.jetbrains.kotlin.fir.expressions.impl.FirThisReceiverExpressionImpl
|
||||||
import org.jetbrains.kotlin.fir.references.impl.FirImplicitThisReference
|
import org.jetbrains.kotlin.fir.references.impl.FirImplicitThisReference
|
||||||
import org.jetbrains.kotlin.fir.renderWithType
|
import org.jetbrains.kotlin.fir.renderWithType
|
||||||
import org.jetbrains.kotlin.fir.resolve.*
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.constructType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.scope
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.*
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeStarProjection
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||||
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
|
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
|
||||||
import java.util.ArrayDeque
|
|
||||||
|
|
||||||
interface Receiver {
|
interface Receiver {
|
||||||
fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope?
|
fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope?
|
||||||
@@ -70,111 +67,6 @@ abstract class AbstractExplicitReceiverValue<E : FirExpression> : AbstractExplic
|
|||||||
get() = explicitReceiver
|
get() = explicitReceiver
|
||||||
}
|
}
|
||||||
|
|
||||||
class QualifierReceiver(override val explicitReceiver: FirResolvedQualifier) : AbstractExplicitReceiver<FirResolvedQualifier>() {
|
|
||||||
private fun collectSuperTypeScopesComposedByDepth(
|
|
||||||
klass: FirClass<*>,
|
|
||||||
useSiteSession: FirSession,
|
|
||||||
scopeSession: ScopeSession
|
|
||||||
): List<FirScope> {
|
|
||||||
val result = mutableListOf<FirScope>()
|
|
||||||
val provider = klass.scopeProvider
|
|
||||||
val levelScopes = mutableListOf<FirScope>()
|
|
||||||
var currentDepth = 1
|
|
||||||
val queue = ArrayDeque<Pair<ConeClassLikeType, Int>>()
|
|
||||||
queue.addAll(
|
|
||||||
lookupSuperTypes(klass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession).map { it to 1 }
|
|
||||||
)
|
|
||||||
val visitedSymbols = mutableSetOf<FirRegularClassSymbol>()
|
|
||||||
while (queue.isNotEmpty()) {
|
|
||||||
val (useSiteSuperType, depth) = queue.poll()
|
|
||||||
if (depth > currentDepth) {
|
|
||||||
currentDepth = depth
|
|
||||||
result += FirCompositeScope(levelScopes.toMutableList())
|
|
||||||
levelScopes.clear()
|
|
||||||
}
|
|
||||||
if (useSiteSuperType is ConeClassErrorType) continue
|
|
||||||
val superTypeSymbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession) as? FirRegularClassSymbol
|
|
||||||
?: continue
|
|
||||||
if (!visitedSymbols.add(superTypeSymbol)) continue
|
|
||||||
val superTypeScope = provider.getStaticMemberScopeForCallables(
|
|
||||||
superTypeSymbol.fir, useSiteSession, scopeSession
|
|
||||||
)
|
|
||||||
if (superTypeScope != null) {
|
|
||||||
levelScopes += superTypeScope
|
|
||||||
}
|
|
||||||
queue.addAll(
|
|
||||||
lookupSuperTypes(
|
|
||||||
superTypeSymbol.fir, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession
|
|
||||||
).map { it to currentDepth + 1 }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getClassSymbolWithCallableScopes(
|
|
||||||
classId: ClassId,
|
|
||||||
useSiteSession: FirSession,
|
|
||||||
scopeSession: ScopeSession
|
|
||||||
): Pair<FirClassSymbol<*>?, List<FirScope>> {
|
|
||||||
val symbol = useSiteSession.firSymbolProvider.getClassLikeSymbolByFqName(classId) ?: return null to emptyList()
|
|
||||||
if (symbol is FirTypeAliasSymbol) {
|
|
||||||
val expansionSymbol = symbol.fir.expandedConeType?.lookupTag?.toSymbol(useSiteSession)
|
|
||||||
if (expansionSymbol != null) {
|
|
||||||
return getClassSymbolWithCallableScopes(expansionSymbol.classId, useSiteSession, scopeSession)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return (symbol as? FirClassSymbol<*>)?.let { klassSymbol ->
|
|
||||||
val klass = klassSymbol.fir
|
|
||||||
klassSymbol to run {
|
|
||||||
val result = mutableListOf<FirScope>()
|
|
||||||
val provider = klass.scopeProvider
|
|
||||||
val klassScope = provider.getStaticMemberScopeForCallables(klass, useSiteSession, scopeSession)
|
|
||||||
if (klassScope != null) {
|
|
||||||
result += klassScope
|
|
||||||
if (provider is KotlinScopeProvider) return@run result
|
|
||||||
result += collectSuperTypeScopesComposedByDepth(klass, useSiteSession, scopeSession)
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
} ?: (null to emptyList())
|
|
||||||
}
|
|
||||||
|
|
||||||
return null to emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun qualifierScopes(useSiteSession: FirSession, scopeSession: ScopeSession): List<FirScope> {
|
|
||||||
val classId = explicitReceiver.classId ?: return emptyList()
|
|
||||||
|
|
||||||
val (classSymbol, callableScopes) = getClassSymbolWithCallableScopes(classId, useSiteSession, scopeSession)
|
|
||||||
if (classSymbol != null) {
|
|
||||||
val klass = classSymbol.fir
|
|
||||||
val classifierScope = if (klass is FirClassImpl || klass is FirSealedClassImpl) {
|
|
||||||
nestedClassifierScope(klass)
|
|
||||||
} else {
|
|
||||||
useSiteSession.firSymbolProvider.getNestedClassifierScope(classId)
|
|
||||||
}
|
|
||||||
|
|
||||||
return when {
|
|
||||||
classifierScope == null -> {
|
|
||||||
callableScopes.map { FirQualifierScope(it, null) }
|
|
||||||
}
|
|
||||||
callableScopes.isEmpty() -> {
|
|
||||||
listOf(FirQualifierScope(null, classifierScope))
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
listOf(FirQualifierScope(callableScopes.first(), classifierScope)) +
|
|
||||||
callableScopes.drop(1).map { FirQualifierScope(it, null) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? {
|
|
||||||
return FirCompositeScope(qualifierScopes(useSiteSession, scopeSession).toMutableList())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class ExpressionReceiverValue(
|
internal class ExpressionReceiverValue(
|
||||||
override val explicitReceiver: FirExpression
|
override val explicitReceiver: FirExpression
|
||||||
) : AbstractExplicitReceiverValue<FirExpression>(), ReceiverValue
|
) : AbstractExplicitReceiverValue<FirExpression>(), ReceiverValue
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.resolve.calls
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.expandedConeType
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.impl.FirSealedClassImpl
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.FirQualifierScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import java.util.ArrayDeque
|
||||||
|
|
||||||
|
class QualifierReceiver(override val explicitReceiver: FirResolvedQualifier) : AbstractExplicitReceiver<FirResolvedQualifier>() {
|
||||||
|
private fun collectSuperTypeScopesComposedByDepth(
|
||||||
|
klass: FirClass<*>,
|
||||||
|
useSiteSession: FirSession,
|
||||||
|
scopeSession: ScopeSession
|
||||||
|
): List<FirScope> {
|
||||||
|
val result = mutableListOf<FirScope>()
|
||||||
|
val provider = klass.scopeProvider
|
||||||
|
val levelScopes = mutableListOf<FirScope>()
|
||||||
|
var currentDepth = 1
|
||||||
|
val queue =
|
||||||
|
ArrayDeque<Pair<ConeClassLikeType, Int>>()
|
||||||
|
queue.addAll(
|
||||||
|
lookupSuperTypes(klass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession).map { it to 1 }
|
||||||
|
)
|
||||||
|
val visitedSymbols = mutableSetOf<FirRegularClassSymbol>()
|
||||||
|
while (queue.isNotEmpty()) {
|
||||||
|
val (useSiteSuperType, depth) = queue.poll()
|
||||||
|
if (depth > currentDepth) {
|
||||||
|
currentDepth = depth
|
||||||
|
result += FirCompositeScope(levelScopes.toMutableList())
|
||||||
|
levelScopes.clear()
|
||||||
|
}
|
||||||
|
if (useSiteSuperType is ConeClassErrorType) continue
|
||||||
|
val superTypeSymbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession) as? FirRegularClassSymbol
|
||||||
|
?: continue
|
||||||
|
if (!visitedSymbols.add(superTypeSymbol)) continue
|
||||||
|
val superTypeScope = provider.getStaticMemberScopeForCallables(
|
||||||
|
superTypeSymbol.fir, useSiteSession, scopeSession
|
||||||
|
)
|
||||||
|
if (superTypeScope != null) {
|
||||||
|
levelScopes += superTypeScope
|
||||||
|
}
|
||||||
|
queue.addAll(
|
||||||
|
lookupSuperTypes(
|
||||||
|
superTypeSymbol.fir, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession
|
||||||
|
).map { it to currentDepth + 1 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getClassSymbolWithCallableScopes(
|
||||||
|
classId: ClassId,
|
||||||
|
useSiteSession: FirSession,
|
||||||
|
scopeSession: ScopeSession
|
||||||
|
): Pair<FirClassSymbol<*>?, List<FirScope>> {
|
||||||
|
val symbol = useSiteSession.firSymbolProvider.getClassLikeSymbolByFqName(classId) ?: return null to emptyList()
|
||||||
|
if (symbol is FirTypeAliasSymbol) {
|
||||||
|
val expansionSymbol = symbol.fir.expandedConeType?.lookupTag?.toSymbol(useSiteSession)
|
||||||
|
if (expansionSymbol != null) {
|
||||||
|
return getClassSymbolWithCallableScopes(expansionSymbol.classId, useSiteSession, scopeSession)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return (symbol as? FirClassSymbol<*>)?.let { klassSymbol ->
|
||||||
|
val klass = klassSymbol.fir
|
||||||
|
klassSymbol to run {
|
||||||
|
val result = mutableListOf<FirScope>()
|
||||||
|
val provider = klass.scopeProvider
|
||||||
|
val klassScope = provider.getStaticMemberScopeForCallables(klass, useSiteSession, scopeSession)
|
||||||
|
if (klassScope != null) {
|
||||||
|
result += klassScope
|
||||||
|
if (provider is KotlinScopeProvider) return@run result
|
||||||
|
result += collectSuperTypeScopesComposedByDepth(klass, useSiteSession, scopeSession)
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
} ?: (null to emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
|
return null to emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun qualifierScopes(useSiteSession: FirSession, scopeSession: ScopeSession): List<FirScope> {
|
||||||
|
val classId = explicitReceiver.classId ?: return emptyList()
|
||||||
|
|
||||||
|
val (classSymbol, callableScopes) = getClassSymbolWithCallableScopes(classId, useSiteSession, scopeSession)
|
||||||
|
if (classSymbol != null) {
|
||||||
|
val klass = classSymbol.fir
|
||||||
|
val classifierScope = if (klass is FirClassImpl || klass is FirSealedClassImpl) {
|
||||||
|
nestedClassifierScope(klass)
|
||||||
|
} else {
|
||||||
|
useSiteSession.firSymbolProvider.getNestedClassifierScope(classId)
|
||||||
|
}
|
||||||
|
|
||||||
|
return when {
|
||||||
|
classifierScope == null -> {
|
||||||
|
callableScopes.map { FirQualifierScope(it, null) }
|
||||||
|
}
|
||||||
|
callableScopes.isEmpty() -> {
|
||||||
|
listOf(FirQualifierScope(null, classifierScope))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
listOf(
|
||||||
|
FirQualifierScope(callableScopes.first(), classifierScope)
|
||||||
|
) +
|
||||||
|
callableScopes.drop(1).map {
|
||||||
|
FirQualifierScope(it, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? {
|
||||||
|
return FirCompositeScope(qualifierScopes(useSiteSession, scopeSession).toMutableList())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user