From 90798d88573078f1daca4b1ac37e73cb49f1d0aa Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Tue, 4 May 2021 13:13:08 +0200 Subject: [PATCH] FIR IDE: add KDoc for KtScope, choose better names for KtScope members --- .../KotlinFirLookupElementFactory.kt | 2 +- .../idea/frontend/api/scopes/KtScope.kt | 47 ++++++++++++++++--- .../api/fir/scopes/KtFirCompositeScope.kt | 16 +++---- .../api/fir/scopes/KtFirDelegatingScope.kt | 16 +++---- .../api/fir/scopes/KtFirEmptyMemberScope.kt | 8 ++-- .../frontend/api/fir/scopes/KtFirFileScope.kt | 6 +-- .../fir/scopes/KtFirNonStarImportingScope.kt | 8 ++-- .../api/fir/scopes/KtFirPackageScope.kt | 8 ++-- .../api/fir/scopes/KtFirStarImportingScope.kt | 8 ++-- .../api/scopes/AbstractFileScopeTest.kt | 4 +- 10 files changed, 79 insertions(+), 44 deletions(-) diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirLookupElementFactory.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirLookupElementFactory.kt index da0ffd0ef04..6c8aec6519f 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirLookupElementFactory.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirLookupElementFactory.kt @@ -375,7 +375,7 @@ private fun alreadyHasImport(file: KtFile, nameToImport: CallableId): Boolean { withAllowedResolve { analyse(file) { val scopes = file.getScopeContextForFile().scopes - if (!scopes.containsName(nameToImport.callableName)) return false + if (!scopes.mayContainName(nameToImport.callableName)) return false return scopes .getCallableSymbols { it == nameToImport.callableName } diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/scopes/KtScope.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/scopes/KtScope.kt index e4a61eb4153..1d8e6097366 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/scopes/KtScope.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/scopes/KtScope.kt @@ -13,15 +13,32 @@ import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name + interface KtScope : ValidityTokenOwner { - // TODO check that names are accessible - // maybe return some kind of lazy set - fun getAllNames(): Set = withValidityAssertion { getCallableNames() + getClassifierNames() } + /** + * Returns a **subset** of names which current scope may contain. + * In other words `ALL_NAMES(scope)` is a subset of `scope.getAllNames()` + */ + fun getAllPossibleNames(): Set = withValidityAssertion { + getPossibleCallableNames() + getPossibleClassifierNames() + } - fun getCallableNames(): Set - fun getClassifierNames(): Set + /** + * Returns a **subset** of callable names which current scope may contain. + * In other words `ALL_CALLABLE_NAMES(scope)` is a subset of `scope.getCallableNames()` + */ + fun getPossibleCallableNames(): Set + + /** + * Returns a **subset** of classifier names which current scope may contain. + * In other words `ALL_CLASSIFIER_NAMES(scope)` is a subset of `scope.getClassifierNames()` + */ + fun getPossibleClassifierNames(): Set + /** + * Return a sequence of all [KtSymbol] which current scope contain + */ fun getAllSymbols(): Sequence = withValidityAssertion { sequence { yieldAll(getCallableSymbols()) @@ -30,12 +47,28 @@ interface KtScope : ValidityTokenOwner { } } + /** + * Return a sequence of [KtCallableSymbol] which current scope contain if declaration name matches [nameFilter] + */ fun getCallableSymbols(nameFilter: KtScopeNameFilter = { true }): Sequence + + /** + * Return a sequence of [KtClassifierSymbol] which current scope contain if declaration name matches [nameFilter] + */ fun getClassifierSymbols(nameFilter: KtScopeNameFilter = { true }): Sequence + + /** + * Return a sequence of [KtConstructorSymbol] which current scope contain + */ fun getConstructors(): Sequence - fun containsName(name: Name): Boolean = withValidityAssertion { - name in getCallableNames() || name in getClassifierNames() + /** + * return true if the scope may contain name, false otherwise. + * + * In other words `(mayContainName(name) == false) => (name !in scope)`; vice versa is not always true + */ + fun mayContainName(name: Name): Boolean = withValidityAssertion { + name in getPossibleCallableNames() || name in getPossibleClassifierNames() } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirCompositeScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirCompositeScope.kt index fa8f931ea08..e8789b827d4 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirCompositeScope.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirCompositeScope.kt @@ -24,21 +24,21 @@ class KtFirCompositeScope( override val subScopes: List, override val token: ValidityToken ) : KtCompositeScope, ValidityTokenOwner { - override fun getAllNames(): Set = withValidityAssertion { + override fun getAllPossibleNames(): Set = withValidityAssertion { buildSet { - subScopes.flatMapTo(this) { it.getAllNames() } + subScopes.flatMapTo(this) { it.getAllPossibleNames() } } } - override fun getCallableNames(): Set = withValidityAssertion { + override fun getPossibleCallableNames(): Set = withValidityAssertion { buildSet { - subScopes.flatMapTo(this) { it.getCallableNames() } + subScopes.flatMapTo(this) { it.getPossibleCallableNames() } } } - override fun getClassifierNames(): Set = withValidityAssertion { + override fun getPossibleClassifierNames(): Set = withValidityAssertion { buildSet { - subScopes.flatMapTo(this) { it.getClassifierNames() } + subScopes.flatMapTo(this) { it.getPossibleClassifierNames() } } } @@ -66,7 +66,7 @@ class KtFirCompositeScope( } } - override fun containsName(name: Name): Boolean = withValidityAssertion { - subScopes.any { it.containsName(name) } + override fun mayContainName(name: Name): Boolean = withValidityAssertion { + subScopes.any { it.mayContainName(name) } } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirDelegatingScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirDelegatingScope.kt index d03ef36d374..2a13894d8d8 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirDelegatingScope.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirDelegatingScope.kt @@ -29,33 +29,33 @@ internal abstract class KtFirDelegatingScope( abstract val firScope: S private val allNamesCached by cached { - getCallableNames() + getClassifierNames() + getPossibleCallableNames() + getPossibleClassifierNames() } - override fun getAllNames(): Set = allNamesCached + override fun getAllPossibleNames(): Set = allNamesCached - override fun getCallableNames(): Set = withValidityAssertion { + override fun getPossibleCallableNames(): Set = withValidityAssertion { firScope.getCallableNames() } - override fun getClassifierNames(): Set = withValidityAssertion { + override fun getPossibleClassifierNames(): Set = withValidityAssertion { firScope.getClassifierNames() } override fun getCallableSymbols(nameFilter: KtScopeNameFilter): Sequence = withValidityAssertion { - firScope.getCallableSymbols(getCallableNames().filter(nameFilter), builder) + firScope.getCallableSymbols(getPossibleCallableNames().filter(nameFilter), builder) } override fun getClassifierSymbols(nameFilter: KtScopeNameFilter): Sequence = withValidityAssertion { - firScope.getClassifierSymbols(getClassifierNames().filter(nameFilter), builder) + firScope.getClassifierSymbols(getPossibleClassifierNames().filter(nameFilter), builder) } override fun getConstructors(): Sequence = withValidityAssertion { firScope.getConstructors(builder) } - override fun containsName(name: Name): Boolean = withValidityAssertion { - name in getAllNames() + override fun mayContainName(name: Name): Boolean = withValidityAssertion { + name in getAllPossibleNames() } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirEmptyMemberScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirEmptyMemberScope.kt index 941516ad511..03751e97ec3 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirEmptyMemberScope.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirEmptyMemberScope.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 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. */ @@ -17,9 +17,9 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithMember import org.jetbrains.kotlin.name.Name internal class KtFirEmptyMemberScope(override val owner: KtSymbolWithMembers) : KtMemberScope, KtDeclaredMemberScope, ValidityTokenOwner { - override fun getCallableNames(): Set = emptySet() + override fun getPossibleCallableNames(): Set = emptySet() - override fun getClassifierNames(): Set = emptySet() + override fun getPossibleClassifierNames(): Set = emptySet() override fun getCallableSymbols(nameFilter: KtScopeNameFilter): Sequence = emptySequence() @@ -30,6 +30,8 @@ internal class KtFirEmptyMemberScope(override val owner: KtSymbolWithMembers) : override fun getConstructors(): Sequence = emptySequence() + override fun mayContainName(name: Name): Boolean = false + override val token: ValidityToken get() = owner.token } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirFileScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirFileScope.kt index 0ce65e10b28..6774f5ff6e1 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirFileScope.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirFileScope.kt @@ -33,7 +33,7 @@ internal class KtFirFileScope( _callableNames + _classifierNames } - override fun getAllNames(): Set = allNamesCached + override fun getAllPossibleNames(): Set = allNamesCached private val _callableNames: Set by cached { val result = mutableSetOf() @@ -49,7 +49,7 @@ internal class KtFirFileScope( result } - override fun getCallableNames(): Set = _callableNames + override fun getPossibleCallableNames(): Set = _callableNames private val _classifierNames: Set by cached { val result = mutableSetOf() @@ -61,7 +61,7 @@ internal class KtFirFileScope( result } - override fun getClassifierNames(): Set = _classifierNames + override fun getPossibleClassifierNames(): Set = _classifierNames override fun getCallableSymbols(nameFilter: KtScopeNameFilter): Sequence = withValidityAssertion { owner.firRef.withFir { diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirNonStarImportingScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirNonStarImportingScope.kt index 9765371aabf..51e4120de0f 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirNonStarImportingScope.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirNonStarImportingScope.kt @@ -45,20 +45,20 @@ internal class KtFirNonStarImportingScope( } override fun getCallableSymbols(nameFilter: KtScopeNameFilter): Sequence = withValidityAssertion { - firScope.getCallableSymbols(getCallableNames().filter(nameFilter), builder) + firScope.getCallableSymbols(getPossibleCallableNames().filter(nameFilter), builder) } override fun getClassifierSymbols(nameFilter: KtScopeNameFilter): Sequence = withValidityAssertion { - firScope.getClassifierSymbols(getClassifierNames().filter(nameFilter), builder) + firScope.getClassifierSymbols(getPossibleClassifierNames().filter(nameFilter), builder) } override fun getConstructors(): Sequence = emptySequence() - override fun getCallableNames(): Set = withValidityAssertion { + override fun getPossibleCallableNames(): Set = withValidityAssertion { imports.mapNotNullTo(hashSetOf()) { it.callableName } } - override fun getClassifierNames(): Set = withValidityAssertion { + override fun getPossibleClassifierNames(): Set = withValidityAssertion { imports.mapNotNullTo((hashSetOf())) { it.relativeClassName?.shortName() } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.kt index bffe2b533c8..98a46237809 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.kt @@ -32,7 +32,7 @@ internal class KtFirPackageScope( private val firScope by weakRef(firScope) override val fqName: FqName get() = firScope.fqName - override fun getCallableNames() = withValidityAssertion { + override fun getPossibleCallableNames() = withValidityAssertion { hashSetOf().apply { KotlinTopLevelPropertyByPackageIndex.getInstance()[fqName.asString(), project, firScope.session.searchScope] .mapNotNullTo(this) { it.nameAsName } @@ -41,17 +41,17 @@ internal class KtFirPackageScope( } } - override fun getClassifierNames(): Set = withValidityAssertion { + override fun getPossibleClassifierNames(): Set = withValidityAssertion { KotlinTopLevelClassByPackageIndex.getInstance()[fqName.asString(), project, firScope.session.searchScope] .mapNotNullTo(hashSetOf()) { it.nameAsName } } override fun getCallableSymbols(nameFilter: KtScopeNameFilter): Sequence = withValidityAssertion { - firScope.getCallableSymbols(getCallableNames().filter(nameFilter), builder) + firScope.getCallableSymbols(getPossibleCallableNames().filter(nameFilter), builder) } override fun getClassifierSymbols(nameFilter: KtScopeNameFilter): Sequence = withValidityAssertion { - firScope.getClassifierSymbols(getClassifierNames().filter(nameFilter), builder) + firScope.getClassifierSymbols(getPossibleClassifierNames().filter(nameFilter), builder) } override fun getConstructors(): Sequence = emptySequence() diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirStarImportingScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirStarImportingScope.kt index d2b4e0f33ae..64b26debae9 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirStarImportingScope.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirStarImportingScope.kt @@ -50,18 +50,18 @@ internal class KtFirStarImportingScope( } override fun getCallableSymbols(nameFilter: KtScopeNameFilter): Sequence = withValidityAssertion { - firScope.getCallableSymbols(getCallableNames().filter(nameFilter), builder) + firScope.getCallableSymbols(getPossibleCallableNames().filter(nameFilter), builder) } override fun getClassifierSymbols(nameFilter: KtScopeNameFilter): Sequence = withValidityAssertion { - firScope.getClassifierSymbols(getClassifierNames().filter(nameFilter), builder) + firScope.getClassifierSymbols(getPossibleClassifierNames().filter(nameFilter), builder) } override fun getConstructors(): Sequence = emptySequence() // todo cache? @OptIn(ExperimentalStdlibApi::class) - override fun getCallableNames(): Set = withValidityAssertion { + override fun getPossibleCallableNames(): Set = withValidityAssertion { imports.flatMapTo(hashSetOf()) { import: Import -> if (import.relativeClassName == null) { // top level callable packageHelper.getPackageTopLevelCallables(import.packageFqName) @@ -72,7 +72,7 @@ internal class KtFirStarImportingScope( } } - override fun getClassifierNames(): Set = withValidityAssertion { + override fun getPossibleClassifierNames(): Set = withValidityAssertion { imports.flatMapTo(hashSetOf()) { import -> if (import.relativeClassName == null) { packageHelper.getPackageTopLevelClassifiers(import.packageFqName) diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/scopes/AbstractFileScopeTest.kt b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/scopes/AbstractFileScopeTest.kt index 395f54953df..93f11786fb9 100644 --- a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/scopes/AbstractFileScopeTest.kt +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/scopes/AbstractFileScopeTest.kt @@ -25,9 +25,9 @@ abstract class AbstractFileScopeTest : KotlinLightCodeInsightFixtureTestCase() { val scope = symbol.getFileScope() val renderedSymbol = DebugSymbolRenderer.render(symbol) - val callableNames = scope.getCallableNames() + val callableNames = scope.getPossibleCallableNames() val renderedCallables = scope.getCallableSymbols().map { DebugSymbolRenderer.render(it) } - val classifierNames = scope.getClassifierNames() + val classifierNames = scope.getPossibleClassifierNames() val renderedClassifiers = scope.getClassifierSymbols().map { DebugSymbolRenderer.render(it) } "FILE SYMBOL:\n" + renderedSymbol +