diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/DefaultNavBarExtension.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/DefaultNavBarExtension.java index 06928197028d..8f888a825472 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/DefaultNavBarExtension.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/DefaultNavBarExtension.java @@ -29,6 +29,7 @@ import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiFileSystemItemProcessor; import com.intellij.psi.util.PsiUtilCore; +import com.intellij.util.PathUtil; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -181,4 +182,51 @@ public class DefaultNavBarExtension extends AbstractNavBarModelExtension { } }); } + + @Nullable + @Override + public PsiElement getParent(PsiElement psiElement) { + PsiFile containingFile = psiElement.getContainingFile(); + if (containingFile != null) { + PsiDirectory containingDirectory = containingFile.getContainingDirectory(); + if (containingDirectory != null) { + return containingDirectory; + } + } + else if (psiElement instanceof PsiDirectory) { + PsiDirectory psiDirectory = (PsiDirectory)psiElement; + Project project = psiElement.getProject(); + + PsiDirectory parentDirectory = psiDirectory.getParentDirectory(); + + if (parentDirectory == null) { + VirtualFile jar = PathUtil.getLocalFile(psiDirectory.getVirtualFile()); + if (ProjectRootManager.getInstance(project).getFileIndex().isInContent(jar)) { + parentDirectory = PsiManager.getInstance(project).findDirectory(jar.getParent()); + } + } + return parentDirectory; + } + else if (psiElement instanceof PsiFileSystemItem) { + VirtualFile virtualFile = ((PsiFileSystemItem)psiElement).getVirtualFile(); + if (virtualFile == null) return null; + PsiManager psiManager = psiElement.getManager(); + PsiElement resultElement; + if (virtualFile.isDirectory()) { + resultElement = psiManager.findDirectory(virtualFile); + } + else { + resultElement = psiManager.findFile(virtualFile); + } + if (resultElement == null) return null; + VirtualFile parentVFile = virtualFile.getParent(); + if (parentVFile != null) { + PsiDirectory parentDirectory = psiManager.findDirectory(parentVFile); + if (parentDirectory != null) { + return parentDirectory; + } + } + } + return null; + } } diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarModel.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarModel.java index 98cf21272902..ddaa4682e896 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarModel.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarModel.java @@ -33,9 +33,9 @@ import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.CommonProcessors; import com.intellij.util.ObjectUtils; -import com.intellij.util.PathUtil; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -174,7 +174,7 @@ public class NavBarModel { } }); - setModel(updatedModel); + setModel(ContainerUtil.reverse(updatedModel)); } void revalidate() { @@ -215,81 +215,42 @@ public class NavBarModel { } } - private void traverseToRoot(@NotNull PsiElement psiElement, Set roots, List model) { - if (!psiElement.isValid()) return; - final PsiFile containingFile = psiElement.getContainingFile(); - if (containingFile != null && containingFile.getVirtualFile() == null) return; //non physical elements - psiElement = getOriginalElement(psiElement); - PsiElement resultElement = psiElement; + private static void traverseToRoot(@NotNull PsiElement psiElement, Set roots, List model) { + if (!isValid(psiElement)) return; - resultElement = normalize(resultElement); - if (resultElement == null) return; + NavBarModelExtension[] extensions = Extensions.getExtensions(NavBarModelExtension.EP_NAME); - boolean foundByExtension = false; - for (final NavBarModelExtension modelExtension : Extensions.getExtensions(NavBarModelExtension.EP_NAME)) { - final PsiElement parent = modelExtension.getParent(resultElement); - if (parent != null) { - if (parent != resultElement) { // HACK is to return same element to stop traversing - traverseToRoot(parent, roots, model); - } - foundByExtension = true; - break; - } - } + for (PsiElement e = normalize(getOriginalElement(psiElement)), next = null; + e != null; e = normalize(getOriginalElement(next)), next = null) { + // check if we're running circles due to getParent()->normalize/adjust() + if (model.contains(e)) break; - if (!foundByExtension) { - if (containingFile != null) { - final PsiDirectory containingDirectory = containingFile.getContainingDirectory(); - if (containingDirectory != null) { - traverseToRoot(containingDirectory, roots, model); - } - } - else if (psiElement instanceof PsiDirectory) { - final PsiDirectory psiDirectory = (PsiDirectory)psiElement; + model.add(e); - if (!roots.contains(psiDirectory.getVirtualFile())) { - PsiDirectory parentDirectory = psiDirectory.getParentDirectory(); + // check if a root is reached + VirtualFile vFile = PsiUtilCore.getVirtualFile(e); + if (roots.contains(vFile)) break; - if (parentDirectory == null) { - VirtualFile jar = PathUtil.getLocalFile(psiDirectory.getVirtualFile()); - if (ProjectRootManager.getInstance(myProject).getFileIndex().isInContent(jar)) { - parentDirectory = PsiManager.getInstance(myProject).findDirectory(jar.getParent()); - } - } - - - if (parentDirectory != null) { - traverseToRoot(parentDirectory, roots, model); - } - } - } - else if (psiElement instanceof PsiFileSystemItem) { - final VirtualFile virtualFile = ((PsiFileSystemItem)psiElement).getVirtualFile(); - if (virtualFile == null) return; - final PsiManager psiManager = PsiManager.getInstance(myProject); - if (virtualFile.isDirectory()) { - resultElement = psiManager.findDirectory(virtualFile); - } - else { - resultElement = psiManager.findFile(virtualFile); - } - if (resultElement == null) return; - final VirtualFile parentVFile = virtualFile.getParent(); - if (parentVFile != null && !roots.contains(parentVFile)) { - final PsiDirectory parentDirectory = psiManager.findDirectory(parentVFile); - if (parentDirectory != null) { - traverseToRoot(parentDirectory, roots, model); - } + for (NavBarModelExtension ext : extensions) { + PsiElement parent = ext.getParent(e); + if (parent != null && parent != e) { + //noinspection AssignmentToForLoopParameter + next = parent; + break; } } } - - model.add(resultElement); } - private static PsiElement getOriginalElement(PsiElement psiElement) { - final PsiElement originalElement = psiElement.getOriginalElement(); - return !(psiElement instanceof PsiCompiledElement) && originalElement instanceof PsiCompiledElement ? psiElement : originalElement; + @Nullable + private static PsiElement getOriginalElement(@Nullable PsiElement e) { + if (e == null || !e.isValid()) return null; + + PsiFile containingFile = e.getContainingFile(); + if (containingFile != null && containingFile.getVirtualFile() == null) return null; + + PsiElement orig = e.getOriginalElement(); + return !(e instanceof PsiCompiledElement) && orig instanceof PsiCompiledElement ? e : orig; }