From 9fa0dfe4bc33b82b3d7d5bb775fae929eb151829 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Wed, 20 Sep 2023 14:04:15 +0200 Subject: [PATCH] [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 --- .../scopes/KtFe10ScopeResolution.kt | 10 ++-- .../api/fir/components/KtFirScopeProvider.kt | 2 +- .../fir/scopes/FirCallableFilteringScope.kt | 2 +- .../scopes/FirNonStaticCallablesOnlyScope.kt | 32 ---------- .../fir/scopes/FirNonStaticMembersScope.kt | 60 +++++++++++++++++++ .../api/components/KtScopeProvider.kt | 9 +-- 6 files changed, 71 insertions(+), 44 deletions(-) delete mode 100644 analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirNonStaticCallablesOnlyScope.kt create mode 100644 analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirNonStaticMembersScope.kt diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/scopes/KtFe10ScopeResolution.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/scopes/KtFe10ScopeResolution.kt index 89824d79b11..e45213e6d99 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/scopes/KtFe10ScopeResolution.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/scopes/KtFe10ScopeResolution.kt @@ -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.scopes.KtScope import org.jetbrains.kotlin.analysis.api.scopes.KtScopeNameFilter -import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol -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.* import org.jetbrains.kotlin.analysis.api.symbols.markers.KtPossiblyNamedSymbol import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.name.Name @@ -109,6 +104,9 @@ internal open class KtFe10ScopeNonStaticMember( constructors: Collection, analysisContext: Fe10AnalysisContext ) : KtFe10ScopeMember(scope, constructors, analysisContext) { + override fun getClassifierSymbols(nameFilter: KtScopeNameFilter): Sequence = + super.getClassifierSymbols(nameFilter).filter { it is KtNamedClassOrObjectSymbol && it.isInner } + override fun getCallableSymbols(nameFilter: KtScopeNameFilter): Sequence = withValidityAssertion { super.getCallableSymbols(nameFilter).filter { symbol -> when (symbol) { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt index 06a47d03363..bf19b54bd9e 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt @@ -105,7 +105,7 @@ internal class KtFirScopeProvider( ): FirContainingNamesAwareScope { val combinedScope = getCombinedFirKotlinDeclaredMemberScope(classSymbol) return when (kind) { - DeclaredMemberScopeKind.NON_STATIC -> FirNonStaticCallablesOnlyScope(combinedScope) + DeclaredMemberScopeKind.NON_STATIC -> FirNonStaticMembersScope(combinedScope) DeclaredMemberScopeKind.STATIC -> FirStaticScope(combinedScope) } } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirCallableFilteringScope.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirCallableFilteringScope.kt index aa678b8d767..fe8b4e364df 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirCallableFilteringScope.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirCallableFilteringScope.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol 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. */ internal abstract class FirCallableFilteringScope(private val baseScope: FirContainingNamesAwareScope) : FirContainingNamesAwareScope() { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirNonStaticCallablesOnlyScope.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirNonStaticCallablesOnlyScope.kt deleted file mode 100644 index ab542600535..00000000000 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirNonStaticCallablesOnlyScope.kt +++ /dev/null @@ -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 = emptySet() - - override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) { - } -} diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirNonStaticMembersScope.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirNonStaticMembersScope.kt new file mode 100644 index 00000000000..f195a105b7e --- /dev/null +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/FirNonStaticMembersScope.kt @@ -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 = 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) + } + } + } +} diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtScopeProvider.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtScopeProvider.kt index 4f2f42f8b10..beb0e898fce 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtScopeProvider.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtScopeProvider.kt @@ -157,11 +157,12 @@ public interface KtScopeProviderMixIn : KtAnalysisSessionMixIn { withValidityAssertion { analysisSession.scopeProvider.getCombinedMemberScope(this) } /** - * Returns a [KtScope] containing the *non-static* callables (functions, properties, and constructors) explicitly declared in the given - * [KtSymbolWithMembers]. + * Returns a [KtScope] containing the *non-static* callables (functions, properties, and constructors) and inner classes explicitly + * declared in the given [KtSymbolWithMembers]. * - * The declared member scope does not contain classifiers (including the companion object). To retrieve the classifiers declared in this - * [KtSymbolWithMembers], please use the *static* declared member scope provided by [getStaticDeclaredMemberScope]. + * The declared member scope does not contain classifiers (including the companion object) except for inner classes. To retrieve the + * classifiers declared in this [KtSymbolWithMembers], please use the *static* declared member scope provided by + * [getStaticDeclaredMemberScope]. * * @see getStaticDeclaredMemberScope */