diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt index 5c96d5f1a90..04aa72a4133 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt @@ -31,5 +31,5 @@ abstract class KtAnalysisSession(override val token: ValidityToken) : ValidityTo abstract fun resolveCall(call: KtCallExpression): CallInfo? abstract fun resolveCall(call: KtBinaryExpression): CallInfo? - abstract fun analyzeInContext(): KtAnalysisSession + abstract fun createContextDependentCopy(): KtAnalysisSession } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirCompletionContributor.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirCompletionContributor.kt index 61628a43eeb..be4bf4491d0 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirCompletionContributor.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirCompletionContributor.kt @@ -34,7 +34,7 @@ private object KotlinHighLevelApiContributor : CompletionProvider, + private val typesCache: BuilderCache +) : ValidityTokenOwner { + + constructor( + firProvider: FirSymbolProvider, + typeCheckerContext: ConeTypeCheckerContext, + project: Project, + token: ValidityToken + ) : this( + firProvider = firProvider, + typeCheckerContext = typeCheckerContext, + project = project, + token = token, + withReadOnlyCaching = false, + symbolsCache = BuilderCache(), + typesCache = BuilderCache() + ) + private val firProvider by weakRef(firProvider) private val typeCheckerContext by weakRef(typeCheckerContext) - private val symbolsCache = BuilderCache() - private val typesCache = BuilderCache() + fun createReadOnlyCopy(): KtSymbolByFirBuilder { + check(!withReadOnlyCaching) { "Cannot create readOnly KtSymbolByFirBuilder from a readonly one" } + return KtSymbolByFirBuilder( + firProvider, + typeCheckerContext, + project, + token, + withReadOnlyCaching = true, + symbolsCache.createReadOnlyCopy(), + typesCache.createReadOnlyCopy() + ) + } + fun buildSymbol(fir: FirDeclaration): KtSymbol = symbolsCache.cache(fir) { when (fir) { @@ -153,11 +184,23 @@ internal class KtSymbolByFirBuilder( } } -private class BuilderCache { - private val cache = MapMaker().weakKeys().makeMap() +private class BuilderCache private constructor( + private val cache: ConcurrentMap, + private val isReadOnly: Boolean +) { + constructor() : this(cache = MapMaker().weakKeys().makeMap(), isReadOnly = false) - inline fun cache(key: From, calculation: () -> S): S = - cache.getOrPut(key, calculation) as S + fun createReadOnlyCopy(): BuilderCache { + check(!isReadOnly) { "Cannot create readOnly BuilderCache from a readonly one" } + return BuilderCache(cache, isReadOnly = true) + } + + inline fun cache(key: From, calculation: () -> S): S { + if (isReadOnly) { + return (cache[key] ?: calculation()) as S + } + return cache.getOrPut(key, calculation) as S + } } internal fun FirElement.buildSymbol(builder: KtSymbolByFirBuilder) = diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirDelegatingScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirDelegatingScope.kt index a2b33fbc481..1925f0314c7 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirDelegatingScope.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirDelegatingScope.kt @@ -27,12 +27,14 @@ import org.jetbrains.kotlin.name.Name internal abstract class KtFirDelegatingScope( private val builder: KtSymbolByFirBuilder, - override val token: ValidityToken -) : KtScope, ValidityTokenOwner { + final override val token: ValidityToken +) : KtScope { abstract val firScope: FirScope - private val allNamesCached by cached { getCallableNames() + getClassLikeSymbolNames() } + private val allNamesCached by cached(token) { + getCallableNames() + getClassLikeSymbolNames() + } override fun getAllNames(): Set = allNamesCached diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirNonStarImportingScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirNonStarImportingScope.kt index 0dccdb6538f..e3ac3113f8b 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirNonStarImportingScope.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirNonStarImportingScope.kt @@ -19,7 +19,7 @@ import org.jetbrains.kotlin.name.Name internal class KtFirNonStarImportingScope( firScope: FirAbstractSimpleImportingScope, builder: KtSymbolByFirBuilder, - override val token: ValidityToken + token: ValidityToken ) : KtFirDelegatingScope(builder, token), KtNonStarImportingScope, ValidityTokenOwner { override val firScope: FirAbstractSimpleImportingScope = firScope