mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
refactor to avoid SOE and fail to stop problems ever (IDEA-140324)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<VirtualFile> roots, List<Object> 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<VirtualFile> roots, List<Object> 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user