[FIR] Qualifier resolve

This commit is contained in:
simon.ogorodnik
2020-01-22 17:39:34 +03:00
parent 723ebb4f57
commit c29c140a9c
21 changed files with 238 additions and 175 deletions
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.java
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.FirClass
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.classId
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope
import org.jetbrains.kotlin.fir.java.scopes.JavaClassUseSiteMemberScope import org.jetbrains.kotlin.fir.java.scopes.JavaClassUseSiteMemberScope
@@ -111,7 +112,15 @@ class JavaScopeProvider(
) )
) )
} }
return FirStaticScope(enhancementScope) return FirOnlyCallablesScope(FirStaticScope(enhancementScope))
}
override fun getNestedClassifierScope(klass: FirClass<*>, useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? {
return lazyNestedClassifierScope(
klass.classId,
(klass as FirJavaClass).existingNestedClassifierNames,
useSiteSession.firSymbolProvider
)
} }
} }
@@ -227,7 +227,7 @@ class JavaSymbolProvider(
symbol = constructorSymbol symbol = constructorSymbol
this.visibility = visibility this.visibility = visibility
this.isPrimary = isPrimary this.isPrimary = isPrimary
isInner = !javaClass.isStatic isInner = javaClass.outerClass != null && !javaClass.isStatic
returnTypeRef = buildResolvedTypeRef { returnTypeRef = buildResolvedTypeRef {
type = firSymbol.constructType( type = firSymbol.constructType(
classTypeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(), classTypeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
@@ -27,4 +27,8 @@ object StubFirScopeProvider : FirScopeProvider() {
): FirScope? { ): FirScope? {
return null return null
} }
override fun getNestedClassifierScope(klass: FirClass<*>, useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? {
return null
}
} }
@@ -127,6 +127,7 @@ class FirCallResolver(
explicitReceiver, explicitReceiver,
arguments, arguments,
functionCall.safe, functionCall.safe,
isPotentialQualifierPart = false,
typeArguments, typeArguments,
session, session,
file, file,
@@ -166,6 +167,7 @@ class FirCallResolver(
qualifiedAccess.explicitReceiver, qualifiedAccess.explicitReceiver,
emptyList(), emptyList(),
qualifiedAccess.safe, qualifiedAccess.safe,
qualifiedAccess.explicitReceiver is FirResolvedQualifier && qualifiedResolver.isPotentialQualifierPartPosition(),
emptyList(), emptyList(),
session, session,
file, file,
@@ -314,6 +316,7 @@ class FirCallResolver(
explicitReceiver = null, explicitReceiver = null,
delegatedConstructorCall.arguments, delegatedConstructorCall.arguments,
isSafeCall = false, isSafeCall = false,
isPotentialQualifierPart = false,
typeArguments = typeArguments, typeArguments = typeArguments,
session, session,
file, file,
@@ -364,6 +367,7 @@ class FirCallResolver(
callableReferenceAccess.explicitReceiver, callableReferenceAccess.explicitReceiver,
emptyList(), emptyList(),
false, false,
isPotentialQualifierPart = false,
emptyList(), emptyList(),
session, session,
file, file,
@@ -28,6 +28,18 @@ class FirQualifiedNameResolver(components: BodyResolveComponents) : BodyResolveC
qualifierPartsToDrop = 0 qualifierPartsToDrop = 0
} }
/**
* NB: 0 if current 'qualifiedAccess.safe || callee.name.isSpecial', 1 if current is fine, 2 if potential qualifier
* a.b.c
* ^ here stack will be ['c', 'b'], so possible
* a.b?.c
* ^ here stack will be ['b'], so impossible
* a?.b.c
* ^ here stack will be [], so impossible
*/
fun isPotentialQualifierPartPosition() = qualifierStack.size > 1
fun initProcessingQualifiedAccess(qualifiedAccess: FirQualifiedAccess, callee: FirSimpleNamedReference) { fun initProcessingQualifiedAccess(qualifiedAccess: FirQualifiedAccess, callee: FirSimpleNamedReference) {
if (qualifiedAccess.safe || callee.name.isSpecial) { if (qualifiedAccess.safe || callee.name.isSpecial) {
qualifierStack.clear() qualifierStack.clear()
@@ -33,6 +33,7 @@ data class CallInfo(
val explicitReceiver: FirExpression?, val explicitReceiver: FirExpression?,
val arguments: List<FirExpression>, val arguments: List<FirExpression>,
val isSafeCall: Boolean, val isSafeCall: Boolean,
val isPotentialQualifierPart: Boolean,
val typeArguments: List<FirTypeProjection>, val typeArguments: List<FirTypeProjection>,
val session: FirSession, val session: FirSession,
@@ -50,26 +51,18 @@ data class CallInfo(
fun noStubReceiver(): CallInfo = fun noStubReceiver(): CallInfo =
if (stubReceiver == null) this else CallInfo( if (stubReceiver == null) this else CallInfo(
callKind, name, explicitReceiver, arguments, callKind, name, explicitReceiver, arguments,
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs, null isSafeCall, isPotentialQualifierPart, typeArguments, session,
containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs, null
) )
fun replaceWithVariableAccess(): CallInfo = fun replaceWithVariableAccess(): CallInfo =
CallInfo( copy(callKind = CallKind.VariableAccess, arguments = emptyList())
CallKind.VariableAccess, name, explicitReceiver, emptyList(),
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs, stubReceiver
)
fun replaceExplicitReceiver(explicitReceiver: FirExpression?): CallInfo = fun replaceExplicitReceiver(explicitReceiver: FirExpression?): CallInfo =
CallInfo( copy(explicitReceiver = explicitReceiver)
callKind, name, explicitReceiver, arguments,
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs, stubReceiver
)
fun withReceiverAsArgument(receiverExpression: FirExpression): CallInfo = fun withReceiverAsArgument(receiverExpression: FirExpression): CallInfo =
CallInfo( copy(arguments = listOf(receiverExpression) + arguments)
callKind, name, explicitReceiver, listOf(receiverExpression) + arguments,
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs, stubReceiver
)
} }
enum class CandidateApplicability { enum class CandidateApplicability {
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.resolve.constructType
import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirQualifierScope
import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
@@ -32,7 +31,7 @@ import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
interface Receiver { interface Receiver {
fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope?
} }
interface ReceiverValue : Receiver { interface ReceiverValue : Receiver {
@@ -40,7 +39,7 @@ interface ReceiverValue : Receiver {
val receiverExpression: FirExpression val receiverExpression: FirExpression
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? = fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? =
type.scope(useSiteSession, scopeSession) type.scope(useSiteSession, scopeSession)
} }
@@ -8,8 +8,6 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.builder.buildImport
import org.jetbrains.kotlin.fir.declarations.builder.buildResolvedImport
import org.jetbrains.kotlin.fir.declarations.isCompanion import org.jetbrains.kotlin.fir.declarations.isCompanion
import org.jetbrains.kotlin.fir.declarations.isInner import org.jetbrains.kotlin.fir.declarations.isInner
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
@@ -22,13 +20,11 @@ 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 import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirExplicitSimpleImportingScope
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.scopes.impl.FirStaticScope import org.jetbrains.kotlin.fir.scopes.impl.FirStaticScope
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
@@ -79,35 +75,54 @@ class FirTowerResolver(
return implicitReceivers return implicitReceivers
} }
private suspend fun processQualifierScopes(
manager: TowerResolveManager,
info: CallInfo, qualifierReceiver: QualifierReceiver?
) {
if (qualifierReceiver == null) return
for ((depth, qualifierScope) in qualifierReceiver.callableScopes().withIndex()) {
manager.processLevel(
ScopeTowerLevel(session, components, qualifierScope, noInnerConstructors = true),
info.noStubReceiver(), TowerGroup.Qualifier(depth)
)
}
}
private suspend fun processClassifierScope(
manager: TowerResolveManager,
info: CallInfo, qualifierReceiver: QualifierReceiver?, prioritized: Boolean
) {
if (qualifierReceiver == null) return
if (info.callKind != CallKind.CallableReference &&
qualifierReceiver is ClassQualifierReceiver &&
qualifierReceiver.classSymbol != qualifierReceiver.originalSymbol
) return
val scope = qualifierReceiver.classifierScope() ?: return
manager.processLevel(
ScopeTowerLevel(session, components, scope, noInnerConstructors = true), info.noStubReceiver(),
if (prioritized) TowerGroup.ClassifierPrioritized else TowerGroup.Classifier
)
}
private suspend fun runResolverForQualifierReceiver( private suspend fun runResolverForQualifierReceiver(
info: CallInfo, info: CallInfo,
collector: CandidateCollector, collector: CandidateCollector,
resolvedQualifier: FirResolvedQualifier, resolvedQualifier: FirResolvedQualifier,
manager: TowerResolveManager manager: TowerResolveManager
) { ) {
val qualifierScopes = if (resolvedQualifier.classId == null) { val qualifierReceiver = createQualifierReceiver(resolvedQualifier, session, components.scopeSession)
listOf(
FirExplicitSimpleImportingScope( when {
listOf( info.isPotentialQualifierPart -> {
buildResolvedImport { processClassifierScope(manager, info, qualifierReceiver, prioritized = true)
delegate = buildImport { processQualifierScopes(manager, info, qualifierReceiver)
importedFqName = FqName.topLevel(info.name) }
isAllUnder = false else -> {
} processQualifierScopes(manager, info, qualifierReceiver)
packageFqName = resolvedQualifier.packageFqName processClassifierScope(manager, info, qualifierReceiver, prioritized = false)
} }
), session, components.scopeSession
)
)
} else {
QualifierReceiver(resolvedQualifier).qualifierScopes(session, components.scopeSession)
} }
for ((depth, qualifierScope) in qualifierScopes.withIndex()) {
manager.processLevel(
ScopeTowerLevel(session, components, qualifierScope), info.noStubReceiver(), TowerGroup.Qualifier(depth)
)
}
if (resolvedQualifier.classId != null) { if (resolvedQualifier.classId != null) {
val typeRef = resolvedQualifier.typeRef val typeRef = resolvedQualifier.typeRef
@@ -6,9 +6,8 @@
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.*
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.declarations.expandedConeType
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
@@ -16,9 +15,8 @@ import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
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.KotlinScopeProvider
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.scopes.impl.FirQualifierScope import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
@@ -27,11 +25,51 @@ import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import java.util.ArrayDeque import java.util.ArrayDeque
class QualifierReceiver(override val explicitReceiver: FirResolvedQualifier) : AbstractExplicitReceiver<FirResolvedQualifier>() {
fun FirClassLikeDeclaration<*>.fullyExpandedClass(useSiteSession: FirSession): FirRegularClass? {
if (this is FirTypeAlias) return this.expandedConeType?.lookupTag?.toSymbol(useSiteSession)?.fir?.fullyExpandedClass(useSiteSession)
if (this is FirRegularClass) return this
error("Not supported: $this")
}
fun createQualifierReceiver(
explicitReceiver: FirResolvedQualifier,
useSiteSession: FirSession,
scopeSession: ScopeSession,
): QualifierReceiver? {
val classId = explicitReceiver.classId
when {
classId != null -> {
val classLikeSymbol = useSiteSession.firSymbolProvider.getClassLikeSymbolByFqName(classId) ?: return null
val classSymbol = classLikeSymbol.fir.fullyExpandedClass(useSiteSession)?.symbol ?: return null
return ClassQualifierReceiver(explicitReceiver, classSymbol, classLikeSymbol, useSiteSession, scopeSession)
}
else -> {
return PackageQualifierReceiver(explicitReceiver, useSiteSession)
}
}
}
abstract class QualifierReceiver(final override val explicitReceiver: FirExpression) : AbstractExplicitReceiver<FirResolvedQualifier>() {
abstract fun classifierScope(): FirScope?
abstract fun callableScopes(): List<FirScope>
}
class ClassQualifierReceiver(
explicitReceiver: FirResolvedQualifier,
val classSymbol: FirRegularClassSymbol,
val originalSymbol: FirClassLikeSymbol<*>,
val useSiteSession: FirSession,
val scopeSession: ScopeSession
) : QualifierReceiver(explicitReceiver) {
private fun collectSuperTypeScopesComposedByDepth( private fun collectSuperTypeScopesComposedByDepth(
klass: FirClass<*>, klass: FirClass<*>,
useSiteSession: FirSession, useSiteSession: FirSession,
scopeSession: ScopeSession scopeSession: ScopeSession,
): List<FirScope> { ): List<FirScope> {
val result = mutableListOf<FirScope>() val result = mutableListOf<FirScope>()
val provider = klass.scopeProvider val provider = klass.scopeProvider
@@ -40,7 +78,7 @@ class QualifierReceiver(override val explicitReceiver: FirResolvedQualifier) : A
val queue = val queue =
ArrayDeque<Pair<ConeClassLikeType, Int>>() ArrayDeque<Pair<ConeClassLikeType, Int>>()
queue.addAll( queue.addAll(
lookupSuperTypes(klass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession).map { it to 1 } lookupSuperTypes(klass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession).map { it to 1 },
) )
val visitedSymbols = mutableSetOf<FirRegularClassSymbol>() val visitedSymbols = mutableSetOf<FirRegularClassSymbol>()
while (queue.isNotEmpty()) { while (queue.isNotEmpty()) {
@@ -55,84 +93,58 @@ class QualifierReceiver(override val explicitReceiver: FirResolvedQualifier) : A
?: continue ?: continue
if (!visitedSymbols.add(superTypeSymbol)) continue if (!visitedSymbols.add(superTypeSymbol)) continue
val superTypeScope = provider.getStaticMemberScopeForCallables( val superTypeScope = provider.getStaticMemberScopeForCallables(
superTypeSymbol.fir, useSiteSession, scopeSession superTypeSymbol.fir, useSiteSession, scopeSession,
) )
if (superTypeScope != null) { if (superTypeScope != null) {
levelScopes += superTypeScope levelScopes += superTypeScope
} }
queue.addAll( queue.addAll(
lookupSuperTypes( lookupSuperTypes(
superTypeSymbol.fir, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession superTypeSymbol.fir, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession,
).map { it to currentDepth + 1 } ).map { it to currentDepth + 1 },
) )
} }
return result return result
} }
private fun getClassSymbolWithCallableScopes( private fun getCallableScopes(
classId: ClassId,
useSiteSession: FirSession, useSiteSession: FirSession,
scopeSession: ScopeSession scopeSession: ScopeSession,
): Pair<FirClassSymbol<*>?, List<FirScope>> { ): List<FirScope> {
val symbol = useSiteSession.firSymbolProvider.getClassLikeSymbolByFqName(classId) ?: return null to emptyList() val klass = classSymbol.fir
if (symbol is FirTypeAliasSymbol) { val result = mutableListOf<FirScope>()
val expansionSymbol = symbol.fir.expandedConeType?.lookupTag?.toSymbol(useSiteSession) val provider = klass.scopeProvider
if (expansionSymbol != null) { val klassScope = provider.getStaticMemberScopeForCallables(klass, useSiteSession, scopeSession)
return getClassSymbolWithCallableScopes(expansionSymbol.classId, useSiteSession, scopeSession) if (klassScope != null) {
} result += klassScope
} else { if (provider is KotlinScopeProvider) return result
return (symbol as? FirClassSymbol<*>)?.let { klassSymbol -> result += collectSuperTypeScopesComposedByDepth(klass, useSiteSession, scopeSession)
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 result
return null to emptyList()
} }
fun qualifierScopes(useSiteSession: FirSession, scopeSession: ScopeSession): List<FirScope> { override fun callableScopes(): List<FirScope> {
val classId = explicitReceiver.classId ?: return emptyList() return getCallableScopes(useSiteSession, scopeSession)
val (classSymbol, callableScopes) = getClassSymbolWithCallableScopes(classId, useSiteSession, scopeSession)
if (classSymbol != null) {
val klass = classSymbol.fir
val classifierScope = if ((klass as? FirRegularClass)?.hasLazyNestedClassifiers == false) {
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? { override fun classifierScope(): FirScope? {
return FirCompositeScope(qualifierScopes(useSiteSession, scopeSession).toMutableList()) val klass = classSymbol.fir
return klass.scopeProvider.getNestedClassifierScope(klass, useSiteSession, scopeSession)
}
}
class PackageQualifierReceiver(
explicitReceiver: FirResolvedQualifier,
useSiteSession: FirSession
) : QualifierReceiver(explicitReceiver) {
val scope = FirPackageMemberScope(explicitReceiver.packageFqName, useSiteSession)
override fun classifierScope(): FirScope? {
return FirOnlyClassifiersScope(scope)
}
override fun callableScopes(): List<FirScope> {
return listOf(FirOnlyCallablesScope(scope))
} }
} }
@@ -10,23 +10,27 @@ sealed class TowerGroupKind(private val index: Int) : Comparable<TowerGroupKind>
object Start : TowerGroupKind(Integer.MIN_VALUE) object Start : TowerGroupKind(Integer.MIN_VALUE)
class Weakened(depth: Int) : WithDepth(-10, depth) class Weakened(depth: Int) : WithDepth(-20, depth)
object ClassifierPrioritized : TowerGroupKind(-10)
class Qualifier(depth: Int) : WithDepth(0, depth) class Qualifier(depth: Int) : WithDepth(0, depth)
class TopPrioritized(depth: Int) : WithDepth(1, depth) object Classifier : TowerGroupKind(10)
object Member : TowerGroupKind(2) class TopPrioritized(depth: Int) : WithDepth(20, depth)
class Local(depth: Int) : WithDepth(3, depth) object Member : TowerGroupKind(30)
class Implicit(depth: Int) : WithDepth(4, depth) class Local(depth: Int) : WithDepth(40, depth)
object InvokeExtension : TowerGroupKind(5) class Implicit(depth: Int) : WithDepth(50, depth)
class Top(depth: Int) : WithDepth(6, depth) object InvokeExtension : TowerGroupKind(60)
class Static(depth: Int) : WithDepth(7, depth) class Top(depth: Int) : WithDepth(70, depth)
class Static(depth: Int) : WithDepth(80, depth)
object Last : TowerGroupKind(Integer.MAX_VALUE) object Last : TowerGroupKind(Integer.MAX_VALUE)
@@ -47,8 +51,12 @@ class TowerGroup private constructor(private val kinds: Array<TowerGroupKind>) :
val Start = kindOf(TowerGroupKind.Start) val Start = kindOf(TowerGroupKind.Start)
val ClassifierPrioritized = kindOf(TowerGroupKind.ClassifierPrioritized)
fun Qualifier(depth: Int) = kindOf(TowerGroupKind.Qualifier(depth)) fun Qualifier(depth: Int) = kindOf(TowerGroupKind.Qualifier(depth))
val Classifier = kindOf(TowerGroupKind.Classifier)
val Member = kindOf(TowerGroupKind.Member) val Member = kindOf(TowerGroupKind.Member)
fun Local(depth: Int) = kindOf(TowerGroupKind.Local(depth)) fun Local(depth: Int) = kindOf(TowerGroupKind.Local(depth))
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractImportingScope import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractImportingScope
import org.jetbrains.kotlin.fir.scopes.impl.FirQualifierScope
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.*
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
@@ -167,7 +166,8 @@ class ScopeTowerLevel(
private val bodyResolveComponents: BodyResolveComponents, private val bodyResolveComponents: BodyResolveComponents,
val scope: FirScope, val scope: FirScope,
val extensionReceiver: ReceiverValue? = null, val extensionReceiver: ReceiverValue? = null,
private val extensionsOnly: Boolean = false private val extensionsOnly: Boolean = false,
private val noInnerConstructors: Boolean = false
) : SessionBasedTowerLevel(session) { ) : SessionBasedTowerLevel(session) {
private fun FirCallableSymbol<*>.hasConsistentReceivers(extensionReceiver: Receiver?): Boolean = private fun FirCallableSymbol<*>.hasConsistentReceivers(extensionReceiver: Receiver?): Boolean =
when { when {
@@ -198,7 +198,7 @@ class ScopeTowerLevel(
name, name,
session, session,
bodyResolveComponents, bodyResolveComponents,
noInnerConstructors = scope is FirQualifierScope noInnerConstructors = noInnerConstructors
) { candidate -> ) { candidate ->
empty = false empty = false
if (candidate.hasConsistentReceivers(extensionReceiver)) { if (candidate.hasConsistentReceivers(extensionReceiver)) {
@@ -7,8 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope
@@ -156,6 +156,7 @@ class FirSyntheticCallGenerator(
explicitReceiver = null, explicitReceiver = null,
arguments = arguments, arguments = arguments,
isSafeCall = false, isSafeCall = false,
isPotentialQualifierPart = false,
typeArguments = emptyList(), typeArguments = emptyList(),
session = session, session = session,
containingFile = file, containingFile = file,
@@ -66,10 +66,14 @@ class KotlinScopeProvider(
scopeSession: ScopeSession scopeSession: ScopeSession
): FirScope? { ): FirScope? {
return when (klass.classKind) { return when (klass.classKind) {
ClassKind.ENUM_CLASS -> FirStaticScope(declaredMemberScope(klass)) ClassKind.ENUM_CLASS -> FirOnlyCallablesScope(FirStaticScope(declaredMemberScope(klass)))
else -> null else -> null
} }
} }
override fun getNestedClassifierScope(klass: FirClass<*>, useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? {
return nestedClassifierScope(klass)
}
} }
@@ -0,0 +1,21 @@
/*
* 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.scopes.impl
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.name.Name
class FirOnlyCallablesScope(val delegate: FirScope) : FirScope() {
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) {
return delegate.processFunctionsByName(name, processor)
}
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
return delegate.processPropertiesByName(name, processor)
}
}
@@ -0,0 +1,16 @@
/*
* 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.scopes.impl
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
import org.jetbrains.kotlin.name.Name
class FirOnlyClassifiersScope(val delegate: FirScope) : FirScope() {
override fun processClassifiersByName(name: Name, processor: (FirClassifierSymbol<*>) -> Unit) {
return delegate.processClassifiersByName(name, processor)
}
}
@@ -1,40 +0,0 @@
/*
* 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.scopes.impl
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.name.Name
class FirQualifierScope(
private val delegateCallablesScope: FirScope?,
private val delegateClassifiersScope: FirScope?
) : FirScope() {
override fun processClassifiersByName(
name: Name,
processor: (FirClassifierSymbol<*>) -> Unit
) {
delegateClassifiersScope?.processClassifiersByName(name) {
if (it is FirRegularClassSymbol) {
processor(it)
}
}
}
override fun processFunctionsByName(
name: Name,
processor: (FirFunctionSymbol<*>) -> Unit
) {
delegateCallablesScope?.processFunctionsByName(name, processor)
}
override fun processPropertiesByName(
name: Name,
processor: (FirVariableSymbol<*>) -> Unit
) {
delegateCallablesScope?.processPropertiesByName(name, processor)
}
}
@@ -21,4 +21,10 @@ abstract class FirScopeProvider {
useSiteSession: FirSession, useSiteSession: FirSession,
scopeSession: ScopeSession scopeSession: ScopeSession
): FirScope? ): FirScope?
abstract fun getNestedClassifierScope(
klass: FirClass<*>,
useSiteSession: FirSession,
scopeSession: ScopeSession
): FirScope?
} }
@@ -10,6 +10,6 @@ class C {
typealias CA = C typealias CA = C
val test1 = CA val test1 = CA
val test2 = CA.Companion val test2 = CA.<!UNRESOLVED_REFERENCE!>Companion<!>
val test3 = CA.x val test3 = CA.x
val test4 = CA.Companion.x val test4 = CA.<!UNRESOLVED_REFERENCE!>Companion<!>.<!UNRESOLVED_REFERENCE!>x<!>
@@ -34,8 +34,8 @@ val seeAlsoDerivedFoo: String = JDerived.foo()
// Referencing nested classes via type alias should be prohibited // Referencing nested classes via type alias should be prohibited
// (in type position and in expression position) // (in type position and in expression position)
val testNested1: JT.Nested = JT.<!UNRESOLVED_REFERENCE!>Nested<!>() val testNested1: JT.Nested = JT.<!UNRESOLVED_REFERENCE!>Nested<!>()
val testNested2: KT.Nested = KT.Nested() val testNested2: KT.Nested = KT.<!UNRESOLVED_REFERENCE!>Nested<!>()
val testNested3: IT.Nested = IT.Nested() val testNested3: IT.Nested = IT.<!UNRESOLVED_REFERENCE!>Nested<!>()
val testInner1: JT.Inner = JT.<!UNRESOLVED_REFERENCE!>Inner<!>() val testInner1: JT.Inner = JT.<!UNRESOLVED_REFERENCE!>Inner<!>()
val testInner2: KT.Inner = KT.<!UNRESOLVED_REFERENCE!>Inner<!>() val testInner2: KT.Inner = KT.<!UNRESOLVED_REFERENCE!>Inner<!>()
fun testNestedAsTypeArgument1(x: List<JT.Nested>) {} fun testNestedAsTypeArgument1(x: List<JT.Nested>) {}
@@ -53,7 +53,7 @@ fun foo(
test.ClassAlias::func test.ClassAlias::func
test.ClassSample.Nested::func test.ClassSample.Nested::func
test.ClassAlias.Nested::func <!UNRESOLVED_REFERENCE!>test.ClassAlias.<!UNRESOLVED_REFERENCE!>Nested<!>::func<!>
test.ObjectSample::Nested test.ObjectSample::Nested
test.ObjectAlias::Nested test.ObjectAlias::Nested
@@ -71,5 +71,5 @@ fun foo(
test.EnumAlias::func test.EnumAlias::func
test.EnumSample.Nested::func test.EnumSample.Nested::func
test.EnumAlias.Nested::func <!UNRESOLVED_REFERENCE!>test.EnumAlias.<!UNRESOLVED_REFERENCE!>Nested<!>::func<!>
} }