diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java index a5299ae5fb7f..600bfc0415a4 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java @@ -1,5 +1,8 @@ package com.intellij.psi.impl.search; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ReadActionProcessor; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.TextRange; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; @@ -12,6 +15,7 @@ import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiUtil; import com.intellij.util.PairProcessor; import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; /** * @author max @@ -19,31 +23,30 @@ import com.intellij.util.Processor; public class ConstructorReferencesSearchHelper { private final PsiManager myManager; - public ConstructorReferencesSearchHelper(final PsiManager manager) { + public ConstructorReferencesSearchHelper(@NotNull PsiManager manager) { myManager = manager; } - public boolean processConstructorReferences(final Processor processor, - final PsiMethod constructor, - final SearchScope searchScope, + public boolean processConstructorReferences(@NotNull final Processor processor, + @NotNull final PsiMethod constructor, + @NotNull final PsiClass containingClass, + @NotNull final SearchScope searchScope, boolean ignoreAccessScope, - final boolean isStrictSignatureSearch, SearchRequestCollector collector) { - PsiClass aClass = constructor.getContainingClass(); - if (aClass == null) { - return true; - } - - if (aClass.isEnum()) { - for (PsiField field : aClass.getFields()) { - if (field instanceof PsiEnumConstant) { - PsiReference reference = field.getReference(); - if (reference != null && reference.isReferenceTo(constructor)) { - if (!processor.process(reference)) { - return false; - } - } - } + final boolean isStrictSignatureSearch, + @NotNull SearchRequestCollector collector) { + final boolean[] constructorCanBeCalledImplicitly = new boolean[1]; + final boolean[] isEnum = new boolean[1]; + final boolean[] isUnder18 = new boolean[1]; + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + constructorCanBeCalledImplicitly[0] = constructor.getParameterList().getParametersCount() == 0; + isEnum[0] = containingClass.isEnum(); + isUnder18[0] = PsiUtil.getLanguageLevel(containingClass).isAtLeast(LanguageLevel.JDK_1_8); } + }); + + if (isEnum[0]) { + if (!processEnumReferences(processor, constructor, containingClass)) return false; } // search usages like "new XXX(..)" @@ -63,7 +66,7 @@ public class ConstructorReferencesSearchHelper { } } else { - if (myManager.areElementsEquivalent(constructor.getContainingClass(), constructor1.getContainingClass())) { + if (myManager.areElementsEquivalent(containingClass, constructor1.getContainingClass())) { return processor.process(reference); } } @@ -73,30 +76,18 @@ public class ConstructorReferencesSearchHelper { } }; - ReferencesSearch.searchOptimized(aClass, searchScope, ignoreAccessScope, collector, true, processor1); - if (PsiUtil.getLanguageLevel(aClass).isAtLeast(LanguageLevel.JDK_1_8)) { - ReferencesSearch.search(aClass).forEach(new Processor() { - @Override - public boolean process(PsiReference reference) { - final PsiElement element = reference.getElement(); - if (element != null) { - final PsiElement parent = element.getParent(); - if (parent instanceof PsiMethodReferenceExpression && - ((PsiMethodReferenceExpression)parent).getReferenceNameElement() instanceof PsiKeyword) { - if (((PsiMethodReferenceExpression)parent).isReferenceTo(constructor)) { - processor.process((PsiReference)parent); - } - } - } - return true; - } - }); + ReferencesSearch.searchOptimized(containingClass, searchScope, ignoreAccessScope, collector, true, processor1); + if (isUnder18[0]) { + if (!process18MethodPointers(processor, constructor, containingClass)) return false; } - final boolean constructorCanBeCalledImplicitly = constructor.getParameterList().getParametersCount() == 0; // search usages like "this(..)" - if (!processSuperOrThis(processor, aClass, constructor, constructorCanBeCalledImplicitly, searchScope, isStrictSignatureSearch, - PsiKeyword.THIS)) { + if (!ApplicationManager.getApplication().runReadAction(new Computable() { + public Boolean compute() { + return processSuperOrThis(containingClass, constructor, constructorCanBeCalledImplicitly[0], searchScope, isStrictSignatureSearch, + PsiKeyword.THIS, processor); + } + })) { return false; } @@ -106,23 +97,67 @@ public class ConstructorReferencesSearchHelper { public boolean process(PsiClass inheritor) { final PsiElement navigationElement = inheritor.getNavigationElement(); if (navigationElement instanceof PsiClass) { - return processSuperOrThis(processor, (PsiClass)navigationElement, constructor, constructorCanBeCalledImplicitly, searchScope, isStrictSignatureSearch, PsiKeyword.SUPER); + return processSuperOrThis((PsiClass)navigationElement, constructor, constructorCanBeCalledImplicitly[0], searchScope, + isStrictSignatureSearch, PsiKeyword.SUPER, processor); } return true; } }; - return ClassInheritorsSearch.search(aClass, searchScope, false).forEach(processor2); + return ClassInheritorsSearch.search(containingClass, searchScope, false).forEach(processor2); } - private boolean processSuperOrThis(final Processor processor, - final PsiClass inheritor, - final PsiMethod constructor, final boolean constructorCanBeCalledImplicitly, final SearchScope searchScope, - final boolean isStrictSignatureSearch, - final String superOrThisKeyword) { + private static boolean processEnumReferences(@NotNull final Processor processor, + @NotNull final PsiMethod constructor, + @NotNull final PsiClass aClass) { + return ApplicationManager.getApplication().runReadAction(new Computable() { + public Boolean compute() { + for (PsiField field : aClass.getFields()) { + if (field instanceof PsiEnumConstant) { + PsiReference reference = field.getReference(); + if (reference != null && reference.isReferenceTo(constructor)) { + if (!processor.process(reference)) { + return false; + } + } + } + } + return true; + } + }); + } + + private static boolean process18MethodPointers(@NotNull final Processor processor, + @NotNull final PsiMethod constructor, + @NotNull PsiClass aClass) { + return ReferencesSearch.search(aClass).forEach(new ReadActionProcessor() { + @Override + public boolean processInReadAction(PsiReference reference) { + final PsiElement element = reference.getElement(); + if (element != null) { + final PsiElement parent = element.getParent(); + if (parent instanceof PsiMethodReferenceExpression && + ((PsiMethodReferenceExpression)parent).getReferenceNameElement() instanceof PsiKeyword) { + if (((PsiMethodReferenceExpression)parent).isReferenceTo(constructor)) { + if (!processor.process((PsiReference)parent)) return false; + } + } + } + return true; + } + }); + } + + private boolean processSuperOrThis(@NotNull PsiClass inheritor, + @NotNull PsiMethod constructor, + final boolean constructorCanBeCalledImplicitly, + @NotNull SearchScope searchScope, + final boolean isStrictSignatureSearch, + @NotNull String superOrThisKeyword, + @NotNull Processor processor) { PsiMethod[] constructors = inheritor.getConstructors(); if (constructors.length == 0 && constructorCanBeCalledImplicitly) { - processImplicitConstructorCall(inheritor, processor, constructor, inheritor); + if (!processImplicitConstructorCall(inheritor, processor, constructor, inheritor)) return false; } for (PsiMethod method : constructors) { PsiCodeBlock body = method.getBody(); @@ -137,7 +172,7 @@ public class ConstructorReferencesSearchHelper { if (expr instanceof PsiMethodCallExpression) { PsiReferenceExpression refExpr = ((PsiMethodCallExpression)expr).getMethodExpression(); if (PsiSearchScopeUtil.isInScope(searchScope, refExpr)) { - if (refExpr.getText().equals(superOrThisKeyword)) { + if (refExpr.textMatches(superOrThisKeyword)) { PsiElement referencedElement = refExpr.resolve(); if (referencedElement instanceof PsiMethod) { PsiMethod constructor1 = (PsiMethod)referencedElement; @@ -154,43 +189,48 @@ public class ConstructorReferencesSearchHelper { } } if (constructorCanBeCalledImplicitly) { - processImplicitConstructorCall(method, processor, constructor, inheritor); + if (!processImplicitConstructorCall(method, processor, constructor, inheritor)) return false; } } return true; } - private void processImplicitConstructorCall(final PsiMember usage, - final Processor processor, - final PsiMethod constructor, - final PsiClass containingClass) { - if (containingClass instanceof PsiAnonymousClass) return; - PsiClass superClass = containingClass.getSuperClass(); - if (myManager.areElementsEquivalent(constructor.getContainingClass(), superClass)) { - processor.process(new LightMemberReference(myManager, usage, PsiSubstitutor.EMPTY) { - @Override - public PsiElement getElement() { - return usage; - } - - @Override - public TextRange getRangeInElement() { - if (usage instanceof PsiClass) { - PsiIdentifier identifier = ((PsiClass)usage).getNameIdentifier(); - if (identifier != null) return TextRange.from(identifier.getStartOffsetInParent(), identifier.getTextLength()); - } - else if (usage instanceof PsiField) { - PsiIdentifier identifier = ((PsiField)usage).getNameIdentifier(); - return TextRange.from(identifier.getStartOffsetInParent(), identifier.getTextLength()); - } - else if (usage instanceof PsiMethod) { - PsiIdentifier identifier = ((PsiMethod)usage).getNameIdentifier(); - if (identifier != null) return TextRange.from(identifier.getStartOffsetInParent(), identifier.getTextLength()); - } - return super.getRangeInElement(); - } - }); + private boolean processImplicitConstructorCall(@NotNull final PsiMember usage, + @NotNull final Processor processor, + @NotNull final PsiMethod constructor, + @NotNull final PsiClass containingClass) { + if (containingClass instanceof PsiAnonymousClass) return true; + boolean same = ApplicationManager.getApplication().runReadAction(new Computable() { + public Boolean compute() { + return myManager.areElementsEquivalent(constructor.getContainingClass(), containingClass.getSuperClass()); + } + }); + if (!same) { + return true; } + return processor.process(new LightMemberReference(myManager, usage, PsiSubstitutor.EMPTY) { + @Override + public PsiElement getElement() { + return usage; + } + + @Override + public TextRange getRangeInElement() { + if (usage instanceof PsiClass) { + PsiIdentifier identifier = ((PsiClass)usage).getNameIdentifier(); + if (identifier != null) return TextRange.from(identifier.getStartOffsetInParent(), identifier.getTextLength()); + } + else if (usage instanceof PsiField) { + PsiIdentifier identifier = ((PsiField)usage).getNameIdentifier(); + return TextRange.from(identifier.getStartOffsetInParent(), identifier.getTextLength()); + } + else if (usage instanceof PsiMethod) { + PsiIdentifier identifier = ((PsiMethod)usage).getNameIdentifier(); + if (identifier != null) return TextRange.from(identifier.getStartOffsetInParent(), identifier.getTextLength()); + } + return super.getRangeInElement(); + } + }); } } diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearcher.java index 933a748e9874..5bc07cb4e4bd 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearcher.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearcher.java @@ -1,9 +1,9 @@ package com.intellij.psi.impl.search; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.QueryExecutorBase; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiReference; +import com.intellij.openapi.util.Computable; +import com.intellij.psi.*; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; @@ -12,16 +12,26 @@ import org.jetbrains.annotations.NotNull; * @author max */ public class ConstructorReferencesSearcher extends QueryExecutorBase { - public ConstructorReferencesSearcher() { - super(true); - } - @Override public void processQuery(@NotNull ReferencesSearch.SearchParameters p, @NotNull Processor consumer) { final PsiElement element = p.getElementToSearch(); - if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) { - new ConstructorReferencesSearchHelper(element.getManager()) - .processConstructorReferences(consumer, (PsiMethod)p.getElementToSearch(), p.getScope(), p.isIgnoreAccessScope(), true, p.getOptimizer()); + if (!(element instanceof PsiMethod)) { + return; } + final PsiMethod method = (PsiMethod)element; + final PsiManager[] manager = new PsiManager[1]; + PsiClass aClass = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiClass compute() { + if (!method.isConstructor()) return null; + PsiClass aClass = method.getContainingClass(); + manager[0] = aClass == null ? null : aClass.getManager(); + return aClass; + } + }); + if (aClass == null) { + return; + } + new ConstructorReferencesSearchHelper(manager[0]) + .processConstructorReferences(consumer, method, aClass, p.getScope(), p.isIgnoreAccessScope(), true, p.getOptimizer()); } } diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java index 49bd3f3c2ca3..ec298ce5c8c6 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java @@ -1,7 +1,8 @@ package com.intellij.psi.impl.search; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.QueryExecutorBase; -import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.search.SearchRequestCollector; @@ -17,66 +18,77 @@ import org.jetbrains.annotations.NotNull; * @author max */ public class MethodUsagesSearcher extends QueryExecutorBase { - private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.search.MethodUsagesSearcher"); - public MethodUsagesSearcher() { - super(true); - } - @Override public void processQuery(@NotNull MethodReferencesSearch.SearchParameters p, @NotNull final Processor consumer) { final PsiMethod method = p.getMethod(); + final boolean[] isConstructor = new boolean[1]; + final PsiManager[] psiManager = new PsiManager[1]; + final String[] methodName = new String[1]; + final boolean[] isValueAnnotation = new boolean[1]; + final boolean[] needStrictSignatureSearch = new boolean[1]; + final boolean strictSignatureSearch = p.isStrictSignatureSearch(); + + final PsiClass aClass = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiClass compute() { + PsiClass aClass = method.getContainingClass(); + if (aClass == null) return null; + isConstructor[0] = method.isConstructor(); + psiManager[0] = aClass.getManager(); + methodName[0] = method.getName(); + isValueAnnotation[0] = PsiUtil.isAnnotationMethod(method) && + PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals(methodName[0]) && + method.getParameterList().getParametersCount() == 0; + needStrictSignatureSearch[0] = strictSignatureSearch && (aClass instanceof PsiAnonymousClass + || aClass.hasModifierProperty(PsiModifier.FINAL) + || method.hasModifierProperty(PsiModifier.STATIC) + || method.hasModifierProperty(PsiModifier.FINAL) + || method.hasModifierProperty(PsiModifier.PRIVATE)); + return aClass; + } + }); + if (aClass == null) return; + final SearchRequestCollector collector = p.getOptimizer(); final SearchScope searchScope = p.getScope(); - final PsiManager psiManager = method.getManager(); - - final PsiClass aClass = method.getContainingClass(); - if (aClass == null) return; - - final boolean strictSignatureSearch = p.isStrictSignatureSearch(); - - if (method.isConstructor()) { - new ConstructorReferencesSearchHelper(psiManager). - processConstructorReferences(consumer, method, searchScope, !strictSignatureSearch, strictSignatureSearch, collector); + if (isConstructor[0]) { + new ConstructorReferencesSearchHelper(psiManager[0]). + processConstructorReferences(consumer, method, aClass, searchScope, !strictSignatureSearch, strictSignatureSearch, collector); } - if (PsiUtil.isAnnotationMethod(method) && - PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals(method.getName()) && - method.getParameterList().getParametersCount() == 0) { - ReferencesSearch.search(aClass, p.getScope()).forEach(PsiAnnotationMethodReferencesSearcher.createImplicitDefaultAnnotationMethodConsumer( consumer)); + if (isValueAnnotation[0]) { + Processor refProcessor = PsiAnnotationMethodReferencesSearcher.createImplicitDefaultAnnotationMethodConsumer(consumer); + ReferencesSearch.search(aClass, searchScope).forEach(refProcessor); } - boolean needStrictSignatureSearch = strictSignatureSearch && (aClass instanceof PsiAnonymousClass - || aClass.hasModifierProperty(PsiModifier.FINAL) - || method.hasModifierProperty(PsiModifier.STATIC) - || method.hasModifierProperty(PsiModifier.FINAL) - || method.hasModifierProperty(PsiModifier.PRIVATE)); - if (needStrictSignatureSearch) { + if (needStrictSignatureSearch[0]) { ReferencesSearch.searchOptimized(method, searchScope, false, collector, consumer); return; } - final String textToSearch = method.getName(); - if (StringUtil.isEmpty(textToSearch)) { + if (StringUtil.isEmpty(methodName[0])) { return; } - final PsiMethod[] methods = strictSignatureSearch ? new PsiMethod[]{method} : aClass.findMethodsByName(textToSearch, false); - SearchScope accessScope = methods[0].getUseScope(); - for (int i = 1; i < methods.length; i++) { - PsiMethod method1 = methods[i]; - accessScope = accessScope.union(method1.getUseScope()); - } + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + final PsiMethod[] methods = strictSignatureSearch ? new PsiMethod[]{method} : aClass.findMethodsByName(methodName[0], false); + SearchScope accessScope = methods[0].getUseScope(); + for (int i = 1; i < methods.length; i++) { + PsiMethod method1 = methods[i]; + accessScope = accessScope.union(method1.getUseScope()); + } - final SearchScope restrictedByAccess = searchScope.intersectWith(accessScope); + SearchScope restrictedByAccessScope = searchScope.intersectWith(accessScope); - short searchContext = UsageSearchContext.IN_CODE | UsageSearchContext.IN_COMMENTS | UsageSearchContext.IN_FOREIGN_LANGUAGES; - collector.searchWord(textToSearch, restrictedByAccess, searchContext, true, - new MethodTextOccurrenceProcessor(aClass, strictSignatureSearch, methods)); - - SimpleAccessorReferenceSearcher.addPropertyAccessUsages(method, restrictedByAccess, collector); + short searchContext = UsageSearchContext.IN_CODE | UsageSearchContext.IN_COMMENTS | UsageSearchContext.IN_FOREIGN_LANGUAGES; + collector.searchWord(methodName[0], restrictedByAccessScope, searchContext, true, + new MethodTextOccurrenceProcessor(aClass, strictSignatureSearch, methods)); + SimpleAccessorReferenceSearcher.addPropertyAccessUsages(method, restrictedByAccessScope, collector); + } + }); } }