From 9092b337557555d7b9c4b60f6ad4d80eb837fab9 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Mon, 6 Jul 2020 18:38:13 +0300 Subject: [PATCH] FIR IDE: Introduce module resolve state for completion --- .../level/api/FirIdeResolveStateService.kt | 8 ++--- .../low/level/api/FirModuleResolveState.kt | 26 ++++++++++++++-- .../api/FirModuleResolveStateForCompletion.kt | 31 +++++++++++++++++++ .../fir/low/level/api/FirResolutionApi.kt | 5 ++- .../fir/low/level/api/LowLevelFirApiFacade.kt | 4 +++ 5 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateForCompletion.kt diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt index ee97c055a10..d544f557466 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt @@ -19,10 +19,10 @@ internal interface FirIdeResolveStateService { val fallbackModificationTracker: ModificationTracker? - fun getResolveState(moduleInfo: IdeaModuleInfo): FirModuleResolveState + fun getResolveState(moduleInfo: IdeaModuleInfo): FirModuleResolveStateImpl } -private class FirModuleData(val state: FirModuleResolveState, val modificationTracker: ModificationTracker?) { +private class FirModuleData(val state: FirModuleResolveStateImpl, val modificationTracker: ModificationTracker?) { val modificationCount: Long = modificationTracker?.modificationCount ?: Long.MIN_VALUE fun isOutOfDate(): Boolean { @@ -34,7 +34,7 @@ private class FirModuleData(val state: FirModuleResolveState, val modificationTr internal class FirIdeResolveStateServiceImpl(val project: Project) : FirIdeResolveStateService { private val stateCache = mutableMapOf() - private fun createResolveState(): FirModuleResolveState { + private fun createResolveState(): FirModuleResolveStateImpl { val provider = FirProjectSessionProvider(project) return FirModuleResolveStateImpl(provider) } @@ -47,7 +47,7 @@ internal class FirIdeResolveStateServiceImpl(val project: Project) : FirIdeResol } // TODO: multi thread protection - override fun getResolveState(moduleInfo: IdeaModuleInfo): FirModuleResolveState { + override fun getResolveState(moduleInfo: IdeaModuleInfo): FirModuleResolveStateImpl { var moduleData = stateCache.getOrPut(moduleInfo) { createModuleData() } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveState.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveState.kt index 63fe005029f..3933bb2af89 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveState.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveState.kt @@ -60,7 +60,7 @@ abstract class FirModuleResolveState { } } - internal abstract operator fun get(psi: KtElement): FirElement? + internal abstract fun getCachedMapping(psi: KtElement): FirElement? internal abstract fun getDiagnostics(psi: KtElement): List @@ -73,14 +73,34 @@ abstract class FirModuleResolveState { internal abstract fun setDiagnosticsForFile(file: KtFile, fir: FirFile, diagnostics: Iterable> = emptyList()) } -internal class FirModuleResolveStateImpl(override val sessionProvider: FirProjectSessionProvider) : FirModuleResolveState() { +internal abstract class PsiToFirCache { + abstract operator fun get(psi: KtElement): FirElement? + abstract operator fun set(psi: KtElement, fir: FirElement) + abstract fun remove(psi: PsiElement) +} + +internal class PsiToFirCacheImpl : PsiToFirCache() { private val cache = mutableMapOf() + override fun get(psi: KtElement): FirElement? = cache[psi] + + override fun set(psi: KtElement, fir: FirElement) { + cache[psi] = fir + } + + override fun remove(psi: PsiElement) { + cache.remove(psi) + } +} + +open class FirModuleResolveStateImpl(override val sessionProvider: FirProjectSessionProvider) : FirModuleResolveState() { + internal open val cache: PsiToFirCache = PsiToFirCacheImpl() + private val diagnosticCache = mutableMapOf>() private val diagnosedFiles = mutableMapOf() - override fun get(psi: KtElement): FirElement? = cache[psi] + override fun getCachedMapping(psi: KtElement): FirElement? = cache[psi] override fun getDiagnostics(psi: KtElement): List { return diagnosticCache[psi] ?: emptyList() diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateForCompletion.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateForCompletion.kt new file mode 100644 index 00000000000..3ef9506bc6a --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateForCompletion.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.fir.low.level.api + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.psi.KtElement + +class FirModuleResolveStateForCompletion( + mainState: FirModuleResolveStateImpl +) : FirModuleResolveStateImpl(mainState.sessionProvider) { + override val cache: PsiToFirCache = PsiToFirCacheForCompletion(mainState.cache) +} + +private class PsiToFirCacheForCompletion(private val delegate: PsiToFirCache) : PsiToFirCache() { + private val cache = mutableMapOf() + + override fun get(psi: KtElement): FirElement? = + cache[psi] ?: delegate[psi] + + override fun set(psi: KtElement, fir: FirElement) { + cache[psi] = fir + } + + override fun remove(psi: PsiElement) { + cache.remove(psi) + } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirResolutionApi.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirResolutionApi.kt index 025ba546d16..9a4fb840286 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirResolutionApi.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirResolutionApi.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.types.FirErrorTypeRef -import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirUserTypeRef import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid @@ -255,7 +254,7 @@ internal fun KtElement.getOrBuildFir( is KtPropertyDelegate -> this.expression ?: this else -> this } - return state[this] ?: run { + return state.getCachedMapping(this) ?: run { containerFir.accept(object : FirVisitorVoid() { override fun visitElement(element: FirElement) { (element.realPsi as? KtElement)?.let { @@ -288,7 +287,7 @@ internal fun KtElement.getOrBuildFir( }) var current: PsiElement? = psi while (current is KtElement) { - val mappedFir = state[current] + val mappedFir = state.getCachedMapping(current) if (mappedFir != null) { if (current != this) { state.record(current, mappedFir) diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/LowLevelFirApiFacade.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/LowLevelFirApiFacade.kt index 0fd2d9ef2f4..6158f4e009f 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/LowLevelFirApiFacade.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/LowLevelFirApiFacade.kt @@ -15,6 +15,10 @@ object LowLevelFirApiFacade { fun getResolveStateFor(element: KtElement): FirModuleResolveState = element.firResolveState() + fun getResolveStateForCompletion(element: KtElement, mainState: FirModuleResolveStateImpl): FirModuleResolveStateForCompletion { + return FirModuleResolveStateForCompletion(mainState) + } + fun getSessionFor(element: KtElement, resolveState: FirModuleResolveState): FirSession = resolveState.getSession(element)