FIR IDE: store FirScope strong references only in KtFirAnalysisSession

This commit is contained in:
Ilya Kirillov
2020-07-13 13:24:45 +03:00
parent 7033be588c
commit d10e3f91fa
5 changed files with 45 additions and 20 deletions
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
class FirCompositeScope(private val scopes: Iterable<FirScope>) : FirScope() { class FirCompositeScope(val scopes: Iterable<FirScope>) : FirScope() {
override fun processClassifiersByNameWithSubstitution( override fun processClassifiersByNameWithSubstitution(
name: Name, name: Name,
@@ -15,10 +15,10 @@ import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.idea.fir.* import org.jetbrains.kotlin.idea.fir.*
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
@@ -59,7 +59,10 @@ private constructor(
firSymbolBuilder firSymbolBuilder
) )
override val scopeProvider: KtScopeProvider = KtFirScopeProvider(token, firSymbolBuilder, project, firSession, firResolveState) private val firScopeStorage = FirScopeRegistry()
override val scopeProvider: KtScopeProvider =
KtFirScopeProvider(token, firSymbolBuilder, project, firSession, firResolveState, firScopeStorage)
init { init {
assertIsValid() assertIsValid()
@@ -221,4 +224,17 @@ private constructor(
) )
} }
} }
}
/**
* Stores strong references to all instances of [FirScope] used
* Needed as the only entity which may have a strong references to FIR internals is [KtFirAnalysisSession]
* Entities which needs storing [FirScope] instances will store them as weak references via [org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef]
*/
internal class FirScopeRegistry {
private val scopes = mutableListOf<FirScope>()
fun register(scope: FirScope) {
scopes += scope
}
} }
@@ -17,12 +17,13 @@ import org.jetbrains.kotlin.idea.frontend.api.scopes.KtUnsubstitutedScope
internal class KtFirDeclaredMemberScope( internal class KtFirDeclaredMemberScope(
override val owner: KtFirClassOrObjectSymbol, override val owner: KtFirClassOrObjectSymbol,
firScope: FirScope,
token: ValidityToken, token: ValidityToken,
builder: KtSymbolByFirBuilder builder: KtSymbolByFirBuilder
) : KtFirDelegatingScope(builder, token), ) : KtFirDelegatingScope(builder, token),
KtDeclaredMemberScope, KtDeclaredMemberScope,
KtUnsubstitutedScope<KtFirDelegatingScope>, KtUnsubstitutedScope<KtFirDelegatingScope>,
ValidityTokenOwner { ValidityTokenOwner {
override val firScope: FirScope by weakRef(declaredMemberScope(owner.fir)) override val firScope: FirScope by weakRef(firScope)
} }
@@ -5,8 +5,6 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.scopes package org.jetbrains.kotlin.idea.frontend.api.fir.scopes
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.buildUseSiteMemberScope
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
@@ -18,11 +16,10 @@ import org.jetbrains.kotlin.idea.frontend.api.scopes.KtUnsubstitutedScope
internal class KtFirMemberScope( internal class KtFirMemberScope(
override val owner: KtFirClassOrObjectSymbol, override val owner: KtFirClassOrObjectSymbol,
firScope: FirScope,
token: ValidityToken, token: ValidityToken,
builder: KtSymbolByFirBuilder builder: KtSymbolByFirBuilder
) : KtFirDelegatingScope(builder, token), KtMemberScope, KtUnsubstitutedScope<KtMemberScope>, ValidityTokenOwner { ) : KtFirDelegatingScope(builder, token), KtMemberScope, KtUnsubstitutedScope<KtMemberScope>, ValidityTokenOwner {
override val firScope: FirScope by weakRef { override val firScope: FirScope by weakRef(firScope)
owner.fir.buildUseSiteMemberScope(owner.fir.session, ScopeSession())
}
} }
@@ -9,15 +9,18 @@ import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.buildUseSiteMemberScope
import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractSimpleImportingScope import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractSimpleImportingScope
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractStarImportingScope import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractStarImportingScope
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
import org.jetbrains.kotlin.idea.fir.getOrBuildFirOfType import org.jetbrains.kotlin.idea.fir.getOrBuildFirOfType
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
import org.jetbrains.kotlin.idea.fir.low.level.api.LowLevelFirApiFacade import org.jetbrains.kotlin.idea.fir.low.level.api.LowLevelFirApiFacade
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
import org.jetbrains.kotlin.idea.frontend.api.fir.FirScopeRegistry
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirClassOrObjectSymbol import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirPackageSymbol import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirPackageSymbol
@@ -40,9 +43,12 @@ internal class KtFirScopeProvider(
private val builder: KtSymbolByFirBuilder, private val builder: KtSymbolByFirBuilder,
private val project: Project, private val project: Project,
session: FirSession, session: FirSession,
val firResolveState: FirModuleResolveState firResolveState: FirModuleResolveState,
firScopeRegistry: FirScopeRegistry,
) : KtScopeProvider(), ValidityTokenOwner { ) : KtScopeProvider(), ValidityTokenOwner {
private val session by weakRef(session) private val session by weakRef(session)
private val firResolveState by weakRef(firResolveState)
private val firScopeStorage by weakRef(firScopeRegistry)
private val memberScopeCache = IdentityHashMap<KtClassOrObjectSymbol, KtMemberScope>() private val memberScopeCache = IdentityHashMap<KtClassOrObjectSymbol, KtMemberScope>()
private val declaredMemberScopeCache = IdentityHashMap<KtClassOrObjectSymbol, KtDeclaredMemberScope>() private val declaredMemberScopeCache = IdentityHashMap<KtClassOrObjectSymbol, KtDeclaredMemberScope>()
@@ -51,14 +57,16 @@ internal class KtFirScopeProvider(
override fun getMemberScope(classSymbol: KtClassOrObjectSymbol): KtMemberScope = withValidityAssertion { override fun getMemberScope(classSymbol: KtClassOrObjectSymbol): KtMemberScope = withValidityAssertion {
memberScopeCache.getOrPut(classSymbol) { memberScopeCache.getOrPut(classSymbol) {
check(classSymbol is KtFirClassOrObjectSymbol) check(classSymbol is KtFirClassOrObjectSymbol)
KtFirMemberScope(classSymbol, token, builder) val firScope = classSymbol.fir.buildUseSiteMemberScope(classSymbol.fir.session, ScopeSession()).also(firScopeStorage::register)
KtFirMemberScope(classSymbol, firScope, token, builder)
} }
} }
override fun getDeclaredMemberScope(classSymbol: KtClassOrObjectSymbol): KtDeclaredMemberScope = withValidityAssertion { override fun getDeclaredMemberScope(classSymbol: KtClassOrObjectSymbol): KtDeclaredMemberScope = withValidityAssertion {
declaredMemberScopeCache.getOrPut(classSymbol) { declaredMemberScopeCache.getOrPut(classSymbol) {
check(classSymbol is KtFirClassOrObjectSymbol) check(classSymbol is KtFirClassOrObjectSymbol)
KtFirDeclaredMemberScope(classSymbol, token, builder) val firScope = declaredMemberScope(classSymbol.fir).also(firScopeStorage::register)
KtFirDeclaredMemberScope(classSymbol, firScope, token, builder)
} }
} }
@@ -110,17 +118,20 @@ internal class KtFirScopeProvider(
KtScopeContext(getCompositeScope(allKtScopes), implicitReceiversTypes) KtScopeContext(getCompositeScope(allKtScopes), implicitReceiversTypes)
} }
private fun convertToKtScope(firScope: FirScope): KtScope = when (firScope) { private fun convertToKtScope(firScope: FirScope): KtScope {
is FirAbstractSimpleImportingScope -> KtFirNonStarImportingScope(firScope, builder, token) firScopeStorage.register(firScope)
is FirAbstractStarImportingScope -> KtFirStarImportingScope(firScope, builder, project, token) return when (firScope) {
else -> { is FirAbstractSimpleImportingScope -> KtFirNonStarImportingScope(firScope, builder, token)
// todo create concrete KtScope here instead of a generic one is FirAbstractStarImportingScope -> KtFirStarImportingScope(firScope, builder, project, token)
KtFirDelegatingScopeImpl(firScope, builder, token) else -> {
// todo create concrete KtScope here instead of a generic one
KtFirDelegatingScopeImpl(firScope, builder, token)
}
} }
} }
} }
private class KtFirDelegatingScopeImpl(firScope: FirScope, builder: KtSymbolByFirBuilder, token: ValidityToken) : private class KtFirDelegatingScopeImpl(firScope: FirScope, builder: KtSymbolByFirBuilder, token: ValidityToken) :
KtFirDelegatingScope(builder, token), ValidityTokenOwner { KtFirDelegatingScope(builder, token), ValidityTokenOwner {
override val firScope: FirScope = firScope override val firScope: FirScope by weakRef(firScope)
} }