don't do psi.getProject each time a searcher needs it to run a read action via dumb mode, because getProject itself requires a read action

This commit is contained in:
peter
2015-03-11 14:49:37 +01:00
parent fff42b7c97
commit 4ddd214f43
5 changed files with 44 additions and 16 deletions
@@ -16,6 +16,7 @@
package com.intellij.psi.impl.search;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.TextRange;
import com.intellij.pom.java.LanguageLevel;
@@ -41,17 +42,25 @@ public class ConstructorReferencesSearchHelper {
myManager = manager;
}
/*
* Project is passed around explicitly to avoid invoking PsiElement.getProject each time we need it. There are two reasons:
* 1. Performance. getProject traverses AST upwards
* 2. Exception avoidance. Project is needed outside of read action (to run it via DumbService in the first place),
* and so getProject would fail with an assertion that read action is required but not present.
*/
public boolean processConstructorReferences(@NotNull final Processor<PsiReference> processor,
@NotNull final PsiMethod constructor,
@NotNull final PsiClass containingClass,
@NotNull final SearchScope searchScope,
@NotNull final Project project,
boolean ignoreAccessScope,
final boolean isStrictSignatureSearch,
@NotNull SearchRequestCollector collector) {
final boolean[] constructorCanBeCalledImplicitly = new boolean[1];
final boolean[] isEnum = new boolean[1];
final boolean[] isUnder18 = new boolean[1];
DumbService.getInstance(constructor.getProject()).runReadActionInSmartMode(new Runnable() {
DumbService.getInstance(project).runReadActionInSmartMode(new Runnable() {
@Override
public void run() {
constructorCanBeCalledImplicitly[0] = constructor.getParameterList().getParametersCount() == 0;
@@ -61,7 +70,7 @@ public class ConstructorReferencesSearchHelper {
});
if (isEnum[0]) {
if (!processEnumReferences(processor, constructor, containingClass)) return false;
if (!processEnumReferences(processor, constructor, project, containingClass)) return false;
}
// search usages like "new XXX(..)"
@@ -93,14 +102,14 @@ public class ConstructorReferencesSearchHelper {
ReferencesSearch.searchOptimized(containingClass, searchScope, ignoreAccessScope, collector, true, processor1);
if (isUnder18[0]) {
if (!process18MethodPointers(processor, constructor, containingClass, searchScope)) return false;
if (!process18MethodPointers(processor, constructor, project, containingClass, searchScope)) return false;
}
// search usages like "this(..)"
if (!DumbService.getInstance(constructor.getProject()).runReadActionInSmartMode(new Computable<Boolean>() {
if (!DumbService.getInstance(project).runReadActionInSmartMode(new Computable<Boolean>() {
@Override
public Boolean compute() {
return processSuperOrThis(containingClass, constructor, constructorCanBeCalledImplicitly[0], searchScope, isStrictSignatureSearch,
return processSuperOrThis(containingClass, constructor, constructorCanBeCalledImplicitly[0], searchScope, project, isStrictSignatureSearch,
PsiKeyword.THIS, processor);
}
})) {
@@ -113,7 +122,7 @@ public class ConstructorReferencesSearchHelper {
public boolean process(PsiClass inheritor) {
final PsiElement navigationElement = inheritor.getNavigationElement();
if (navigationElement instanceof PsiClass) {
return processSuperOrThis((PsiClass)navigationElement, constructor, constructorCanBeCalledImplicitly[0], searchScope,
return processSuperOrThis((PsiClass)navigationElement, constructor, constructorCanBeCalledImplicitly[0], searchScope, project,
isStrictSignatureSearch, PsiKeyword.SUPER, processor);
}
return true;
@@ -125,8 +134,9 @@ public class ConstructorReferencesSearchHelper {
private static boolean processEnumReferences(@NotNull final Processor<PsiReference> processor,
@NotNull final PsiMethod constructor,
@NotNull final Project project,
@NotNull final PsiClass aClass) {
return DumbService.getInstance(constructor.getProject()).runReadActionInSmartMode(new Computable<Boolean>() {
return DumbService.getInstance(project).runReadActionInSmartMode(new Computable<Boolean>() {
@Override
public Boolean compute() {
for (PsiField field : aClass.getFields()) {
@@ -146,13 +156,14 @@ public class ConstructorReferencesSearchHelper {
private static boolean process18MethodPointers(@NotNull final Processor<PsiReference> processor,
@NotNull final PsiMethod constructor,
@NotNull final Project project,
@NotNull PsiClass aClass, SearchScope searchScope) {
return ReferencesSearch.search(aClass, searchScope).forEach(new Processor<PsiReference>() {
@Override
public boolean process(PsiReference reference) {
final PsiElement element = reference.getElement();
if (element != null) {
return DumbService.getInstance(element.getProject()).runReadActionInSmartMode(new Computable<Boolean>() {
return DumbService.getInstance(project).runReadActionInSmartMode(new Computable<Boolean>() {
@Override
public Boolean compute() {
final PsiElement parent = element.getParent();
@@ -175,12 +186,13 @@ public class ConstructorReferencesSearchHelper {
@NotNull PsiMethod constructor,
final boolean constructorCanBeCalledImplicitly,
@NotNull SearchScope searchScope,
@NotNull Project project,
final boolean isStrictSignatureSearch,
@NotNull String superOrThisKeyword,
@NotNull Processor<PsiReference> processor) {
PsiMethod[] constructors = inheritor.getConstructors();
if (constructors.length == 0 && constructorCanBeCalledImplicitly) {
if (!processImplicitConstructorCall(inheritor, processor, constructor, inheritor)) return false;
if (!processImplicitConstructorCall(inheritor, processor, constructor, project, inheritor)) return false;
}
for (PsiMethod method : constructors) {
PsiCodeBlock body = method.getBody();
@@ -212,7 +224,7 @@ public class ConstructorReferencesSearchHelper {
}
}
if (constructorCanBeCalledImplicitly) {
if (!processImplicitConstructorCall(method, processor, constructor, inheritor)) return false;
if (!processImplicitConstructorCall(method, processor, constructor, project, inheritor)) return false;
}
}
@@ -222,9 +234,10 @@ public class ConstructorReferencesSearchHelper {
private boolean processImplicitConstructorCall(@NotNull final PsiMember usage,
@NotNull final Processor<PsiReference> processor,
@NotNull final PsiMethod constructor,
@NotNull final Project project,
@NotNull final PsiClass containingClass) {
if (containingClass instanceof PsiAnonymousClass) return true;
boolean same = DumbService.getInstance(constructor.getProject()).runReadActionInSmartMode(new Computable<Boolean>() {
boolean same = DumbService.getInstance(project).runReadActionInSmartMode(new Computable<Boolean>() {
@Override
public Boolean compute() {
return myManager.areElementsEquivalent(constructor.getContainingClass(), containingClass.getSuperClass());
@@ -39,6 +39,6 @@ public class ConstructorReferencesSearcher extends QueryExecutorBase<PsiReferenc
}
});
new ConstructorReferencesSearchHelper(manager[0])
.processConstructorReferences(consumer, method, aClass, scope, p.isIgnoreAccessScope(), true, p.getOptimizer());
.processConstructorReferences(consumer, method, aClass, scope, p.getProject(), p.isIgnoreAccessScope(), true, p.getOptimizer());
}
}
@@ -43,7 +43,7 @@ public class MethodUsagesSearcher extends QueryExecutorBase<PsiReference, Method
final boolean[] needStrictSignatureSearch = new boolean[1];
final boolean strictSignatureSearch = p.isStrictSignatureSearch();
final PsiClass aClass = DumbService.getInstance(method.getProject()).runReadActionInSmartMode(new Computable<PsiClass>() {
final PsiClass aClass = DumbService.getInstance(p.getProject()).runReadActionInSmartMode(new Computable<PsiClass>() {
public PsiClass compute() {
PsiClass aClass = method.getContainingClass();
if (aClass == null) return null;
@@ -65,7 +65,7 @@ public class MethodUsagesSearcher extends QueryExecutorBase<PsiReference, Method
final SearchRequestCollector collector = p.getOptimizer();
final SearchScope searchScope = DumbService.getInstance(method.getProject()).runReadActionInSmartMode(new Computable<SearchScope>() {
final SearchScope searchScope = DumbService.getInstance(p.getProject()).runReadActionInSmartMode(new Computable<SearchScope>() {
@Override
public SearchScope compute() {
return p.getEffectiveSearchScope();
@@ -74,7 +74,7 @@ public class MethodUsagesSearcher extends QueryExecutorBase<PsiReference, Method
if (isConstructor[0]) {
new ConstructorReferencesSearchHelper(psiManager[0]).
processConstructorReferences(consumer, method, aClass, searchScope, false, strictSignatureSearch, collector);
processConstructorReferences(consumer, method, aClass, searchScope, p.getProject(), false, strictSignatureSearch, collector);
}
if (isValueAnnotation[0]) {
@@ -91,7 +91,7 @@ public class MethodUsagesSearcher extends QueryExecutorBase<PsiReference, Method
return;
}
DumbService.getInstance(method.getProject()).runReadActionInSmartMode(new Runnable() {
DumbService.getInstance(p.getProject()).runReadActionInSmartMode(new Runnable() {
public void run() {
final PsiMethod[] methods = strictSignatureSearch ? new PsiMethod[]{method} : aClass.findMethodsByName(methodName[0], false);
SearchScope accessScope = methods[0].getUseScope();