From 80c0a1a0f70568742cd0a2a884ba80605259f570 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Mon, 12 Aug 2013 14:07:37 +0400 Subject: [PATCH] Create descriptors cache for the whole project and store file-specific session only for created temporary files --- .../resolve/DeclarationsCacheProvider.java | 42 ++++++++++++ .../caches/resolve/KotlinCacheManager.java | 6 ++ .../project/AnalyzerFacadeProvider.java | 5 ++ .../project/AnalyzerFacadeWithCache.java | 65 +++++++++---------- .../project/CancelableResolveSession.java | 17 +++-- .../project/WholeProjectAnalyzerFacade.java | 2 +- .../inline/KotlinInlineValHandler.java | 4 +- 7 files changed, 101 insertions(+), 40 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/caches/resolve/DeclarationsCacheProvider.java b/idea/src/org/jetbrains/jet/plugin/caches/resolve/DeclarationsCacheProvider.java index 99d755aafd1..07fbc87aaa3 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/resolve/DeclarationsCacheProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/resolve/DeclarationsCacheProvider.java @@ -17,16 +17,58 @@ package org.jetbrains.jet.plugin.caches.resolve; import com.intellij.openapi.project.Project; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.CachedValue; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.psi.util.CachedValuesManager; +import com.intellij.psi.util.PsiModificationTracker; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.java.JetFilesProvider; +import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; +import org.jetbrains.jet.plugin.project.AnalyzerFacadeProvider; +import org.jetbrains.jet.plugin.project.CancelableResolveSession; import org.jetbrains.jet.plugin.project.TargetPlatform; +import java.util.Collection; + public abstract class DeclarationsCacheProvider { + private final CachedValue lazyResolveCache; + protected final TargetPlatform platform; protected final Project project; DeclarationsCacheProvider(Project project, TargetPlatform platform) { this.platform = platform; this.project = project; + + this.lazyResolveCache = CachedValuesManager.getManager(project).createCachedValue( + new CancelableResolveSessionValueProvider(project, platform), true); } public abstract KotlinDeclarationsCache getDeclarations(boolean allowIncomplete); + + @NotNull + public CancelableResolveSession getLazyResolveSession() { + return lazyResolveCache.getValue(); + } + + private static class CancelableResolveSessionValueProvider implements CachedValueProvider { + private final Project project; + private final TargetPlatform platform; + + private CancelableResolveSessionValueProvider(Project project, TargetPlatform platform) { + this.project = project; + this.platform = platform; + } + + @Nullable + @Override + public synchronized Result compute() { + Collection files = JetFilesProvider.getInstance(project).allInScope(GlobalSearchScope.allScope(project)); + ResolveSession resolveSession = AnalyzerFacadeProvider.getAnalyzerFacade(platform).getLazyResolveSession(project, files); + return Result.create(new CancelableResolveSession(project, resolveSession), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); + } + } } diff --git a/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheManager.java b/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheManager.java index 71492df9875..a05e86a6598 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheManager.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheManager.java @@ -21,6 +21,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.plugin.project.CancelableResolveSession; import org.jetbrains.jet.plugin.project.TargetPlatform; import java.util.Map; @@ -70,6 +71,11 @@ public class KotlinCacheManager { return getRegisteredProvider(TargetPlatform.JVM).getDeclarations(true); } + @NotNull + public CancelableResolveSession getLazyResolveSession(@NotNull TargetPlatform platform) { + return cacheProviders.get(platform).getLazyResolveSession(); + } + @NotNull private DeclarationsCacheProvider getRegisteredProvider(TargetPlatform platform) { DeclarationsCacheProvider provider = cacheProviders.get(platform); diff --git a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeProvider.java b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeProvider.java index e98f79df860..34aa5d19248 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeProvider.java @@ -29,4 +29,9 @@ public final class AnalyzerFacadeProvider { public static AnalyzerFacade getAnalyzerFacadeForFile(@NotNull JetFile file) { return TargetPlatformDetector.getPlatform(file) == TargetPlatform.JVM ? AnalyzerFacadeForJVM.INSTANCE : JSAnalyzerFacadeForIDEA.INSTANCE; } + + @NotNull + public static AnalyzerFacade getAnalyzerFacade(@NotNull TargetPlatform targetPlatform) { + return targetPlatform == TargetPlatform.JVM ? AnalyzerFacadeForJVM.INSTANCE : JSAnalyzerFacadeForIDEA.INSTANCE; + } } diff --git a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java index 611f86cf214..efca4dfb0f6 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java +++ b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java @@ -28,10 +28,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.impl.PsiModificationTrackerImpl; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.util.CachedValue; -import com.intellij.psi.util.CachedValueProvider; -import com.intellij.psi.util.CachedValuesManager; -import com.intellij.psi.util.PsiModificationTracker; +import com.intellij.psi.util.*; import com.intellij.util.containers.SLRUCache; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -45,6 +42,7 @@ import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM; import org.jetbrains.jet.lang.resolve.java.JetFilesProvider; import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; import org.jetbrains.jet.lang.types.ErrorUtils; +import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager; import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManagerUtil; import org.jetbrains.jet.plugin.caches.resolve.KotlinDeclarationsCache; import org.jetbrains.jet.plugin.caches.resolve.KotlinDeclarationsCacheImpl; @@ -167,38 +165,39 @@ public final class AnalyzerFacadeWithCache { LOG.error(e); } - private static final SLRUCache> RESOLVE_SESSION_CACHE = new SLRUCache>(2, 4) { - @NotNull - @Override - public CachedValue createValue(final JetFile file) { - final Project fileProject = file.getProject(); - return CachedValuesManager.getManager(fileProject).createCachedValue( - new CachedValueProvider() { - @Nullable - @Override - public Result compute() { - Project project = file.getProject(); - Collection files = - JetFilesProvider.getInstance(project).allInScope(GlobalSearchScope.allScope(project)); + private final static Key> PER_FILE_LAZY_RESOLVE_SESSION = Key.create("PER_FILE_LAZY_RESOLVE_SESSION"); - // Given file can differ from the original because it can be a virtual copy with some modifications - JetFile originalFile = (JetFile) file.getOriginalFile(); - files.remove(originalFile); - files.add(file); - - ResolveSession resolveSession = - AnalyzerFacadeProvider.getAnalyzerFacadeForFile(file).getLazyResolveSession(fileProject, files); - return Result.create(new CancelableResolveSession(file, resolveSession), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); - } - }, - true); + public static CancelableResolveSession getLazyResolveSessionForFile(@NotNull JetFile file) { + Project project = file.getProject(); + if (file.getOriginalFile() != file) { + // Completion creates special non-physical file. Create a separate session for them. + return CachedValuesManager.getManager(project).getParameterizedCachedValue( + project, PER_FILE_LAZY_RESOLVE_SESSION, PerFileLazyResolveSessionProvider.INSTANCE, true, file); } - }; - @NotNull - public static CancelableResolveSession getLazyResolveSession(@NotNull JetFile file) { - synchronized (RESOLVE_SESSION_CACHE) { - return RESOLVE_SESSION_CACHE.get(file).getValue(); + return KotlinCacheManager.getInstance(project).getLazyResolveSession(TargetPlatformDetector.getPlatform(file)); + } + + private static class PerFileLazyResolveSessionProvider implements ParameterizedCachedValueProvider { + private static final PerFileLazyResolveSessionProvider INSTANCE = new PerFileLazyResolveSessionProvider(); + + @Override + public CachedValueProvider.Result compute(@NotNull JetFile file) { + Project project = file.getProject(); + Collection files = JetFilesProvider.getInstance(project).allInScope(GlobalSearchScope.allScope(project)); + + JetFile originalFile = (JetFile) file.getOriginalFile(); + assert originalFile != file: "Should be used only for non-physical files"; + + // Virtual file can differ from the original and there can be requests to psi elements from this file + files.remove(originalFile); + files.add(file); + + ResolveSession resolveSession = + AnalyzerFacadeProvider.getAnalyzerFacadeForFile(file).getLazyResolveSession(project, files); + + return CachedValueProvider.Result.create(new CancelableResolveSession(file, resolveSession), + PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); } } } diff --git a/idea/src/org/jetbrains/jet/plugin/project/CancelableResolveSession.java b/idea/src/org/jetbrains/jet/plugin/project/CancelableResolveSession.java index 34f0c8be903..1f60db7837b 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/CancelableResolveSession.java +++ b/idea/src/org/jetbrains/jet/plugin/project/CancelableResolveSession.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.plugin.project; import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.ModificationTracker; import org.jetbrains.annotations.NotNull; @@ -38,15 +39,23 @@ import org.jetbrains.jet.lang.resolve.name.Name; import java.util.concurrent.atomic.AtomicLong; public class CancelableResolveSession implements KotlinCodeAnalyzer, ModificationTracker { - private final JetFile file; + private final Object createdForObject; private final ResolveSession resolveSession; private final ResolveElementCache resolveElementCache; private final AtomicLong canceledTracker = new AtomicLong(); public CancelableResolveSession(@NotNull JetFile file, @NotNull ResolveSession resolveSession) { - this.file = file; + this(file, file.getProject(), resolveSession); + } + + public CancelableResolveSession(@NotNull Project project, @NotNull ResolveSession resolveSession) { + this(project, project, resolveSession); + } + + private CancelableResolveSession(Object createdForObject, Project project, ResolveSession resolveSession) { + this.createdForObject = createdForObject; this.resolveSession = resolveSession; - this.resolveElementCache = new ResolveElementCache(resolveSession, file.getProject()); + this.resolveElementCache = new ResolveElementCache(resolveSession, project); } public BindingContext resolveToElement(final JetElement element) { @@ -151,6 +160,6 @@ public class CancelableResolveSession implements KotlinCodeAnalyzer, Modificatio @Override public String toString() { - return "SessionResult: " + file + " " + file.hashCode(); + return "CancelableResolveSession: " + getModificationCount() + " " + createdForObject + " " + createdForObject.hashCode(); } } diff --git a/idea/src/org/jetbrains/jet/plugin/project/WholeProjectAnalyzerFacade.java b/idea/src/org/jetbrains/jet/plugin/project/WholeProjectAnalyzerFacade.java index 4162b5aa03e..478a04fe626 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/WholeProjectAnalyzerFacade.java +++ b/idea/src/org/jetbrains/jet/plugin/project/WholeProjectAnalyzerFacade.java @@ -34,7 +34,7 @@ public final class WholeProjectAnalyzerFacade { @NotNull public static CancelableResolveSession getLazyResolveResultForFile(@NotNull JetFile file) { - return AnalyzerFacadeWithCache.getLazyResolveSession(file); + return AnalyzerFacadeWithCache.getLazyResolveSessionForFile(file); } public static BindingContext getContextForElement(@NotNull JetElement jetElement) { diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/inline/KotlinInlineValHandler.java b/idea/src/org/jetbrains/jet/plugin/refactoring/inline/KotlinInlineValHandler.java index 8328904b04a..93d568b9b93 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/inline/KotlinInlineValHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/inline/KotlinInlineValHandler.java @@ -260,7 +260,7 @@ public class KotlinInlineValHandler extends InlineActionHandler { JetFile containingFile = (JetFile) inlinedExpressions.get(0).getContainingFile(); List functionsToAddParameters = Lists.newArrayList(); - CancelableResolveSession cancelableResolveSession = AnalyzerFacadeWithCache.getLazyResolveSession(containingFile); + CancelableResolveSession cancelableResolveSession = AnalyzerFacadeWithCache.getLazyResolveSessionForFile(containingFile); for (JetExpression inlinedExpression : inlinedExpressions) { JetFunctionLiteralExpression functionLiteralExpression = getFunctionLiteralExpression(inlinedExpression); assert functionLiteralExpression != null : "can't find function literal expression for " + inlinedExpression.getText(); @@ -320,7 +320,7 @@ public class KotlinInlineValHandler extends InlineActionHandler { JetFile containingFile = (JetFile) inlinedExpressions.get(0).getContainingFile(); List callsToAddArguments = Lists.newArrayList(); - CancelableResolveSession cancelableResolveSession = AnalyzerFacadeWithCache.getLazyResolveSession(containingFile); + CancelableResolveSession cancelableResolveSession = AnalyzerFacadeWithCache.getLazyResolveSessionForFile(containingFile); for (JetExpression inlinedExpression : inlinedExpressions) { JetCallExpression callExpression = getCallExpression(inlinedExpression); assert callExpression != null : "can't find call expression for " + inlinedExpression.getText();