Create consolidated caching service to provide all lazily resolved data
Other caches are to be removed later
This commit is contained in:
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
public abstract class JetFilesProvider {
|
public abstract class JetFilesProvider {
|
||||||
|
@NotNull
|
||||||
public static JetFilesProvider getInstance(Project project) {
|
public static JetFilesProvider getInstance(Project project) {
|
||||||
return ServiceManager.getService(project, JetFilesProvider.class);
|
return ServiceManager.getService(project, JetFilesProvider.class);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,6 +117,9 @@
|
|||||||
<projectService serviceInterface="org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager"
|
<projectService serviceInterface="org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager"
|
||||||
serviceImplementation="org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager"/>
|
serviceImplementation="org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager"/>
|
||||||
|
|
||||||
|
<projectService serviceInterface="org.jetbrains.jet.plugin.caches.resolve.KotlinCacheService"
|
||||||
|
serviceImplementation="org.jetbrains.jet.plugin.caches.resolve.KotlinCacheService"/>
|
||||||
|
|
||||||
<projectService serviceInterface="org.jetbrains.jet.lang.resolve.kotlin.VirtualFileFinder"
|
<projectService serviceInterface="org.jetbrains.jet.lang.resolve.kotlin.VirtualFileFinder"
|
||||||
serviceImplementation="org.jetbrains.jet.plugin.vfilefinder.IDEVirtualFileFinder"/>
|
serviceImplementation="org.jetbrains.jet.plugin.vfilefinder.IDEVirtualFileFinder"/>
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.plugin.caches.resolve
|
package org.jetbrains.jet.plugin.caches.resolve
|
||||||
|
|
||||||
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession
|
|
||||||
import org.jetbrains.jet.lang.psi.JetElement
|
import org.jetbrains.jet.lang.psi.JetElement
|
||||||
import org.jetbrains.jet.lang.psi.JetFile
|
import org.jetbrains.jet.lang.psi.JetFile
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
@@ -40,19 +39,144 @@ import com.intellij.psi.util.CachedValueProvider
|
|||||||
import org.jetbrains.jet.asJava.LightClassUtil
|
import org.jetbrains.jet.asJava.LightClassUtil
|
||||||
import com.intellij.openapi.roots.libraries.LibraryUtil
|
import com.intellij.openapi.roots.libraries.LibraryUtil
|
||||||
import org.jetbrains.jet.lang.resolve.LibrarySourceHacks
|
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 com.google.common.collect.ImmutableMap
|
||||||
|
import org.jetbrains.jet.lang.resolve.Diagnostics
|
||||||
|
import org.jetbrains.jet.util.slicedmap.ReadOnlySlice
|
||||||
|
import org.jetbrains.jet.util.slicedmap.WritableSlice
|
||||||
|
import org.jetbrains.jet.lang.diagnostics.Diagnostic
|
||||||
|
import java.util.HashSet
|
||||||
|
|
||||||
private val LOG = Logger.getInstance(javaClass<KotlinResolveCache>())
|
private val LOG = Logger.getInstance(javaClass<KotlinResolveCache>())
|
||||||
|
|
||||||
class KotlinResolveCache(
|
fun JetElement.getLazyResolveSession(): ResolveSessionForBodies {
|
||||||
|
return KotlinCacheService.getInstance(getProject()).getLazyResolveSession(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun JetElement.getAnalysisResults(): AnalyzeExhaust {
|
||||||
|
return KotlinCacheService.getInstance(getProject()).getAnalysisResults(listOf(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun JetElement.getBindingContext(): BindingContext {
|
||||||
|
return getAnalysisResults().getBindingContext()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAnalysisResultsForElements(elements: Collection<JetElement>): 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<KotlinCacheService>())!!
|
||||||
|
}
|
||||||
|
|
||||||
|
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 resolveSession = AnalyzerFacadeProvider.getAnalyzerFacade(platform).getLazyResolveSession(project, files)
|
||||||
|
CachedValueProvider.Result.create(ResolveSessionForBodies(project, resolveSession), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun collectFilesForSyntheticFile(allFiles: Collection<JetFile>, syntheticFile: JetFile): Collection<JetFile> {
|
||||||
|
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<JetFile, SynchronizedCachedValue<KotlinResolveCache>>(2, 3) {
|
||||||
|
override fun createValue(file: JetFile?): SynchronizedCachedValue<KotlinResolveCache> {
|
||||||
|
return SynchronizedCachedValue<KotlinResolveCache>(
|
||||||
|
project,
|
||||||
|
{
|
||||||
|
CachedValueProvider.Result(
|
||||||
|
KotlinResolveCache(
|
||||||
|
project,
|
||||||
|
globalResolveSessionProvider(
|
||||||
|
TargetPlatformDetector.getPlatform(file!!),
|
||||||
|
file
|
||||||
|
)
|
||||||
|
),
|
||||||
|
PsiModificationTracker.MODIFICATION_COUNT
|
||||||
|
)
|
||||||
|
},
|
||||||
|
false)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun getLazyResolveSession(element: JetElement): ResolveSessionForBodies {
|
||||||
|
val file = element.getContainingJetFile()
|
||||||
|
if (!isFileInScope(file)) {
|
||||||
|
return synchronized(syntheticFileCaches) {
|
||||||
|
syntheticFileCaches[file].getValue().getLazyResolveSession()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return globalCachesPerPlatform[TargetPlatformDetector.getPlatform(file)]!!.getLazyResolveSession()
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun getAnalysisResults(elements: Collection<JetElement>): AnalyzeExhaust {
|
||||||
|
if (elements.isEmpty()) return AnalyzeExhaust.EMPTY
|
||||||
|
|
||||||
|
val firstFile = elements.first().getContainingJetFile()
|
||||||
|
if (elements.size == 1 && !isFileInScope(firstFile)) {
|
||||||
|
return synchronized(syntheticFileCaches) {
|
||||||
|
syntheticFileCaches[firstFile].getValue().getAnalysisResultsForElements(elements)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val resolveCache = globalCachesPerPlatform[TargetPlatformDetector.getPlatform(firstFile)]!!
|
||||||
|
return synchronized(resolveCache) {
|
||||||
|
resolveCache.getAnalysisResultsForElements(elements)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isFileInScope(jetFile: JetFile): Boolean {
|
||||||
|
val project = jetFile.getProject()
|
||||||
|
return JetFilesProvider.getInstance(project).isFileInScope(jetFile, GlobalSearchScope.allScope(project))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class KotlinResolveCache(
|
||||||
val project: Project,
|
val project: Project,
|
||||||
val resolveSession: ResolveSession
|
val resolveSessionProvider: () -> CachedValueProvider.Result<ResolveSessionForBodies>
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
private val resolveSessionCache = SynchronizedCachedValue(project, resolveSessionProvider)
|
||||||
|
|
||||||
|
public fun getLazyResolveSession(): ResolveSessionForBodies = resolveSessionCache.getValue()
|
||||||
|
|
||||||
private data class Task(
|
private data class Task(
|
||||||
val elements: Set<JetElement>
|
val elements: Set<JetElement>
|
||||||
)
|
)
|
||||||
|
|
||||||
private val analysisResults = CachedValuesManager.getManager(project).createCachedValue ({
|
private val analysisResults = CachedValuesManager.getManager(project).createCachedValue ({
|
||||||
|
val resolveSession = getLazyResolveSession()
|
||||||
val results = object : SLRUCache<Task, AnalyzeExhaust>(2, 3) {
|
val results = object : SLRUCache<Task, AnalyzeExhaust>(2, 3) {
|
||||||
override fun createValue(task: Task?): AnalyzeExhaust {
|
override fun createValue(task: Task?): AnalyzeExhaust {
|
||||||
if (DumbService.isDumb(project)) {
|
if (DumbService.isDumb(project)) {
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.util.PsiModificationTracker
|
||||||
|
import java.util.concurrent.locks.Lock
|
||||||
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
import com.intellij.psi.util.CachedValuesManager
|
||||||
|
import com.intellij.util.containers.SLRUCache
|
||||||
|
import com.intellij.psi.util.CachedValueProvider
|
||||||
|
|
||||||
|
class SynchronizedCachedValue<V>(project: Project, provider: () -> CachedValueProvider.Result<V>, trackValue: Boolean = true) {
|
||||||
|
private val cachedValue = CachedValuesManager.getManager(project).createCachedValue(
|
||||||
|
provider,
|
||||||
|
trackValue
|
||||||
|
)
|
||||||
|
|
||||||
|
public fun getValue(): V {
|
||||||
|
return synchronized(cachedValue) {
|
||||||
|
cachedValue.getValue() as V
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ import org.jetbrains.jet.lang.resolve.java.JetFilesProvider;
|
|||||||
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
|
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
|
||||||
import org.jetbrains.jet.plugin.caches.resolve.DeclarationsCacheProvider;
|
import org.jetbrains.jet.plugin.caches.resolve.DeclarationsCacheProvider;
|
||||||
import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager;
|
import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager;
|
||||||
|
import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -48,7 +49,7 @@ public final class AnalyzerFacadeWithCache {
|
|||||||
// TODO: Also need to pass several files when user have multi-file environment
|
// TODO: Also need to pass several files when user have multi-file environment
|
||||||
@NotNull
|
@NotNull
|
||||||
public static AnalyzeExhaust analyzeFileWithCache(@NotNull JetFile file) {
|
public static AnalyzeExhaust analyzeFileWithCache(@NotNull JetFile file) {
|
||||||
return getLazyResolveSessionForFile(file).getResolveCache().getAnalysisResultsForElement(file);
|
return ResolvePackage.getAnalysisResults(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
|
|||||||
import org.jetbrains.jet.lang.resolve.lazy.ScopeProvider;
|
import org.jetbrains.jet.lang.resolve.lazy.ScopeProvider;
|
||||||
import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyPackageDescriptor;
|
import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyPackageDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||||
import org.jetbrains.jet.plugin.caches.resolve.KotlinResolveCache;
|
|
||||||
import org.jetbrains.jet.storage.ExceptionTracker;
|
import org.jetbrains.jet.storage.ExceptionTracker;
|
||||||
import org.jetbrains.jet.storage.StorageManager;
|
import org.jetbrains.jet.storage.StorageManager;
|
||||||
|
|
||||||
@@ -42,7 +41,6 @@ public class ResolveSessionForBodies implements KotlinCodeAnalyzer, Modification
|
|||||||
private final Object createdForObject;
|
private final Object createdForObject;
|
||||||
private final ResolveSession resolveSession;
|
private final ResolveSession resolveSession;
|
||||||
private final ResolveElementCache resolveElementCache;
|
private final ResolveElementCache resolveElementCache;
|
||||||
private final KotlinResolveCache resolveCache;
|
|
||||||
|
|
||||||
public ResolveSessionForBodies(@NotNull JetFile file, @NotNull ResolveSession resolveSession) {
|
public ResolveSessionForBodies(@NotNull JetFile file, @NotNull ResolveSession resolveSession) {
|
||||||
this(file, file.getProject(), resolveSession);
|
this(file, file.getProject(), resolveSession);
|
||||||
@@ -56,7 +54,6 @@ public class ResolveSessionForBodies implements KotlinCodeAnalyzer, Modification
|
|||||||
this.createdForObject = createdForObject;
|
this.createdForObject = createdForObject;
|
||||||
this.resolveSession = resolveSession;
|
this.resolveSession = resolveSession;
|
||||||
this.resolveElementCache = new ResolveElementCache(resolveSession, project);
|
this.resolveElementCache = new ResolveElementCache(resolveSession, project);
|
||||||
this.resolveCache = new KotlinResolveCache(project, resolveSession);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -103,11 +100,6 @@ public class ResolveSessionForBodies implements KotlinCodeAnalyzer, Modification
|
|||||||
return "ResolveSessionForBodies: " + getModificationCount() + " " + createdForObject + " " + createdForObject.hashCode();
|
return "ResolveSessionForBodies: " + getModificationCount() + " " + createdForObject + " " + createdForObject.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public KotlinResolveCache getResolveCache() {
|
|
||||||
return resolveCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public LazyPackageDescriptor getPackageFragment(@NotNull FqName fqName) {
|
public LazyPackageDescriptor getPackageFragment(@NotNull FqName fqName) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
|
|||||||
import org.jetbrains.jet.lang.resolve.java.JetFilesProvider;
|
import org.jetbrains.jet.lang.resolve.java.JetFilesProvider;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
|
import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
@@ -72,8 +72,7 @@ public class DebuggerUtils {
|
|||||||
// In the rare case that there's more than one file with this name in this package,
|
// In the rare case that there's more than one file with this name in this package,
|
||||||
// we may actually need to analyze the project in order to find a file which produces this class
|
// we may actually need to analyze the project in order to find a file which produces this class
|
||||||
// TODO: this code is not entirely correct, because it takes a session for only one file
|
// TODO: this code is not entirely correct, because it takes a session for only one file
|
||||||
AnalyzeExhaust analyzeExhaust = AnalyzerFacadeWithCache.getLazyResolveSessionForFile(anyFile).getResolveCache()
|
AnalyzeExhaust analyzeExhaust = ResolvePackage.getAnalysisResultsForElements(files);
|
||||||
.getAnalysisResultsForElements(files);
|
|
||||||
|
|
||||||
return PsiCodegenPredictor.getFileForCodegenNamedClass(analyzeExhaust.getBindingContext(), allPackageFiles, className.getInternalName());
|
return PsiCodegenPredictor.getFileForCodegenNamedClass(analyzeExhaust.getBindingContext(), allPackageFiles, className.getInternalName());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user