[analysis api] introduce KtTypeScope which will contain callable signatures

This commit is contained in:
Ilya Kirillov
2022-06-07 16:16:55 +02:00
parent 3ee0410c77
commit 3033a91567
8 changed files with 222 additions and 46 deletions
@@ -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 {
@@ -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())
}
}
}
@@ -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<Name> = withValidityAssertion { withValidityAssertion { allNamesCached } }
override fun getPossibleCallableNames(): Set<Name> = withValidityAssertion {
firScope.getCallableNames()
}
override fun getPossibleClassifierNames(): Set<Name> = withValidityAssertion {
firScope.getClassifierNames()
}
override fun getCallableSignatures(nameFilter: KtScopeNameFilter): Sequence<KtSignature<*>> = withValidityAssertion {
firScope.getCallableSignatures(getPossibleCallableNames().filter(nameFilter), builder)
}
override fun getClassifierSymbols(nameFilter: KtScopeNameFilter): Sequence<KtClassifierSymbol> = withValidityAssertion {
firScope.getClassifierSymbols(getPossibleClassifierNames().filter(nameFilter), builder)
}
override fun getConstructors(): Sequence<KtConstructorSymbol> = withValidityAssertion {
firScope.getConstructors(builder)
}
override fun mayContainName(name: Name): Boolean = withValidityAssertion {
name in getAllPossibleNames()
}
}
@@ -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<Name>, builde
}
}
internal fun FirScope.getCallableSignatures(callableNames: Collection<Name>, builder: KtSymbolByFirBuilder) = sequence {
callableNames.forEach { name ->
val signatures = mutableListOf<KtSignature<*>>()
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<Name>, builder: KtSymbolByFirBuilder): Sequence<KtClassifierSymbol> =
sequence {
classLikeNames.forEach { name ->
@@ -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<KtTypeScope>,
override val token: KtLifetimeToken
) : KtTypeScope {
override fun getAllPossibleNames(): Set<Name> = withValidityAssertion {
buildSet {
subScopes.flatMapTo(this) { it.getAllPossibleNames() }
}
}
override fun getPossibleCallableNames(): Set<Name> = withValidityAssertion {
buildSet {
subScopes.flatMapTo(this) { it.getPossibleCallableNames() }
}
}
override fun getPossibleClassifierNames(): Set<Name> = withValidityAssertion {
buildSet {
subScopes.flatMapTo(this) { it.getPossibleClassifierNames() }
}
}
override fun getCallableSignatures(nameFilter: KtScopeNameFilter): Sequence<KtSignature<*>> = withValidityAssertion {
sequence {
subScopes.forEach { yieldAll(it.getCallableSignatures(nameFilter)) }
}
}
override fun getClassifierSymbols(nameFilter: KtScopeNameFilter): Sequence<KtClassifierSymbol> = withValidityAssertion {
sequence {
subScopes.forEach { yieldAll(it.getClassifierSymbols(nameFilter)) }
}
}
override fun getConstructors(): Sequence<KtConstructorSymbol> = withValidityAssertion {
sequence {
subScopes.forEach { yieldAll(it.getConstructors()) }
}
}
override fun mayContainName(name: Name): Boolean = withValidityAssertion {
subScopes.any { it.mayContainName(name) }
}
}
@@ -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<Name> = 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<Name>
/**
* 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<Name>
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<KtPackageSymbol>
/**
* 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()
}
}
@@ -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<Name> = 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<Name>
/**
* 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<Name>
/**
* 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()
}
}
@@ -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<KtSignature<*>>
/**
* Return a sequence of [KtClassifierSymbol] which current scope contain if declaration name matches [nameFilter]
*/
public fun getClassifierSymbols(nameFilter: KtScopeNameFilter = { true }): Sequence<KtClassifierSymbol>
/**
* Return a sequence of [KtConstructorSymbol] which current scope contain
*/
public fun getConstructors(): Sequence<KtConstructorSymbol>
}