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
;
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
) {
86 myElementsToSearch
= elementsToSearch
;
87 myFindClassOptions
= findClassOptions
;
88 myFindMethodOptions
= findMethodOptions
;
89 myFindPackageOptions
= findPackageOptions
;
90 myFindThrowOptions
= findThrowOptions
;
91 myFindVariableOptions
= findVariableOptions
;
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
;
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
;
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();
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();
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
);
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
);
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;
277 else if (options
.isUsages
) {
278 addElementUsages(element
, processor
, options
);
281 ApplicationManager
.getApplication().runReadAction(new Runnable() {
283 if (ThrowSearchUtil
.isSearchable (element
) && options
.isThrowUsages
) {
284 ThrowSearchUtil
.Root root
= options
.getUserData(ThrowSearchUtil
.THROW_SEARCH_ROOT_KEY
);
286 final ThrowSearchUtil
.Root
[] roots
= ThrowSearchUtil
.getSearchRoots(element
);
287 if (roots
!= null && roots
.length
> 0) {
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
);
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);
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
)) {
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){
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() {
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();
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
);
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
);
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();
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
);
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
);
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
);
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();
498 if (!(type
instanceof PsiClassType
)) return null;
499 return PsiUtil
.resolveClassInType(type
);
502 if (expr
instanceof PsiReferenceExpression
) {
503 PsiElement refElement
= ((PsiReferenceExpression
)expr
).resolve();
504 if (refElement
instanceof PsiClass
) return (PsiClass
)refElement
;
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
;
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);
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);
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);
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
);
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
);
595 addConstructorUsages(method
, searchScope
, result
, options
);
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
);
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));
633 private static boolean filterUsage(PsiElement usage
, FindUsagesOptions options
, PsiElement refElement
) {
634 if (!(usage
instanceof PsiJavaCodeReferenceElement
)) {
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
) {
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
){
656 if (options
.isSkipPackageStatements
){
657 PsiElement parent
= usage
.getParent();
658 while(parent
instanceof PsiJavaCodeReferenceElement
){
659 parent
= parent
.getParent();
661 if (parent
instanceof PsiPackageStatement
){
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
);