diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10ScopeProvider.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10ScopeProvider.kt index b133fb20354..84fc3b5fe61 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10ScopeProvider.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10ScopeProvider.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.analysis.api.impl.base.scopes.KtEmptyScope 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.KtTypeScope import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtPackageSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol @@ -180,9 +181,9 @@ internal class KtFe10ScopeProvider( return KtCompositeScope(subScopes, token) } - override fun getTypeScope(type: KtType): KtScope { + override fun getTypeScope(type: KtType): KtTypeScope { require(type is KtFe10Type) - return KtFe10ScopeMember(type.type.memberScope, analysisContext) + TODO() } override fun getScopeContextForPosition(originalFile: KtFile, positionInFakeFile: KtElement): KtScopeContext { 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 38e1572e20d..ab36f78cd55 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 @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.analysis.api.fir.components import com.intellij.openapi.project.Project import com.intellij.psi.search.GlobalSearchScope -import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeOwner +import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals import org.jetbrains.kotlin.analysis.api.components.KtImplicitReceiver import org.jetbrains.kotlin.analysis.api.components.KtScopeContext import org.jetbrains.kotlin.analysis.api.components.KtScopeProvider @@ -19,16 +19,15 @@ import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirEnumEntrySymbol import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirFileSymbol import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirNamedClassOrObjectSymbol import org.jetbrains.kotlin.analysis.api.fir.types.KtFirType -import org.jetbrains.kotlin.analysis.api.fir.utils.weakRef import org.jetbrains.kotlin.analysis.api.impl.base.scopes.KtCompositeScope +import org.jetbrains.kotlin.analysis.api.impl.base.scopes.KtCompositeTypeScope import org.jetbrains.kotlin.analysis.api.impl.base.scopes.KtEmptyScope import org.jetbrains.kotlin.analysis.api.scopes.KtScope +import org.jetbrains.kotlin.analysis.api.scopes.KtTypeScope import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtPackageSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers -import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken import org.jetbrains.kotlin.analysis.api.types.KtType -import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext import org.jetbrains.kotlin.fir.FirSession @@ -168,7 +167,8 @@ internal class KtFirScopeProvider( return KtCompositeScope(subScopes, token) } - override fun getTypeScope(type: KtType): KtScope? { + @OptIn(KtAnalysisApiInternals::class) + override fun getTypeScope(type: KtType): KtTypeScope? { check(type is KtFirType) { "KtFirScopeProvider can only work with KtFirType, but ${type::class} was provided" } val firSession = firResolveSession.useSiteFirSession val firTypeScope = type.coneType.scope( @@ -176,17 +176,15 @@ internal class KtFirScopeProvider( scopeSession, FakeOverrideTypeCalculator.Forced ) ?: return null - return getCompositeScope( + return KtCompositeTypeScope( listOf( - convertToKtScope(firTypeScope), - firTypeScope.getSyntheticPropertiesScope(firSession) - ) + convertToKtTypeScope(firTypeScope), + convertToKtTypeScope(FirSyntheticPropertiesScope(firSession, firTypeScope)) + ), + token ) } - private fun FirTypeScope.getSyntheticPropertiesScope(firSession: FirSession): KtScope = - convertToKtScope(FirSyntheticPropertiesScope(firSession, this)) - override fun getScopeContextForPosition( originalFile: KtFile, positionInFakeFile: KtElement @@ -238,4 +236,11 @@ internal class KtFirScopeProvider( else -> TODO(firScope::class.toString()) } } + + private fun convertToKtTypeScope(firScope: FirScope): KtTypeScope { + return when (firScope) { + is FirContainingNamesAwareScope -> KtFirDelegatingTypeScope(firScope, builder, token) + else -> TODO(firScope::class.toString()) + } + } } \ No newline at end of file diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirDelegatingTypeScope.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirDelegatingTypeScope.kt new file mode 100644 index 00000000000..4fea5cfa517 --- /dev/null +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirDelegatingTypeScope.kt @@ -0,0 +1,54 @@ +/* + * 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.analysis.api.fir.scopes + +import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.analysis.api.fir.utils.cached +import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken +import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion +import org.jetbrains.kotlin.analysis.api.scopes.KtScopeNameFilter +import org.jetbrains.kotlin.analysis.api.scopes.KtTypeScope +import org.jetbrains.kotlin.analysis.api.symbols.KtClassifierSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtConstructorSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtSignature +import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope +import org.jetbrains.kotlin.name.Name + +internal open class KtFirDelegatingTypeScope( + val firScope: FirContainingNamesAwareScope, + private val builder: KtSymbolByFirBuilder, + final override val token: KtLifetimeToken +) : KtTypeScope { + private val allNamesCached by cached { + getPossibleCallableNames() + getPossibleClassifierNames() + } + + override fun getAllPossibleNames(): Set = withValidityAssertion { withValidityAssertion { allNamesCached } } + + override fun getPossibleCallableNames(): Set = withValidityAssertion { + firScope.getCallableNames() + } + + override fun getPossibleClassifierNames(): Set = withValidityAssertion { + firScope.getClassifierNames() + } + + override fun getCallableSignatures(nameFilter: KtScopeNameFilter): Sequence> = withValidityAssertion { + firScope.getCallableSignatures(getPossibleCallableNames().filter(nameFilter), builder) + } + + override fun getClassifierSymbols(nameFilter: KtScopeNameFilter): Sequence = withValidityAssertion { + firScope.getClassifierSymbols(getPossibleClassifierNames().filter(nameFilter), builder) + } + + override fun getConstructors(): Sequence = withValidityAssertion { + firScope.getConstructors(builder) + } + + override fun mayContainName(name: Name): Boolean = withValidityAssertion { + name in getAllPossibleNames() + } +} \ No newline at end of file diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/firScopeUtils.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/firScopeUtils.kt index 90d642f1d6a..743cd212355 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/firScopeUtils.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/firScopeUtils.kt @@ -4,6 +4,7 @@ import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder 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.KtSignature import org.jetbrains.kotlin.fir.isSubstitutionOverride import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.processClassifiersByName @@ -34,6 +35,19 @@ internal fun FirScope.getCallableSymbols(callableNames: Collection, builde } } +internal fun FirScope.getCallableSignatures(callableNames: Collection, builder: KtSymbolByFirBuilder) = sequence { + callableNames.forEach { name -> + val signatures = mutableListOf>() + processFunctionsByName(name) { firSymbol -> + signatures.add(builder.functionLikeBuilder.buildFunctionLikeSignature(firSymbol)) + } + processPropertiesByName(name) { firSymbol -> + signatures.add(builder.variableLikeBuilder.buildVariableLikeSignature(firSymbol)) + } + yieldAll(signatures) + } +} + internal fun FirScope.getClassifierSymbols(classLikeNames: Collection, builder: KtSymbolByFirBuilder): Sequence = sequence { classLikeNames.forEach { name -> diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/scopes/KtCompositeTypeScope.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/scopes/KtCompositeTypeScope.kt new file mode 100644 index 00000000000..fd70d788bd2 --- /dev/null +++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/scopes/KtCompositeTypeScope.kt @@ -0,0 +1,61 @@ +/* + * 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. + */ + +package org.jetbrains.kotlin.analysis.api.impl.base.scopes + +import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals +import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken +import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion +import org.jetbrains.kotlin.analysis.api.scopes.KtScopeNameFilter +import org.jetbrains.kotlin.analysis.api.scopes.KtTypeScope +import org.jetbrains.kotlin.analysis.api.symbols.* +import org.jetbrains.kotlin.name.Name + +@KtAnalysisApiInternals +class KtCompositeTypeScope( + private val subScopes: List, + override val token: KtLifetimeToken +) : KtTypeScope { + override fun getAllPossibleNames(): Set = withValidityAssertion { + buildSet { + subScopes.flatMapTo(this) { it.getAllPossibleNames() } + } + } + + override fun getPossibleCallableNames(): Set = withValidityAssertion { + buildSet { + subScopes.flatMapTo(this) { it.getPossibleCallableNames() } + } + } + + override fun getPossibleClassifierNames(): Set = withValidityAssertion { + buildSet { + subScopes.flatMapTo(this) { it.getPossibleClassifierNames() } + } + } + + + override fun getCallableSignatures(nameFilter: KtScopeNameFilter): Sequence> = withValidityAssertion { + sequence { + subScopes.forEach { yieldAll(it.getCallableSignatures(nameFilter)) } + } + } + + override fun getClassifierSymbols(nameFilter: KtScopeNameFilter): Sequence = withValidityAssertion { + sequence { + subScopes.forEach { yieldAll(it.getClassifierSymbols(nameFilter)) } + } + } + + override fun getConstructors(): Sequence = withValidityAssertion { + sequence { + subScopes.forEach { yieldAll(it.getConstructors()) } + } + } + + override fun mayContainName(name: Name): Boolean = withValidityAssertion { + subScopes.any { it.mayContainName(name) } + } +} \ No newline at end of file diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/scopes/KtScope.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/scopes/KtScope.kt index 7f3125cf44b..cf70266a720 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/scopes/KtScope.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/scopes/KtScope.kt @@ -11,28 +11,7 @@ import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion import org.jetbrains.kotlin.name.Name -public interface KtScope : KtLifetimeOwner { - /** - * Returns a **subset** of names which current scope may contain. - * In other words `ALL_NAMES(scope)` is a subset of `scope.getAllNames()` - */ - public fun getAllPossibleNames(): Set = withValidityAssertion { - getPossibleCallableNames() + getPossibleClassifierNames() - } - - /** - * Returns a **subset** of callable names which current scope may contain. - * In other words `ALL_CALLABLE_NAMES(scope)` is a subset of `scope.getCallableNames()` - */ - public 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()` - */ - public fun getPossibleClassifierNames(): Set - - +public interface KtScope : KtScopeLike { /** * Return a sequence of all [KtSymbol] which current scope contain */ @@ -64,15 +43,5 @@ public interface KtScope : KtLifetimeOwner { * Return a sequence of [KtPackageSymbol] nested in current scope contain if package name matches [nameFilter] */ public fun getPackageSymbols(nameFilter: KtScopeNameFilter = { true }): Sequence - - - /** - * 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 - */ - public fun mayContainName(name: Name): Boolean = withValidityAssertion { - name in getPossibleCallableNames() || name in getPossibleClassifierNames() - } } diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/scopes/KtScopeLike.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/scopes/KtScopeLike.kt new file mode 100644 index 00000000000..3bce38e8f49 --- /dev/null +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/scopes/KtScopeLike.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2022 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.scopes + +import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeOwner +import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion +import org.jetbrains.kotlin.name.Name + +public interface KtScopeLike : KtLifetimeOwner { + /** + * Returns a **subset** of names which current scope may contain. + * In other words `ALL_NAMES(scope)` is a subset of `scope.getAllNames()` + */ + public fun getAllPossibleNames(): Set = withValidityAssertion { + getPossibleCallableNames() + getPossibleClassifierNames() + } + + /** + * Returns a **subset** of callable names which current scope may contain. + * In other words `ALL_CALLABLE_NAMES(scope)` is a subset of `scope.getCallableNames()` + */ + public 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()` + */ + public fun getPossibleClassifierNames(): Set + + /** + * 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 + */ + public fun mayContainName(name: Name): Boolean = withValidityAssertion { + name in getPossibleCallableNames() || name in getPossibleClassifierNames() + } +} \ No newline at end of file diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/scopes/KtTypeScope.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/scopes/KtTypeScope.kt new file mode 100644 index 00000000000..c585d46a4a5 --- /dev/null +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/scopes/KtTypeScope.kt @@ -0,0 +1,31 @@ +/* + * 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.analysis.api.scopes + +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.KtSignature + + +public interface KtTypeScope : KtScopeLike { + + /** + * Return a sequence of [KtCallableSymbol] which current scope contain if declaration name matches [nameFilter] + */ + public fun getCallableSignatures(nameFilter: KtScopeNameFilter = { true }): Sequence> + + /** + * Return a sequence of [KtClassifierSymbol] which current scope contain if declaration name matches [nameFilter] + */ + public fun getClassifierSymbols(nameFilter: KtScopeNameFilter = { true }): Sequence + + /** + * Return a sequence of [KtConstructorSymbol] which current scope contain + */ + public fun getConstructors(): Sequence +} +