diff --git a/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java b/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java index 9de12bd4dfec..f2c24d3b8ebf 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java @@ -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 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. * diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java index aa389214205a..6f31641ed805 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java @@ -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 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 classes = new SmartList(); - for (PsiElementFinder finder : finders()) { + PsiElementFinder[] finders = finders(); + Condition classesFilter = getFilterFromFinders(scope, finders); + + List 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(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 getFilterFromFinders(@NotNull GlobalSearchScope scope, @NotNull PsiElementFinder[] finders) { + Condition filter = null; + for (PsiElementFinder finder : finders) { + Condition 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 classesFilter = getFilterFromFinders(scope, finders); + List 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(); - ContainerUtil.addAll(result, classes); + if (result == null) result = new ArrayList(classes.length); + filterClassesAndAppend(classesFilter, classes, result); } return result == null ? PsiClass.EMPTY_ARRAY : result.toArray(new PsiClass[result.size()]); } + private static void filterClassesAndAppend(@Nullable Condition classesFilter, + @NotNull PsiClass[] classes, + @NotNull List 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 filter = null;