Create descriptors cache for the whole project and store file-specific session only for created temporary files

This commit is contained in:
Nikolay Krasko
2013-08-12 14:07:37 +04:00
parent 388f365900
commit 80c0a1a0f7
7 changed files with 101 additions and 40 deletions
@@ -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<CancelableResolveSession> 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<CancelableResolveSession> {
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<CancelableResolveSession> compute() {
Collection<JetFile> 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);
}
}
}
@@ -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);
@@ -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;
}
}
@@ -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<JetFile, CachedValue<CancelableResolveSession>> RESOLVE_SESSION_CACHE = new SLRUCache<JetFile, CachedValue<CancelableResolveSession>>(2, 4) {
@NotNull
@Override
public CachedValue<CancelableResolveSession> createValue(final JetFile file) {
final Project fileProject = file.getProject();
return CachedValuesManager.getManager(fileProject).createCachedValue(
new CachedValueProvider<CancelableResolveSession>() {
@Nullable
@Override
public Result<CancelableResolveSession> compute() {
Project project = file.getProject();
Collection<JetFile> files =
JetFilesProvider.getInstance(project).allInScope(GlobalSearchScope.allScope(project));
private final static Key<ParameterizedCachedValue<CancelableResolveSession, JetFile>> 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<CancelableResolveSession, JetFile> {
private static final PerFileLazyResolveSessionProvider INSTANCE = new PerFileLazyResolveSessionProvider();
@Override
public CachedValueProvider.Result<CancelableResolveSession> compute(@NotNull JetFile file) {
Project project = file.getProject();
Collection<JetFile> 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);
}
}
}
@@ -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();
}
}
@@ -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) {
@@ -260,7 +260,7 @@ public class KotlinInlineValHandler extends InlineActionHandler {
JetFile containingFile = (JetFile) inlinedExpressions.get(0).getContainingFile();
List<JetFunctionLiteralExpression> 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<JetCallExpression> 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();