Custom regions in structure view for all languages (IDEA-129599)

This commit is contained in:
Rustam Vishnyakov
2016-11-15 19:05:42 +03:00
parent af898723a5
commit 67207b64be
3 changed files with 21 additions and 8 deletions
@@ -18,10 +18,7 @@ package com.intellij.ide.structureView.customRegions;
import com.intellij.ide.structureView.StructureViewTreeElement;
import com.intellij.lang.folding.CustomFoldingProvider;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.StubBasedPsiElement;
import com.intellij.psi.SyntaxTraverser;
import com.intellij.psi.*;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,7 +38,7 @@ public class CustomRegionStructureUtil {
}
Set<TextRange> childrenRanges = ContainerUtil.map2SetNotNull(originalElements, element -> {
Object value = element.getValue();
return value instanceof PsiElement ? ((PsiElement)value).getTextRange() : null;
return value instanceof PsiElement ? getTextRange((PsiElement)value) : null;
});
Collection<CustomRegionTreeElement> customRegions = collectCustomRegions(rootElement, childrenRanges);
if (customRegions.size() > 0) {
@@ -63,6 +60,21 @@ public class CustomRegionStructureUtil {
return originalElements;
}
/*
* Fix cases when a line comment before an element (for example, method) gets inside it as a first child.
*/
private static TextRange getTextRange(@NotNull PsiElement element) {
PsiElement first = element.getFirstChild();
if (first instanceof PsiComment && !first.textContains('\n')) {
PsiElement next = first.getNextSibling();
if (next instanceof PsiWhiteSpace) next = next.getNextSibling();
if (next != null) {
return new TextRange(next.getTextRange().getStartOffset(), element.getTextRange().getEndOffset());
}
}
return element.getTextRange();
}
private static Collection<CustomRegionTreeElement> collectCustomRegions(@NotNull PsiElement rootElement, @NotNull Set<TextRange> ranges) {
Iterator<PsiElement> iterator = SyntaxTraverser.psiTraverser(rootElement)
.regard(element -> isCustomRegionCommentCandidate(element) && !isInsideRanges(element, ranges))
@@ -112,7 +124,7 @@ public class CustomRegionStructureUtil {
}
return false;
}
private static boolean isCustomRegionCommentCandidate(@NotNull PsiElement element) {
return element instanceof PsiComment && !element.textContains('\n');
}
@@ -133,7 +133,7 @@ public class CustomRegionTreeElement implements StructureViewTreeElement {
Object o = element.getValue();
if (o instanceof PsiElement) {
TextRange elementRange = ((PsiElement)o).getTextRange();
if(elementRange.getStartOffset() > myStartElement.getTextRange().getStartOffset() && elementRange.getEndOffset() < myEndOffset) {
if(elementRange.getStartOffset() >= myStartElement.getTextRange().getStartOffset() && elementRange.getEndOffset() <= myEndOffset) {
return true;
}
}
@@ -18,6 +18,7 @@ package com.intellij.ide.structureView.impl.common;
import com.intellij.ide.structureView.StructureViewExtension;
import com.intellij.ide.structureView.StructureViewFactoryEx;
import com.intellij.ide.structureView.StructureViewTreeElement;
import com.intellij.ide.structureView.customRegions.CustomRegionStructureUtil;
import com.intellij.ide.util.treeView.NodeDescriptorProvidingKey;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.util.Iconable;
@@ -102,7 +103,7 @@ public abstract class PsiTreeElementBase <T extends PsiElement> implements Struc
if (element == null) return EMPTY_ARRAY;
List<StructureViewTreeElement> result = new ArrayList<>();
Collection<StructureViewTreeElement> baseChildren = getChildrenBase();
result.addAll(baseChildren);
result.addAll(CustomRegionStructureUtil.groupByCustomRegions(element, baseChildren));
StructureViewFactoryEx structureViewFactory = StructureViewFactoryEx.getInstanceEx(element.getProject());
Class<? extends PsiElement> aClass = element.getClass();
for (StructureViewExtension extension : structureViewFactory.getAllExtensions(aClass)) {