FIR IDE: resolve kt symbols only to the phase they actually need

This commit is contained in:
Ilya Kirillov
2020-08-10 15:14:02 +03:00
parent 75be9cf31f
commit a700d1fccb
30 changed files with 285 additions and 118 deletions
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.fir.highlighter.visitors.FirAfterResolveHighlightingVisitor import org.jetbrains.kotlin.idea.fir.highlighter.visitors.FirAfterResolveHighlightingVisitor
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.analyze import org.jetbrains.kotlin.idea.frontend.api.analyze
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.highlighter.AbstractKotlinPsiChecker import org.jetbrains.kotlin.idea.highlighter.AbstractKotlinPsiChecker
import org.jetbrains.kotlin.idea.highlighter.Diagnostic2Annotation import org.jetbrains.kotlin.idea.highlighter.Diagnostic2Annotation
import org.jetbrains.kotlin.idea.highlighter.IdeErrorMessages import org.jetbrains.kotlin.idea.highlighter.IdeErrorMessages
@@ -50,5 +50,5 @@ object DebugSymbolRenderer {
else -> value::class.simpleName!! else -> value::class.simpleName!!
} }
private val ignoredPropertyNames = setOf("fir", "psi", "token") private val ignoredPropertyNames = setOf("firRef", "psi", "token")
} }
@@ -9,6 +9,8 @@ dependencies {
compile(project(":idea:idea-frontend-api")) compile(project(":idea:idea-frontend-api"))
compile(project(":idea:idea-core")) compile(project(":idea:idea-core"))
compile(project(":compiler:fir:fir2ir")) compile(project(":compiler:fir:fir2ir"))
compile(project(":compiler:fir:fir2ir:jvm-backend"))
compile(project(":compiler:ir.serialization.common"))
compile(project(":compiler:fir:resolve")) compile(project(":compiler:fir:resolve"))
compile(project(":compiler:fir:checkers")) compile(project(":compiler:fir:checkers"))
compile(project(":compiler:fir:java")) compile(project(":compiler:fir:java"))
@@ -41,6 +41,8 @@ abstract class FirModuleResolveState {
// todo temporary, used only in completion // todo temporary, used only in completion
abstract fun getCachedMappingForCompletion(element: KtElement): FirElement? abstract fun getCachedMappingForCompletion(element: KtElement): FirElement?
abstract fun <D : FirDeclaration> resolvedFirToPhase(declaration: D, toPhase: FirResolvePhase): D
// todo temporary, used only in completion // todo temporary, used only in completion
internal abstract fun lazyResolveFunctionForCompletion( internal abstract fun lazyResolveFunctionForCompletion(
firFunction: FirFunction<*>, firFunction: FirFunction<*>,
@@ -77,6 +79,11 @@ internal open class FirModuleResolveStateImpl(
psiToFirCache.recordElementsForCompletionFrom(fir, firFile, ktFile) psiToFirCache.recordElementsForCompletionFrom(fir, firFile, ktFile)
} }
override fun <D : FirDeclaration> resolvedFirToPhase(declaration: D, toPhase: FirResolvePhase): D {
elementBuilder.lazyResolveDeclaration(declaration, fileCache, toPhase)
return declaration
}
override fun getCachedMappingForCompletion(element: KtElement): FirElement? = override fun getCachedMappingForCompletion(element: KtElement): FirElement? =
psiToFirCache.getCachedMapping(element) psiToFirCache.getCachedMapping(element)
@@ -51,6 +51,10 @@ internal class FirModuleResolveStateForCompletion(
return null return null
} }
override fun <D : FirDeclaration> resolvedFirToPhase(declaration: D, toPhase: FirResolvePhase): D {
return originalState.resolvedFirToPhase(declaration, toPhase)
}
override fun lazyResolveFunctionForCompletion( override fun lazyResolveFunctionForCompletion(
firFunction: FirFunction<*>, firFunction: FirFunction<*>,
containerFirFile: FirFile, containerFirFile: FirFile,
@@ -0,0 +1,20 @@
/*
* 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.idea.fir.low.level.api
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmKotlinMangler
import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer
data class IdeSessionComponents(val signatureComposer: FirBasedSignatureComposer): FirSessionComponent {
companion object {
fun create(session: FirSession) = IdeSessionComponents(
signatureComposer = FirBasedSignatureComposer(FirJvmKotlinMangler(session))
)
}
}
val FirSession.ideSessionComponents: IdeSessionComponents by FirSession.sessionComponentAccessor()
@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.FirTowerDataContext import org.jetbrains.kotlin.fir.resolve.FirTowerDataContext
import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider
@@ -21,6 +23,7 @@ import org.jetbrains.kotlin.idea.util.getElementTextInContext
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.idea.fir.low.level.api.annotations.ThreadSafe import org.jetbrains.kotlin.idea.fir.low.level.api.annotations.ThreadSafe
import org.jetbrains.kotlin.idea.fir.low.level.api.util.getContainingFile
/** /**
* Maps [KtElement] to [FirElement] * Maps [KtElement] to [FirElement]
@@ -55,13 +58,26 @@ internal class FirElementBuilder(
return psiToFirCache.getFir(element, containerFir, firFile) return psiToFirCache.getFir(element, containerFir, firFile)
} }
fun lazyResolveDeclaration(
declaration: FirDeclaration,
moduleFileCache: ModuleFileCache,
toPhase: FirResolvePhase
) {
if (declaration.resolvePhase < toPhase) {
val firFile = declaration.getContainingFile() ?: error("FirFile was not found for\n${declaration.render()}")
firFileBuilder.runCustomResolve(firFile, moduleFileCache) {
runLazyResolveWithoutLock(declaration, firFile, declaration.session.firProvider, toPhase)
}
}
}
/** /**
* Should be invoked under lock * Should be invoked under lock
*/ */
private fun runLazyResolveWithoutLock( private fun runLazyResolveWithoutLock(
firDeclarationToResolve: FirDeclaration, firDeclarationToResolve: FirDeclaration,
containerFirFile: FirFile, containerFirFile: FirFile,
firIdeProvider: FirIdeProvider, provider: FirProvider,
toPhase: FirResolvePhase, toPhase: FirResolvePhase,
towerDataContextForStatement: MutableMap<FirStatement, FirTowerDataContext>? = null, towerDataContextForStatement: MutableMap<FirStatement, FirTowerDataContext>? = null,
) { ) {
@@ -72,6 +88,7 @@ internal class FirElementBuilder(
if (toPhase <= nonLazyPhase) return if (toPhase <= nonLazyPhase) return
val designation = mutableListOf<FirDeclaration>(containerFirFile) val designation = mutableListOf<FirDeclaration>(containerFirFile)
if (firDeclarationToResolve !is FirFile) { if (firDeclarationToResolve !is FirFile) {
val id = when (firDeclarationToResolve) { val id = when (firDeclarationToResolve) {
is FirCallableDeclaration<*> -> { is FirCallableDeclaration<*> -> {
firDeclarationToResolve.symbol.callableId.classId firDeclarationToResolve.symbol.callableId.classId
@@ -83,7 +100,7 @@ internal class FirElementBuilder(
} }
val outerClasses = generateSequence(id) { classId -> val outerClasses = generateSequence(id) { classId ->
classId.outerClassId classId.outerClassId
}.mapTo(mutableListOf()) { firIdeProvider.getFirClassifierByFqName(it)!! } }.mapTo(mutableListOf()) { provider.getFirClassifierByFqName(it)!! }
designation += outerClasses.asReversed() designation += outerClasses.asReversed()
if (firDeclarationToResolve is FirCallableDeclaration<*>) { if (firDeclarationToResolve is FirCallableDeclaration<*>) {
designation += firDeclarationToResolve designation += firDeclarationToResolve
@@ -115,7 +132,6 @@ internal class FirElementBuilder(
} }
private fun KtElement.getNonLocalContainingDeclarationWithFqName(): KtDeclaration? { private fun KtElement.getNonLocalContainingDeclarationWithFqName(): KtDeclaration? {
var container = parent var container = parent
while (container != null && container !is KtFile) { while (container != null && container !is KtFile) {
@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.file.builder
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
@@ -44,6 +46,8 @@ internal abstract class ModuleFileCache {
*/ */
abstract fun fileCached(file: KtFile, createValue: () -> FirFile): FirFile abstract fun fileCached(file: KtFile, createValue: () -> FirFile): FirFile
abstract fun getContainerFirFile(declaration: FirDeclaration): FirFile?
abstract fun getCachedFirFile(ktFile: KtFile): FirFile? abstract fun getCachedFirFile(ktFile: KtFile): FirFile?
// todo make it ReadWriteLock and allow access fir elements only under read lock // todo make it ReadWriteLock and allow access fir elements only under read lock
@@ -65,6 +69,10 @@ internal class ModuleFileCacheImpl(override val session: FirSession) : ModuleFil
override fun getCachedFirFile(ktFile: KtFile): FirFile? = ktFileToFirFile[ktFile] override fun getCachedFirFile(ktFile: KtFile): FirFile? = ktFileToFirFile[ktFile]
override fun getContainerFirFile(declaration: FirDeclaration): FirFile? {
val ktFile = declaration.psi?.containingFile as? KtFile ?: return null
return getCachedFirFile(ktFile)
}
override val firFileLockProvider: LockProvider<FirFile, ReentrantLock> = LockProvider { ReentrantLock() } override val firFileLockProvider: LockProvider<FirFile, ReentrantLock> = LockProvider { ReentrantLock() }
} }
@@ -76,7 +76,7 @@ internal class FirIdeProvider(
override fun getFirClassifierContainerFileIfAny(fqName: ClassId): FirFile? { override fun getFirClassifierContainerFileIfAny(fqName: ClassId): FirFile? {
val fir = getFirClassifierByFqName(fqName) ?: return null // Necessary to ensure cacheProvider contains this classifier val fir = getFirClassifierByFqName(fqName) ?: return null // Necessary to ensure cacheProvider contains this classifier
return providerHelper.getContainingFirFile(fir.symbol) return cache.getContainerFirFile(fir)
} }
override fun getFirClassifierContainerFile(symbol: FirClassLikeSymbol<*>): FirFile { override fun getFirClassifierContainerFile(symbol: FirClassLikeSymbol<*>): FirFile {
@@ -85,7 +85,7 @@ internal class FirIdeProvider(
} }
override fun getFirClassifierContainerFileIfAny(symbol: FirClassLikeSymbol<*>): FirFile? = override fun getFirClassifierContainerFileIfAny(symbol: FirClassLikeSymbol<*>): FirFile? =
providerHelper.getContainingFirFile(symbol) cache.getContainerFirFile(symbol.fir)
override fun getFirCallableContainerFile(symbol: FirCallableSymbol<*>): FirFile? { override fun getFirCallableContainerFile(symbol: FirCallableSymbol<*>): FirFile? {
@@ -98,7 +98,7 @@ internal class FirIdeProvider(
return getFirCallableContainerFile(fir.getter.delegate.symbol) return getFirCallableContainerFile(fir.getter.delegate.symbol)
} }
} }
return providerHelper.getContainingFirFile(symbol) return cache.getContainerFirFile(symbol.fir)
} }
override fun getFirFilesByPackage(fqName: FqName): List<FirFile> = error("Should not be called in FIR IDE") override fun getFirFilesByPackage(fqName: FqName): List<FirFile> = error("Should not be called in FIR IDE")
@@ -72,11 +72,6 @@ internal class FirProviderHelper(
} }
} }
fun getContainingFirFile(symbol: FirBasedSymbol<*>): FirFile? {
val ktFile = symbol.fir.psi?.containingFile as? KtFile ?: return null
return cache.getCachedFirFile(ktFile)
}
private fun FirFile.collectCallableDeclarationsTo(list: MutableList<FirCallableSymbol<*>>, name: Name) { private fun FirFile.collectCallableDeclarationsTo(list: MutableList<FirCallableSymbol<*>>, name: Name) {
declarations.mapNotNullTo(list) { declaration -> declarations.mapNotNullTo(list) { declaration ->
if (declaration is FirCallableDeclaration<*> && declaration.symbol.callableId.callableName == name) { if (declaration is FirCallableDeclaration<*> && declaration.symbol.callableId.callableName == name) {
@@ -0,0 +1,21 @@
/*
* 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.idea.fir.low.level.api.util
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.firProvider
fun FirDeclaration.getContainingFile(): FirFile? {
val provider = session.firProvider
return when (this) {
is FirCallableDeclaration<*> -> provider.getFirCallableContainerFile(symbol)
is FirClassLikeDeclaration<*> -> provider.getFirClassifierContainerFile(symbol)
else -> error("Unsupported declaration ${this::class.java}")
}
}
@@ -102,7 +102,7 @@ abstract class AbstractFirLazyResolveTest : KotlinLightCodeInsightFixtureTestCas
val files = FileTypeIndex.getFiles(KotlinFileType.INSTANCE, contentScope) val files = FileTypeIndex.getFiles(KotlinFileType.INSTANCE, contentScope)
for (file in files) { for (file in files) {
val psiFile = psiManager.findFile(file) as KtFile val psiFile = psiManager.findFile(file) as KtFile
val session = resolveState.firSession val session = resolveState.firIdeSourcesSession
val firProvider = session.firIdeProvider val firProvider = session.firIdeProvider
val firFile = firProvider.cache.getCachedFirFile(psiFile) ?: continue val firFile = firProvider.cache.getCachedFirFile(psiFile) ?: continue
KotlinTestUtils.assertEqualsToFile(File(expectedTxtPath(file)), firFile.render()) KotlinTestUtils.assertEqualsToFile(File(expectedTxtPath(file)), firFile.render())
@@ -39,7 +39,7 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
class KtFirAnalysisSession internal class KtFirAnalysisSession
private constructor( private constructor(
private val element: KtElement, private val element: KtElement,
val firSession: FirSession, val firSession: FirSession,
@@ -132,7 +132,7 @@ private constructor(
element, element,
firSession, firSession,
contextResolveState, contextResolveState,
firSymbolBuilder.createReadOnlyCopy(), firSymbolBuilder.createReadOnlyCopy(contextResolveState),
typeContext, typeContext,
token, token,
isContextSession = true isContextSession = true
@@ -211,6 +211,7 @@ private constructor(
val firSymbolBuilder = KtSymbolByFirBuilder( val firSymbolBuilder = KtSymbolByFirBuilder(
firSession.firSymbolProvider, firSession.firSymbolProvider,
typeContext, typeContext,
firResolveState,
project, project,
token token
) )
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
import org.jetbrains.kotlin.idea.frontend.api.* import org.jetbrains.kotlin.idea.frontend.api.*
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.* import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.*
@@ -45,6 +46,7 @@ internal class KtSymbolByFirBuilder private constructor(
firProvider: FirSymbolProvider, firProvider: FirSymbolProvider,
typeCheckerContext: ConeTypeCheckerContext, typeCheckerContext: ConeTypeCheckerContext,
private val project: Project, private val project: Project,
resolveState: FirModuleResolveState,
override val token: ValidityToken, override val token: ValidityToken,
val withReadOnlyCaching: Boolean, val withReadOnlyCaching: Boolean,
private val symbolsCache: BuilderCache<FirDeclaration, KtSymbol>, private val symbolsCache: BuilderCache<FirDeclaration, KtSymbol>,
@@ -54,6 +56,7 @@ internal class KtSymbolByFirBuilder private constructor(
constructor( constructor(
firProvider: FirSymbolProvider, firProvider: FirSymbolProvider,
typeCheckerContext: ConeTypeCheckerContext, typeCheckerContext: ConeTypeCheckerContext,
resolveState: FirModuleResolveState,
project: Project, project: Project,
token: ValidityToken token: ValidityToken
) : this( ) : this(
@@ -61,24 +64,27 @@ internal class KtSymbolByFirBuilder private constructor(
typeCheckerContext = typeCheckerContext, typeCheckerContext = typeCheckerContext,
project = project, project = project,
token = token, token = token,
resolveState = resolveState,
withReadOnlyCaching = false, withReadOnlyCaching = false,
symbolsCache = BuilderCache(), symbolsCache = BuilderCache(),
typesCache = BuilderCache() typesCache = BuilderCache()
) )
private val firProvider by weakRef(firProvider) private val firProvider by weakRef(firProvider)
private val resolveState by weakRef(resolveState)
private val typeCheckerContext by weakRef(typeCheckerContext) private val typeCheckerContext by weakRef(typeCheckerContext)
fun createReadOnlyCopy(): KtSymbolByFirBuilder { fun createReadOnlyCopy(newResolveState: FirModuleResolveState): KtSymbolByFirBuilder {
check(!withReadOnlyCaching) { "Cannot create readOnly KtSymbolByFirBuilder from a readonly one" } check(!withReadOnlyCaching) { "Cannot create readOnly KtSymbolByFirBuilder from a readonly one" }
return KtSymbolByFirBuilder( return KtSymbolByFirBuilder(
firProvider, firProvider,
typeCheckerContext, typeCheckerContext,
project, project,
token, token = token,
resolveState = newResolveState,
withReadOnlyCaching = true, withReadOnlyCaching = true,
symbolsCache.createReadOnlyCopy(), symbolsCache = symbolsCache.createReadOnlyCopy(),
typesCache.createReadOnlyCopy() typesCache = typesCache.createReadOnlyCopy()
) )
} }
@@ -110,30 +116,33 @@ internal class KtSymbolByFirBuilder private constructor(
TODO(fir::class.toString()) TODO(fir::class.toString())
} }
fun buildClassSymbol(fir: FirRegularClass) = symbolsCache.cache(fir) { KtFirClassOrObjectSymbol(fir, token, this) } fun buildClassSymbol(fir: FirRegularClass) = symbolsCache.cache(fir) { KtFirClassOrObjectSymbol(fir, resolveState, token, this) }
// TODO it can be a constructor parameter, which may be split into parameter & property // TODO it can be a constructor parameter, which may be split into parameter & property
// we should handle them both // we should handle them both
fun buildParameterSymbol(fir: FirValueParameterImpl) = symbolsCache.cache(fir) { KtFirFunctionValueParameterSymbol(fir, token, this) } fun buildParameterSymbol(fir: FirValueParameterImpl) =
symbolsCache.cache(fir) { KtFirFunctionValueParameterSymbol(fir, resolveState, token, this) }
fun buildFirConstructorParameter(fir: FirValueParameterImpl) = fun buildFirConstructorParameter(fir: FirValueParameterImpl) =
symbolsCache.cache(fir) { KtFirConstructorValueParameterSymbol(fir, token, this) } symbolsCache.cache(fir) { KtFirConstructorValueParameterSymbol(fir, resolveState, token, this) }
fun buildFunctionSymbol(fir: FirSimpleFunction, forcedOrigin: FirDeclarationOrigin? = null) = symbolsCache.cache(fir) { fun buildFunctionSymbol(fir: FirSimpleFunction, forcedOrigin: FirDeclarationOrigin? = null) = symbolsCache.cache(fir) {
KtFirFunctionSymbol(fir, token, this, forcedOrigin) KtFirFunctionSymbol(fir, resolveState, token, this, forcedOrigin)
} }
fun buildConstructorSymbol(fir: FirConstructor) = symbolsCache.cache(fir) { KtFirConstructorSymbol(fir, token, this) } fun buildConstructorSymbol(fir: FirConstructor) = symbolsCache.cache(fir) { KtFirConstructorSymbol(fir, resolveState, token, this) }
fun buildTypeParameterSymbol(fir: FirTypeParameter) = symbolsCache.cache(fir) { KtFirTypeParameterSymbol(fir, token) } fun buildTypeParameterSymbol(fir: FirTypeParameter) = symbolsCache.cache(fir) { KtFirTypeParameterSymbol(fir, resolveState, token) }
fun buildTypeAliasSymbol(fir: FirTypeAlias) = symbolsCache.cache(fir) { KtFirTypeAliasSymbol(fir, token) } fun buildTypeAliasSymbol(fir: FirTypeAlias) = symbolsCache.cache(fir) { KtFirTypeAliasSymbol(fir, resolveState, token) }
fun buildEnumEntrySymbol(fir: FirEnumEntry) = symbolsCache.cache(fir) { KtFirEnumEntrySymbol(fir, token, this) } fun buildEnumEntrySymbol(fir: FirEnumEntry) = symbolsCache.cache(fir) { KtFirEnumEntrySymbol(fir, resolveState, token, this) }
fun buildFieldSymbol(fir: FirField) = symbolsCache.cache(fir) { KtFirJavaFieldSymbol(fir, token, this) } fun buildFieldSymbol(fir: FirField) = symbolsCache.cache(fir) { KtFirJavaFieldSymbol(fir, resolveState, token, this) }
fun buildAnonymousFunctionSymbol(fir: FirAnonymousFunction) = symbolsCache.cache(fir) { KtFirAnonymousFunctionSymbol(fir, token, this) } fun buildAnonymousFunctionSymbol(fir: FirAnonymousFunction) =
symbolsCache.cache(fir) { KtFirAnonymousFunctionSymbol(fir, resolveState, token, this) }
fun buildVariableSymbol(fir: FirProperty, forcedOrigin: FirDeclarationOrigin? = null): KtVariableSymbol = symbolsCache.cache(fir) { fun buildVariableSymbol(fir: FirProperty, forcedOrigin: FirDeclarationOrigin? = null): KtVariableSymbol = symbolsCache.cache(fir) {
when { when {
fir.isLocal -> KtFirLocalVariableSymbol(fir, token, this) fir.isLocal -> KtFirLocalVariableSymbol(fir, resolveState, token, this)
else -> KtFirPropertySymbol(fir, token, this, forcedOrigin) else -> KtFirPropertySymbol(fir, resolveState, token, this, forcedOrigin)
} }
} }
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.scopes
import com.intellij.openapi.project.Project 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.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
@@ -58,7 +59,10 @@ 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)
val firScope = classSymbol.fir.unsubstitutedScope(classSymbol.fir.session, ScopeSession()).also(firScopeStorage::register) val firScope =
classSymbol.firRef.withFir(FirResolvePhase.SUPER_TYPES) { fir ->
fir.unsubstitutedScope(fir.session, ScopeSession())
}.also(firScopeStorage::register)
KtFirMemberScope(classSymbol, firScope, token, builder) KtFirMemberScope(classSymbol, firScope, token, builder)
} }
} }
@@ -66,7 +70,8 @@ internal class KtFirScopeProvider(
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)
val firScope = declaredMemberScope(classSymbol.fir).also(firScopeStorage::register) val firScope = classSymbol.firRef.withFir(FirResolvePhase.SUPER_TYPES) { declaredMemberScope(it) }
.also(firScopeStorage::register)
KtFirDeclaredMemberScope(classSymbol, firScope, token, builder) KtFirDeclaredMemberScope(classSymbol, firScope, token, builder)
} }
} }
@@ -7,26 +7,31 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
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.types.KtType import org.jetbrains.kotlin.idea.frontend.api.types.KtType
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.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.* import org.jetbrains.kotlin.idea.frontend.api.symbols.*
internal class KtFirAnonymousFunctionSymbol( internal class KtFirAnonymousFunctionSymbol(
fir: FirAnonymousFunction, fir: FirAnonymousFunction,
resolveState: FirModuleResolveState,
override val token: ValidityToken, override val token: ValidityToken,
private val builder: KtSymbolByFirBuilder private val builder: KtSymbolByFirBuilder
) : KtAnonymousFunctionSymbol(), KtFirSymbol<FirAnonymousFunction> { ) : KtAnonymousFunctionSymbol(), KtFirSymbol<FirAnonymousFunction> {
override val fir: FirAnonymousFunction by weakRef(fir) override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) } override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) } override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { builder.buildKtType(it.returnTypeRef) }
override val valueParameters: List<KtParameterSymbol> by cached { override val valueParameters: List<KtParameterSymbol> by firRef.withFirAndCache {
fir.valueParameters.map { valueParameter -> fir.valueParameters.map { valueParameter ->
check(valueParameter is FirValueParameterImpl) check(valueParameter is FirValueParameterImpl)
builder.buildParameterSymbol(valueParameter) builder.buildParameterSymbol(valueParameter)
@@ -9,38 +9,37 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
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.fir.KtSymbolByFirBuilder import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.ReadOnlyWeakRef
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.* import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
internal class KtFirClassOrObjectSymbol( internal class KtFirClassOrObjectSymbol(
fir: FirRegularClass, fir: FirRegularClass,
resolveState: FirModuleResolveState,
override val token: ValidityToken, override val token: ValidityToken,
private val builder: KtSymbolByFirBuilder private val builder: KtSymbolByFirBuilder
) : KtClassOrObjectSymbol(), KtFirSymbol<FirRegularClass> { ) : KtClassOrObjectSymbol(), KtFirSymbol<FirRegularClass> {
override val fir: FirRegularClass by weakRef(fir) override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) } override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) }
override val name: Name get() = withValidityAssertion { fir.classId.shortClassName } override val name: Name get() = firRef.withFir { it.symbol.classId.shortClassName }
override val classId: ClassId get() = withValidityAssertion { fir.classId } override val classId: ClassId get() = firRef.withFir { it.symbol.classId }
override val modality: KtSymbolModality override val modality: KtSymbolModality
get() = withValidityAssertion { fir.modality.getSymbolModality() } get() = firRef.withFir { it.modality.getSymbolModality() }
override val typeParameters by cached { override val typeParameters by firRef.withFirAndCache {
fir.typeParameters.map { typeParameter -> fir.typeParameters.map { typeParameter ->
builder.buildTypeParameterSymbol(typeParameter.symbol.fir) builder.buildTypeParameterSymbol(typeParameter.symbol.fir)
} }
} }
override val classKind: KtClassKind override val classKind: KtClassKind
get() = withValidityAssertion { get() = firRef.withFir { fir ->
when (fir.classKind) { when (fir.classKind) {
ClassKind.INTERFACE -> KtClassKind.INTERFACE ClassKind.INTERFACE -> KtClassKind.INTERFACE
ClassKind.ENUM_CLASS -> KtClassKind.ENUM_CLASS ClassKind.ENUM_CLASS -> KtClassKind.ENUM_CLASS
@@ -51,7 +50,7 @@ internal class KtFirClassOrObjectSymbol(
} }
} }
override val symbolKind: KtSymbolKind override val symbolKind: KtSymbolKind
get() = withValidityAssertion { get() = firRef.withFir { fir ->
when { when {
fir.isLocal -> KtSymbolKind.LOCAL fir.isLocal -> KtSymbolKind.LOCAL
fir.symbol.classId.isNestedClass -> KtSymbolKind.MEMBER fir.symbol.classId.isNestedClass -> KtSymbolKind.MEMBER
@@ -8,15 +8,18 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.getPrimaryConstructorIfAny import org.jetbrains.kotlin.fir.declarations.getPrimaryConstructorIfAny
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
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.types.KtType import org.jetbrains.kotlin.idea.frontend.api.types.KtType
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.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.* import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
@@ -24,29 +27,30 @@ import org.jetbrains.kotlin.name.ClassId
internal class KtFirConstructorSymbol( internal class KtFirConstructorSymbol(
fir: FirConstructor, fir: FirConstructor,
resolveState: FirModuleResolveState,
override val token: ValidityToken, override val token: ValidityToken,
private val builder: KtSymbolByFirBuilder private val builder: KtSymbolByFirBuilder
) : KtConstructorSymbol(), KtFirSymbol<FirConstructor> { ) : KtConstructorSymbol(), KtFirSymbol<FirConstructor> {
override val fir: FirConstructor by weakRef(fir) override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) } override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) } override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { builder.buildKtType(it.returnTypeRef) }
override val valueParameters: List<KtConstructorParameterSymbol> by cached { override val valueParameters: List<KtConstructorParameterSymbol> by firRef.withFirAndCache { fir ->
fir.valueParameters.map { valueParameter -> fir.valueParameters.map { valueParameter ->
check(valueParameter is FirValueParameterImpl) check(valueParameter is FirValueParameterImpl)
builder.buildFirConstructorParameter(valueParameter) builder.buildFirConstructorParameter(valueParameter)
} }
} }
override val isPrimary: Boolean get() = withValidityAssertion { fir.isPrimary } override val isPrimary: Boolean get() = firRef.withFir { it.isPrimary }
override val symbolKind: KtSymbolKind get() = KtSymbolKind.MEMBER override val symbolKind: KtSymbolKind get() = KtSymbolKind.MEMBER
override val ownerClassId: ClassId override val ownerClassId: ClassId
get() = withValidityAssertion { get() = firRef.withFir {
fir.symbol.callableId.classId ?: error("ClassID should present for constructor") it.symbol.callableId.classId ?: error("ClassID should present for constructor")
} }
override val owner: KtClassOrObjectSymbol by cached { override val owner: KtClassOrObjectSymbol by firRef.withFirAndCache { fir ->
val session = fir.session val session = fir.session
val classId = ownerClassId val classId = ownerClassId
val firClass = session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.fir val firClass = session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.fir
@@ -64,7 +68,8 @@ internal class KtFirConstructorSymbol(
return symbolPointer { session -> return symbolPointer { session ->
val ownerSymbol = session.symbolProvider.getClassOrObjectSymbolByClassId(ownerClassId) ?: return@symbolPointer null val ownerSymbol = session.symbolProvider.getClassOrObjectSymbolByClassId(ownerClassId) ?: return@symbolPointer null
check(ownerSymbol is KtFirSymbol<*>) check(ownerSymbol is KtFirSymbol<*>)
val classFir = (ownerSymbol.fir as? FirRegularClass) ?: error("FirRegularClass expected but ${ownerSymbol.fir::class} found") val classFir = ownerSymbol.firRef.withFir { (it as? FirRegularClass) }
?: error("FirRegularClass expected")
classFir.getPrimaryConstructorIfAny()?.let(builder::buildConstructorSymbol) classFir.getPrimaryConstructorIfAny()?.let(builder::buildConstructorSymbol)
} }
} }
@@ -8,9 +8,11 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
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.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorParameterSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorParameterSymbolKind import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorParameterSymbolKind
@@ -21,23 +23,24 @@ import org.jetbrains.kotlin.name.Name
internal class KtFirConstructorValueParameterSymbol( internal class KtFirConstructorValueParameterSymbol(
fir: FirValueParameterImpl, fir: FirValueParameterImpl,
resolveState: FirModuleResolveState,
override val token: ValidityToken, override val token: ValidityToken,
private val builder: KtSymbolByFirBuilder private val builder: KtSymbolByFirBuilder
) : KtConstructorParameterSymbol(), KtFirSymbol<FirValueParameterImpl> { ) : KtConstructorParameterSymbol(), KtFirSymbol<FirValueParameterImpl> {
override val fir: FirValueParameterImpl by weakRef(fir) override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) } override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) }
override val name: Name get() = withValidityAssertion { fir.name } override val name: Name get() = firRef.withFir { it.name }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) } override val type: KtType by firRef.withFirAndCache { builder.buildKtType(it.returnTypeRef) }
override val symbolKind: KtSymbolKind override val symbolKind: KtSymbolKind
get() = withValidityAssertion { get() = firRef.withFir { fir ->
when { when {
fir.isVal || fir.isVal -> KtSymbolKind.MEMBER fir.isVal || fir.isVal -> KtSymbolKind.MEMBER
else -> KtSymbolKind.LOCAL else -> KtSymbolKind.LOCAL
} }
} }
override val constructorParameterKind: KtConstructorParameterSymbolKind override val constructorParameterKind: KtConstructorParameterSymbolKind
get() = withValidityAssertion { get() = firRef.withFir { fir ->
when { when {
fir.isVal -> KtConstructorParameterSymbolKind.VAL_PROPERTY fir.isVal -> KtConstructorParameterSymbolKind.VAL_PROPERTY
fir.isVar -> KtConstructorParameterSymbolKind.VAR_PROPERTY fir.isVar -> KtConstructorParameterSymbolKind.VAR_PROPERTY
@@ -7,12 +7,15 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
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.types.KtType import org.jetbrains.kotlin.idea.frontend.api.types.KtType
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.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtEnumEntrySymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtEnumEntrySymbol
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
@@ -20,12 +23,13 @@ import org.jetbrains.kotlin.name.Name
internal class KtFirEnumEntrySymbol( internal class KtFirEnumEntrySymbol(
fir: FirEnumEntry, fir: FirEnumEntry,
resolveState: FirModuleResolveState,
override val token: ValidityToken, override val token: ValidityToken,
private val builder: KtSymbolByFirBuilder private val builder: KtSymbolByFirBuilder
) : KtEnumEntrySymbol(), KtFirSymbol<FirEnumEntry> { ) : KtEnumEntrySymbol(), KtFirSymbol<FirEnumEntry> {
override val fir: FirEnumEntry by weakRef(fir) override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) } override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) }
override val name: Name get() = withValidityAssertion { fir.name } override val name: Name get() = firRef.withFir { it.name }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) } override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) }
} }
@@ -9,11 +9,13 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
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.types.KtType import org.jetbrains.kotlin.idea.frontend.api.types.KtType
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.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCommonSymbolModality import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCommonSymbolModality
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
@@ -25,38 +27,40 @@ import org.jetbrains.kotlin.name.Name
internal class KtFirFunctionSymbol( internal class KtFirFunctionSymbol(
fir: FirSimpleFunction, fir: FirSimpleFunction,
resolveState: FirModuleResolveState,
override val token: ValidityToken, override val token: ValidityToken,
private val builder: KtSymbolByFirBuilder, private val builder: KtSymbolByFirBuilder,
private val forcedOrigin: FirDeclarationOrigin? = null private val forcedOrigin: FirDeclarationOrigin? = null
) : KtFunctionSymbol(), KtFirSymbol<FirSimpleFunction> { ) : KtFunctionSymbol(), KtFirSymbol<FirSimpleFunction> {
override val fir: FirSimpleFunction by weakRef(fir) override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) } override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) }
override val name: Name get() = withValidityAssertion { fir.name } override val name: Name get() = firRef.withFir { it.name }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) } override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) }
override val valueParameters: List<KtFirFunctionValueParameterSymbol> by cached { override val valueParameters: List<KtFirFunctionValueParameterSymbol> by firRef.withFirAndCache { fir ->
fir.valueParameters.map { valueParameter -> fir.valueParameters.map { valueParameter ->
check(valueParameter is FirValueParameterImpl) check(valueParameter is FirValueParameterImpl)
builder.buildParameterSymbol(valueParameter) builder.buildParameterSymbol(valueParameter)
} }
} }
override val typeParameters by cached { override val typeParameters by firRef.withFirAndCache { fir ->
fir.typeParameters.map { typeParameter -> fir.typeParameters.map { typeParameter ->
builder.buildTypeParameterSymbol(typeParameter.symbol.fir) builder.buildTypeParameterSymbol(typeParameter.symbol.fir)
} }
} }
override val origin: KtSymbolOrigin get() = withValidityAssertion { forcedOrigin?.asKtSymbolOrigin() ?: super.origin } override val origin: KtSymbolOrigin get() = withValidityAssertion { forcedOrigin?.asKtSymbolOrigin() ?: super.origin }
override val isSuspend: Boolean get() = withValidityAssertion { fir.isSuspend } override val isSuspend: Boolean get() = firRef.withFir { it.isSuspend }
override val receiverType: KtType? by cached { fir.receiverTypeRef?.let(builder::buildKtType) } override val receiverType: KtType? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir -> fir.receiverTypeRef?.let(builder::buildKtType) }
override val isOperator: Boolean get() = withValidityAssertion { fir.isOperator } override val isOperator: Boolean get() = firRef.withFir { it.isOperator }
override val isExtension: Boolean get() = withValidityAssertion { fir.receiverTypeRef != null } override val isExtension: Boolean get() = firRef.withFir { it.receiverTypeRef != null }
override val fqName: FqName? get() = withValidityAssertion { fir.symbol.callableId.asFqNameForDebugInfo() } override val fqName: FqName? get() = firRef.withFir { it.symbol.callableId.asFqNameForDebugInfo() }
override val symbolKind: KtSymbolKind override val symbolKind: KtSymbolKind
get() = withValidityAssertion { get() = firRef.withFir { fir ->
when { when {
fir.isLocal -> KtSymbolKind.LOCAL fir.isLocal -> KtSymbolKind.LOCAL
fir.symbol.callableId.classId == null -> KtSymbolKind.TOP_LEVEL fir.symbol.callableId.classId == null -> KtSymbolKind.TOP_LEVEL
else -> KtSymbolKind.MEMBER else -> KtSymbolKind.MEMBER
} }
} }
override val modality: KtCommonSymbolModality get() = withValidityAssertion { fir.modality.getSymbolModality() } override val modality: KtCommonSymbolModality get() = firRef.withFir { it.modality.getSymbolModality() }
} }
@@ -6,11 +6,14 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.symbols package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
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.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionParameterSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind
@@ -20,15 +23,16 @@ import org.jetbrains.kotlin.name.Name
internal class KtFirFunctionValueParameterSymbol( internal class KtFirFunctionValueParameterSymbol(
fir: FirValueParameterImpl, fir: FirValueParameterImpl,
resolveState: FirModuleResolveState,
override val token: ValidityToken, override val token: ValidityToken,
private val builder: KtSymbolByFirBuilder private val builder: KtSymbolByFirBuilder
) : KtFunctionParameterSymbol(), KtFirSymbol<FirValueParameterImpl> { ) : KtFunctionParameterSymbol(), KtFirSymbol<FirValueParameterImpl> {
override val fir: FirValueParameterImpl by weakRef(fir) override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) } override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) }
override val name: Name get() = withValidityAssertion { fir.name } override val name: Name get() = firRef.withFir { it.name }
override val isVararg: Boolean get() = withValidityAssertion { fir.isVararg } override val isVararg: Boolean get() = firRef.withFir { it.isVararg }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) } override val type: KtType by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir -> builder.buildKtType(fir.returnTypeRef) }
override val symbolKind: KtSymbolKind get() = KtSymbolKind.LOCAL override val symbolKind: KtSymbolKind get() = KtSymbolKind.LOCAL
override val hasDefaultValue: Boolean get() = withValidityAssertion { fir.defaultValue != null } override val hasDefaultValue: Boolean get() = withValidityAssertion { fir.defaultValue != null }
} }
@@ -7,13 +7,16 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirField import org.jetbrains.kotlin.fir.declarations.FirField
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.modality import org.jetbrains.kotlin.fir.declarations.modality
import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
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.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCommonSymbolModality import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCommonSymbolModality
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtJavaFieldSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtJavaFieldSymbol
@@ -22,15 +25,16 @@ import org.jetbrains.kotlin.name.Name
internal class KtFirJavaFieldSymbol( internal class KtFirJavaFieldSymbol(
fir: FirField, fir: FirField,
resolveState: FirModuleResolveState,
override val token: ValidityToken, override val token: ValidityToken,
private val builder: KtSymbolByFirBuilder private val builder: KtSymbolByFirBuilder
) : KtJavaFieldSymbol(), KtFirSymbol<FirField> { ) : KtJavaFieldSymbol(), KtFirSymbol<FirField> {
override val fir: FirField by weakRef(fir) override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) } override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) } override val type: KtType by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir -> builder.buildKtType(fir.returnTypeRef) }
override val isVal: Boolean get() = withValidityAssertion { fir.isVal } override val isVal: Boolean get() = firRef.withFir { it.isVal }
override val name: Name get() = withValidityAssertion { fir.name } override val name: Name get() = firRef.withFir { it.name }
override val modality: KtCommonSymbolModality get() = withValidityAssertion { fir.modality.getSymbolModality() } override val modality: KtCommonSymbolModality get() = firRef.withFir { it.modality.getSymbolModality() }
} }
@@ -7,12 +7,15 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
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.types.KtType import org.jetbrains.kotlin.idea.frontend.api.types.KtType
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.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtLocalVariableSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtLocalVariableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind
@@ -21,6 +24,7 @@ import org.jetbrains.kotlin.name.Name
internal class KtFirLocalVariableSymbol( internal class KtFirLocalVariableSymbol(
fir: FirProperty, fir: FirProperty,
resolveState: FirModuleResolveState,
override val token: ValidityToken, override val token: ValidityToken,
private val builder: KtSymbolByFirBuilder private val builder: KtSymbolByFirBuilder
) : KtLocalVariableSymbol(), ) : KtLocalVariableSymbol(),
@@ -29,11 +33,11 @@ internal class KtFirLocalVariableSymbol(
assert(fir.isLocal) assert(fir.isLocal)
} }
override val fir: FirProperty by weakRef(fir) override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) } override val psi: PsiElement? by cached { fir.findPsi(fir.session) }
override val isVal: Boolean get() = withValidityAssertion { fir.isVal } override val isVal: Boolean get() = firRef.withFir { it.isVal }
override val name: Name get() = withValidityAssertion { fir.name } override val name: Name get() = firRef.withFir { it.name }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) } override val type: KtType by firRef.withFirAndCache(FirResolvePhase.BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) }
override val symbolKind: KtSymbolKind get() = KtSymbolKind.LOCAL override val symbolKind: KtSymbolKind get() = KtSymbolKind.LOCAL
} }
@@ -8,13 +8,16 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.modality import org.jetbrains.kotlin.fir.declarations.modality
import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
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.types.KtType import org.jetbrains.kotlin.idea.frontend.api.types.KtType
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.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCommonSymbolModality import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCommonSymbolModality
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
@@ -26,6 +29,7 @@ import org.jetbrains.kotlin.name.Name
internal class KtFirPropertySymbol( internal class KtFirPropertySymbol(
fir: FirProperty, fir: FirProperty,
resolveState: FirModuleResolveState,
override val token: ValidityToken, override val token: ValidityToken,
private val builder: KtSymbolByFirBuilder, private val builder: KtSymbolByFirBuilder,
private val forcedOrigin: FirDeclarationOrigin? private val forcedOrigin: FirDeclarationOrigin?
@@ -34,23 +38,23 @@ internal class KtFirPropertySymbol(
assert(!fir.isLocal) assert(!fir.isLocal)
} }
override val fir: FirProperty by weakRef(fir) override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) } override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) }
override val origin: KtSymbolOrigin get() = withValidityAssertion { forcedOrigin?.asKtSymbolOrigin() ?: super.origin } override val origin: KtSymbolOrigin get() = withValidityAssertion { forcedOrigin?.asKtSymbolOrigin() ?: super.origin }
override val fqName: FqName get() = withValidityAssertion { fir.symbol.callableId.asFqNameForDebugInfo() } override val fqName: FqName get() = firRef.withFir { it.symbol.callableId.asFqNameForDebugInfo() }
override val isVal: Boolean get() = withValidityAssertion { fir.isVal } override val isVal: Boolean get() = firRef.withFir { it.isVal }
override val name: Name get() = withValidityAssertion { fir.name } override val name: Name get() = firRef.withFir { it.name }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) } override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) }
override val receiverType: KtType? by cached { builder.buildKtType(fir.returnTypeRef) } override val receiverType: KtType? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir -> builder.buildKtType(fir.returnTypeRef) }
override val isExtension: Boolean get() = withValidityAssertion { fir.receiverTypeRef != null } override val isExtension: Boolean get() = firRef.withFir { it.receiverTypeRef != null }
override val symbolKind: KtSymbolKind override val symbolKind: KtSymbolKind
get() = withValidityAssertion { get() = firRef.withFir { fir ->
when (fir.symbol.callableId.classId) { when (fir.symbol.callableId.classId) {
null -> KtSymbolKind.TOP_LEVEL null -> KtSymbolKind.TOP_LEVEL
else -> KtSymbolKind.MEMBER else -> KtSymbolKind.MEMBER
} }
} }
override val modality: KtCommonSymbolModality get() = withValidityAssertion { fir.modality.getSymbolModality() } override val modality: KtCommonSymbolModality get() = firRef.withFir { it.modality.getSymbolModality() }
} }
@@ -7,14 +7,17 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.FirRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
internal interface KtFirSymbol<F : FirDeclaration> : KtSymbol, ValidityTokenOwner { internal interface KtFirSymbol<F : FirDeclaration> : KtSymbol, ValidityTokenOwner {
val fir: F val firRef: FirRef<F>
override val origin: KtSymbolOrigin get() = withValidityAssertion { fir.origin.asKtSymbolOrigin() }
override val origin: KtSymbolOrigin get() = firRef.withFir { it.origin.asKtSymbolOrigin() }
} }
internal fun FirDeclarationOrigin.asKtSymbolOrigin() = when (this) { internal fun FirDeclarationOrigin.asKtSymbolOrigin() = when (this) {
@@ -8,10 +8,12 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
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.utils.ReadOnlyWeakRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.ReadOnlyWeakRef
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeAliasSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeAliasSymbol
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
@@ -20,10 +22,11 @@ import org.jetbrains.kotlin.name.Name
internal class KtFirTypeAliasSymbol( internal class KtFirTypeAliasSymbol(
fir: FirTypeAlias, fir: FirTypeAlias,
resolveState: FirModuleResolveState,
override val token: ValidityToken override val token: ValidityToken
) : KtTypeAliasSymbol(), KtFirSymbol<FirTypeAlias> { ) : KtTypeAliasSymbol(), KtFirSymbol<FirTypeAlias> {
override val fir: FirTypeAlias by weakRef(fir) override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) } override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) }
override val name: Name get() = withValidityAssertion { fir.name } override val name: Name get() = firRef.withFir { it.name }
override val classId: ClassId get() = withValidityAssertion { fir.symbol.classId } override val classId: ClassId get() = firRef.withFir { it.symbol.classId }
} }
@@ -8,9 +8,11 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
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.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
@@ -18,10 +20,11 @@ import org.jetbrains.kotlin.name.Name
internal class KtFirTypeParameterSymbol( internal class KtFirTypeParameterSymbol(
fir: FirTypeParameter, fir: FirTypeParameter,
resolveState: FirModuleResolveState,
override val token: ValidityToken override val token: ValidityToken
) : KtTypeParameterSymbol(), KtFirSymbol<FirTypeParameter> { ) : KtTypeParameterSymbol(), KtFirSymbol<FirTypeParameter> {
override val fir: FirTypeParameter by weakRef(fir) override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) } override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) }
override val name: Name get() = withValidityAssertion { fir.name } override val name: Name get() = firRef.withFir { it.name }
} }
@@ -0,0 +1,36 @@
/*
* 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.idea.frontend.api.fir.utils
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
import org.jetbrains.kotlin.idea.frontend.api.assertIsValid
import java.lang.ref.WeakReference
internal class FirRef<D : FirDeclaration>(fir: D, resolveState: FirModuleResolveState, val token: ValidityToken) {
private val firWeakRef = WeakReference(fir)
private val resolveStateWeakRef = WeakReference(resolveState)
inline fun <R> withFir(phase: FirResolvePhase = FirResolvePhase.RAW_FIR, action: (fir: D) -> R): R {
token.assertIsValid()
val fir = firWeakRef.get() ?: error("FirElement was garbage collected while analysis session is still valid")
val resolveState =
resolveStateWeakRef.get() ?: error("FirModuleResolveState was garbage collected while analysis session is still valid")
return action(resolveState.resolvedFirToPhase(fir, phase))
}
inline fun <R> withFirAndCache(phase: FirResolvePhase = FirResolvePhase.RAW_FIR, crossinline createValue: (fir: D) -> R) =
ValidityAwareCachedValue(token) {
withFir(phase) { fir -> createValue(fir) }
}
}
@Suppress("NOTHING_TO_INLINE")
internal inline fun <D : FirDeclaration> ValidityTokenOwner.firRef(fir: D, resolveState: FirModuleResolveState) =
FirRef(fir, resolveState, token)
@@ -8,8 +8,7 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.utils
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
@Suppress("EXPERIMENTAL_FEATURE_WARNING") internal class ThreadLocalValue<V>(private val threadLocal: ThreadLocal<V>) {
internal inline class ThreadLocalValue<V>(private val threadLocal: ThreadLocal<V>) {
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
inline operator fun getValue(thisRef: Any?, property: KProperty<*>): V = threadLocal.get() inline operator fun getValue(thisRef: Any?, property: KProperty<*>): V = threadLocal.get()
} }