Additional cache for not-found packages
This commit is contained in:
@@ -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);
|
||||
|
||||
+68
-10
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user