@Nullable
[fedora-idea.git] / lang-impl / src / com / intellij / ide / projectView / impl / nodes / ProjectViewDirectoryHelper.java
blob456aa12c39848d7a7d2c64fe7bebae4f4ea3a9d9
1 /*
2 * User: anna
3 * Date: 23-Jan-2008
4 */
5 package com.intellij.ide.projectView.impl.nodes;
7 import com.intellij.ide.projectView.ProjectViewNode;
8 import com.intellij.ide.projectView.ViewSettings;
9 import com.intellij.ide.util.treeView.AbstractTreeNode;
10 import com.intellij.openapi.components.ServiceManager;
11 import com.intellij.openapi.diagnostic.Logger;
12 import com.intellij.openapi.module.Module;
13 import com.intellij.openapi.project.Project;
14 import com.intellij.openapi.roots.ModuleFileIndex;
15 import com.intellij.openapi.roots.ModuleRootManager;
16 import com.intellij.openapi.roots.ProjectFileIndex;
17 import com.intellij.openapi.roots.ProjectRootManager;
18 import com.intellij.openapi.util.Comparing;
19 import com.intellij.openapi.vfs.VirtualFile;
20 import com.intellij.psi.PsiDirectory;
21 import com.intellij.psi.PsiElement;
22 import com.intellij.psi.PsiFile;
23 import org.jetbrains.annotations.NotNull;
24 import org.jetbrains.annotations.Nullable;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.List;
30 public class ProjectViewDirectoryHelper {
31 protected static final Logger LOG = Logger.getInstance("#" + ProjectViewDirectoryHelper.class.getName());
33 private final Project myProject;
35 public static ProjectViewDirectoryHelper getInstance(Project project) {
36 return ServiceManager.getService(project, ProjectViewDirectoryHelper.class);
39 public ProjectViewDirectoryHelper(Project project) {
40 myProject = project;
43 public Project getProject() {
44 return myProject;
47 @Nullable
48 public String getLocationString(@NotNull PsiDirectory psiDirectory, boolean forceLocation) {
49 final VirtualFile directory = psiDirectory.getVirtualFile();
50 final VirtualFile contentRootForFile = ProjectRootManager.getInstance(myProject)
51 .getFileIndex().getContentRootForFile(directory);
52 if (Comparing.equal(contentRootForFile, psiDirectory)) {
53 return directory.getPresentableUrl();
55 return null;
60 public boolean isShowFQName(ViewSettings settings, Object parentValue, PsiDirectory value) {
61 return false;
65 @Nullable
66 public String getNodeName(ViewSettings settings, Object parentValue, PsiDirectory directory) {
67 return directory.getName();
70 public boolean skipDirectory(PsiDirectory directory) {
71 return true;
74 public boolean showFileInLibClasses(VirtualFile vFile) {
75 return true;
78 public boolean isEmptyMiddleDirectory(PsiDirectory directory, final boolean strictlyEmpty) {
79 return false;
82 public boolean canRepresent(Object element, PsiDirectory directory) {
83 if (element instanceof VirtualFile) {
84 VirtualFile vFile = (VirtualFile) element;
85 return directory.getVirtualFile() == vFile;
87 return false;
90 public Collection<AbstractTreeNode> getDirectoryChildren(final PsiDirectory psiDirectory,
91 final ViewSettings settings,
92 final boolean withSubDirectories) {
93 final List<AbstractTreeNode> children = new ArrayList<AbstractTreeNode>();
94 final Project project = psiDirectory.getProject();
95 final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
96 final Module module = fileIndex.getModuleForFile(psiDirectory.getVirtualFile());
97 final ModuleFileIndex moduleFileIndex = module == null ? null : ModuleRootManager.getInstance(module).getFileIndex();
98 if (!settings.isFlattenPackages() || skipDirectory(psiDirectory)) {
99 processPsiDirectoryChildren(psiDirectory, psiDirectory.getChildren(), children, fileIndex, moduleFileIndex, settings,
100 withSubDirectories);
102 else { // source directory in "flatten packages" mode
103 final PsiDirectory parentDir = psiDirectory.getParentDirectory();
104 if (parentDir == null || skipDirectory(parentDir) /*|| !rootDirectoryFound(parentDir)*/ && withSubDirectories) {
105 addAllSubpackages(children, psiDirectory, moduleFileIndex, settings);
107 PsiDirectory[] subdirs = psiDirectory.getSubdirectories();
108 for (PsiDirectory subdir : subdirs) {
109 if (!skipDirectory(subdir)) {
110 continue;
112 if (moduleFileIndex != null) {
113 if (!moduleFileIndex.isInContent(subdir.getVirtualFile())) {
114 continue;
117 if (withSubDirectories) {
118 children.add(new PsiDirectoryNode(project, subdir, settings));
121 processPsiDirectoryChildren(psiDirectory, psiDirectory.getFiles(), children, fileIndex, moduleFileIndex, settings,
122 withSubDirectories);
124 return children;
127 // used only for non-flatten packages mode
128 public void processPsiDirectoryChildren(final PsiDirectory psiDir,
129 PsiElement[] children,
130 List<AbstractTreeNode> container,
131 ProjectFileIndex projectFileIndex,
132 ModuleFileIndex moduleFileIndex,
133 ViewSettings viewSettings,
134 boolean withSubDirectories) {
135 for (PsiElement child : children) {
136 LOG.assertTrue(child.isValid());
138 final VirtualFile vFile;
139 if (child instanceof PsiFile) {
140 vFile = ((PsiFile)child).getVirtualFile();
141 addNode(moduleFileIndex, projectFileIndex, psiDir, vFile, container, PsiFileNode.class, child, viewSettings);
143 else if (child instanceof PsiDirectory) {
144 if (withSubDirectories) {
145 PsiDirectory dir = (PsiDirectory)child;
146 vFile = dir.getVirtualFile();
147 if (!vFile.equals(projectFileIndex.getSourceRootForFile(vFile))) { // if is not a source root
148 if (viewSettings.isHideEmptyMiddlePackages() && !skipDirectory(psiDir) && isEmptyMiddleDirectory(dir, true)) {
149 processPsiDirectoryChildren(dir, dir.getChildren(), container, projectFileIndex, moduleFileIndex, viewSettings,
150 withSubDirectories); // expand it recursively
151 continue;
154 addNode(moduleFileIndex, projectFileIndex, psiDir, vFile, container, PsiDirectoryNode.class, child, viewSettings);
157 else {
158 LOG.assertTrue(false, "Either PsiFile or PsiDirectory expected as a child of " + child.getParent() + ", but was " + child);
163 public void addNode(ModuleFileIndex moduleFileIndex,
164 ProjectFileIndex projectFileIndex,
165 PsiDirectory psiDir,
166 VirtualFile vFile,
167 List<AbstractTreeNode> container,
168 Class<? extends AbstractTreeNode> nodeClass,
169 PsiElement element,
170 final ViewSettings settings) {
171 if (vFile == null) {
172 return;
174 // this check makes sense for classes not in library content only
175 if (moduleFileIndex != null && !moduleFileIndex.isInContent(vFile)) {
176 return;
178 final boolean childInLibraryClasses = projectFileIndex.isInLibraryClasses(vFile);
179 if (!projectFileIndex.isInSourceContent(vFile)) {
180 if (childInLibraryClasses) {
181 final VirtualFile psiDirVFile = psiDir.getVirtualFile();
182 final boolean parentInLibraryContent =
183 projectFileIndex.isInLibraryClasses(psiDirVFile) || projectFileIndex.isInLibrarySource(psiDirVFile);
184 if (!parentInLibraryContent) {
185 return;
189 if (childInLibraryClasses && !projectFileIndex.isInContent(vFile) && !showFileInLibClasses(vFile)) {
190 return; // skip java sources in classpath
193 try {
194 container.add(ProjectViewNode.createTreeNode(nodeClass, element.getProject(), element, settings));
196 catch (Exception e) {
197 LOG.error(e);
201 // used only in flatten packages mode
202 public void addAllSubpackages(List<AbstractTreeNode> container,
203 PsiDirectory dir,
204 ModuleFileIndex moduleFileIndex,
205 ViewSettings viewSettings) {
206 final Project project = dir.getProject();
207 PsiDirectory[] subdirs = dir.getSubdirectories();
208 for (PsiDirectory subdir : subdirs) {
209 if (skipDirectory(subdir)) {
210 continue;
212 if (moduleFileIndex != null) {
213 if (!moduleFileIndex.isInContent(subdir.getVirtualFile())) {
214 continue;
217 if (viewSettings.isHideEmptyMiddlePackages()) {
218 if (!isEmptyMiddleDirectory(subdir, false)) {
220 container.add(new PsiDirectoryNode(project, subdir, viewSettings));
223 else {
224 container.add(new PsiDirectoryNode(project, subdir, viewSettings));
226 addAllSubpackages(container, subdir, moduleFileIndex, viewSettings);