diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/JavaProjectViewDirectoryHelper.java b/java/java-impl/src/com/intellij/ide/projectView/impl/JavaProjectViewDirectoryHelper.java index c248ddf5445b..a12e54670176 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/JavaProjectViewDirectoryHelper.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/JavaProjectViewDirectoryHelper.java @@ -19,6 +19,7 @@ import com.intellij.ide.projectView.ViewSettings; import com.intellij.ide.projectView.impl.nodes.PackageElement; import com.intellij.ide.projectView.impl.nodes.PackageUtil; import com.intellij.ide.projectView.impl.nodes.ProjectViewDirectoryHelper; +import com.intellij.ide.projectView.impl.nodes.PsiFileSystemItemFilter; import com.intellij.ide.util.treeView.TreeViewUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.impl.DirectoryIndex; @@ -91,8 +92,11 @@ public class JavaProjectViewDirectoryHelper extends ProjectViewDirectoryHelper { } @Override - public boolean isEmptyMiddleDirectory(final PsiDirectory directory, final boolean strictlyEmpty) { - return JavaDirectoryService.getInstance().getPackage(directory) != null && TreeViewUtil.isEmptyMiddlePackage(directory, strictlyEmpty); + public boolean isEmptyMiddleDirectory(final PsiDirectory directory, + final boolean strictlyEmpty, + @Nullable PsiFileSystemItemFilter filter) { + return JavaDirectoryService.getInstance().getPackage(directory) != null && + TreeViewUtil.isEmptyMiddlePackage(directory, strictlyEmpty, filter); } @Override diff --git a/java/java-impl/src/com/intellij/ide/util/treeView/TreeViewUtil.java b/java/java-impl/src/com/intellij/ide/util/treeView/TreeViewUtil.java index ba4cb56311a5..f3c134e9e0e2 100644 --- a/java/java-impl/src/com/intellij/ide/util/treeView/TreeViewUtil.java +++ b/java/java-impl/src/com/intellij/ide/util/treeView/TreeViewUtil.java @@ -15,18 +15,17 @@ */ package com.intellij.ide.util.treeView; +import com.intellij.ide.projectView.impl.nodes.PsiFileSystemItemFilter; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.UserDataHolderEx; 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.impl.PsiManagerEx; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.concurrent.ConcurrentMap; @@ -94,8 +93,11 @@ public class TreeViewUtil { * * @param strictlyEmpty if true, the package is considered empty if it has only 1 child and this child is a directory * otherwise the package is considered as empty if all direct children that it has are directories + * @param filter if returns false for some element, that elements is not counted */ - public static boolean isEmptyMiddlePackage(@NotNull PsiDirectory dir, boolean strictlyEmpty) { + public static boolean isEmptyMiddlePackage(@NotNull PsiDirectory dir, + boolean strictlyEmpty, + @Nullable PsiFileSystemItemFilter filter) { final VirtualFile[] files = dir.getVirtualFile().getChildren(); if (files.length == 0) { return false; @@ -105,9 +107,13 @@ public class TreeViewUtil { int directoriesCount = 0; for (VirtualFile file : files) { if (FileTypeManager.getInstance().isFileIgnored(file)) continue; - if (!file.isDirectory()) return false; + if (!file.isDirectory()) { + if (filter == null) return false; + PsiFile childFile = manager.findFile(file); + if (childFile != null && filter.shouldShow(childFile)) return false; + } PsiDirectory childDir = manager.findDirectory(file); - if (childDir != null) { + if (childDir != null && (filter == null || filter.shouldShow(childDir))) { directoriesCount++; if (strictlyEmpty && directoriesCount > 1) return false; if (JavaDirectoryService.getInstance().getPackage(childDir) != null) { diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewDirectoryHelper.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewDirectoryHelper.java index 69cb48b52b5a..127d4a64a2ff 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewDirectoryHelper.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewDirectoryHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -123,6 +123,12 @@ public class ProjectViewDirectoryHelper { } public boolean isEmptyMiddleDirectory(PsiDirectory directory, final boolean strictlyEmpty) { + return isEmptyMiddleDirectory(directory, strictlyEmpty, null); + } + + public boolean isEmptyMiddleDirectory(PsiDirectory directory, + final boolean strictlyEmpty, + @Nullable PsiFileSystemItemFilter filter) { return false; } @@ -142,9 +148,18 @@ public class ProjectViewDirectoryHelper { return false; } + @NotNull public Collection getDirectoryChildren(final PsiDirectory psiDirectory, final ViewSettings settings, final boolean withSubDirectories) { + return getDirectoryChildren(psiDirectory, settings, withSubDirectories, null); + } + + @NotNull + public Collection getDirectoryChildren(final PsiDirectory psiDirectory, + final ViewSettings settings, + final boolean withSubDirectories, + @Nullable PsiFileSystemItemFilter filter) { final List children = new ArrayList<>(); final Project project = psiDirectory.getProject(); final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); @@ -152,17 +167,17 @@ public class ProjectViewDirectoryHelper { final ModuleFileIndex moduleFileIndex = module == null ? null : ModuleRootManager.getInstance(module).getFileIndex(); if (!settings.isFlattenPackages() || skipDirectory(psiDirectory)) { processPsiDirectoryChildren(psiDirectory, directoryChildrenInProject(psiDirectory, settings), - children, fileIndex, null, settings, withSubDirectories); + children, fileIndex, null, settings, withSubDirectories, filter); } else { // source directory in "flatten packages" mode final PsiDirectory parentDir = psiDirectory.getParentDirectory(); if (parentDir == null || skipDirectory(parentDir) && withSubDirectories) { - addAllSubpackages(children, psiDirectory, moduleFileIndex, settings); + addAllSubpackages(children, psiDirectory, moduleFileIndex, settings, filter); } if (withSubDirectories) { PsiDirectory[] subdirs = psiDirectory.getSubdirectories(); for (PsiDirectory subdir : subdirs) { - if (!skipDirectory(subdir)) { + if (!skipDirectory(subdir) || filter != null && !filter.shouldShow(subdir)) { continue; } VirtualFile directoryFile = subdir.getVirtualFile(); @@ -174,11 +189,11 @@ public class ProjectViewDirectoryHelper { if (FileTypeRegistry.getInstance().isFileIgnored(directoryFile)) continue; } - children.add(new PsiDirectoryNode(project, subdir, settings)); + children.add(new PsiDirectoryNode(project, subdir, settings, filter)); } } processPsiDirectoryChildren(psiDirectory, psiDirectory.getFiles(), children, fileIndex, moduleFileIndex, settings, - withSubDirectories); + withSubDirectories, filter); } return children; } @@ -260,7 +275,8 @@ public class ProjectViewDirectoryHelper { ProjectFileIndex projectFileIndex, @Nullable ModuleFileIndex moduleFileIndex, ViewSettings viewSettings, - boolean withSubDirectories) { + boolean withSubDirectories, + @Nullable PsiFileSystemItemFilter filter) { for (PsiElement child : children) { LOG.assertTrue(child.isValid()); @@ -275,6 +291,9 @@ public class ProjectViewDirectoryHelper { if (moduleFileIndex != null && !moduleFileIndex.isInContent(vFile)) { continue; } + if (filter != null && !filter.shouldShow((PsiFileSystemItem)child)) { + continue; + } if (child instanceof PsiFile) { container.add(new PsiFileNode(child.getProject(), (PsiFile) child, viewSettings)); } @@ -282,13 +301,14 @@ public class ProjectViewDirectoryHelper { if (withSubDirectories) { PsiDirectory dir = (PsiDirectory)child; if (!vFile.equals(projectFileIndex.getSourceRootForFile(vFile))) { // if is not a source root - if (viewSettings.isHideEmptyMiddlePackages() && !skipDirectory(psiDir) && isEmptyMiddleDirectory(dir, true)) { - processPsiDirectoryChildren(dir, directoryChildrenInProject(dir, viewSettings), - container, projectFileIndex, moduleFileIndex, viewSettings, withSubDirectories); // expand it recursively + if (viewSettings.isHideEmptyMiddlePackages() && !skipDirectory(psiDir) && isEmptyMiddleDirectory(dir, true, filter)) { + processPsiDirectoryChildren( + dir, directoryChildrenInProject(dir, viewSettings), container, projectFileIndex, moduleFileIndex, viewSettings, true, filter + ); // expand it recursively continue; } } - container.add(new PsiDirectoryNode(child.getProject(), (PsiDirectory) child, viewSettings)); + container.add(new PsiDirectoryNode(child.getProject(), (PsiDirectory)child, viewSettings, filter)); } } } @@ -298,27 +318,28 @@ public class ProjectViewDirectoryHelper { public void addAllSubpackages(List container, PsiDirectory dir, @Nullable ModuleFileIndex moduleFileIndex, - ViewSettings viewSettings) { + ViewSettings viewSettings, + @Nullable PsiFileSystemItemFilter filter) { final Project project = dir.getProject(); PsiDirectory[] subdirs = dir.getSubdirectories(); for (PsiDirectory subdir : subdirs) { - if (skipDirectory(subdir)) { + if (skipDirectory(subdir) || filter != null && !filter.shouldShow(subdir)) { continue; } if (moduleFileIndex != null && !moduleFileIndex.isInContent(subdir.getVirtualFile())) { - container.add(new PsiDirectoryNode(project, subdir, viewSettings)); + container.add(new PsiDirectoryNode(project, subdir, viewSettings, filter)); continue; } if (viewSettings.isHideEmptyMiddlePackages()) { - if (!isEmptyMiddleDirectory(subdir, false)) { + if (!isEmptyMiddleDirectory(subdir, false, filter)) { - container.add(new PsiDirectoryNode(project, subdir, viewSettings)); + container.add(new PsiDirectoryNode(project, subdir, viewSettings, filter)); } } else { - container.add(new PsiDirectoryNode(project, subdir, viewSettings)); + container.add(new PsiDirectoryNode(project, subdir, viewSettings, filter)); } - addAllSubpackages(container, subdir, moduleFileIndex, viewSettings); + addAllSubpackages(container, subdir, moduleFileIndex, viewSettings, filter); } } } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java index a869465f64bf..e32b00009027 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -41,19 +41,35 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.NavigatableWithText; import com.intellij.projectImport.ProjectAttachProcessor; import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; import com.intellij.psi.impl.file.PsiDirectoryFactory; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.IconUtil; import com.intellij.util.PathUtil; import com.intellij.util.PlatformUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.Collection; public class PsiDirectoryNode extends BasePsiNode implements NavigatableWithText { + + private final PsiFileSystemItemFilter myFilter; + public PsiDirectoryNode(Project project, PsiDirectory value, ViewSettings viewSettings) { + this(project, value, viewSettings, null); + } + + public PsiDirectoryNode(Project project, PsiDirectory value, ViewSettings viewSettings, @Nullable PsiFileSystemItemFilter filter) { super(project, value, viewSettings); + myFilter = filter; + } + + @Nullable + public PsiFileSystemItemFilter getFilter() { + return myFilter; } protected boolean shouldShowModuleName() { @@ -140,7 +156,7 @@ public class PsiDirectoryNode extends BasePsiNode implements Navig @Override public Collection getChildrenImpl() { - return ProjectViewDirectoryHelper.getInstance(myProject).getDirectoryChildren(getValue(), getSettings(), true); + return ProjectViewDirectoryHelper.getInstance(myProject).getDirectoryChildren(getValue(), getSettings(), true, getFilter()); } @Override @@ -169,8 +185,17 @@ public class PsiDirectoryNode extends BasePsiNode implements Navig return false; } + final Project project = value.getProject(); + PsiFileSystemItemFilter filter = getFilter(); + if (filter != null) { + PsiFile psiFile = PsiManager.getInstance(project).findFile(file); + if (psiFile != null && !filter.shouldShow(psiFile)) return false; + + PsiDirectory psiDirectory = PsiManager.getInstance(project).findDirectory(file); + if (psiDirectory != null && !filter.shouldShow(psiDirectory)) return false; + } + if (Registry.is("ide.hide.excluded.files")) { - final Project project = value.getProject(); final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); return !fileIndex.isExcluded(file); } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiFileSystemItemFilter.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiFileSystemItemFilter.java new file mode 100644 index 000000000000..07c7073abd1d --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiFileSystemItemFilter.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2016 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.ide.projectView.impl.nodes; + +import com.intellij.ide.projectView.ViewSettings; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileSystemItem; +import org.jetbrains.annotations.NotNull; + +public interface PsiFileSystemItemFilter { + + /** + * @param item {@link PsiFile file} or {@link PsiDirectory directory}. + * @return true if item should be showed in project view, otherwise false. + * @see ProjectViewDirectoryHelper#getDirectoryChildren(PsiDirectory, ViewSettings, boolean, PsiFileSystemItemFilter) + */ + boolean shouldShow(@NotNull PsiFileSystemItem item); +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/projectView/GradleTreeStructureProvider.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/projectView/GradleTreeStructureProvider.java index 4ee1e5ea8a03..1c6b82c4352e 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/projectView/GradleTreeStructureProvider.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/projectView/GradleTreeStructureProvider.java @@ -19,10 +19,7 @@ import com.intellij.ide.projectView.PresentationData; import com.intellij.ide.projectView.TreeStructureProvider; import com.intellij.ide.projectView.ViewSettings; import com.intellij.ide.projectView.impl.ProjectRootsUtil; -import com.intellij.ide.projectView.impl.nodes.ProjectViewModuleGroupNode; -import com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode; -import com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode; -import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode; +import com.intellij.ide.projectView.impl.nodes.*; import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.module.Module; @@ -204,7 +201,7 @@ public class GradleTreeStructureProvider implements TreeStructureProvider { final Module module = fileIndex.getModuleForFile(virtualFile); String sourceSetName = getSourceSetName(module); if (sourceSetName == null) return null; - return new GradleSourceSetDirectoryNode(project, psiDirectory, settings, module, sourceSetName); + return new GradleSourceSetDirectoryNode(project, psiDirectory, settings, module, sourceSetName, directoryNode.getFilter()); } @Nullable @@ -228,8 +225,9 @@ public class GradleTreeStructureProvider implements TreeStructureProvider { PsiDirectory psiDirectory, ViewSettings settings, Module module, - String sourceSetName) { - super(project, psiDirectory, settings); + String sourceSetName, + PsiFileSystemItemFilter filter) { + super(project, psiDirectory, settings, filter); mySourceSetName = sourceSetName; myModule = module; }