Additional cache for not-found packages
This commit is contained in:
@@ -74,6 +74,11 @@ public class JavaClassFinderImpl implements JavaClassFinder {
|
|||||||
public Project getProject() {
|
public Project getProject() {
|
||||||
return project;
|
return project;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "JCFI: " + baseScope;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
javaFacade = KotlinJavaPsiFacade.getInstance(project);
|
javaFacade = KotlinJavaPsiFacade.getInstance(project);
|
||||||
|
|||||||
+68
-10
@@ -51,7 +51,16 @@ import java.util.concurrent.ConcurrentMap;
|
|||||||
|
|
||||||
public class KotlinJavaPsiFacade {
|
public class KotlinJavaPsiFacade {
|
||||||
private volatile KotlinPsiElementFinderWrapper[] elementFinders;
|
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;
|
private final Project project;
|
||||||
|
|
||||||
public static KotlinJavaPsiFacade getInstance(Project project) {
|
public static KotlinJavaPsiFacade getInstance(Project project) {
|
||||||
@@ -72,6 +81,7 @@ public class KotlinJavaPsiFacade {
|
|||||||
long now = modificationTracker.getJavaStructureModificationCount();
|
long now = modificationTracker.getJavaStructureModificationCount();
|
||||||
if (lastTimeSeen != now) {
|
if (lastTimeSeen != now) {
|
||||||
lastTimeSeen = now;
|
lastTimeSeen = now;
|
||||||
|
|
||||||
packageCache = null;
|
packageCache = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,24 +165,56 @@ public class KotlinJavaPsiFacade {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PsiPackage findPackage(@NotNull String qualifiedName, GlobalSearchScope searchScope) {
|
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) {
|
if (cache == null) {
|
||||||
packageCache = new SoftReference<ConcurrentMap<Pair<String, GlobalSearchScope>, PsiPackage>>(
|
packageCache = new SoftReference<PackageCache>(cache = new PackageCache());
|
||||||
cache = new ConcurrentHashMap<Pair<String, GlobalSearchScope>, PsiPackage>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<String, GlobalSearchScope> key = new Pair<String, GlobalSearchScope>(qualifiedName, searchScope);
|
Pair<String, GlobalSearchScope> key = new Pair<String, GlobalSearchScope>(qualifiedName, searchScope);
|
||||||
PsiPackage aPackage = cache.get(key);
|
PsiPackage aPackage = cache.packageInScopeCache.get(key);
|
||||||
if (aPackage != null) {
|
if (aPackage != null) {
|
||||||
return aPackage;
|
return aPackage;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (KotlinPsiElementFinderWrapper finder : filteredFinders()) {
|
KotlinPsiElementFinderWrapper[] finders = filteredFinders();
|
||||||
aPackage = finder.findPackage(qualifiedName, searchScope);
|
|
||||||
if (aPackage != null) {
|
Boolean packageFoundInAllScope = cache.hasPackageInAllScopeCache.get(qualifiedName);
|
||||||
return ConcurrencyUtil.cacheOrGet(cache, key, aPackage);
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -202,12 +244,13 @@ public class KotlinJavaPsiFacade {
|
|||||||
interface KotlinPsiElementFinderWrapper {
|
interface KotlinPsiElementFinderWrapper {
|
||||||
PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope);
|
PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope);
|
||||||
PsiPackage findPackage(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope);
|
PsiPackage findPackage(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope);
|
||||||
|
boolean isSameResultForAnyScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class KotlinPsiElementFinderWrapperImpl implements KotlinPsiElementFinderWrapper {
|
private static class KotlinPsiElementFinderWrapperImpl implements KotlinPsiElementFinderWrapper {
|
||||||
private final PsiElementFinder finder;
|
private final PsiElementFinder finder;
|
||||||
|
|
||||||
private KotlinPsiElementFinderWrapperImpl(PsiElementFinder finder) {
|
private KotlinPsiElementFinderWrapperImpl(@NotNull PsiElementFinder finder) {
|
||||||
this.finder = finder;
|
this.finder = finder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,6 +264,16 @@ public class KotlinJavaPsiFacade {
|
|||||||
// Original element finder can't search packages with scope
|
// Original element finder can't search packages with scope
|
||||||
return finder.findPackage(qualifiedName);
|
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 {
|
private static class KotlinPsiElementFinderWrapperImplDumbAware extends KotlinPsiElementFinderWrapperImpl implements DumbAware {
|
||||||
@@ -278,6 +331,11 @@ public class KotlinJavaPsiFacade {
|
|||||||
return hasDirectoriesInScope(dirs, scope) ? new PsiPackageImpl(psiManager, qualifiedName) : null;
|
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) {
|
private static boolean hasDirectoriesInScope(Query<VirtualFile> dirs, final GlobalSearchScope scope) {
|
||||||
CommonProcessors.FindProcessor<VirtualFile> findProcessor = new CommonProcessors.FindProcessor<VirtualFile>() {
|
CommonProcessors.FindProcessor<VirtualFile> findProcessor = new CommonProcessors.FindProcessor<VirtualFile>() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user