diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageElementNode.java b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageElementNode.java index 6568e2ff6e6b..3d73fdd48c0c 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageElementNode.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageElementNode.java @@ -28,7 +28,9 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiFile; import com.intellij.psi.PsiPackage; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.PlatformIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -93,9 +95,12 @@ public class PackageElementNode extends ProjectViewNode { } } // process only files in package's directories - final PsiDirectory[] dirs = PackageUtil.getDirectories(aPackage, module, isLibraryElement()); - for (final PsiDirectory dir : dirs) { - children.addAll(ProjectViewDirectoryHelper.getInstance(myProject).getDirectoryChildren(dir, getSettings(), false)); + final GlobalSearchScope scopeToShow = PackageUtil.getScopeToShow(aPackage.getProject(), module, isLibraryElement()); + PsiFile[] packageChildren = aPackage.getFiles(scopeToShow); + for (PsiFile file : packageChildren) { + if (file.getVirtualFile() != null) { + children.add(new PsiFileNode(getProject(), file, getSettings())); + } } return children; } diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageUtil.java b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageUtil.java index 28e3b85d3b7d..885913402e80 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageUtil.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageUtil.java @@ -23,12 +23,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.JavaDirectoryService; -import com.intellij.psi.PsiDirectory; -import com.intellij.psi.PsiManager; -import com.intellij.psi.PsiPackage; +import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,23 +35,17 @@ public class PackageUtil { public static PsiPackage[] getSubpackages(@NotNull PsiPackage aPackage, @Nullable Module module, final boolean searchInLibraries) { - final PsiDirectory[] dirs = getDirectories(aPackage, module, searchInLibraries); - final Set subpackages = new HashSet(); - for (PsiDirectory dir : dirs) { - final PsiDirectory[] subdirectories = dir.getSubdirectories(); - for (PsiDirectory subdirectory : subdirectories) { - final PsiPackage psiPackage = JavaDirectoryService.getInstance().getPackage(subdirectory); - if (psiPackage != null) { - final String name = psiPackage.getName(); - // skip "default" subpackages as they should be attributed to other modules - // this is the case when contents of one module is nested into contents of another - if (name != null && !name.isEmpty()) { - subpackages.add(psiPackage); - } - } + final GlobalSearchScope scopeToShow = getScopeToShow(aPackage.getProject(), module, searchInLibraries); + List result = new ArrayList(); + for (PsiPackage psiPackage : aPackage.getSubPackages(scopeToShow)) { + // skip "default" subpackages as they should be attributed to other modules + // this is the case when contents of one module is nested into contents of another + final String name = psiPackage.getName(); + if (name != null && !name.isEmpty()) { + result.add(psiPackage); } } - return subpackages.toArray(new PsiPackage[subpackages.size()]); + return result.toArray(new PsiPackage[result.size()]); } public static void addPackageAsChild(@NotNull Collection children, @@ -80,13 +70,17 @@ public class PackageUtil { @Nullable Module module, boolean strictlyEmpty, final boolean inLibrary) { - final PsiDirectory[] dirs = getDirectories(aPackage, module, inLibrary); - for (final PsiDirectory dir : dirs) { - if (!TreeViewUtil.isEmptyMiddlePackage(dir, strictlyEmpty)) { - return false; - } + final Project project = aPackage.getProject(); + final GlobalSearchScope scopeToShow = getScopeToShow(project, module, inLibrary); + PsiElement[] children = aPackage.getFiles(scopeToShow); + if (children.length > 0) { + return false; } - return true; + PsiPackage[] subPackages = aPackage.getSubPackages(scopeToShow); + if (strictlyEmpty) { + return subPackages.length == 1; + } + return subPackages.length > 0; } @NotNull @@ -98,7 +92,7 @@ public class PackageUtil { } @NotNull - private static GlobalSearchScope getScopeToShow(@NotNull Project project, @Nullable Module module, boolean forLibraries) { + public static GlobalSearchScope getScopeToShow(@NotNull Project project, @Nullable Module module, boolean forLibraries) { if (module == null) { if (forLibraries) { return new ProjectLibrariesSearchScope(project); @@ -239,7 +233,7 @@ public class PackageUtil { @Override public int compare(@NotNull VirtualFile file1, @NotNull VirtualFile file2) { - throw new IncorrectOperationException("not implemented"); + return 0; } @Override 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 85b5cf1b6e42..b33600944ffa 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java @@ -101,33 +101,31 @@ public abstract class PsiElementFinder { } /** - * Returns a list of children (classes, subpackages and possibly other elements) belonging to the specified package. + * Returns a list of files belonging to the specified package which are not located in any of the package directories. * - * @param psiPackage the package to return the list of children for. - * @param scope the scope in which children are searched. - * @return the list of children. + * @param psiPackage the package to return the list of files for. + * @param scope the scope in which files are searched. + * @return the list of files. * @since 14.1 */ @NotNull - public PsiNamedElement[] getChildren(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { - Set children = new HashSet(); - Collections.addAll(children, getSubPackages(psiPackage, scope)); - Collections.addAll(children, getClasses(psiPackage, scope)); - return children.toArray(new PsiNamedElement[children.size()]); + public PsiFile[] getPackageFiles(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + return PsiFile.EMPTY_ARRAY; } /** - * Returns the filter to use for filtering the list of children for a given package produced by other PsiElementFinder - * implementations. (For example, the list of children for a Kotlin package includes files directly, rather than classes, - * so the classes located by the standard Java package children finder need to be excluded.) + * Returns the filter to use for filtering the list of files in the directories belonging to a package to exclude files + * that actually belong to a different package. (For example, in Kotlin the package of a file is determined by its + * package statement and not by its location in the directory structure, so the files which have a differring package + * statement need to be excluded.) * - * @param psiPackage the package to return the list of children for. - * @param scope the scope in which children are searched. + * @param psiPackage the package for which the list of files is requested. + * @param scope the scope in which children are requested. * @return the filter to use, or null if no additional filtering is necessary. * @since 14.1 */ @Nullable - public Predicate getPackageChildrenFilter(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + public Predicate getPackageFilesFilter(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { return null; } 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 cab1728ad650..1a3db4d1301b 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiPackage.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiPackage.java @@ -84,12 +84,13 @@ public interface PsiPackage extends PsiCheckedRenameElement, NavigationItem, Psi PsiClass[] getClasses(@NotNull GlobalSearchScope scope); /** - * Returns the list of all elements (classes, subpackages and potentially other elements) belonging to this package - * (non-recursively), restricted by the specified scope. + * Returns the list of all files in the package, restricted by the specified scope. (This is + * normally the list of all files in all directories corresponding to the package, but it can + * be modified by custom language plugins which have a different notion of packages.) * * @since 14.1 */ - PsiElement[] getChildren(@NotNull GlobalSearchScope scope); + PsiFile[] getFiles(@NotNull GlobalSearchScope scope); /** * Returns the list of package-level annotations for the package. 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 028e067666fc..a99550bad82c 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 @@ -243,17 +243,17 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { return result == null ? PsiClass.EMPTY_ARRAY : result.toArray(new PsiClass[result.size()]); } - private static class AndPredicate implements Predicate { - private final List> myComponents = new SmartList>(); + private static class AndPredicate implements Predicate { + private final List> myComponents = new SmartList>(); - public AndPredicate(Predicate filter1, Predicate filter2) { + public AndPredicate(Predicate filter1, Predicate filter2) { myComponents.add(filter1); myComponents.add(filter2); } @Override - public boolean apply(@Nullable PsiNamedElement input) { - for (Predicate component : myComponents) { + public boolean apply(@Nullable T input) { + for (Predicate component : myComponents) { if (!component.apply(input)) { return false; } @@ -263,34 +263,38 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { } @NotNull - public PsiElement[] getPackageChildren(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { - Map result = new HashMap(); - Predicate filter = null; + public PsiFile[] getPackageFiles(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + Predicate filter = null; for (PsiElementFinder finder : filteredFinders()) { - Predicate finderFilter = finder.getPackageChildrenFilter(psiPackage, scope); + Predicate finderFilter = finder.getPackageFilesFilter(psiPackage, scope); if (finderFilter != null) { if (filter == null) { filter = finderFilter; } else if (filter instanceof AndPredicate) { - ((AndPredicate) filter).myComponents.add(finderFilter); + ((AndPredicate) filter).myComponents.add(finderFilter); } else { - filter = new AndPredicate(filter, finderFilter); + filter = new AndPredicate(filter, finderFilter); + } + } + } + + Set result = new HashSet(); + PsiDirectory[] directories = psiPackage.getDirectories(scope); + for (PsiDirectory directory : directories) { + for (PsiFile file : directory.getFiles()) { + if (filter == null || filter.apply(file)) { + result.add(file); } } } for (PsiElementFinder finder : filteredFinders()) { - PsiNamedElement[] children = finder.getChildren(psiPackage, scope); - for (PsiNamedElement child : children) { - if (!result.containsKey(child.getName()) && (filter == null || filter.apply(child))) { - result.put(child.getName(), child); - } - } + Collections.addAll(result, finder.getPackageFiles(psiPackage, scope)); } - return result.values().toArray(new PsiElement[result.size()]); + return result.toArray(new PsiFile[result.size()]); } public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, 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 2cda50ec8309..1915df3b09c8 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 @@ -157,15 +157,9 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya return getFacade().getClasses(this, scope); } - @NotNull @Override - public PsiElement[] getChildren() { - return getChildren(allScope()); - } - - @Override - public PsiElement[] getChildren(@NotNull GlobalSearchScope scope) { - return getFacade().getPackageChildren(this, scope); + public PsiFile[] getFiles(@NotNull GlobalSearchScope scope) { + return getFacade().getPackageFiles(this, scope); } @Override diff --git a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java index 19b2f20d7054..2d858e573247 100644 --- a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java +++ b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java @@ -217,22 +217,31 @@ public class JavaCoverageViewExtension extends CoverageViewExtension { return isInCoverageScope(psiPackage); } })) { - final PsiElement[] childElements = ApplicationManager.getApplication().runReadAction(new Computable() { - public PsiElement[] compute() { - return psiPackage.getChildren(mySuitesBundle.getSearchScope(node.getProject())); + final PsiPackage[] subPackages = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiPackage[] compute() { + return psiPackage.getSubPackages(mySuitesBundle.getSearchScope(node.getProject())); } }); - for (PsiElement element : childElements) { - if (element instanceof PsiClass) { - PsiClass aClass = (PsiClass) element; - if (!(node instanceof CoverageListRootNode) && getClassCoverageInfo(aClass) == null) continue; - children.add(new CoverageListNode(myProject, aClass, mySuitesBundle, myStateBean)); + for (PsiPackage subPackage: subPackages) { + processSubPackage(subPackage, children); + } + + final PsiFile[] childFiles = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiFile[] compute() { + return psiPackage.getFiles(mySuitesBundle.getSearchScope(node.getProject())); } - else if (element instanceof PsiPackage) { - processSubPackage((PsiPackage) element, children); + }); + for (PsiFile file : childFiles) { + if (file instanceof PsiJavaFile) { + PsiClass[] classes = ((PsiJavaFile)file).getClasses(); + if (classes.length > 0) { + PsiClass aClass = classes[0]; + if (!(node instanceof CoverageListRootNode) && getClassCoverageInfo(aClass) == null) continue; + children.add(new CoverageListNode(myProject, aClass, mySuitesBundle, myStateBean)); + } } - else if (element instanceof PsiNamedElement) { - children.add(new CoverageListNode(myProject, (PsiNamedElement) element, mySuitesBundle, myStateBean)); + else { + children.add(new CoverageListNode(myProject, file, mySuitesBundle, myStateBean)); } } }