don't show 3 identical groovy property usages (IDEA-50789), and don't ask to search...
[fedora-idea.git] / java / java-impl / src / com / intellij / find / findUsages / JavaFindUsagesHandler.java
blob752d4677189ed751b925d76925eef9ebfabc2374
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.find.findUsages;
18 import com.intellij.CommonBundle;
19 import com.intellij.find.FindBundle;
20 import com.intellij.ide.util.SuperMethodWarningUtil;
21 import com.intellij.openapi.application.ApplicationManager;
22 import com.intellij.openapi.application.ReadActionProcessor;
23 import com.intellij.openapi.diagnostic.Logger;
24 import com.intellij.openapi.progress.ProgressIndicator;
25 import com.intellij.openapi.progress.ProgressManager;
26 import com.intellij.openapi.ui.DialogWrapper;
27 import com.intellij.openapi.ui.Messages;
28 import com.intellij.openapi.util.Comparing;
29 import com.intellij.openapi.util.Computable;
30 import com.intellij.openapi.util.TextRange;
31 import com.intellij.psi.*;
32 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
33 import com.intellij.psi.codeStyle.VariableKind;
34 import com.intellij.psi.impl.search.ThrowSearchUtil;
35 import com.intellij.psi.meta.PsiMetaData;
36 import com.intellij.psi.meta.PsiMetaOwner;
37 import com.intellij.psi.search.*;
38 import com.intellij.psi.search.searches.ClassInheritorsSearch;
39 import com.intellij.psi.search.searches.MethodReferencesSearch;
40 import com.intellij.psi.search.searches.OverridingMethodsSearch;
41 import com.intellij.psi.search.searches.ReferencesSearch;
42 import com.intellij.psi.util.MethodSignature;
43 import com.intellij.psi.util.PropertyUtil;
44 import com.intellij.psi.util.PsiUtil;
45 import com.intellij.psi.xml.XmlAttributeValue;
46 import com.intellij.usageView.UsageInfo;
47 import com.intellij.util.Processor;
48 import com.intellij.util.containers.ContainerUtil;
49 import org.jetbrains.annotations.NotNull;
50 import org.jetbrains.annotations.Nullable;
52 import java.util.*;
54 /**
55 * @author peter
57 public class JavaFindUsagesHandler extends FindUsagesHandler{
58 private static final Logger LOG = Logger.getInstance("#com.intellij.find.findUsages.DefaultFindUsagesHandler");
59 public static final String ACTION_STRING = FindBundle.message("find.super.method.warning.action.verb");
61 private final PsiElement[] myElementsToSearch;
62 private final FindUsagesOptions myFindPackageOptions;
63 private final FindUsagesOptions myFindClassOptions;
64 private final FindUsagesOptions myFindMethodOptions;
65 private final FindUsagesOptions myFindVariableOptions;
66 private final FindUsagesOptions myFindThrowOptions;
68 public JavaFindUsagesHandler(@NotNull PsiElement psiElement,
69 @NotNull FindUsagesOptions findClassOptions,
70 @NotNull FindUsagesOptions findMethodOptions,
71 @NotNull FindUsagesOptions findPackageOptions,
72 @NotNull FindUsagesOptions findThrowOptions,
73 @NotNull FindUsagesOptions findVariableOptions) {
74 this(psiElement, PsiElement.EMPTY_ARRAY, findClassOptions, findMethodOptions, findPackageOptions, findThrowOptions, findVariableOptions);
78 public JavaFindUsagesHandler(@NotNull PsiElement psiElement,
79 @NotNull PsiElement[] elementsToSearch,
80 @NotNull FindUsagesOptions findClassOptions,
81 @NotNull FindUsagesOptions findMethodOptions,
82 @NotNull FindUsagesOptions findPackageOptions,
83 @NotNull FindUsagesOptions findThrowOptions,
84 @NotNull FindUsagesOptions findVariableOptions) {
85 super(psiElement);
86 myElementsToSearch = elementsToSearch;
87 myFindClassOptions = findClassOptions;
88 myFindMethodOptions = findMethodOptions;
89 myFindPackageOptions = findPackageOptions;
90 myFindThrowOptions = findThrowOptions;
91 myFindVariableOptions = findVariableOptions;
94 @NotNull
95 public AbstractFindUsagesDialog getFindUsagesDialog(boolean isSingleFile, boolean toShowInNewTab, boolean mustOpenInNewTab) {
96 PsiElement element = getPsiElement();
97 if (element instanceof PsiPackage) {
98 return new FindPackageUsagesDialog(element, getProject(), myFindPackageOptions, toShowInNewTab, mustOpenInNewTab, isSingleFile, this);
100 if (element instanceof PsiClass) {
101 return new FindClassUsagesDialog(element, getProject(), myFindClassOptions, toShowInNewTab, mustOpenInNewTab, isSingleFile, this);
103 if (element instanceof PsiMethod) {
104 return new FindMethodUsagesDialog(element, getProject(), myFindMethodOptions, toShowInNewTab, mustOpenInNewTab, isSingleFile, this);
106 if (element instanceof PsiVariable) {
107 return new FindVariableUsagesDialog(element, getProject(), myFindVariableOptions, toShowInNewTab, mustOpenInNewTab, isSingleFile, this);
109 if (ThrowSearchUtil.isSearchable(element)) {
110 return new FindThrowUsagesDialog(element, getProject(), myFindThrowOptions, toShowInNewTab, mustOpenInNewTab, isSingleFile, this);
112 return super.getFindUsagesDialog(isSingleFile, toShowInNewTab, mustOpenInNewTab);
115 private static boolean askWhetherShouldSearchForParameterInOverridingMethods(final PsiElement psiElement, final PsiParameter parameter) {
116 return Messages.showDialog(psiElement.getProject(),
117 FindBundle.message("find.parameter.usages.in.overriding.methods.prompt", parameter.getName()),
118 FindBundle.message("find.parameter.usages.in.overriding.methods.title"),
119 new String[]{CommonBundle.getYesButtonText(), CommonBundle.getNoButtonText()}, 0,
120 Messages.getQuestionIcon()) == 0;
123 private static PsiElement[] getParameterElementsToSearch(final PsiParameter parameter) {
124 final PsiMethod method = (PsiMethod)parameter.getDeclarationScope();
125 PsiMethod[] overrides = OverridingMethodsSearch.search(method, method.getUseScope(), true).toArray(PsiMethod.EMPTY_ARRAY);
126 for (int i = 0; i < overrides.length; i++) {
127 overrides[i] = (PsiMethod)overrides[i].getNavigationElement();
129 PsiElement[] elementsToSearch = new PsiElement[overrides.length + 1];
130 elementsToSearch[0] = parameter;
131 int idx = method.getParameterList().getParameterIndex(parameter);
132 for (int i = 0; i < overrides.length; i++) {
133 elementsToSearch[i + 1] = overrides[i].getParameterList().getParameters()[idx];
135 return elementsToSearch;
139 @NotNull
140 public PsiElement[] getPrimaryElements() {
141 final PsiElement element = getPsiElement();
142 if (element instanceof PsiParameter) {
143 final PsiParameter parameter = (PsiParameter)element;
144 final PsiElement scope = parameter.getDeclarationScope();
145 if (scope instanceof PsiMethod) {
146 final PsiMethod method = (PsiMethod)scope;
147 if (PsiUtil.canBeOverriden(method)) {
148 final PsiClass aClass = method.getContainingClass();
149 LOG.assertTrue(aClass != null); //Otherwise can not be overriden
151 boolean hasOverridden = OverridingMethodsSearch.search(method).findFirst() != null;
152 if (hasOverridden && askWhetherShouldSearchForParameterInOverridingMethods(element, parameter)) {
153 return getParameterElementsToSearch(parameter);
158 return myElementsToSearch.length == 0 ? new PsiElement[]{element} : myElementsToSearch;
161 @NotNull
162 public PsiElement[] getSecondaryElements() {
163 PsiElement element = getPsiElement();
164 if (element instanceof PsiField) {
165 final PsiField field = (PsiField)element;
166 PsiClass containingClass = field.getContainingClass();
167 if (containingClass != null) {
168 final String propertyName = JavaCodeStyleManager.getInstance(getProject()).variableNameToPropertyName(field.getName(), VariableKind.FIELD);
169 PsiMethod getter = PropertyUtil.
170 findPropertyGetterWithType(propertyName, field.hasModifierProperty(PsiModifier.STATIC), field.getType(),
171 ContainerUtil.iterate(containingClass.getMethods()));
172 PsiMethod setter = PropertyUtil.
173 findPropertySetterWithType(propertyName, field.hasModifierProperty(PsiModifier.STATIC), field.getType(),
174 ContainerUtil.iterate(containingClass.getMethods()));
175 if (getter != null && getter.isPhysical() || setter != null && setter.isPhysical()) {
176 if (Messages.showDialog(FindBundle.message("find.field.accessors.prompt", field.getName()),
177 FindBundle.message("find.field.accessors.title"),
178 new String[]{CommonBundle.getYesButtonText(), CommonBundle.getNoButtonText()}, 0,
179 Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE) {
180 final List<PsiElement> elements = new ArrayList<PsiElement>();
181 if (getter != null) {
182 elements.addAll(Arrays.asList(SuperMethodWarningUtil.checkSuperMethods(getter, ACTION_STRING)));
184 if (setter != null) {
185 elements.addAll(Arrays.asList(SuperMethodWarningUtil.checkSuperMethods(setter, ACTION_STRING)));
187 return elements.toArray(new PsiElement[elements.size()]);
192 return super.getSecondaryElements();
195 @NotNull
196 public FindUsagesOptions getFindUsagesOptions() {
197 PsiElement element = getPsiElement();
198 if (element instanceof PsiPackage) {
199 return myFindPackageOptions;
201 if (element instanceof PsiClass) {
202 return myFindClassOptions;
204 if (element instanceof PsiMethod) {
205 return myFindMethodOptions;
207 if (element instanceof PsiVariable) {
208 return myFindVariableOptions;
210 if (ThrowSearchUtil.isSearchable(element)) {
211 return myFindThrowOptions;
213 return super.getFindUsagesOptions();
216 @Override
217 protected String getStringToSearch(final PsiElement element) {
218 return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
219 public String compute() {
220 PsiElement norm = element;
221 if (element instanceof PsiDirectory) { // normalize a directory to a corresponding package
222 norm = JavaDirectoryService.getInstance().getPackage((PsiDirectory)element);
224 if (norm instanceof PsiPackage) {
225 return ((PsiPackage)norm).getQualifiedName();
227 if (norm instanceof PsiClass) {
228 return ((PsiClass)norm).getQualifiedName();
230 if (norm instanceof PsiMethod) {
231 return ((PsiMethod)norm).getName();
233 if (norm instanceof PsiVariable) {
234 return ((PsiVariable)norm).getName();
236 if (norm instanceof PsiMetaOwner) {
237 final PsiMetaData metaData = ((PsiMetaOwner)norm).getMetaData();
238 if (metaData != null) {
239 return metaData.getName();
242 if (norm instanceof PsiNamedElement) {
243 return ((PsiNamedElement)norm).getName();
245 if (norm instanceof XmlAttributeValue) {
246 return ((XmlAttributeValue)norm).getValue();
249 LOG.error("Unknown element type: " + element);
250 return null;
255 @Override
256 public void processElementUsages(@NotNull final PsiElement element, @NotNull final Processor<UsageInfo> processor, @NotNull final FindUsagesOptions options) {
257 if (element instanceof PsiVariable){
258 if (options.isReadAccess || options.isWriteAccess){
259 if (options.isReadAccess && options.isWriteAccess){
260 //todo[myakovlev] this also shows param in javadoc (PsiDocParamRef), but should not
261 addElementUsages(element, processor, options);
263 else{
264 addElementUsages(element, new Processor<UsageInfo>() {
265 public boolean process(UsageInfo info) {
266 final PsiElement element = info.getElement();
267 boolean isWrite = element instanceof PsiExpression && PsiUtil.isAccessedForWriting((PsiExpression)element);
268 if (isWrite == options.isWriteAccess) {
269 if (!processor.process(info)) return false;
271 return true;
273 }, options);
277 else if (options.isUsages) {
278 addElementUsages(element, processor, options);
281 ApplicationManager.getApplication().runReadAction(new Runnable() {
282 public void run() {
283 if (ThrowSearchUtil.isSearchable (element) && options.isThrowUsages) {
284 ThrowSearchUtil.Root root = options.getUserData(ThrowSearchUtil.THROW_SEARCH_ROOT_KEY);
285 if (root == null) {
286 final ThrowSearchUtil.Root[] roots = ThrowSearchUtil.getSearchRoots(element);
287 if (roots != null && roots.length > 0) {
288 root = roots [0];
291 if (root != null) {
292 ThrowSearchUtil.addThrowUsages(processor, root, options);
298 if (element instanceof PsiPackage && options.isClassesUsages){
299 addClassesUsages((PsiPackage)element, processor, options);
302 if (element instanceof PsiClass && options.isMethodsUsages){
303 addMethodsUsages((PsiClass)element, processor, options);
306 if (element instanceof PsiClass && options.isFieldsUsages){
307 addFieldsUsages((PsiClass)element, processor, options);
310 if (element instanceof PsiClass){
311 if (((PsiClass)element).isInterface()) {
312 if (options.isDerivedInterfaces){
313 if (options.isImplementingClasses){
314 addInheritors((PsiClass)element, processor, options);
316 else{
317 addDerivedInterfaces((PsiClass)element, processor, options);
320 else if (options.isImplementingClasses){
321 addImplementingClasses((PsiClass)element, processor, options);
324 else if (options.isDerivedClasses) {
325 addInheritors((PsiClass)element, processor, options);
329 if (element instanceof PsiMethod){
330 final PsiMethod psiMethod = (PsiMethod)element;
331 boolean isAbstract = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
332 public Boolean compute() {
333 return psiMethod.hasModifierProperty(PsiModifier.ABSTRACT);
336 if (isAbstract && options.isImplementingMethods || options.isOverridingMethods) {
337 processOverridingMethods(psiMethod, processor, options);
341 if (!ThrowSearchUtil.isSearchable(element) && options.isSearchForTextOccurences && options.searchScope instanceof GlobalSearchScope) {
342 processUsagesInText(element, processor, (GlobalSearchScope)options.searchScope);
346 private static void processOverridingMethods(PsiMethod psiMethod, final Processor<UsageInfo> processor, final FindUsagesOptions options) {
347 OverridingMethodsSearch.search(psiMethod, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiMethod>(
348 new PsiElementProcessor<PsiMethod>() {
349 public boolean execute(PsiMethod element) {
350 addResult(processor, element.getNavigationElement(), options, null);
351 return true;
353 }));
357 private static void addClassesUsages(PsiPackage aPackage, final Processor<UsageInfo> results, final FindUsagesOptions options) {
358 final HashSet<PsiFile> filesSet = new HashSet<PsiFile>();
359 final ArrayList<PsiFile> files = new ArrayList<PsiFile>();
360 ReferencesSearch.search(aPackage, options.searchScope, false).forEach(new ReadActionProcessor<PsiReference>() {
361 public boolean processInReadAction(final PsiReference psiReference) {
362 PsiElement ref = psiReference.getElement();
363 PsiFile file = ref.getContainingFile();
364 if (filesSet.add(file)) {
365 files.add(file);
367 return true;
371 ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
372 if (progress != null){
373 progress.pushState();
376 ArrayList<PsiClass> classes = new ArrayList<PsiClass>();
377 addClassesInPackage(aPackage, options.isIncludeSubpackages, classes);
378 for (final PsiClass aClass : classes) {
379 if (progress != null) {
380 progress.setText(FindBundle.message("find.searching.for.references.to.class.progress", aClass.getName()));
382 for (PsiFile file : files) {
383 ProgressManager.checkCanceled();
384 ReferencesSearch.search(aClass, new LocalSearchScope(file), false).forEach(new ReadActionProcessor<PsiReference>() {
385 public boolean processInReadAction(final PsiReference psiReference) {
386 return addResult(results, psiReference, options, aClass);
392 if (progress != null){
393 progress.popState();
397 private static void addClassesInPackage(PsiPackage aPackage, boolean includeSubpackages, ArrayList<PsiClass> array) {
398 PsiDirectory[] dirs = aPackage.getDirectories();
399 for (PsiDirectory dir : dirs) {
400 addClassesInDirectory(dir, includeSubpackages, array);
404 private static void addClassesInDirectory(final PsiDirectory dir, final boolean includeSubdirs, final ArrayList<PsiClass> array) {
405 ApplicationManager.getApplication().runReadAction(new Runnable() {
406 public void run() {
407 PsiClass[] classes = JavaDirectoryService.getInstance().getClasses(dir);
408 array.addAll(Arrays.asList(classes));
409 if (includeSubdirs) {
410 PsiDirectory[] dirs = dir.getSubdirectories();
411 for (PsiDirectory directory : dirs) {
412 addClassesInDirectory(directory, includeSubdirs, array);
419 private static void addMethodsUsages(final PsiClass aClass, final Processor<UsageInfo> results, final FindUsagesOptions options) {
420 if (options.isIncludeInherited) {
421 final PsiManager manager = aClass.getManager();
422 PsiMethod[] methods = aClass.getAllMethods();
423 MethodsLoop:
424 for(int i = 0; i < methods.length; i++){
425 final PsiMethod method = methods[i];
426 // filter overriden methods
427 MethodSignature methodSignature = method.getSignature(PsiSubstitutor.EMPTY);
428 for(int j = 0; j < i; j++){
429 if (methodSignature.equals(methods[j].getSignature(PsiSubstitutor.EMPTY))) continue MethodsLoop;
431 final PsiClass methodClass = method.getContainingClass();
432 if (methodClass != null && manager.areElementsEquivalent(methodClass, aClass)){
433 addMethodUsages(methods[i], results, options, options.searchScope);
435 else{
436 boolean strictSignatureSearch = !options.isIncludeOverloadUsages;
437 MethodReferencesSearch.search(method, options.searchScope, strictSignatureSearch).forEach(new PsiReferenceProcessorAdapter(new PsiReferenceProcessor() {
438 public boolean execute(PsiReference reference) {
439 addResultFromReference(reference, methodClass, manager, aClass, results, options, method);
440 return true;
442 }));
446 else {
447 PsiMethod[] methods = aClass.getMethods();
448 for (PsiMethod method : methods) {
449 addMethodUsages(method, results, options, options.searchScope);
454 private static void addFieldsUsages(final PsiClass aClass, final Processor<UsageInfo> results, final FindUsagesOptions options) {
455 if (options.isIncludeInherited) {
456 final PsiManager manager = aClass.getManager();
457 PsiField[] fields = aClass.getAllFields();
458 FieldsLoop:
459 for (int i = 0; i < fields.length; i++) {
460 final PsiField field = fields[i];
461 // filter hidden fields
462 for (int j = 0; j < i; j++) {
463 if (Comparing.strEqual(field.getName(), fields[j].getName())) continue FieldsLoop;
465 final PsiClass fieldClass = field.getContainingClass();
466 if (manager.areElementsEquivalent(fieldClass, aClass)) {
467 addElementUsages(fields[i], results, options);
469 else {
470 ReferencesSearch.search(field, options.searchScope, false).forEach(new ReadActionProcessor<PsiReference>() {
471 public boolean processInReadAction(final PsiReference reference) {
472 addResultFromReference(reference, fieldClass, manager, aClass, results, options, field);
473 return true;
479 else {
480 PsiField[] fields = ApplicationManager.getApplication().runReadAction(new Computable<PsiField[]>() {
481 public PsiField[] compute() {
482 return aClass.getFields();
485 for (PsiField field : fields) {
486 addElementUsages(field, results, options);
491 @Nullable
492 private static PsiClass getFieldOrMethodAccessedClass(PsiReferenceExpression ref, PsiClass fieldOrMethodClass) {
493 PsiElement[] children = ref.getChildren();
494 if (children.length > 1 && children[0] instanceof PsiExpression) {
495 PsiExpression expr = (PsiExpression)children[0];
496 PsiType type = expr.getType();
497 if (type != null) {
498 if (!(type instanceof PsiClassType)) return null;
499 return PsiUtil.resolveClassInType(type);
501 else {
502 if (expr instanceof PsiReferenceExpression) {
503 PsiElement refElement = ((PsiReferenceExpression)expr).resolve();
504 if (refElement instanceof PsiClass) return (PsiClass)refElement;
506 return null;
509 PsiManager manager = ref.getManager();
510 for(PsiElement parent = ref; parent != null; parent = parent.getParent()){
511 if (parent instanceof PsiClass
512 && (manager.areElementsEquivalent(parent, fieldOrMethodClass) || ((PsiClass)parent).isInheritor(fieldOrMethodClass, true))){
513 return (PsiClass)parent;
516 return null;
519 private static void addInheritors(final PsiClass aClass, final Processor<UsageInfo> results, final FindUsagesOptions options) {
520 ClassInheritorsSearch.search(aClass, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>(
521 new PsiElementProcessor<PsiClass>() {
522 public boolean execute(PsiClass element) {
523 addResult(results, element, options, null);
524 return true;
527 }));
530 private static void addDerivedInterfaces(PsiClass anInterface, final Processor<UsageInfo> results, final FindUsagesOptions options) {
531 ClassInheritorsSearch.search(anInterface, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>(
532 new PsiElementProcessor<PsiClass>() {
533 public boolean execute(PsiClass inheritor) {
534 if (inheritor.isInterface()) {
535 addResult(results, inheritor, options, null);
537 return true;
540 }));
543 private static void addImplementingClasses(PsiClass anInterface, final Processor<UsageInfo> results, final FindUsagesOptions options) {
544 ClassInheritorsSearch.search(anInterface, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>(
545 new PsiElementProcessor<PsiClass>() {
546 public boolean execute(PsiClass inheritor) {
547 if (!inheritor.isInterface()) {
548 addResult(results, inheritor, options, null);
550 return true;
553 }));
556 private static void addResultFromReference(final PsiReference reference,
557 final PsiClass methodClass,
558 final PsiManager manager,
559 final PsiClass aClass,
560 final Processor<UsageInfo> results,
561 final FindUsagesOptions options,
562 final PsiElement element) {
563 PsiElement refElement = reference.getElement();
564 if (refElement instanceof PsiReferenceExpression) {
565 PsiClass usedClass = getFieldOrMethodAccessedClass((PsiReferenceExpression)refElement, methodClass);
566 if (usedClass != null) {
567 if (manager.areElementsEquivalent(usedClass, aClass) || usedClass.isInheritor(aClass, true)) {
568 addResult(results, refElement, options, element);
574 public static void addElementUsages(final PsiElement element, final Processor<UsageInfo> results, final FindUsagesOptions options) {
575 if (element instanceof PsiMethod){
576 addMethodUsages((PsiMethod)element, results, options, options.searchScope);
578 else {
579 ReferencesSearch.search(element, options.searchScope, false).forEach(new ReadActionProcessor<PsiReference>() {
580 public boolean processInReadAction(final PsiReference ref) {
581 return addResult(results, ref, options, element);
587 private static void addMethodUsages(final PsiMethod method, final Processor<UsageInfo> result, final FindUsagesOptions options, SearchScope searchScope) {
588 if (method.isConstructor()) {
589 if (options.isIncludeOverloadUsages) {
590 for (PsiMethod constructor : method.getContainingClass().getConstructors()) {
591 addConstructorUsages(constructor, searchScope, result, options);
594 else {
595 addConstructorUsages(method, searchScope, result, options);
598 else {
599 boolean strictSignatureSearch = !options.isIncludeOverloadUsages;
600 MethodReferencesSearch.search(method, searchScope, strictSignatureSearch).forEach(new PsiReferenceProcessorAdapter(new PsiReferenceProcessor() {
601 public boolean execute(PsiReference ref) {
602 return addResult(result, ref, options, method);
604 }));
608 private static void addConstructorUsages(PsiMethod method, SearchScope searchScope, final Processor<UsageInfo> result, final FindUsagesOptions options) {
609 final PsiClass parentClass = method.getContainingClass();
610 if (parentClass == null) return;
612 ReferencesSearch.search(method, searchScope, false).forEach(new ReadActionProcessor<PsiReference>() {
613 public boolean processInReadAction(final PsiReference ref) {
614 return addResult(result, ref, options, parentClass);
619 public static void addResult(Processor<UsageInfo> total, PsiElement element, FindUsagesOptions options, PsiElement refElement) {
620 if (filterUsage(element, options, refElement)){
621 total.process(new UsageInfo(element));
625 public static boolean addResult(Processor<UsageInfo> results, PsiReference ref, FindUsagesOptions options, PsiElement refElement) {
626 if (filterUsage(ref.getElement(), options, refElement)){
627 TextRange rangeInElement = ref.getRangeInElement();
628 return results.process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false));
630 return true;
633 private static boolean filterUsage(PsiElement usage, FindUsagesOptions options, PsiElement refElement) {
634 if (!(usage instanceof PsiJavaCodeReferenceElement)) {
635 return true;
637 if (refElement instanceof PsiPackage && !options.isIncludeSubpackages &&
638 ((PsiReference)usage).resolve() instanceof PsiPackage) {
639 PsiElement parent = usage.getParent();
640 if (parent instanceof PsiJavaCodeReferenceElement && ((PsiJavaCodeReferenceElement)parent).resolve() instanceof PsiPackage) {
641 return false;
645 if (!(usage instanceof PsiReferenceExpression)){
646 if (options.isSkipImportStatements){
647 PsiElement parent = usage.getParent();
648 while(parent instanceof PsiJavaCodeReferenceElement){
649 parent = parent.getParent();
651 if (parent instanceof PsiImportStatement){
652 return false;
656 if (options.isSkipPackageStatements){
657 PsiElement parent = usage.getParent();
658 while(parent instanceof PsiJavaCodeReferenceElement){
659 parent = parent.getParent();
661 if (parent instanceof PsiPackageStatement){
662 return false;
666 return true;
670 protected boolean isSearchForTextOccurencesAvailable(PsiElement psiElement, boolean isSingleFile) {
671 if (isSingleFile) return false;
672 if (psiElement instanceof PsiClass) {
673 return ((PsiClass)psiElement).getQualifiedName() != null;
675 return psiElement instanceof PsiPackage;
678 public Collection<PsiReference> findReferencesToHighlight(final PsiElement target, final SearchScope searchScope) {
679 if (target instanceof PsiMethod) {
680 return MethodReferencesSearch.search((PsiMethod)target, searchScope, true).findAll();
682 return super.findReferencesToHighlight(target, searchScope);