From e73a57388546b86fa8cb01d833fecdd0decc5808 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Fri, 3 Apr 2020 22:02:10 +0200 Subject: [PATCH] Fetch analysis results if it is available The general idea is to try to fetch a full analysis if it is existed in PerFileAnalysisCache instead of go to ResolveElementCache and do analysis there. Do not perform analysis if it is not in PerFileAnalysisCache. #KT-37467 Fixed --- .../resolve/ModuleResolutionFacadeImpl.kt | 9 +++++- .../caches/resolve/ProjectResolutionFacade.kt | 31 +++++++++++++++---- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleResolutionFacadeImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleResolutionFacadeImpl.kt index c92227486ae..173804cac57 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleResolutionFacadeImpl.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleResolutionFacadeImpl.kt @@ -57,7 +57,14 @@ internal class ModuleResolutionFacadeImpl( override fun analyze(elements: Collection, bodyResolveMode: BodyResolveMode): BindingContext { ResolveInDispatchThreadManager.assertNoResolveInDispatchThread() - if (elements.isEmpty()) return BindingContext.EMPTY + when (elements.size) { + 0 -> return BindingContext.EMPTY + 1 -> { + runWithCancellationCheck { + projectFacade.fetchAnalysisResultsForElement(elements.first())?.bindingContext + }?.let { return it } + } + } val resolveElementCache = getFrontendService(elements.first(), ResolveElementCache::class.java) return runWithCancellationCheck { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt index f342e967a2d..09e936c7b88 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.CompositeBindingContext import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult +import java.util.concurrent.locks.ReentrantLock internal class ProjectResolutionFacade( private val debugString: String, @@ -50,12 +51,34 @@ internal class ProjectResolutionFacade( { val resolverForProject = cachedResolverForProject val results = object : SLRUCache(2, 3) { + private val lock = ReentrantLock() + override fun createValue(file: KtFile): PerFileAnalysisCache { return PerFileAnalysisCache( file, resolverForProject.resolverForModule(file.getModuleInfo()).componentProvider ) } + + override fun get(key: KtFile?): PerFileAnalysisCache { + lock.lock() + try { + return super.get(key) + } finally { + lock.unlock() + } + } + + override fun getIfCached(key: KtFile?): PerFileAnalysisCache? { + if (lock.tryLock()) { + try { + return super.getIfCached(key) + } finally { + lock.unlock() + } + } + return null + } } val allDependencies = resolverForProjectDependencies + listOf( @@ -121,9 +144,7 @@ internal class ProjectResolutionFacade( analysisResults.value!! } val results = elements.map { - val perFileCache = synchronized(slruCache) { - slruCache[it.containingKtFile] - } + val perFileCache = slruCache[it.containingKtFile] perFileCache.getAnalysisResults(it) } val withError = results.firstOrNull { it.isError() } @@ -140,9 +161,7 @@ internal class ProjectResolutionFacade( val slruCache = synchronized(analysisResults) { analysisResults.upToDateOrNull?.get() ?: return null } - val perFileCache = synchronized(slruCache) { - slruCache.getIfCached(element.containingKtFile) - } + val perFileCache = slruCache.getIfCached(element.containingKtFile) return perFileCache?.fetchAnalysisResults(element) }