update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / find / findUsages / JavaFindUsagesHandler.java
blob035e43899a302a1b405f7af7ff1c284e5012ce84
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 || setter != null) {
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 if (psiMethod.hasModifierProperty(PsiModifier.ABSTRACT)) {
332 if (options.isImplementingMethods){
333 processOverridingMethods(psiMethod, processor, options);
336 else if (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(final PsiMethod psiMethod,
347 final Processor<UsageInfo> processor, final FindUsagesOptions options) {
348 OverridingMethodsSearch.search(psiMethod, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiMethod>(
349 new PsiElementProcessor<PsiMethod>() {
350 public boolean execute(PsiMethod element) {
351 addResult(processor, element.getNavigationElement(), options, null);
352 return true;
355 }));
359 private static void addClassesUsages(PsiPackage aPackage, final Processor<UsageInfo> results, final FindUsagesOptions options) {
360 final HashSet<PsiFile> filesSet = new HashSet<PsiFile>();
361 final ArrayList<PsiFile> files = new ArrayList<PsiFile>();
362 ReferencesSearch.search(aPackage, options.searchScope, false).forEach(new ReadActionProcessor<PsiReference>() {
363 public boolean processInReadAction(final PsiReference psiReference) {
364 PsiElement ref = psiReference.getElement();
365 PsiFile file = ref.getContainingFile();
366 if (filesSet.add(file)) {
367 files.add(file);
369 return true;
373 ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
374 if (progress != null){
375 progress.pushState();
378 ArrayList<PsiClass> classes = new ArrayList<PsiClass>();
379 addClassesInPackage(aPackage, options.isIncludeSubpackages, classes);
380 for (final PsiClass aClass : classes) {
381 if (progress != null) {
382 progress.setText(FindBundle.message("find.searching.for.references.to.class.progress", aClass.getName()));
384 for (PsiFile file : files) {
385 ProgressManager.getInstance().checkCanceled();
386 ReferencesSearch.search(aClass, new LocalSearchScope(file), false).forEach(new ReadActionProcessor<PsiReference>() {
387 public boolean processInReadAction(final PsiReference psiReference) {
388 return addResult(results, psiReference, options, aClass);
394 if (progress != null){
395 progress.popState();
399 private static void addClassesInPackage(PsiPackage aPackage, boolean includeSubpackages, ArrayList<PsiClass> array) {
400 PsiDirectory[] dirs = aPackage.getDirectories();
401 for (PsiDirectory dir : dirs) {
402 addClassesInDirectory(dir, includeSubpackages, array);
406 private static void addClassesInDirectory(final PsiDirectory dir, final boolean includeSubdirs, final ArrayList<PsiClass> array) {
407 ApplicationManager.getApplication().runReadAction(new Runnable() {
408 public void run() {
409 PsiClass[] classes = JavaDirectoryService.getInstance().getClasses(dir);
410 array.addAll(Arrays.asList(classes));
411 if (includeSubdirs) {
412 PsiDirectory[] dirs = dir.getSubdirectories();
413 for (PsiDirectory directory : dirs) {
414 addClassesInDirectory(directory, includeSubdirs, array);
421 private static void addMethodsUsages(final PsiClass aClass, final Processor<UsageInfo> results, final FindUsagesOptions options) {
422 if (options.isIncludeInherited) {
423 final PsiManager manager = aClass.getManager();
424 PsiMethod[] methods = aClass.getAllMethods();
425 MethodsLoop:
426 for(int i = 0; i < methods.length; i++){
427 final PsiMethod method = methods[i];
428 // filter overriden methods
429 MethodSignature methodSignature = method.getSignature(PsiSubstitutor.EMPTY);
430 for(int j = 0; j < i; j++){
431 if (methodSignature.equals(methods[j].getSignature(PsiSubstitutor.EMPTY))) continue MethodsLoop;
433 final PsiClass methodClass = method.getContainingClass();
434 if (methodClass != null && manager.areElementsEquivalent(methodClass, aClass)){
435 addMethodUsages(methods[i], results, options, options.searchScope);
437 else{
438 boolean strictSignatureSearch = !options.isIncludeOverloadUsages;
439 MethodReferencesSearch.search(method, options.searchScope, strictSignatureSearch).forEach(new PsiReferenceProcessorAdapter(new PsiReferenceProcessor() {
440 public boolean execute(PsiReference reference) {
441 addResultFromReference(reference, methodClass, manager, aClass, results, options, method);
442 return true;
444 }));
448 else {
449 PsiMethod[] methods = aClass.getMethods();
450 for (PsiMethod method : methods) {
451 addMethodUsages(method, results, options, options.searchScope);
456 private static void addFieldsUsages(final PsiClass aClass, final Processor<UsageInfo> results, final FindUsagesOptions options) {
457 if (options.isIncludeInherited) {
458 final PsiManager manager = aClass.getManager();
459 PsiField[] fields = aClass.getAllFields();
460 FieldsLoop:
461 for (int i = 0; i < fields.length; i++) {
462 final PsiField field = fields[i];
463 // filter hidden fields
464 for (int j = 0; j < i; j++) {
465 if (Comparing.strEqual(field.getName(), fields[j].getName())) continue FieldsLoop;
467 final PsiClass fieldClass = field.getContainingClass();
468 if (manager.areElementsEquivalent(fieldClass, aClass)) {
469 addElementUsages(fields[i], results, options);
471 else {
472 ReferencesSearch.search(field, options.searchScope, false).forEach(new ReadActionProcessor<PsiReference>() {
473 public boolean processInReadAction(final PsiReference reference) {
474 addResultFromReference(reference, fieldClass, manager, aClass, results, options, field);
475 return true;
481 else {
482 PsiField[] fields = ApplicationManager.getApplication().runReadAction(new Computable<PsiField[]>() {
483 public PsiField[] compute() {
484 return aClass.getFields();
487 for (PsiField field : fields) {
488 addElementUsages(field, results, options);
493 @Nullable
494 private static PsiClass getFieldOrMethodAccessedClass(PsiReferenceExpression ref, PsiClass fieldOrMethodClass) {
495 PsiElement[] children = ref.getChildren();
496 if (children.length > 1 && children[0] instanceof PsiExpression) {
497 PsiExpression expr = (PsiExpression)children[0];
498 PsiType type = expr.getType();
499 if (type != null) {
500 if (!(type instanceof PsiClassType)) return null;
501 return PsiUtil.resolveClassInType(type);
503 else {
504 if (expr instanceof PsiReferenceExpression) {
505 PsiElement refElement = ((PsiReferenceExpression)expr).resolve();
506 if (refElement instanceof PsiClass) return (PsiClass)refElement;
508 return null;
511 PsiManager manager = ref.getManager();
512 for(PsiElement parent = ref; parent != null; parent = parent.getParent()){
513 if (parent instanceof PsiClass
514 && (manager.areElementsEquivalent(parent, fieldOrMethodClass) || ((PsiClass)parent).isInheritor(fieldOrMethodClass, true))){
515 return (PsiClass)parent;
518 return null;
521 private static void addInheritors(final PsiClass aClass, final Processor<UsageInfo> results, final FindUsagesOptions options) {
522 ClassInheritorsSearch.search(aClass, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>(
523 new PsiElementProcessor<PsiClass>() {
524 public boolean execute(PsiClass element) {
525 addResult(results, element, options, null);
526 return true;
529 }));
532 private static void addDerivedInterfaces(PsiClass anInterface, final Processor<UsageInfo> results, final FindUsagesOptions options) {
533 ClassInheritorsSearch.search(anInterface, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>(
534 new PsiElementProcessor<PsiClass>() {
535 public boolean execute(PsiClass inheritor) {
536 if (inheritor.isInterface()) {
537 addResult(results, inheritor, options, null);
539 return true;
542 }));
545 private static void addImplementingClasses(PsiClass anInterface, final Processor<UsageInfo> results, final FindUsagesOptions options) {
546 ClassInheritorsSearch.search(anInterface, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>(
547 new PsiElementProcessor<PsiClass>() {
548 public boolean execute(PsiClass inheritor) {
549 if (!inheritor.isInterface()) {
550 addResult(results, inheritor, options, null);
552 return true;
555 }));
558 private static void addResultFromReference(final PsiReference reference,
559 final PsiClass methodClass,
560 final PsiManager manager,
561 final PsiClass aClass,
562 final Processor<UsageInfo> results,
563 final FindUsagesOptions options,
564 final PsiElement element) {
565 PsiElement refElement = reference.getElement();
566 if (refElement instanceof PsiReferenceExpression) {
567 PsiClass usedClass = getFieldOrMethodAccessedClass((PsiReferenceExpression)refElement, methodClass);
568 if (usedClass != null) {
569 if (manager.areElementsEquivalent(usedClass, aClass) || usedClass.isInheritor(aClass, true)) {
570 addResult(results, refElement, options, element);
576 public static void addElementUsages(final PsiElement element, final Processor<UsageInfo> results, final FindUsagesOptions options) {
577 if (element instanceof PsiMethod){
578 addMethodUsages((PsiMethod)element, results, options, options.searchScope);
580 else {
581 ReferencesSearch.search(element, options.searchScope, false).forEach(new ReadActionProcessor<PsiReference>() {
582 public boolean processInReadAction(final PsiReference ref) {
583 return addResult(results, ref, options, element);
589 private static void addMethodUsages(final PsiMethod method, final Processor<UsageInfo> result, final FindUsagesOptions options, SearchScope searchScope) {
590 if (method.isConstructor()) {
591 if (options.isIncludeOverloadUsages) {
592 for (PsiMethod constructor : method.getContainingClass().getConstructors()) {
593 addConstructorUsages(constructor, searchScope, result, options);
596 else {
597 addConstructorUsages(method, searchScope, result, options);
600 else {
601 boolean strictSignatureSearch = !options.isIncludeOverloadUsages;
602 MethodReferencesSearch.search(method, searchScope, strictSignatureSearch).forEach(new PsiReferenceProcessorAdapter(new PsiReferenceProcessor() {
603 public boolean execute(PsiReference ref) {
604 return addResult(result, ref, options, method);
606 }));
610 private static void addConstructorUsages(PsiMethod method, SearchScope searchScope, final Processor<UsageInfo> result, final FindUsagesOptions options) {
611 final PsiClass parentClass = method.getContainingClass();
612 if (parentClass == null) return;
614 ReferencesSearch.search(method, searchScope, false).forEach(new ReadActionProcessor<PsiReference>() {
615 public boolean processInReadAction(final PsiReference ref) {
616 return addResult(result, ref, options, parentClass);
621 public static void addResult(Processor<UsageInfo> total, PsiElement element, FindUsagesOptions options, PsiElement refElement) {
622 if (filterUsage(element, options, refElement)){
623 total.process(new UsageInfo(element));
627 public static boolean addResult(Processor<UsageInfo> results, PsiReference ref, FindUsagesOptions options, PsiElement refElement) {
628 if (filterUsage(ref.getElement(), options, refElement)){
629 TextRange rangeInElement = ref.getRangeInElement();
630 return results.process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false));
632 return true;
635 private static boolean filterUsage(PsiElement usage, FindUsagesOptions options, PsiElement refElement) {
636 if (!(usage instanceof PsiJavaCodeReferenceElement)) {
637 return true;
639 if (refElement instanceof PsiPackage && !options.isIncludeSubpackages &&
640 ((PsiReference)usage).resolve() instanceof PsiPackage) {
641 PsiElement parent = usage.getParent();
642 if (parent instanceof PsiJavaCodeReferenceElement && ((PsiJavaCodeReferenceElement)parent).resolve() instanceof PsiPackage) {
643 return false;
647 if (!(usage instanceof PsiReferenceExpression)){
648 if (options.isSkipImportStatements){
649 PsiElement parent = usage.getParent();
650 while(parent instanceof PsiJavaCodeReferenceElement){
651 parent = parent.getParent();
653 if (parent instanceof PsiImportStatement){
654 return false;
658 if (options.isSkipPackageStatements){
659 PsiElement parent = usage.getParent();
660 while(parent instanceof PsiJavaCodeReferenceElement){
661 parent = parent.getParent();
663 if (parent instanceof PsiPackageStatement){
664 return false;
668 return true;
672 protected boolean isSearchForTextOccurencesAvailable(PsiElement psiElement, boolean isSingleFile) {
673 if (isSingleFile) return false;
674 if (psiElement instanceof PsiClass) {
675 return ((PsiClass)psiElement).getQualifiedName() != null;
677 return psiElement instanceof PsiPackage;
680 public Collection<PsiReference> findReferencesToHighlight(final PsiElement target, final SearchScope searchScope) {
681 if (target instanceof PsiMethod) {
682 return MethodReferencesSearch.search((PsiMethod)target, searchScope, true).findAll();
684 return super.findReferencesToHighlight(target, searchScope);