mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
number of moves to make processElementUsages() available in java-analysis
This commit is contained in:
@@ -0,0 +1,654 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.find.findUsages;
|
||||
|
||||
import com.intellij.find.FindBundle;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadActionProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.NullableComputable;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.pom.PomTarget;
|
||||
import com.intellij.pom.references.PomService;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.search.ThrowSearchUtil;
|
||||
import com.intellij.psi.meta.PsiMetaData;
|
||||
import com.intellij.psi.meta.PsiMetaOwner;
|
||||
import com.intellij.psi.search.*;
|
||||
import com.intellij.psi.search.searches.*;
|
||||
import com.intellij.psi.targets.AliasingPsiTarget;
|
||||
import com.intellij.psi.targets.AliasingPsiTargetMapper;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.xml.XmlAttributeValue;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class JavaFindUsagesHelper {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.find.findUsages.JavaFindUsagesHelper");
|
||||
|
||||
@NotNull
|
||||
static Set<String> getElementNames(@NotNull final PsiElement element) {
|
||||
if (element instanceof PsiDirectory) { // normalize a directory to a corresponding package
|
||||
PsiPackage aPackage = ApplicationManager.getApplication().runReadAction(new Computable<PsiPackage>() {
|
||||
@Override
|
||||
public PsiPackage compute() {
|
||||
return JavaDirectoryService.getInstance().getPackage((PsiDirectory)element);
|
||||
}
|
||||
});
|
||||
return aPackage == null ? Collections.<String>emptySet() : getElementNames(aPackage);
|
||||
}
|
||||
|
||||
final Set<String> result = new HashSet<String>();
|
||||
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (element instanceof PsiPackage) {
|
||||
ContainerUtil.addIfNotNull(result, ((PsiPackage)element).getQualifiedName());
|
||||
}
|
||||
else if (element instanceof PsiClass) {
|
||||
final String qname = ((PsiClass)element).getQualifiedName();
|
||||
if (qname != null) {
|
||||
result.add(qname);
|
||||
PsiClass topLevelClass = PsiUtil.getTopLevelClass(element);
|
||||
if (topLevelClass != null) {
|
||||
String topName = topLevelClass.getQualifiedName();
|
||||
assert topName != null;
|
||||
if (qname.length() > topName.length()) {
|
||||
result.add(topName + qname.substring(topName.length()).replace('.', '$'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (element instanceof PsiMethod) {
|
||||
ContainerUtil.addIfNotNull(result, ((PsiMethod)element).getName());
|
||||
}
|
||||
else if (element instanceof PsiVariable) {
|
||||
ContainerUtil.addIfNotNull(result, ((PsiVariable)element).getName());
|
||||
}
|
||||
else if (element instanceof PsiMetaOwner) {
|
||||
final PsiMetaData metaData = ((PsiMetaOwner)element).getMetaData();
|
||||
if (metaData != null) {
|
||||
ContainerUtil.addIfNotNull(result, metaData.getName());
|
||||
}
|
||||
}
|
||||
else if (element instanceof PsiNamedElement) {
|
||||
ContainerUtil.addIfNotNull(result, ((PsiNamedElement)element).getName());
|
||||
}
|
||||
else if (element instanceof XmlAttributeValue) {
|
||||
ContainerUtil.addIfNotNull(result, ((XmlAttributeValue)element).getValue());
|
||||
}
|
||||
else {
|
||||
LOG.error("Unknown element type: " + element);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean processElementUsages(@NotNull final PsiElement element,
|
||||
@NotNull final FindUsagesOptions options, @NotNull final Processor<UsageInfo> processor) {
|
||||
if (options instanceof JavaVariableFindUsagesOptions) {
|
||||
final JavaVariableFindUsagesOptions varOptions = (JavaVariableFindUsagesOptions) options;
|
||||
if (varOptions.isReadAccess || varOptions.isWriteAccess){
|
||||
if (varOptions.isReadAccess && varOptions.isWriteAccess){
|
||||
if (!addElementUsages(element, options, processor)) return false;
|
||||
}
|
||||
else{
|
||||
if (!addElementUsages(element, varOptions, new Processor<UsageInfo>() {
|
||||
@Override
|
||||
public boolean process(UsageInfo info) {
|
||||
final PsiElement element = info.getElement();
|
||||
boolean isWrite = element instanceof PsiExpression && PsiUtil.isAccessedForWriting((PsiExpression)element);
|
||||
if (isWrite == varOptions.isWriteAccess) {
|
||||
if (!processor.process(info)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
})) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (options.isUsages) {
|
||||
if (!addElementUsages(element, options, processor)) return false;
|
||||
}
|
||||
|
||||
boolean success = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
if (ThrowSearchUtil.isSearchable(element) && options instanceof JavaThrowFindUsagesOptions && options.isUsages) {
|
||||
ThrowSearchUtil.Root root = ((JavaThrowFindUsagesOptions)options).getRoot();
|
||||
if (root == null) {
|
||||
final ThrowSearchUtil.Root[] roots = ThrowSearchUtil.getSearchRoots(element);
|
||||
if (roots != null && roots.length > 0) {
|
||||
root = roots [0];
|
||||
}
|
||||
}
|
||||
if (root != null) {
|
||||
return ThrowSearchUtil.addThrowUsages(processor, root, options);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!success) return false;
|
||||
|
||||
if (options instanceof JavaPackageFindUsagesOptions && ((JavaPackageFindUsagesOptions)options).isClassesUsages){
|
||||
if (!addClassesUsages((PsiPackage)element, (JavaPackageFindUsagesOptions)options, processor)) return false;
|
||||
}
|
||||
|
||||
if (options instanceof JavaClassFindUsagesOptions) {
|
||||
final JavaClassFindUsagesOptions classOptions = (JavaClassFindUsagesOptions)options;
|
||||
final PsiClass psiClass = (PsiClass)element;
|
||||
PsiManager manager = ApplicationManager.getApplication().runReadAction(new Computable<PsiManager>() {
|
||||
@Override
|
||||
public PsiManager compute() {
|
||||
return psiClass.getManager();
|
||||
}
|
||||
});
|
||||
if (classOptions.isMethodsUsages){
|
||||
if (!addMethodsUsages(psiClass, manager, classOptions, processor)) return false;
|
||||
}
|
||||
if (classOptions.isFieldsUsages){
|
||||
if (!addFieldsUsages(psiClass, manager, classOptions, processor)) return false;
|
||||
}
|
||||
if (psiClass.isInterface()) {
|
||||
if (classOptions.isDerivedInterfaces){
|
||||
if (classOptions.isImplementingClasses){
|
||||
if (!addInheritors(psiClass, classOptions, processor)) return false;
|
||||
}
|
||||
else{
|
||||
if (!addDerivedInterfaces(psiClass, classOptions, processor)) return false;
|
||||
}
|
||||
}
|
||||
else if (classOptions.isImplementingClasses){
|
||||
if (!addImplementingClasses(psiClass, classOptions, processor)) return false;
|
||||
}
|
||||
|
||||
if (classOptions.isImplementingClasses) {
|
||||
FunctionalExpressionSearch
|
||||
.search(psiClass, classOptions.searchScope).forEach(new PsiElementProcessorAdapter<PsiFunctionalExpression>(
|
||||
new PsiElementProcessor<PsiFunctionalExpression>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiFunctionalExpression expression) {
|
||||
return addResult(expression, options, processor);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
else if (classOptions.isDerivedClasses) {
|
||||
if (!addInheritors(psiClass, classOptions, processor)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (options instanceof JavaMethodFindUsagesOptions){
|
||||
final PsiMethod psiMethod = (PsiMethod)element;
|
||||
boolean isAbstract = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return psiMethod.hasModifierProperty(PsiModifier.ABSTRACT);
|
||||
}
|
||||
});
|
||||
final JavaMethodFindUsagesOptions methodOptions = (JavaMethodFindUsagesOptions)options;
|
||||
if (isAbstract && methodOptions.isImplementingMethods || methodOptions.isOverridingMethods) {
|
||||
if (!processOverridingMethods(psiMethod, processor, methodOptions)) return false;
|
||||
FunctionalExpressionSearch.search(psiMethod, methodOptions.searchScope).forEach(new PsiElementProcessorAdapter<PsiFunctionalExpression>(
|
||||
new PsiElementProcessor<PsiFunctionalExpression>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiFunctionalExpression expression) {
|
||||
return addResult(expression, options, processor);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (element instanceof PomTarget) {
|
||||
if (!addAliasingUsages((PomTarget)element, options, processor)) return false;
|
||||
}
|
||||
final Boolean isSearchable = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return ThrowSearchUtil.isSearchable(element);
|
||||
}
|
||||
});
|
||||
if (!isSearchable && options.isSearchForTextOccurrences && options.searchScope instanceof GlobalSearchScope) {
|
||||
Collection<String> stringsToSearch = ApplicationManager.getApplication().runReadAction(new NullableComputable<Collection<String>>() {
|
||||
@Override
|
||||
public Collection<String> compute() {
|
||||
return getElementNames(element);
|
||||
}
|
||||
});
|
||||
// todo add to fastTrack
|
||||
if (!FindUsagesHelper.processUsagesInText(element, stringsToSearch, (GlobalSearchScope)options.searchScope, processor)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean addAliasingUsages(@NotNull PomTarget pomTarget,
|
||||
@NotNull final FindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
for (AliasingPsiTargetMapper aliasingPsiTargetMapper : Extensions.getExtensions(AliasingPsiTargetMapper.EP_NAME)) {
|
||||
for (AliasingPsiTarget psiTarget : aliasingPsiTargetMapper.getTargets(pomTarget)) {
|
||||
boolean success = ReferencesSearch
|
||||
.search(new ReferencesSearch.SearchParameters(PomService.convertToPsi(psiTarget), options.searchScope, false, options.fastTrack))
|
||||
.forEach(new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(final PsiReference reference) {
|
||||
return addResult(reference, options, processor);
|
||||
}
|
||||
});
|
||||
if (!success) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean processOverridingMethods(@NotNull PsiMethod psiMethod,
|
||||
@NotNull final Processor<UsageInfo> processor,
|
||||
@NotNull final JavaMethodFindUsagesOptions options) {
|
||||
return OverridingMethodsSearch.search(psiMethod, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiMethod>(
|
||||
new PsiElementProcessor<PsiMethod>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiMethod element) {
|
||||
return addResult(element.getNavigationElement(), options, processor);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private static boolean addClassesUsages(@NotNull PsiPackage aPackage,
|
||||
@NotNull final JavaPackageFindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
|
||||
if (progress != null){
|
||||
progress.pushState();
|
||||
}
|
||||
|
||||
List<PsiClass> classes = new ArrayList<PsiClass>();
|
||||
addClassesInPackage(aPackage, options.isIncludeSubpackages, classes);
|
||||
for (final PsiClass aClass : classes) {
|
||||
if (progress != null) {
|
||||
String name = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
@Override
|
||||
public String compute() {
|
||||
return aClass.getName();
|
||||
}
|
||||
});
|
||||
progress.setText(FindBundle.message("find.searching.for.references.to.class.progress", name));
|
||||
progress.checkCanceled();
|
||||
}
|
||||
boolean success = ReferencesSearch.search(new ReferencesSearch.SearchParameters(aClass, options.searchScope, false, options.fastTrack)).forEach(new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(final PsiReference psiReference) {
|
||||
return addResult(psiReference, options, processor);
|
||||
}
|
||||
});
|
||||
if (!success) return false;
|
||||
}
|
||||
|
||||
if (progress != null){
|
||||
progress.popState();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void addClassesInPackage(@NotNull final PsiPackage aPackage, boolean includeSubpackages, @NotNull List<PsiClass> array) {
|
||||
PsiDirectory[] dirs = ApplicationManager.getApplication().runReadAction(new Computable<PsiDirectory[]>() {
|
||||
@Override
|
||||
public PsiDirectory[] compute() {
|
||||
return aPackage.getDirectories();
|
||||
}
|
||||
});
|
||||
for (PsiDirectory dir : dirs) {
|
||||
addClassesInDirectory(dir, includeSubpackages, array);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addClassesInDirectory(@NotNull final PsiDirectory dir,
|
||||
final boolean includeSubdirs,
|
||||
@NotNull final List<PsiClass> array) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PsiClass[] classes = JavaDirectoryService.getInstance().getClasses(dir);
|
||||
ContainerUtil.addAll(array, classes);
|
||||
if (includeSubdirs) {
|
||||
PsiDirectory[] dirs = dir.getSubdirectories();
|
||||
for (PsiDirectory directory : dirs) {
|
||||
addClassesInDirectory(directory, includeSubdirs, array);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean addMethodsUsages(@NotNull final PsiClass aClass,
|
||||
@NotNull final PsiManager manager,
|
||||
@NotNull final JavaClassFindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
if (options.isIncludeInherited) {
|
||||
final PsiMethod[] methods = ApplicationManager.getApplication().runReadAction(new Computable<PsiMethod[]>() {
|
||||
@Override
|
||||
public PsiMethod[] compute() {
|
||||
return aClass.getAllMethods();
|
||||
}
|
||||
});
|
||||
for(int i = 0; i < methods.length; i++){
|
||||
final PsiMethod method = methods[i];
|
||||
// filter overridden methods
|
||||
final int finalI = i;
|
||||
final PsiClass methodClass =
|
||||
ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
|
||||
@Override
|
||||
public PsiClass compute() {
|
||||
MethodSignature methodSignature = method.getSignature(PsiSubstitutor.EMPTY);
|
||||
for (int j = 0; j < finalI; j++) {
|
||||
if (methodSignature.equals(methods[j].getSignature(PsiSubstitutor.EMPTY))) return null;
|
||||
}
|
||||
return method.getContainingClass();
|
||||
}
|
||||
});
|
||||
if (methodClass == null) continue;
|
||||
boolean equivalent = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return manager.areElementsEquivalent(methodClass, aClass);
|
||||
}
|
||||
});
|
||||
if (equivalent){
|
||||
if (!addElementUsages(method, options, processor)) return false;
|
||||
}
|
||||
else {
|
||||
MethodReferencesSearch.SearchParameters parameters =
|
||||
new MethodReferencesSearch.SearchParameters(method, options.searchScope, true, options.fastTrack);
|
||||
boolean success = MethodReferencesSearch.search(parameters)
|
||||
.forEach(new PsiReferenceProcessorAdapter(new PsiReferenceProcessor() {
|
||||
@Override
|
||||
public boolean execute(PsiReference reference) {
|
||||
addResultFromReference(reference, methodClass, manager, aClass, options, processor);
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
if (!success) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiMethod[] methods = ApplicationManager.getApplication().runReadAction(new Computable<PsiMethod[]>() {
|
||||
@Override
|
||||
public PsiMethod[] compute() {
|
||||
return aClass.getMethods();
|
||||
}
|
||||
});
|
||||
for (PsiMethod method : methods) {
|
||||
if (!addElementUsages(method, options, processor)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean addFieldsUsages(@NotNull final PsiClass aClass,
|
||||
@NotNull final PsiManager manager,
|
||||
@NotNull final JavaClassFindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
if (options.isIncludeInherited) {
|
||||
final PsiField[] fields = ApplicationManager.getApplication().runReadAction(new Computable<PsiField[]>() {
|
||||
@Override
|
||||
public PsiField[] compute() {
|
||||
return aClass.getAllFields();
|
||||
}
|
||||
});
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
final PsiField field = fields[i];
|
||||
// filter hidden fields
|
||||
final int finalI = i;
|
||||
final PsiClass fieldClass =
|
||||
ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
|
||||
@Override
|
||||
public PsiClass compute() {
|
||||
for (int j = 0; j < finalI; j++) {
|
||||
if (Comparing.strEqual(field.getName(), fields[j].getName())) return null;
|
||||
}
|
||||
return field.getContainingClass();
|
||||
}
|
||||
});
|
||||
if (fieldClass == null) continue;
|
||||
boolean equivalent = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return manager.areElementsEquivalent(fieldClass, aClass);
|
||||
}
|
||||
});
|
||||
if (equivalent) {
|
||||
if (!addElementUsages(fields[i], options, processor)) return false;
|
||||
}
|
||||
else {
|
||||
boolean success = ReferencesSearch.search(new ReferencesSearch.SearchParameters(field, options.searchScope, false, options.fastTrack)).forEach(new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(final PsiReference reference) {
|
||||
return addResultFromReference(reference, fieldClass, manager, aClass, options, processor);
|
||||
}
|
||||
});
|
||||
if (!success) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiField[] fields = ApplicationManager.getApplication().runReadAction(new Computable<PsiField[]>() {
|
||||
@Override
|
||||
public PsiField[] compute() {
|
||||
return aClass.getFields();
|
||||
}
|
||||
});
|
||||
for (PsiField field : fields) {
|
||||
if (!addElementUsages(field, options, processor)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiClass getFieldOrMethodAccessedClass(@NotNull PsiReferenceExpression ref, @NotNull PsiClass fieldOrMethodClass) {
|
||||
PsiElement[] children = ref.getChildren();
|
||||
if (children.length > 1 && children[0] instanceof PsiExpression) {
|
||||
PsiExpression expr = (PsiExpression)children[0];
|
||||
PsiType type = expr.getType();
|
||||
if (type != null) {
|
||||
if (!(type instanceof PsiClassType)) return null;
|
||||
return PsiUtil.resolveClassInType(type);
|
||||
}
|
||||
else {
|
||||
if (expr instanceof PsiReferenceExpression) {
|
||||
PsiElement refElement = ((PsiReferenceExpression)expr).resolve();
|
||||
if (refElement instanceof PsiClass) return (PsiClass)refElement;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
PsiManager manager = ref.getManager();
|
||||
for(PsiElement parent = ref; parent != null; parent = parent.getParent()){
|
||||
if (parent instanceof PsiClass
|
||||
&& (manager.areElementsEquivalent(parent, fieldOrMethodClass) || ((PsiClass)parent).isInheritor(fieldOrMethodClass, true))){
|
||||
return (PsiClass)parent;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean addInheritors(@NotNull PsiClass aClass,
|
||||
@NotNull final JavaClassFindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
return ClassInheritorsSearch.search(aClass, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>(
|
||||
new PsiElementProcessor<PsiClass>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiClass element) {
|
||||
return addResult(element, options, processor);
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
|
||||
private static boolean addDerivedInterfaces(@NotNull PsiClass anInterface,
|
||||
@NotNull final JavaClassFindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
return ClassInheritorsSearch.search(anInterface, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>(
|
||||
new PsiElementProcessor<PsiClass>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiClass inheritor) {
|
||||
return !inheritor.isInterface() || addResult(inheritor, options, processor);
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
|
||||
private static boolean addImplementingClasses(@NotNull PsiClass anInterface,
|
||||
@NotNull final JavaClassFindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
return ClassInheritorsSearch.search(anInterface, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>(
|
||||
new PsiElementProcessor<PsiClass>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiClass inheritor) {
|
||||
return inheritor.isInterface() || addResult(inheritor, options, processor);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private static boolean addResultFromReference(@NotNull PsiReference reference,
|
||||
@NotNull PsiClass methodClass,
|
||||
@NotNull PsiManager manager,
|
||||
@NotNull PsiClass aClass,
|
||||
@NotNull FindUsagesOptions options,
|
||||
@NotNull Processor<UsageInfo> processor) {
|
||||
PsiElement refElement = reference.getElement();
|
||||
if (refElement instanceof PsiReferenceExpression) {
|
||||
PsiClass usedClass = getFieldOrMethodAccessedClass((PsiReferenceExpression)refElement, methodClass);
|
||||
if (usedClass != null) {
|
||||
if (manager.areElementsEquivalent(usedClass, aClass) || usedClass.isInheritor(aClass, true)) {
|
||||
if (!addResult(refElement, options, processor)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean addElementUsages(@NotNull final PsiElement element,
|
||||
@NotNull final FindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
final SearchScope searchScope = options.searchScope;
|
||||
final PsiClass[] parentClass = new PsiClass[1];
|
||||
if (element instanceof PsiMethod && ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
PsiMethod method = (PsiMethod)element;
|
||||
parentClass[0] = method.getContainingClass();
|
||||
return method.isConstructor();
|
||||
}
|
||||
})) {
|
||||
PsiMethod method = (PsiMethod)element;
|
||||
|
||||
if (parentClass[0] != null) {
|
||||
boolean strictSignatureSearch =
|
||||
!(options instanceof JavaMethodFindUsagesOptions) || !((JavaMethodFindUsagesOptions)options).isIncludeOverloadUsages;
|
||||
return MethodReferencesSearch
|
||||
.search(new MethodReferencesSearch.SearchParameters(method, searchScope, strictSignatureSearch, options.fastTrack))
|
||||
.forEach(new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(final PsiReference ref) {
|
||||
return addResult(ref, options, processor);
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
final ReadActionProcessor<PsiReference> consumer = new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(final PsiReference ref) {
|
||||
return addResult(ref, options, processor);
|
||||
}
|
||||
};
|
||||
|
||||
if (element instanceof PsiMethod) {
|
||||
final boolean strictSignatureSearch = !(options instanceof JavaMethodFindUsagesOptions) || // field with getter
|
||||
!((JavaMethodFindUsagesOptions)options).isIncludeOverloadUsages;
|
||||
return MethodReferencesSearch
|
||||
.search(new MethodReferencesSearch.SearchParameters((PsiMethod)element, searchScope, strictSignatureSearch, options.fastTrack))
|
||||
.forEach(consumer);
|
||||
}
|
||||
return ReferencesSearch.search(new ReferencesSearch.SearchParameters(element, searchScope, false, options.fastTrack)).forEach(consumer);
|
||||
}
|
||||
|
||||
private static boolean addResult(@NotNull PsiElement element,
|
||||
@NotNull FindUsagesOptions options,
|
||||
@NotNull Processor<UsageInfo> processor) {
|
||||
return !filterUsage(element, options) || processor.process(new UsageInfo(element));
|
||||
}
|
||||
|
||||
private static boolean addResult(@NotNull PsiReference ref, @NotNull FindUsagesOptions options, @NotNull Processor<UsageInfo> processor) {
|
||||
if (filterUsage(ref.getElement(), options)){
|
||||
TextRange rangeInElement = ref.getRangeInElement();
|
||||
return processor.process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean filterUsage(PsiElement usage, @NotNull FindUsagesOptions options) {
|
||||
if (!(usage instanceof PsiJavaCodeReferenceElement)) {
|
||||
return true;
|
||||
}
|
||||
if (options instanceof JavaPackageFindUsagesOptions && !((JavaPackageFindUsagesOptions)options).isIncludeSubpackages &&
|
||||
((PsiReference)usage).resolve() instanceof PsiPackage) {
|
||||
PsiElement parent = usage.getParent();
|
||||
if (parent instanceof PsiJavaCodeReferenceElement && ((PsiJavaCodeReferenceElement)parent).resolve() instanceof PsiPackage) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(usage instanceof PsiReferenceExpression)){
|
||||
if (options instanceof JavaFindUsagesOptions && ((JavaFindUsagesOptions)options).isSkipImportStatements){
|
||||
PsiElement parent = usage.getParent();
|
||||
while(parent instanceof PsiJavaCodeReferenceElement){
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent instanceof PsiImportStatement){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (options instanceof JavaPackageFindUsagesOptions && ((JavaPackageFindUsagesOptions)options).isSkipPackageStatements){
|
||||
PsiElement parent = usage.getParent();
|
||||
while(parent instanceof PsiJavaCodeReferenceElement){
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent instanceof PsiPackageStatement){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -20,33 +20,18 @@ import com.intellij.find.FindBundle;
|
||||
import com.intellij.ide.util.SuperMethodWarningUtil;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadActionProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.pom.PomTarget;
|
||||
import com.intellij.pom.references.PomService;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.impl.search.ThrowSearchUtil;
|
||||
import com.intellij.psi.meta.PsiMetaData;
|
||||
import com.intellij.psi.meta.PsiMetaOwner;
|
||||
import com.intellij.psi.search.*;
|
||||
import com.intellij.psi.search.searches.*;
|
||||
import com.intellij.psi.targets.AliasingPsiTarget;
|
||||
import com.intellij.psi.targets.AliasingPsiTargetMapper;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.psi.xml.XmlAttributeValue;
|
||||
import com.intellij.refactoring.util.JavaNonCodeSearchElementDescriptionProvider;
|
||||
import com.intellij.refactoring.util.NonCodeSearchDescriptionLocation;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
@@ -221,598 +206,16 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{
|
||||
|
||||
@Override
|
||||
protected Set<String> getStringsToSearch(@NotNull final PsiElement element) {
|
||||
if (element instanceof PsiDirectory) { // normalize a directory to a corresponding package
|
||||
PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage((PsiDirectory)element);
|
||||
return aPackage == null ? Collections.<String>emptySet() : getStringsToSearch(aPackage);
|
||||
}
|
||||
|
||||
final Set<String> result = new HashSet<String>();
|
||||
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (element instanceof PsiPackage) {
|
||||
ContainerUtil.addIfNotNull(result, ((PsiPackage)element).getQualifiedName());
|
||||
}
|
||||
else if (element instanceof PsiClass) {
|
||||
final String qname = ((PsiClass)element).getQualifiedName();
|
||||
if (qname != null) {
|
||||
result.add(qname);
|
||||
PsiClass topLevelClass = PsiUtil.getTopLevelClass(element);
|
||||
if (topLevelClass != null) {
|
||||
String topName = topLevelClass.getQualifiedName();
|
||||
assert topName != null;
|
||||
if (qname.length() > topName.length()) {
|
||||
result.add(topName + qname.substring(topName.length()).replace('.', '$'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (element instanceof PsiMethod) {
|
||||
ContainerUtil.addIfNotNull(result, ((PsiMethod)element).getName());
|
||||
}
|
||||
else if (element instanceof PsiVariable) {
|
||||
ContainerUtil.addIfNotNull(result, ((PsiVariable)element).getName());
|
||||
}
|
||||
else if (element instanceof PsiMetaOwner) {
|
||||
final PsiMetaData metaData = ((PsiMetaOwner)element).getMetaData();
|
||||
if (metaData != null) {
|
||||
ContainerUtil.addIfNotNull(result, metaData.getName());
|
||||
}
|
||||
}
|
||||
else if (element instanceof PsiNamedElement) {
|
||||
ContainerUtil.addIfNotNull(result, ((PsiNamedElement)element).getName());
|
||||
}
|
||||
else if (element instanceof XmlAttributeValue) {
|
||||
ContainerUtil.addIfNotNull(result, ((XmlAttributeValue)element).getValue());
|
||||
}
|
||||
else {
|
||||
LOG.error("Unknown element type: " + element);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
return JavaFindUsagesHelper.getElementNames(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processElementUsages(@NotNull final PsiElement element,
|
||||
@NotNull final Processor<UsageInfo> processor,
|
||||
@NotNull final FindUsagesOptions options) {
|
||||
if (options instanceof JavaVariableFindUsagesOptions) {
|
||||
final JavaVariableFindUsagesOptions varOptions = (JavaVariableFindUsagesOptions) options;
|
||||
if (varOptions.isReadAccess || varOptions.isWriteAccess){
|
||||
if (varOptions.isReadAccess && varOptions.isWriteAccess){
|
||||
if (!addElementUsages(element, options, processor)) return false;
|
||||
}
|
||||
else{
|
||||
if (!addElementUsages(element, varOptions, new Processor<UsageInfo>() {
|
||||
@Override
|
||||
public boolean process(UsageInfo info) {
|
||||
final PsiElement element = info.getElement();
|
||||
boolean isWrite = element instanceof PsiExpression && PsiUtil.isAccessedForWriting((PsiExpression)element);
|
||||
if (isWrite == varOptions.isWriteAccess) {
|
||||
if (!processor.process(info)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
})) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (options.isUsages) {
|
||||
if (!addElementUsages(element, options, processor)) return false;
|
||||
}
|
||||
|
||||
boolean success = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
if (ThrowSearchUtil.isSearchable (element) && options instanceof JavaThrowFindUsagesOptions && options.isUsages) {
|
||||
ThrowSearchUtil.Root root = ((JavaThrowFindUsagesOptions)options).getRoot();
|
||||
if (root == null) {
|
||||
final ThrowSearchUtil.Root[] roots = ThrowSearchUtil.getSearchRoots(element);
|
||||
if (roots != null && roots.length > 0) {
|
||||
root = roots [0];
|
||||
}
|
||||
}
|
||||
if (root != null) {
|
||||
return ThrowSearchUtil.addThrowUsages(processor, root, options);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!success) return false;
|
||||
|
||||
if (options instanceof JavaPackageFindUsagesOptions && ((JavaPackageFindUsagesOptions)options).isClassesUsages){
|
||||
if (!addClassesUsages((PsiPackage)element, (JavaPackageFindUsagesOptions)options, processor)) return false;
|
||||
}
|
||||
|
||||
if (options instanceof JavaClassFindUsagesOptions) {
|
||||
final JavaClassFindUsagesOptions classOptions = (JavaClassFindUsagesOptions)options;
|
||||
final PsiClass psiClass = (PsiClass)element;
|
||||
PsiManager manager = ApplicationManager.getApplication().runReadAction(new Computable<PsiManager>() {
|
||||
@Override
|
||||
public PsiManager compute() {
|
||||
return psiClass.getManager();
|
||||
}
|
||||
});
|
||||
if (classOptions.isMethodsUsages){
|
||||
if (!addMethodsUsages(psiClass, manager, classOptions, processor)) return false;
|
||||
}
|
||||
if (classOptions.isFieldsUsages){
|
||||
if (!addFieldsUsages(psiClass, manager, classOptions, processor)) return false;
|
||||
}
|
||||
if (psiClass.isInterface()) {
|
||||
if (classOptions.isDerivedInterfaces){
|
||||
if (classOptions.isImplementingClasses){
|
||||
if (!addInheritors(psiClass, classOptions, processor)) return false;
|
||||
}
|
||||
else{
|
||||
if (!addDerivedInterfaces(psiClass, classOptions, processor)) return false;
|
||||
}
|
||||
}
|
||||
else if (classOptions.isImplementingClasses){
|
||||
if (!addImplementingClasses(psiClass, classOptions, processor)) return false;
|
||||
}
|
||||
|
||||
if (classOptions.isImplementingClasses) {
|
||||
FunctionalExpressionSearch.search(psiClass, classOptions.searchScope).forEach(new PsiElementProcessorAdapter<PsiFunctionalExpression>(
|
||||
new PsiElementProcessor<PsiFunctionalExpression>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiFunctionalExpression expression) {
|
||||
return addResult(expression, options, processor);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
else if (classOptions.isDerivedClasses) {
|
||||
if (!addInheritors(psiClass, classOptions, processor)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (options instanceof JavaMethodFindUsagesOptions){
|
||||
final PsiMethod psiMethod = (PsiMethod)element;
|
||||
boolean isAbstract = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return psiMethod.hasModifierProperty(PsiModifier.ABSTRACT);
|
||||
}
|
||||
});
|
||||
final JavaMethodFindUsagesOptions methodOptions = (JavaMethodFindUsagesOptions)options;
|
||||
if (isAbstract && methodOptions.isImplementingMethods || methodOptions.isOverridingMethods) {
|
||||
if (!processOverridingMethods(psiMethod, processor, methodOptions)) return false;
|
||||
FunctionalExpressionSearch.search(psiMethod, methodOptions.searchScope).forEach(new PsiElementProcessorAdapter<PsiFunctionalExpression>(
|
||||
new PsiElementProcessor<PsiFunctionalExpression>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiFunctionalExpression expression) {
|
||||
return addResult(expression, options, processor);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (element instanceof PomTarget) {
|
||||
if (!addAliasingUsages((PomTarget)element, options, processor)) return false;
|
||||
}
|
||||
final Boolean isSearchable = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return ThrowSearchUtil.isSearchable(element);
|
||||
}
|
||||
});
|
||||
if (!isSearchable && options.isSearchForTextOccurrences && options.searchScope instanceof GlobalSearchScope) {
|
||||
// todo add to fastTrack
|
||||
if (!processUsagesInText(element, processor, (GlobalSearchScope)options.searchScope)) return false;
|
||||
}
|
||||
return true;
|
||||
return JavaFindUsagesHelper.processElementUsages(element, options, processor);
|
||||
}
|
||||
|
||||
private static boolean addAliasingUsages(@NotNull PomTarget pomTarget,
|
||||
@NotNull final FindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
for (AliasingPsiTargetMapper aliasingPsiTargetMapper : Extensions.getExtensions(AliasingPsiTargetMapper.EP_NAME)) {
|
||||
for (AliasingPsiTarget psiTarget : aliasingPsiTargetMapper.getTargets(pomTarget)) {
|
||||
boolean success = ReferencesSearch
|
||||
.search(new ReferencesSearch.SearchParameters(PomService.convertToPsi(psiTarget), options.searchScope, false, options.fastTrack))
|
||||
.forEach(new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(final PsiReference reference) {
|
||||
return addResult(reference, options, processor);
|
||||
}
|
||||
});
|
||||
if (!success) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean processOverridingMethods(@NotNull PsiMethod psiMethod,
|
||||
@NotNull final Processor<UsageInfo> processor,
|
||||
@NotNull final JavaMethodFindUsagesOptions options) {
|
||||
return OverridingMethodsSearch.search(psiMethod, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiMethod>(
|
||||
new PsiElementProcessor<PsiMethod>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiMethod element) {
|
||||
return addResult(element.getNavigationElement(), options, processor);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
private static boolean addClassesUsages(@NotNull PsiPackage aPackage,
|
||||
@NotNull final JavaPackageFindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
|
||||
if (progress != null){
|
||||
progress.pushState();
|
||||
}
|
||||
|
||||
List<PsiClass> classes = new ArrayList<PsiClass>();
|
||||
addClassesInPackage(aPackage, options.isIncludeSubpackages, classes);
|
||||
for (final PsiClass aClass : classes) {
|
||||
if (progress != null) {
|
||||
String name = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
@Override
|
||||
public String compute() {
|
||||
return aClass.getName();
|
||||
}
|
||||
});
|
||||
progress.setText(FindBundle.message("find.searching.for.references.to.class.progress", name));
|
||||
progress.checkCanceled();
|
||||
}
|
||||
boolean success = ReferencesSearch.search(new ReferencesSearch.SearchParameters(aClass, options.searchScope, false, options.fastTrack)).forEach(new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(final PsiReference psiReference) {
|
||||
return addResult(psiReference, options, processor);
|
||||
}
|
||||
});
|
||||
if (!success) return false;
|
||||
}
|
||||
|
||||
if (progress != null){
|
||||
progress.popState();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void addClassesInPackage(@NotNull final PsiPackage aPackage, boolean includeSubpackages, @NotNull List<PsiClass> array) {
|
||||
PsiDirectory[] dirs = ApplicationManager.getApplication().runReadAction(new Computable<PsiDirectory[]>() {
|
||||
@Override
|
||||
public PsiDirectory[] compute() {
|
||||
return aPackage.getDirectories();
|
||||
}
|
||||
});
|
||||
for (PsiDirectory dir : dirs) {
|
||||
addClassesInDirectory(dir, includeSubpackages, array);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addClassesInDirectory(@NotNull final PsiDirectory dir,
|
||||
final boolean includeSubdirs,
|
||||
@NotNull final List<PsiClass> array) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PsiClass[] classes = JavaDirectoryService.getInstance().getClasses(dir);
|
||||
ContainerUtil.addAll(array, classes);
|
||||
if (includeSubdirs) {
|
||||
PsiDirectory[] dirs = dir.getSubdirectories();
|
||||
for (PsiDirectory directory : dirs) {
|
||||
addClassesInDirectory(directory, includeSubdirs, array);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean addMethodsUsages(@NotNull final PsiClass aClass,
|
||||
@NotNull final PsiManager manager,
|
||||
@NotNull final JavaClassFindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
if (options.isIncludeInherited) {
|
||||
final PsiMethod[] methods = ApplicationManager.getApplication().runReadAction(new Computable<PsiMethod[]>() {
|
||||
@Override
|
||||
public PsiMethod[] compute() {
|
||||
return aClass.getAllMethods();
|
||||
}
|
||||
});
|
||||
for(int i = 0; i < methods.length; i++){
|
||||
final PsiMethod method = methods[i];
|
||||
// filter overridden methods
|
||||
final int finalI = i;
|
||||
final PsiClass methodClass =
|
||||
ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
|
||||
@Override
|
||||
public PsiClass compute() {
|
||||
MethodSignature methodSignature = method.getSignature(PsiSubstitutor.EMPTY);
|
||||
for (int j = 0; j < finalI; j++) {
|
||||
if (methodSignature.equals(methods[j].getSignature(PsiSubstitutor.EMPTY))) return null;
|
||||
}
|
||||
return method.getContainingClass();
|
||||
}
|
||||
});
|
||||
if (methodClass == null) continue;
|
||||
boolean equivalent = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return manager.areElementsEquivalent(methodClass, aClass);
|
||||
}
|
||||
});
|
||||
if (equivalent){
|
||||
if (!addElementUsages(method, options, processor)) return false;
|
||||
}
|
||||
else {
|
||||
MethodReferencesSearch.SearchParameters parameters =
|
||||
new MethodReferencesSearch.SearchParameters(method, options.searchScope, true, options.fastTrack);
|
||||
boolean success = MethodReferencesSearch.search(parameters)
|
||||
.forEach(new PsiReferenceProcessorAdapter(new PsiReferenceProcessor() {
|
||||
@Override
|
||||
public boolean execute(PsiReference reference) {
|
||||
addResultFromReference(reference, methodClass, manager, aClass, options, processor);
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
if (!success) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiMethod[] methods = ApplicationManager.getApplication().runReadAction(new Computable<PsiMethod[]>() {
|
||||
@Override
|
||||
public PsiMethod[] compute() {
|
||||
return aClass.getMethods();
|
||||
}
|
||||
});
|
||||
for (PsiMethod method : methods) {
|
||||
if (!addElementUsages(method, options, processor)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean addFieldsUsages(@NotNull final PsiClass aClass,
|
||||
@NotNull final PsiManager manager,
|
||||
@NotNull final JavaClassFindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
if (options.isIncludeInherited) {
|
||||
final PsiField[] fields = ApplicationManager.getApplication().runReadAction(new Computable<PsiField[]>() {
|
||||
@Override
|
||||
public PsiField[] compute() {
|
||||
return aClass.getAllFields();
|
||||
}
|
||||
});
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
final PsiField field = fields[i];
|
||||
// filter hidden fields
|
||||
final int finalI = i;
|
||||
final PsiClass fieldClass =
|
||||
ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
|
||||
@Override
|
||||
public PsiClass compute() {
|
||||
for (int j = 0; j < finalI; j++) {
|
||||
if (Comparing.strEqual(field.getName(), fields[j].getName())) return null;
|
||||
}
|
||||
return field.getContainingClass();
|
||||
}
|
||||
});
|
||||
if (fieldClass == null) continue;
|
||||
boolean equivalent = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return manager.areElementsEquivalent(fieldClass, aClass);
|
||||
}
|
||||
});
|
||||
if (equivalent) {
|
||||
if (!addElementUsages(fields[i], options, processor)) return false;
|
||||
}
|
||||
else {
|
||||
boolean success = ReferencesSearch.search(new ReferencesSearch.SearchParameters(field, options.searchScope, false, options.fastTrack)).forEach(new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(final PsiReference reference) {
|
||||
return addResultFromReference(reference, fieldClass, manager, aClass, options, processor);
|
||||
}
|
||||
});
|
||||
if (!success) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiField[] fields = ApplicationManager.getApplication().runReadAction(new Computable<PsiField[]>() {
|
||||
@Override
|
||||
public PsiField[] compute() {
|
||||
return aClass.getFields();
|
||||
}
|
||||
});
|
||||
for (PsiField field : fields) {
|
||||
if (!addElementUsages(field, options, processor)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiClass getFieldOrMethodAccessedClass(@NotNull PsiReferenceExpression ref, @NotNull PsiClass fieldOrMethodClass) {
|
||||
PsiElement[] children = ref.getChildren();
|
||||
if (children.length > 1 && children[0] instanceof PsiExpression) {
|
||||
PsiExpression expr = (PsiExpression)children[0];
|
||||
PsiType type = expr.getType();
|
||||
if (type != null) {
|
||||
if (!(type instanceof PsiClassType)) return null;
|
||||
return PsiUtil.resolveClassInType(type);
|
||||
}
|
||||
else {
|
||||
if (expr instanceof PsiReferenceExpression) {
|
||||
PsiElement refElement = ((PsiReferenceExpression)expr).resolve();
|
||||
if (refElement instanceof PsiClass) return (PsiClass)refElement;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
PsiManager manager = ref.getManager();
|
||||
for(PsiElement parent = ref; parent != null; parent = parent.getParent()){
|
||||
if (parent instanceof PsiClass
|
||||
&& (manager.areElementsEquivalent(parent, fieldOrMethodClass) || ((PsiClass)parent).isInheritor(fieldOrMethodClass, true))){
|
||||
return (PsiClass)parent;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean addInheritors(@NotNull PsiClass aClass,
|
||||
@NotNull final JavaClassFindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
return ClassInheritorsSearch.search(aClass, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>(
|
||||
new PsiElementProcessor<PsiClass>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiClass element) {
|
||||
return addResult(element, options, processor);
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
|
||||
private static boolean addDerivedInterfaces(@NotNull PsiClass anInterface,
|
||||
@NotNull final JavaClassFindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
return ClassInheritorsSearch.search(anInterface, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>(
|
||||
new PsiElementProcessor<PsiClass>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiClass inheritor) {
|
||||
return !inheritor.isInterface() || addResult(inheritor, options, processor);
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
|
||||
private static boolean addImplementingClasses(@NotNull PsiClass anInterface,
|
||||
@NotNull final JavaClassFindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
return ClassInheritorsSearch.search(anInterface, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>(
|
||||
new PsiElementProcessor<PsiClass>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiClass inheritor) {
|
||||
return inheritor.isInterface() || addResult(inheritor, options, processor);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private static boolean addResultFromReference(@NotNull PsiReference reference,
|
||||
@NotNull PsiClass methodClass,
|
||||
@NotNull PsiManager manager,
|
||||
@NotNull PsiClass aClass,
|
||||
@NotNull FindUsagesOptions options,
|
||||
@NotNull Processor<UsageInfo> processor) {
|
||||
PsiElement refElement = reference.getElement();
|
||||
if (refElement instanceof PsiReferenceExpression) {
|
||||
PsiClass usedClass = getFieldOrMethodAccessedClass((PsiReferenceExpression)refElement, methodClass);
|
||||
if (usedClass != null) {
|
||||
if (manager.areElementsEquivalent(usedClass, aClass) || usedClass.isInheritor(aClass, true)) {
|
||||
if (!addResult(refElement, options, processor)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean addElementUsages(@NotNull final PsiElement element,
|
||||
@NotNull final FindUsagesOptions options,
|
||||
@NotNull final Processor<UsageInfo> processor) {
|
||||
final SearchScope searchScope = options.searchScope;
|
||||
final PsiClass[] parentClass = new PsiClass[1];
|
||||
if (element instanceof PsiMethod && ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
PsiMethod method = (PsiMethod)element;
|
||||
parentClass[0] = method.getContainingClass();
|
||||
return method.isConstructor();
|
||||
}
|
||||
})) {
|
||||
PsiMethod method = (PsiMethod)element;
|
||||
|
||||
if (parentClass[0] != null) {
|
||||
boolean strictSignatureSearch =
|
||||
!(options instanceof JavaMethodFindUsagesOptions) || !((JavaMethodFindUsagesOptions)options).isIncludeOverloadUsages;
|
||||
return MethodReferencesSearch
|
||||
.search(new MethodReferencesSearch.SearchParameters(method, searchScope, strictSignatureSearch, options.fastTrack))
|
||||
.forEach(new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(final PsiReference ref) {
|
||||
return addResult(ref, options, processor);
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
final ReadActionProcessor<PsiReference> consumer = new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(final PsiReference ref) {
|
||||
return addResult(ref, options, processor);
|
||||
}
|
||||
};
|
||||
|
||||
if (element instanceof PsiMethod) {
|
||||
final boolean strictSignatureSearch = !(options instanceof JavaMethodFindUsagesOptions) || // field with getter
|
||||
!((JavaMethodFindUsagesOptions)options).isIncludeOverloadUsages;
|
||||
return MethodReferencesSearch
|
||||
.search(new MethodReferencesSearch.SearchParameters((PsiMethod)element, searchScope, strictSignatureSearch, options.fastTrack))
|
||||
.forEach(consumer);
|
||||
}
|
||||
return ReferencesSearch.search(new ReferencesSearch.SearchParameters(element, searchScope, false, options.fastTrack)).forEach(consumer);
|
||||
}
|
||||
|
||||
private static boolean addResult(@NotNull PsiElement element,
|
||||
@NotNull FindUsagesOptions options,
|
||||
@NotNull Processor<UsageInfo> processor) {
|
||||
return !filterUsage(element, options) || processor.process(new UsageInfo(element));
|
||||
}
|
||||
|
||||
private static boolean addResult(@NotNull PsiReference ref, @NotNull FindUsagesOptions options, @NotNull Processor<UsageInfo> processor) {
|
||||
if (filterUsage(ref.getElement(), options)){
|
||||
TextRange rangeInElement = ref.getRangeInElement();
|
||||
return processor.process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean filterUsage(PsiElement usage, @NotNull FindUsagesOptions options) {
|
||||
if (!(usage instanceof PsiJavaCodeReferenceElement)) {
|
||||
return true;
|
||||
}
|
||||
if (options instanceof JavaPackageFindUsagesOptions && !((JavaPackageFindUsagesOptions)options).isIncludeSubpackages &&
|
||||
((PsiReference)usage).resolve() instanceof PsiPackage) {
|
||||
PsiElement parent = usage.getParent();
|
||||
if (parent instanceof PsiJavaCodeReferenceElement && ((PsiJavaCodeReferenceElement)parent).resolve() instanceof PsiPackage) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(usage instanceof PsiReferenceExpression)){
|
||||
if (options instanceof JavaFindUsagesOptions && ((JavaFindUsagesOptions)options).isSkipImportStatements){
|
||||
PsiElement parent = usage.getParent();
|
||||
while(parent instanceof PsiJavaCodeReferenceElement){
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent instanceof PsiImportStatement){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (options instanceof JavaPackageFindUsagesOptions && ((JavaPackageFindUsagesOptions)options).isSkipPackageStatements){
|
||||
PsiElement parent = usage.getParent();
|
||||
while(parent instanceof PsiJavaCodeReferenceElement){
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent instanceof PsiPackageStatement){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean isSearchForTextOccurencesAvailable(@NotNull PsiElement psiElement, boolean isSingleFile) {
|
||||
if (isSingleFile) return false;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
@@ -34,7 +35,7 @@ public abstract class PsiNavigationSupport {
|
||||
@Nullable
|
||||
public abstract Navigatable getDescriptor(final PsiElement element);
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
public abstract Navigatable createNavigatable(Project project, VirtualFile vFile, int offset);
|
||||
|
||||
public abstract boolean canNavigate(final PsiElement element);
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
+7
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,12 +15,11 @@
|
||||
*/
|
||||
package com.intellij.psi;
|
||||
|
||||
import com.intellij.ide.util.EditSourceUtil;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.ide.util.PsiNavigationSupport;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.PsiDeclaredTarget;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -47,20 +46,20 @@ public class DelegatePsiTarget implements PsiTarget {
|
||||
@Override
|
||||
public void navigate(boolean requestFocus) {
|
||||
final int offset = getTextOffset();
|
||||
final VirtualFile virtualFile = PsiUtilBase.getVirtualFile(myElement);
|
||||
final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(myElement);
|
||||
if (virtualFile != null && virtualFile.isValid()) {
|
||||
new OpenFileDescriptor(myElement.getProject(), virtualFile, offset).navigate(requestFocus);
|
||||
PsiNavigationSupport.getInstance().createNavigatable(myElement.getProject(), virtualFile, offset).navigate(requestFocus);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNavigate() {
|
||||
return EditSourceUtil.canNavigate(myElement);
|
||||
return PsiNavigationSupport.getInstance().canNavigate(myElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNavigateToSource() {
|
||||
return EditSourceUtil.canNavigate(myElement);
|
||||
return PsiNavigationSupport.getInstance().canNavigate(myElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
+1
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,8 +19,6 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.PomRenameableTarget;
|
||||
import com.intellij.psi.DelegatePsiTarget;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.refactoring.RefactoringFactory;
|
||||
import com.intellij.refactoring.RenameRefactoring;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -54,14 +52,4 @@ public class AliasingPsiTarget extends DelegatePsiTarget implements PomRenameabl
|
||||
public String getNameAlias(@Nullable String delegatePsiTargetName) {
|
||||
return delegatePsiTargetName;
|
||||
}
|
||||
|
||||
protected void renameTargets(@NotNull String newDelegateName) {
|
||||
final PsiNamedElement namedElement = (PsiNamedElement)getNavigationElement();
|
||||
if (!newDelegateName.equals(namedElement.getName())) {
|
||||
final RenameRefactoring refactoring =
|
||||
RefactoringFactory.getInstance(namedElement.getProject()).createRename(namedElement, newDelegateName);
|
||||
refactoring.run();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.psi.targets;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.pom.PomTarget;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface AliasingPsiTargetMapper {
|
||||
ExtensionPointName<AliasingPsiTargetMapper> EP_NAME = ExtensionPointName.create("com.intellij.aliasingPsiTargetMapper");
|
||||
|
||||
@NotNull
|
||||
Set<AliasingPsiTarget> getTargets(@NotNull PomTarget target);
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.find.findUsages;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.NullableComputable;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.PsiReferenceService;
|
||||
import com.intellij.psi.impl.search.PsiSearchHelperImpl;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageInfoFactory;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class FindUsagesHelper {
|
||||
protected static boolean processUsagesInText(@NotNull final PsiElement element,
|
||||
@NotNull Collection<String> stringToSearch,
|
||||
@NotNull GlobalSearchScope searchScope,
|
||||
@NotNull Processor<UsageInfo> processor) {
|
||||
final TextRange elementTextRange = ApplicationManager.getApplication().runReadAction(new NullableComputable<TextRange>() {
|
||||
@Override
|
||||
public TextRange compute() {
|
||||
if (!element.isValid()) return null;
|
||||
return element.getTextRange();
|
||||
}
|
||||
});
|
||||
UsageInfoFactory factory = new UsageInfoFactory() {
|
||||
@Override
|
||||
public UsageInfo createUsageInfo(@NotNull PsiElement usage, int startOffset, int endOffset) {
|
||||
if (elementTextRange != null
|
||||
&& usage.getContainingFile() == element.getContainingFile()
|
||||
&& elementTextRange.contains(startOffset)
|
||||
&& elementTextRange.contains(endOffset)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiReference someReference = usage.findReferenceAt(startOffset);
|
||||
if (someReference != null) {
|
||||
PsiElement refElement = someReference.getElement();
|
||||
for (PsiReference ref : PsiReferenceService.getService().getReferences(refElement, new PsiReferenceService.Hints(element, null))) {
|
||||
if (element.getManager().areElementsEquivalent(ref.resolve(), element)) {
|
||||
TextRange range = ref.getRangeInElement().shiftRight(refElement.getTextRange().getStartOffset() - usage.getTextRange().getStartOffset());
|
||||
return new UsageInfo(usage, range.getStartOffset(), range.getEndOffset(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new UsageInfo(usage, startOffset, endOffset, true);
|
||||
}
|
||||
};
|
||||
for (String s : stringToSearch) {
|
||||
if (!PsiSearchHelperImpl.processTextOccurrences(element, s, searchScope, processor, factory)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,12 @@
|
||||
|
||||
package com.intellij.psi.impl.search;
|
||||
|
||||
import com.intellij.concurrency.*;
|
||||
import com.intellij.concurrency.AsyncFuture;
|
||||
import com.intellij.concurrency.AsyncUtil;
|
||||
import com.intellij.concurrency.JobLauncher;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
@@ -39,6 +42,8 @@ import com.intellij.psi.impl.cache.impl.id.IdIndex;
|
||||
import com.intellij.psi.impl.cache.impl.id.IdIndexEntry;
|
||||
import com.intellij.psi.search.*;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageInfoFactory;
|
||||
import com.intellij.util.CommonProcessors;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SmartList;
|
||||
@@ -59,6 +64,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.search.PsiSearchHelperImpl");
|
||||
private final PsiManagerEx myManager;
|
||||
|
||||
@Override
|
||||
@@ -979,4 +985,39 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
public static boolean processTextOccurrences(@NotNull final PsiElement element,
|
||||
@NotNull String stringToSearch,
|
||||
@NotNull GlobalSearchScope searchScope,
|
||||
@NotNull final Processor<UsageInfo> processor,
|
||||
@NotNull final UsageInfoFactory factory) {
|
||||
PsiSearchHelper helper = ApplicationManager.getApplication().runReadAction(new Computable<PsiSearchHelper>() {
|
||||
@Override
|
||||
public PsiSearchHelper compute() {
|
||||
return SERVICE.getInstance(element.getProject());
|
||||
}
|
||||
});
|
||||
|
||||
return helper.processUsagesInNonJavaFiles(element, stringToSearch, new PsiNonJavaFileReferenceProcessor() {
|
||||
@Override
|
||||
public boolean process(final PsiFile psiFile, final int startOffset, final int endOffset) {
|
||||
try {
|
||||
UsageInfo usageInfo = ApplicationManager.getApplication().runReadAction(new Computable<UsageInfo>() {
|
||||
@Override
|
||||
public UsageInfo compute() {
|
||||
return factory.createUsageInfo(psiFile, startOffset, endOffset);
|
||||
}
|
||||
});
|
||||
return usageInfo == null || processor.process(usageInfo);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}, searchScope);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.intellij.psi.targets;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.pom.PomTarget;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface AliasingPsiTargetMapper {
|
||||
ExtensionPointName<AliasingPsiTargetMapper> EP_NAME = ExtensionPointName.create("com.intellij.aliasingPsiTargetMapper");
|
||||
|
||||
@NotNull
|
||||
Set<AliasingPsiTarget> getTargets(@NotNull PomTarget target);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.psi.targets;
|
||||
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.refactoring.RefactoringFactory;
|
||||
import com.intellij.refactoring.RenameRefactoring;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class AliasingPsiTargetUtil {
|
||||
public static void renameTargets(AliasingPsiTarget target, @NotNull String newDelegateName) {
|
||||
final PsiNamedElement namedElement = (PsiNamedElement)target.getNavigationElement();
|
||||
if (!newDelegateName.equals(namedElement.getName())) {
|
||||
final RenameRefactoring refactoring =
|
||||
RefactoringFactory.getInstance(namedElement.getProject()).createRename(namedElement, newDelegateName);
|
||||
refactoring.run();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,13 +25,10 @@ import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.PsiReferenceService;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.refactoring.util.TextOccurrencesUtil;
|
||||
import com.intellij.usageView.UsageInfoFactory;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.Processor;
|
||||
@@ -156,48 +153,7 @@ public abstract class FindUsagesHandler {
|
||||
}
|
||||
});
|
||||
if (stringToSearch == null) return true;
|
||||
return processUsagesInText(element, stringToSearch, searchScope, processor);
|
||||
}
|
||||
|
||||
protected static boolean processUsagesInText(@NotNull final PsiElement element,
|
||||
@NotNull Collection<String> stringToSearch,
|
||||
@NotNull GlobalSearchScope searchScope,
|
||||
@NotNull Processor<UsageInfo> processor) {
|
||||
final TextRange elementTextRange = ApplicationManager.getApplication().runReadAction(new NullableComputable<TextRange>() {
|
||||
@Override
|
||||
public TextRange compute() {
|
||||
if (!element.isValid()) return null;
|
||||
return element.getTextRange();
|
||||
}
|
||||
});
|
||||
UsageInfoFactory factory = new UsageInfoFactory() {
|
||||
@Override
|
||||
public UsageInfo createUsageInfo(@NotNull PsiElement usage, int startOffset, int endOffset) {
|
||||
if (elementTextRange != null
|
||||
&& usage.getContainingFile() == element.getContainingFile()
|
||||
&& elementTextRange.contains(startOffset)
|
||||
&& elementTextRange.contains(endOffset)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiReference someReference = usage.findReferenceAt(startOffset);
|
||||
if (someReference != null) {
|
||||
PsiElement refElement = someReference.getElement();
|
||||
for (PsiReference ref : PsiReferenceService.getService().getReferences(refElement, new PsiReferenceService.Hints(element, null))) {
|
||||
if (element.getManager().areElementsEquivalent(ref.resolve(), element)) {
|
||||
TextRange range = ref.getRangeInElement().shiftRight(refElement.getTextRange().getStartOffset() - usage.getTextRange().getStartOffset());
|
||||
return new UsageInfo(usage, range.getStartOffset(), range.getEndOffset(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new UsageInfo(usage, startOffset, endOffset, true);
|
||||
}
|
||||
};
|
||||
for (String s : stringToSearch) {
|
||||
if (!TextOccurrencesUtil.processTextOccurences(element, s, searchScope, processor, factory)) return false;
|
||||
}
|
||||
return true;
|
||||
return FindUsagesHelper.processUsagesInText(element, stringToSearch, searchScope, processor);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,6 +23,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
@@ -35,7 +36,7 @@ public class PsiNavigationSupportImpl extends PsiNavigationSupport {
|
||||
return EditSourceUtil.getDescriptor(element);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
@Override
|
||||
public Navigatable createNavigatable(Project project, VirtualFile vFile, int offset) {
|
||||
return new OpenFileDescriptor(project, vFile, offset);
|
||||
|
||||
@@ -24,15 +24,11 @@ import com.intellij.find.impl.FindManagerImpl;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.LanguageParserDefinitions;
|
||||
import com.intellij.lang.ParserDefinition;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiPolyVariantReference;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.impl.search.PsiSearchHelperImpl;
|
||||
import com.intellij.psi.search.*;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageInfoFactory;
|
||||
@@ -43,7 +39,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.Collection;
|
||||
|
||||
public class TextOccurrencesUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.util.TextOccurrencesUtil");
|
||||
private TextOccurrencesUtil() {
|
||||
}
|
||||
|
||||
@@ -52,7 +47,7 @@ public class TextOccurrencesUtil {
|
||||
@NotNull GlobalSearchScope searchScope,
|
||||
@NotNull final Collection<UsageInfo> results,
|
||||
@NotNull final UsageInfoFactory factory) {
|
||||
processTextOccurences(element, stringToSearch, searchScope, new Processor<UsageInfo>() {
|
||||
PsiSearchHelperImpl.processTextOccurrences(element, stringToSearch, searchScope, new Processor<UsageInfo>() {
|
||||
@Override
|
||||
public boolean process(UsageInfo t) {
|
||||
results.add(t);
|
||||
@@ -61,41 +56,6 @@ public class TextOccurrencesUtil {
|
||||
}, factory);
|
||||
}
|
||||
|
||||
public static boolean processTextOccurences(@NotNull final PsiElement element,
|
||||
@NotNull String stringToSearch,
|
||||
@NotNull GlobalSearchScope searchScope,
|
||||
@NotNull final Processor<UsageInfo> processor,
|
||||
@NotNull final UsageInfoFactory factory) {
|
||||
PsiSearchHelper helper = ApplicationManager.getApplication().runReadAction(new Computable<PsiSearchHelper>() {
|
||||
@Override
|
||||
public PsiSearchHelper compute() {
|
||||
return PsiSearchHelper.SERVICE.getInstance(element.getProject());
|
||||
}
|
||||
});
|
||||
|
||||
return helper.processUsagesInNonJavaFiles(element, stringToSearch, new PsiNonJavaFileReferenceProcessor() {
|
||||
@Override
|
||||
public boolean process(final PsiFile psiFile, final int startOffset, final int endOffset) {
|
||||
try {
|
||||
UsageInfo usageInfo = ApplicationManager.getApplication().runReadAction(new Computable<UsageInfo>() {
|
||||
@Override
|
||||
public UsageInfo compute() {
|
||||
return factory.createUsageInfo(psiFile, startOffset, endOffset);
|
||||
}
|
||||
});
|
||||
return usageInfo == null || processor.process(usageInfo);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}, searchScope);
|
||||
}
|
||||
|
||||
private static boolean processStringLiteralsContainingIdentifier(@NotNull String identifier, @NotNull SearchScope searchScope, PsiSearchHelper helper, final Processor<PsiElement> processor) {
|
||||
TextOccurenceProcessor occurenceProcessor = new TextOccurenceProcessor() {
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user