[AA] Allow inner classes in non-static declared member scopes

- An inner class `Inner` in a class `Outer` is accessible as
  `Outer().Inner()` and should thus be part of the non-static declared
  member scope.
- Related issue containing a discussion about inner classes in use-site
  scopes: KT-62023.

^KT-61800
This commit is contained in:
Marco Pennekamp
2023-09-20 14:04:15 +02:00
committed by Space Team
parent 239cfa6d29
commit 9fa0dfe4bc
6 changed files with 71 additions and 44 deletions
@@ -13,12 +13,7 @@ import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.scopes.KtScope import org.jetbrains.kotlin.analysis.api.scopes.KtScope
import org.jetbrains.kotlin.analysis.api.scopes.KtScopeNameFilter import org.jetbrains.kotlin.analysis.api.scopes.KtScopeNameFilter
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.KtClassifierSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtConstructorSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtPackageSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtPossiblyNamedSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtPossiblyNamedSymbol
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -109,6 +104,9 @@ internal open class KtFe10ScopeNonStaticMember(
constructors: Collection<ConstructorDescriptor>, constructors: Collection<ConstructorDescriptor>,
analysisContext: Fe10AnalysisContext analysisContext: Fe10AnalysisContext
) : KtFe10ScopeMember(scope, constructors, analysisContext) { ) : KtFe10ScopeMember(scope, constructors, analysisContext) {
override fun getClassifierSymbols(nameFilter: KtScopeNameFilter): Sequence<KtClassifierSymbol> =
super.getClassifierSymbols(nameFilter).filter { it is KtNamedClassOrObjectSymbol && it.isInner }
override fun getCallableSymbols(nameFilter: KtScopeNameFilter): Sequence<KtCallableSymbol> = withValidityAssertion { override fun getCallableSymbols(nameFilter: KtScopeNameFilter): Sequence<KtCallableSymbol> = withValidityAssertion {
super.getCallableSymbols(nameFilter).filter { symbol -> super.getCallableSymbols(nameFilter).filter { symbol ->
when (symbol) { when (symbol) {
@@ -105,7 +105,7 @@ internal class KtFirScopeProvider(
): FirContainingNamesAwareScope { ): FirContainingNamesAwareScope {
val combinedScope = getCombinedFirKotlinDeclaredMemberScope(classSymbol) val combinedScope = getCombinedFirKotlinDeclaredMemberScope(classSymbol)
return when (kind) { return when (kind) {
DeclaredMemberScopeKind.NON_STATIC -> FirNonStaticCallablesOnlyScope(combinedScope) DeclaredMemberScopeKind.NON_STATIC -> FirNonStaticMembersScope(combinedScope)
DeclaredMemberScopeKind.STATIC -> FirStaticScope(combinedScope) DeclaredMemberScopeKind.STATIC -> FirStaticScope(combinedScope)
} }
} }
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
/** /**
* A base implementation for [FirNonStaticCallablesOnlyScope] and [FirDeclaredMembersOnlyScope], which both filter callables based on some * A base implementation for [FirNonStaticMembersScope] and [FirDeclaredMembersOnlyScope], which both filter callables based on some
* condition. * condition.
*/ */
internal abstract class FirCallableFilteringScope(private val baseScope: FirContainingNamesAwareScope) : FirContainingNamesAwareScope() { internal abstract class FirCallableFilteringScope(private val baseScope: FirContainingNamesAwareScope) : FirContainingNamesAwareScope() {
@@ -1,32 +0,0 @@
/*
* Copyright 2010-2023 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.analysis.api.fir.scopes
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.name.Name
/**
* Excludes static callables and all classifiers.
*/
internal class FirNonStaticCallablesOnlyScope(
private val delegate: FirContainingNamesAwareScope,
) : FirCallableFilteringScope(delegate) {
override fun isTargetCallable(callable: FirCallableSymbol<*>): Boolean = !callable.fir.isStatic
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
delegate.processDeclaredConstructors(processor)
}
override fun getClassifierNames(): Set<Name> = emptySet()
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
}
}
@@ -0,0 +1,60 @@
/*
* Copyright 2010-2023 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.analysis.api.fir.scopes
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.utils.isInner
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.name.Name
/**
* [FirNonStaticMembersScope] includes non-static callables and inner classes.
*
* Inner classes are included because they are accessible from a value of the outer class. For example:
*
* ```
* class Outer {
* inner class Inner
* }
*
* fun foo() {
* val outer = Outer()
* outer.Inner()
* }
* ```
*
* While Kotlin always expects a constructor call when accessing `outer.Inner`, it nonetheless requires inner classes to be contained in
* non-static scopes.
*/
internal class FirNonStaticMembersScope(
private val delegate: FirContainingNamesAwareScope,
) : FirCallableFilteringScope(delegate) {
override fun isTargetCallable(callable: FirCallableSymbol<*>): Boolean = !callable.fir.isStatic
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
delegate.processDeclaredConstructors(processor)
}
override fun getClassifierNames(): Set<Name> = delegate.getClassifierNames()
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
processInnerClassesByName(name, processor)
}
private fun processInnerClassesByName(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
delegate.processClassifiersByNameWithSubstitution(name) { classifier, substitutor ->
val firDeclaration = classifier.fir
if (firDeclaration is FirMemberDeclaration && firDeclaration.isInner) {
processor(classifier, substitutor)
}
}
}
}
@@ -157,11 +157,12 @@ public interface KtScopeProviderMixIn : KtAnalysisSessionMixIn {
withValidityAssertion { analysisSession.scopeProvider.getCombinedMemberScope(this) } withValidityAssertion { analysisSession.scopeProvider.getCombinedMemberScope(this) }
/** /**
* Returns a [KtScope] containing the *non-static* callables (functions, properties, and constructors) explicitly declared in the given * Returns a [KtScope] containing the *non-static* callables (functions, properties, and constructors) and inner classes explicitly
* [KtSymbolWithMembers]. * declared in the given [KtSymbolWithMembers].
* *
* The declared member scope does not contain classifiers (including the companion object). To retrieve the classifiers declared in this * The declared member scope does not contain classifiers (including the companion object) except for inner classes. To retrieve the
* [KtSymbolWithMembers], please use the *static* declared member scope provided by [getStaticDeclaredMemberScope]. * classifiers declared in this [KtSymbolWithMembers], please use the *static* declared member scope provided by
* [getStaticDeclaredMemberScope].
* *
* @see getStaticDeclaredMemberScope * @see getStaticDeclaredMemberScope
*/ */