[IDEA-137300] Added ability to filter psi classes returned by JavaPsiFacade

This commit is contained in:
akosyakov
2015-03-23 14:24:13 +03:00
committed by Alexey Kudravtsev
parent 3f69e0236b
commit fce192d5f5
2 changed files with 62 additions and 11 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -100,6 +100,17 @@ public abstract class PsiElementFinder {
return PsiClass.EMPTY_ARRAY;
}
/**
* Returns the filter to exclude classes, for example derived classes.
*
* @param scope the scope in which classes are searched.
* @return the filter to use, or null if no additional filtering is necessary
*/
@Nullable
public Condition<PsiClass> getClassesFilter(@NotNull GlobalSearchScope scope) {
return null;
}
/**
* Returns a list of files belonging to the specified package which are not located in any of the package directories.
*
@@ -35,11 +35,11 @@ import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.reference.SoftReference;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.Processor;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBus;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.util.*;
@@ -95,9 +95,14 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
return null;
}
for (PsiElementFinder finder : finders()) {
PsiElementFinder[] finders = finders();
Condition<PsiClass> classesFilter = getFilterFromFinders(scope, finders);
for (PsiElementFinder finder : finders) {
PsiClass aClass = finder.findClass(qualifiedName, scope);
if (aClass != null) return aClass;
if (aClass != null && (classesFilter == null || classesFilter.value(aClass))) {
return aClass;
}
}
return null;
@@ -131,13 +136,30 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
return findClassesInDumbMode(qualifiedName, scope);
}
List<PsiClass> classes = new SmartList<PsiClass>();
for (PsiElementFinder finder : finders()) {
PsiElementFinder[] finders = finders();
Condition<PsiClass> classesFilter = getFilterFromFinders(scope, finders);
List<PsiClass> result = null;
for (PsiElementFinder finder : finders) {
PsiClass[] finderClasses = finder.findClasses(qualifiedName, scope);
ContainerUtil.addAll(classes, finderClasses);
if (finderClasses.length != 0) {
if (result == null) result = new ArrayList<PsiClass>(finderClasses.length);
filterClassesAndAppend(classesFilter, finderClasses, result);
}
}
return classes.toArray(new PsiClass[classes.size()]);
return result == null || result.isEmpty() ? PsiClass.EMPTY_ARRAY : result.toArray(new PsiClass[result.size()]);
}
private static Condition<PsiClass> getFilterFromFinders(@NotNull GlobalSearchScope scope, @NotNull PsiElementFinder[] finders) {
Condition<PsiClass> filter = null;
for (PsiElementFinder finder : finders) {
Condition<PsiClass> finderFilter = finder.getClassesFilter(scope);
if (finderFilter != null) {
filter = filter == null ? finderFilter : Conditions.and(filter, finderFilter);
}
}
return filter;
}
private boolean shouldUseSlowResolve() {
@@ -231,17 +253,35 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
@NotNull
public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
PsiElementFinder[] finders = filteredFinders();
Condition<PsiClass> classesFilter = getFilterFromFinders(scope, finders);
List<PsiClass> result = null;
for (PsiElementFinder finder : filteredFinders()) {
for (PsiElementFinder finder : finders) {
PsiClass[] classes = finder.getClasses(psiPackage, scope);
if (classes.length == 0) continue;
if (result == null) result = new ArrayList<PsiClass>();
ContainerUtil.addAll(result, classes);
if (result == null) result = new ArrayList<PsiClass>(classes.length);
filterClassesAndAppend(classesFilter, classes, result);
}
return result == null ? PsiClass.EMPTY_ARRAY : result.toArray(new PsiClass[result.size()]);
}
private static void filterClassesAndAppend(@Nullable Condition<PsiClass> classesFilter,
@NotNull PsiClass[] classes,
@NotNull List<PsiClass> result) {
if (classesFilter == null) {
ContainerUtil.addAll(result, classes);
}
else {
for (PsiClass psiClass : classes) {
if (classesFilter.value(psiClass)) {
result.add(psiClass);
}
}
}
}
@NotNull
public PsiFile[] getPackageFiles(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
Condition<PsiFile> filter = null;