Additional cache for not-found packages

This commit is contained in:
Nikolay Krasko
2015-01-20 16:06:33 +03:00
parent a8557180f1
commit e802044c60
2 changed files with 73 additions and 10 deletions
@@ -74,6 +74,11 @@ public class JavaClassFinderImpl implements JavaClassFinder {
public Project getProject() {
return project;
}
@Override
public String toString() {
return "JCFI: " + baseScope;
}
};
javaFacade = KotlinJavaPsiFacade.getInstance(project);
@@ -51,7 +51,16 @@ import java.util.concurrent.ConcurrentMap;
public class KotlinJavaPsiFacade {
private volatile KotlinPsiElementFinderWrapper[] elementFinders;
private volatile SoftReference<ConcurrentMap<Pair<String, GlobalSearchScope>, PsiPackage>> packageCache;
private static class PackageCache {
final ConcurrentMap<Pair<String, GlobalSearchScope>, PsiPackage> packageInScopeCache =
new ConcurrentHashMap<Pair<String, GlobalSearchScope>, PsiPackage>();
final ConcurrentMap<String, Boolean> hasPackageInAllScopeCache =
new ConcurrentHashMap<String, Boolean>();
}
private volatile SoftReference<PackageCache> packageCache;
private final Project project;
public static KotlinJavaPsiFacade getInstance(Project project) {
@@ -72,6 +81,7 @@ public class KotlinJavaPsiFacade {
long now = modificationTracker.getJavaStructureModificationCount();
if (lastTimeSeen != now) {
lastTimeSeen = now;
packageCache = null;
}
}
@@ -155,24 +165,56 @@ public class KotlinJavaPsiFacade {
}
public PsiPackage findPackage(@NotNull String qualifiedName, GlobalSearchScope searchScope) {
ConcurrentMap<Pair<String, GlobalSearchScope>, PsiPackage> cache = SoftReference.dereference(packageCache);
PackageCache cache = SoftReference.dereference(packageCache);
if (cache == null) {
packageCache = new SoftReference<ConcurrentMap<Pair<String, GlobalSearchScope>, PsiPackage>>(
cache = new ConcurrentHashMap<Pair<String, GlobalSearchScope>, PsiPackage>());
packageCache = new SoftReference<PackageCache>(cache = new PackageCache());
}
Pair<String, GlobalSearchScope> key = new Pair<String, GlobalSearchScope>(qualifiedName, searchScope);
PsiPackage aPackage = cache.get(key);
PsiPackage aPackage = cache.packageInScopeCache.get(key);
if (aPackage != null) {
return aPackage;
}
for (KotlinPsiElementFinderWrapper finder : filteredFinders()) {
aPackage = finder.findPackage(qualifiedName, searchScope);
if (aPackage != null) {
return ConcurrencyUtil.cacheOrGet(cache, key, aPackage);
KotlinPsiElementFinderWrapper[] finders = filteredFinders();
Boolean packageFoundInAllScope = cache.hasPackageInAllScopeCache.get(qualifiedName);
if (packageFoundInAllScope != null) {
if (!packageFoundInAllScope.booleanValue()) return null;
// Package was found in AllScope with some of finders but is absent in packageCache for current scope.
// We check only finders that depend on scope.
for (KotlinPsiElementFinderWrapper finder : finders) {
if (!finder.isSameResultForAnyScope()) {
aPackage = finder.findPackage(qualifiedName, searchScope);
if (aPackage != null) {
return ConcurrencyUtil.cacheOrGet(cache.packageInScopeCache, key, aPackage);
}
}
}
}
else {
for (KotlinPsiElementFinderWrapper finder : finders) {
aPackage = finder.findPackage(qualifiedName, searchScope);
if (aPackage != null) {
return ConcurrencyUtil.cacheOrGet(cache.packageInScopeCache, key, aPackage);
}
}
boolean found = false;
for (KotlinPsiElementFinderWrapper finder : finders) {
if (!finder.isSameResultForAnyScope()) {
aPackage = finder.findPackage(qualifiedName, GlobalSearchScope.allScope(project));
if (aPackage != null) {
found = true;
break;
}
}
}
cache.hasPackageInAllScopeCache.put(qualifiedName, found);
}
return null;
}
@@ -202,12 +244,13 @@ public class KotlinJavaPsiFacade {
interface KotlinPsiElementFinderWrapper {
PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope);
PsiPackage findPackage(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope);
boolean isSameResultForAnyScope();
}
private static class KotlinPsiElementFinderWrapperImpl implements KotlinPsiElementFinderWrapper {
private final PsiElementFinder finder;
private KotlinPsiElementFinderWrapperImpl(PsiElementFinder finder) {
private KotlinPsiElementFinderWrapperImpl(@NotNull PsiElementFinder finder) {
this.finder = finder;
}
@@ -221,6 +264,16 @@ public class KotlinJavaPsiFacade {
// Original element finder can't search packages with scope
return finder.findPackage(qualifiedName);
}
@Override
public boolean isSameResultForAnyScope() {
return true;
}
@Override
public String toString() {
return finder.toString();
}
}
private static class KotlinPsiElementFinderWrapperImplDumbAware extends KotlinPsiElementFinderWrapperImpl implements DumbAware {
@@ -278,6 +331,11 @@ public class KotlinJavaPsiFacade {
return hasDirectoriesInScope(dirs, scope) ? new PsiPackageImpl(psiManager, qualifiedName) : null;
}
@Override
public boolean isSameResultForAnyScope() {
return false;
}
private static boolean hasDirectoriesInScope(Query<VirtualFile> dirs, final GlobalSearchScope scope) {
CommonProcessors.FindProcessor<VirtualFile> findProcessor = new CommonProcessors.FindProcessor<VirtualFile>() {
@Override