From a128eacf53d4fd15c738ed708242444f10558380 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 30 Apr 2014 14:16:45 +0400 Subject: [PATCH] KotlinCacheService extracted to a separate file --- .../caches/resolve/KotlinCacheService.kt | 157 ++++++++++++++++++ .../caches/resolve/KotlinResolveCache.kt | 135 +-------------- 2 files changed, 160 insertions(+), 132 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheService.kt diff --git a/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheService.kt b/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheService.kt new file mode 100644 index 00000000000..bfcb8d3e011 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheService.kt @@ -0,0 +1,157 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.caches.resolve + +import org.jetbrains.jet.lang.psi.JetElement +import org.jetbrains.jet.lang.psi.JetFile +import com.intellij.openapi.project.Project +import org.jetbrains.jet.analyzer.AnalyzeExhaust +import com.intellij.openapi.diagnostic.Logger +import com.intellij.util.containers.SLRUCache +import com.intellij.psi.util.PsiModificationTracker +import com.intellij.psi.util.CachedValueProvider +import org.jetbrains.jet.lang.resolve.BindingContext +import com.intellij.openapi.components.ServiceManager +import org.jetbrains.jet.lang.resolve.java.JetFilesProvider +import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.jet.plugin.project.AnalyzerFacadeProvider +import org.jetbrains.jet.plugin.project.TargetPlatform +import org.jetbrains.jet.plugin.project.TargetPlatform.* +import org.jetbrains.jet.plugin.project.ResolveSessionForBodies +import org.jetbrains.jet.plugin.project.TargetPlatformDetector +import java.util.HashSet +import org.jetbrains.jet.analyzer.AnalyzerFacade +import org.jetbrains.jet.lang.psi.JetCodeFragmentImpl + +private val LOG = Logger.getInstance(javaClass()) + +fun JetElement.getLazyResolveSession(): ResolveSessionForBodies { + return KotlinCacheService.getInstance(getProject()).getLazyResolveSession(this) +} + +fun Project.getLazyResolveSession(platform: TargetPlatform): ResolveSessionForBodies { + return KotlinCacheService.getInstance(this).getGlobalLazyResolveSession(platform) +} + +fun JetElement.getAnalysisResults(): AnalyzeExhaust { + return KotlinCacheService.getInstance(getProject()).getAnalysisResults(listOf(this)) +} + +fun JetElement.getBindingContext(): BindingContext { + return getAnalysisResults().getBindingContext() +} + +fun getAnalysisResultsForElements(elements: Collection): AnalyzeExhaust { + if (elements.isEmpty()) return AnalyzeExhaust.EMPTY + val element = elements.first() + return KotlinCacheService.getInstance(element.getProject()).getAnalysisResults(elements) +} + +class KotlinCacheService(val project: Project) { + class object { + fun getInstance(project: Project) = ServiceManager.getService(project, javaClass())!! + } + + private fun globalResolveSessionProvider(platform: TargetPlatform, syntheticFile: JetFile? = null) = { + val allFiles = JetFilesProvider.getInstance(project).allInScope(GlobalSearchScope.allScope(project)) + + val files = if (syntheticFile == null) allFiles else collectFilesForSyntheticFile(allFiles, syntheticFile) + val setup = AnalyzerFacadeProvider.getAnalyzerFacade(platform).createSetup(project, files) + val resolveSessionForBodies = ResolveSessionForBodies(project, setup.getLazyResolveSession()) + CachedValueProvider.Result.create( + SessionAndSetup( + platform, + resolveSessionForBodies, + setup + ), + PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, + resolveSessionForBodies + ) + } + + private fun collectFilesForSyntheticFile(allFiles: Collection, syntheticFile: JetFile): Collection { + val files = HashSet(allFiles) + + // Add requested file to the list of files for searching declarations + files.add(syntheticFile) + + val originalFile = syntheticFile.getOriginalFile() + if (syntheticFile != originalFile) { + // Given file can be a non-physical copy of the file in list (completion case). Remove the prototype file. + files.remove(originalFile) + } + + return files + } + + private val globalCachesPerPlatform = mapOf( + JVM to KotlinResolveCache(project, globalResolveSessionProvider(JVM)), + JS to KotlinResolveCache(project, globalResolveSessionProvider(JS)) + ) + + private val syntheticFileCaches = object : SLRUCache(2, 3) { + override fun createValue(file: JetFile?): KotlinResolveCache { + return KotlinResolveCache( + project, + globalResolveSessionProvider( + TargetPlatformDetector.getPlatform(file!!), + file + ) + ) + } + } + + private fun getCacheForSyntheticFile(file: JetFile): KotlinResolveCache { + return synchronized(syntheticFileCaches) { + syntheticFileCaches[file] + } + } + + public fun getGlobalLazyResolveSession(platform: TargetPlatform): ResolveSessionForBodies { + return globalCachesPerPlatform[platform]!!.getLazyResolveSession() + } + + public fun getLazyResolveSession(element: JetElement): ResolveSessionForBodies { + val file = element.getContainingJetFile() + if (!isFileInScope(file)) { + return getCacheForSyntheticFile(file).getLazyResolveSession() + } + + return getGlobalLazyResolveSession(TargetPlatformDetector.getPlatform(file)) + } + + public fun getAnalysisResults(elements: Collection): AnalyzeExhaust { + if (elements.isEmpty()) return AnalyzeExhaust.EMPTY + + val firstFile = elements.first().getContainingJetFile() + if (elements.size == 1 && (!isFileInScope(firstFile) && firstFile !is JetCodeFragmentImpl)) { + return getCacheForSyntheticFile(firstFile).getAnalysisResultsForElements(elements) + } + + val resolveCache = globalCachesPerPlatform[TargetPlatformDetector.getPlatform(firstFile)]!! + return resolveCache.getAnalysisResultsForElements(elements) + } + + private fun isFileInScope(jetFile: JetFile): Boolean { + val project = jetFile.getProject() + return JetFilesProvider.getInstance(project).isFileInScope(jetFile, GlobalSearchScope.allScope(project)) + } + + public fun get(extension: CacheExtension): T { + return globalCachesPerPlatform[extension.platform]!![extension] + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinResolveCache.kt b/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinResolveCache.kt index 719f2203081..3f14c68994d 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinResolveCache.kt +++ b/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinResolveCache.kt @@ -22,7 +22,6 @@ import com.intellij.psi.util.PsiTreeUtil import com.intellij.openapi.project.Project import org.jetbrains.jet.analyzer.AnalyzeExhaust import com.intellij.psi.util.CachedValuesManager -import com.intellij.openapi.diagnostic.Logger import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils import com.intellij.util.containers.SLRUCache import com.intellij.psi.util.PsiModificationTracker @@ -39,41 +38,13 @@ import com.intellij.psi.util.CachedValueProvider import org.jetbrains.jet.asJava.LightClassUtil import com.intellij.openapi.roots.libraries.LibraryUtil import org.jetbrains.jet.lang.resolve.LibrarySourceHacks -import org.jetbrains.jet.lang.resolve.BindingContext -import com.intellij.openapi.components.ServiceManager -import org.jetbrains.jet.lang.resolve.java.JetFilesProvider -import com.intellij.psi.search.GlobalSearchScope -import org.jetbrains.jet.plugin.project.AnalyzerFacadeProvider import org.jetbrains.jet.plugin.project.TargetPlatform -import org.jetbrains.jet.plugin.project.TargetPlatform.* import org.jetbrains.jet.plugin.project.ResolveSessionForBodies -import org.jetbrains.jet.plugin.project.TargetPlatformDetector -import java.util.HashSet import org.jetbrains.jet.analyzer.AnalyzerFacade -import org.jetbrains.jet.lang.psi.JetCodeFragmentImpl -private val LOG = Logger.getInstance(javaClass()) - -fun JetElement.getLazyResolveSession(): ResolveSessionForBodies { - return KotlinCacheService.getInstance(getProject()).getLazyResolveSession(this) -} - -fun Project.getLazyResolveSession(platform: TargetPlatform): ResolveSessionForBodies { - return KotlinCacheService.getInstance(this).getGlobalLazyResolveSession(platform) -} - -fun JetElement.getAnalysisResults(): AnalyzeExhaust { - return KotlinCacheService.getInstance(getProject()).getAnalysisResults(listOf(this)) -} - -fun JetElement.getBindingContext(): BindingContext { - return getAnalysisResults().getBindingContext() -} - -fun getAnalysisResultsForElements(elements: Collection): AnalyzeExhaust { - if (elements.isEmpty()) return AnalyzeExhaust.EMPTY - val element = elements.first() - return KotlinCacheService.getInstance(element.getProject()).getAnalysisResults(elements) +public trait CacheExtension { + val platform: TargetPlatform + fun getData(setup: AnalyzerFacade.Setup): T } private class SessionAndSetup( @@ -82,106 +53,6 @@ private class SessionAndSetup( val setup: AnalyzerFacade.Setup ) -class KotlinCacheService(val project: Project) { - class object { - fun getInstance(project: Project) = ServiceManager.getService(project, javaClass())!! - } - - private fun globalResolveSessionProvider(platform: TargetPlatform, syntheticFile: JetFile? = null) = { - val allFiles = JetFilesProvider.getInstance(project).allInScope(GlobalSearchScope.allScope(project)) - - val files = if (syntheticFile == null) allFiles else collectFilesForSyntheticFile(allFiles, syntheticFile) - val setup = AnalyzerFacadeProvider.getAnalyzerFacade(platform).createSetup(project, files) - val resolveSessionForBodies = ResolveSessionForBodies(project, setup.getLazyResolveSession()) - CachedValueProvider.Result.create( - SessionAndSetup( - platform, - resolveSessionForBodies, - setup - ), - PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, - resolveSessionForBodies - ) - } - - private fun collectFilesForSyntheticFile(allFiles: Collection, syntheticFile: JetFile): Collection { - val files = HashSet(allFiles) - - // Add requested file to the list of files for searching declarations - files.add(syntheticFile) - - val originalFile = syntheticFile.getOriginalFile() - if (syntheticFile != originalFile) { - // Given file can be a non-physical copy of the file in list (completion case). Remove the prototype file. - files.remove(originalFile) - } - - return files - } - - private val globalCachesPerPlatform = mapOf( - JVM to KotlinResolveCache(project, globalResolveSessionProvider(JVM)), - JS to KotlinResolveCache(project, globalResolveSessionProvider(JS)) - ) - - private val syntheticFileCaches = object : SLRUCache(2, 3) { - override fun createValue(file: JetFile?): KotlinResolveCache { - return KotlinResolveCache( - project, - globalResolveSessionProvider( - TargetPlatformDetector.getPlatform(file!!), - file - ) - ) - } - } - - private fun getCacheForSyntheticFile(file: JetFile): KotlinResolveCache { - return synchronized(syntheticFileCaches) { - syntheticFileCaches[file] - } - } - - public fun getGlobalLazyResolveSession(platform: TargetPlatform): ResolveSessionForBodies { - return globalCachesPerPlatform[platform]!!.getLazyResolveSession() - } - - public fun getLazyResolveSession(element: JetElement): ResolveSessionForBodies { - val file = element.getContainingJetFile() - if (!isFileInScope(file)) { - return getCacheForSyntheticFile(file).getLazyResolveSession() - } - - return getGlobalLazyResolveSession(TargetPlatformDetector.getPlatform(file)) - } - - public fun getAnalysisResults(elements: Collection): AnalyzeExhaust { - if (elements.isEmpty()) return AnalyzeExhaust.EMPTY - - val firstFile = elements.first().getContainingJetFile() - if (elements.size == 1 && (!isFileInScope(firstFile) && firstFile !is JetCodeFragmentImpl)) { - return getCacheForSyntheticFile(firstFile).getAnalysisResultsForElements(elements) - } - - val resolveCache = globalCachesPerPlatform[TargetPlatformDetector.getPlatform(firstFile)]!! - return resolveCache.getAnalysisResultsForElements(elements) - } - - private fun isFileInScope(jetFile: JetFile): Boolean { - val project = jetFile.getProject() - return JetFilesProvider.getInstance(project).isFileInScope(jetFile, GlobalSearchScope.allScope(project)) - } - - public fun get(extension: CacheExtension): T { - return globalCachesPerPlatform[extension.platform]!![extension] - } -} - -trait CacheExtension { - val platform: TargetPlatform - fun getData(setup: AnalyzerFacade.Setup): T -} - private class KotlinResolveCache( val project: Project, setupProvider: () -> CachedValueProvider.Result