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 6bedfff48a42..7638a64265cd 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java @@ -18,12 +18,14 @@ package com.intellij.psi; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.Processor; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; /** @@ -118,4 +120,36 @@ public abstract class PsiElementFinder { public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope, @NotNull Processor consumer) { return true; } + + /** + * Returns the list of classes in the specified package and in the specified search scope. + * + * @param className short name of the class + * @param psiPackage the package to return the list of classes in. + * @param scope the scope in which classes are searched. + * @return the list of classes. + * @see PsiPackage#getClasses(GlobalSearchScope) + */ + @NotNull + public PsiClass[] getClasses(@Nullable String className, @NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + PsiClass[] allClasses = getClasses(psiPackage, scope); + if (className == null) return allClasses; + return filterByName(className, allClasses); + } + + @NotNull + public static PsiClass[] filterByName(@NotNull String className, @NotNull PsiClass[] classes) { + if (classes.length == 0) return PsiClass.EMPTY_ARRAY; + if (classes.length == 1) { + return className.equals(classes[0].getName()) ? classes : PsiClass.EMPTY_ARRAY; + } + List foundClasses = new SmartList(); + for (PsiClass psiClass : classes) { + if (className.equals(psiClass.getName())) { + foundClasses.add(psiClass); + } + } + return foundClasses.isEmpty() ? PsiClass.EMPTY_ARRAY : foundClasses.toArray(new PsiClass[foundClasses.size()]); + } + } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiPackage.java b/java/java-psi-api/src/com/intellij/psi/PsiPackage.java index 97e9e653a828..fd68506ee2d5 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiPackage.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiPackage.java @@ -111,4 +111,7 @@ public interface PsiPackage extends PsiCheckedRenameElement, NavigationItem, Psi String getName(); boolean containsClassNamed(String name); + + @NotNull + PsiClass[] findClassByShortName(@NotNull String name, @NotNull GlobalSearchScope scope); } 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 17e4eecd4d22..07195ba43c32 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 @@ -42,7 +42,9 @@ import com.intellij.util.containers.ConcurrentHashMap; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; 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.*; @@ -118,7 +120,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { if (pkg == null && packageName.length() < qualifiedName.length()) { PsiClass[] containingClasses = findClassesInDumbMode(packageName, scope); if (containingClasses.length == 1) { - return filterByName(className, containingClasses[0].getInnerClasses()); + return PsiElementFinder.filterByName(className, containingClasses[0].getInnerClasses()); } return PsiClass.EMPTY_ARRAY; @@ -128,22 +130,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { return PsiClass.EMPTY_ARRAY; } - return filterByName(className, pkg.getClasses(scope)); - } - - @NotNull - private static PsiClass[] filterByName(@NotNull String className, @NotNull PsiClass[] classes) { - if (classes.length == 0) return PsiClass.EMPTY_ARRAY; - if (classes.length == 1) { - return className.equals(classes[0].getName()) ? classes : PsiClass.EMPTY_ARRAY; - } - List foundClasses = new SmartList(); - for (PsiClass psiClass : classes) { - if (className.equals(psiClass.getName())) { - foundClasses.add(psiClass); - } - } - return foundClasses.isEmpty() ? PsiClass.EMPTY_ARRAY : foundClasses.toArray(new PsiClass[foundClasses.size()]); + return pkg.findClassByShortName(className, scope); } @Override @@ -235,7 +222,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { @NotNull public Set getClassNames(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { - Set result = new HashSet(); + Set result = new THashSet(); for (PsiElementFinder finder : filteredFinders()) { result.addAll(finder.getClassNames(psiPackage, scope)); } @@ -275,6 +262,18 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { return result.toArray(new PsiPackage[result.size()]); } + public PsiClass[] findClassByShortName(String name, PsiPackage psiPackage, GlobalSearchScope scope) { + List result = null; + for (PsiElementFinder finder : filteredFinders()) { + PsiClass[] classes = finder.getClasses(name, psiPackage, scope); + if (classes.length == 0) continue; + if (result == null) result = new ArrayList(); + ContainerUtil.addAll(result, classes); + } + + return result == null ? PsiClass.EMPTY_ARRAY : result.toArray(new PsiClass[result.size()]); + } + private class PsiElementFinderImpl extends PsiElementFinder implements DumbAware { @Override public PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) { @@ -317,6 +316,12 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { @Override @NotNull public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull final GlobalSearchScope scope) { + return getClasses(null, psiPackage, scope); + } + + @Override + @NotNull + public PsiClass[] getClasses(@Nullable String shortName, @NotNull PsiPackage psiPackage, @NotNull final GlobalSearchScope scope) { List list = null; String packageName = psiPackage.getQualifiedName(); for (PsiDirectory dir : psiPackage.getDirectories(scope)) { @@ -328,21 +333,24 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { String qualifiedName = aClass.getQualifiedName(); if (qualifiedName != null) qualifiedName = StringUtil.getPackageName(qualifiedName); if (Comparing.strEqual(qualifiedName, packageName)) { - list.add(aClass); + if (shortName == null || shortName.equals(aClass.getName())) list.add(aClass); } } } if (list == null) { return PsiClass.EMPTY_ARRAY; } - ContainerUtil.quickSort(list, new Comparator() { - @Override - public int compare(PsiClass o1, PsiClass o2) { - VirtualFile file2 = PsiUtilCore.getVirtualFile(o2); - VirtualFile file1 = PsiUtilCore.getVirtualFile(o1); - return scope.compare(file2, file1); - } - }); + + if (list.size() > 1) { + ContainerUtil.quickSort(list, new Comparator() { + @Override + public int compare(PsiClass o1, PsiClass o2) { + VirtualFile file2 = PsiUtilCore.getVirtualFile(o2); + VirtualFile file1 = PsiUtilCore.getVirtualFile(o1); + return scope.compare(file2, file1); + } + }); + } return list.toArray(new PsiClass[list.size()]); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java index a8bcac5e5fcd..2f2c6cb2974d 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java @@ -183,6 +183,12 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya return getClassNamesCache().contains(name); } + @NotNull + @Override + public PsiClass[] findClassByShortName(@NotNull String name, @NotNull GlobalSearchScope scope) { + return getFacade().findClassByShortName(name, this, scope); + } + @Nullable private PsiPackage findSubPackageByName(String name) { final String qName = getQualifiedName();