diff --git a/platform/lang-impl/src/com/intellij/ide/structureView/customRegions/CustomRegionStructureUtil.java b/platform/structure-view-impl/src/com/intellij/ide/structureView/customRegions/CustomRegionStructureUtil.java similarity index 86% rename from platform/lang-impl/src/com/intellij/ide/structureView/customRegions/CustomRegionStructureUtil.java rename to platform/structure-view-impl/src/com/intellij/ide/structureView/customRegions/CustomRegionStructureUtil.java index 9386040f21f1..20fd5f0b00ca 100644 --- a/platform/lang-impl/src/com/intellij/ide/structureView/customRegions/CustomRegionStructureUtil.java +++ b/platform/structure-view-impl/src/com/intellij/ide/structureView/customRegions/CustomRegionStructureUtil.java @@ -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 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 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 collectCustomRegions(@NotNull PsiElement rootElement, @NotNull Set ranges) { Iterator 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'); } diff --git a/platform/lang-impl/src/com/intellij/ide/structureView/customRegions/CustomRegionTreeElement.java b/platform/structure-view-impl/src/com/intellij/ide/structureView/customRegions/CustomRegionTreeElement.java similarity index 97% rename from platform/lang-impl/src/com/intellij/ide/structureView/customRegions/CustomRegionTreeElement.java rename to platform/structure-view-impl/src/com/intellij/ide/structureView/customRegions/CustomRegionTreeElement.java index 17b9409005f0..f0024608e3f8 100644 --- a/platform/lang-impl/src/com/intellij/ide/structureView/customRegions/CustomRegionTreeElement.java +++ b/platform/structure-view-impl/src/com/intellij/ide/structureView/customRegions/CustomRegionTreeElement.java @@ -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; } } diff --git a/platform/structure-view-impl/src/com/intellij/ide/structureView/impl/common/PsiTreeElementBase.java b/platform/structure-view-impl/src/com/intellij/ide/structureView/impl/common/PsiTreeElementBase.java index 2bf56474a7c5..d0bd82ae2c66 100644 --- a/platform/structure-view-impl/src/com/intellij/ide/structureView/impl/common/PsiTreeElementBase.java +++ b/platform/structure-view-impl/src/com/intellij/ide/structureView/impl/common/PsiTreeElementBase.java @@ -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 implements Struc if (element == null) return EMPTY_ARRAY; List result = new ArrayList<>(); Collection baseChildren = getChildrenBase(); - result.addAll(baseChildren); + result.addAll(CustomRegionStructureUtil.groupByCustomRegions(element, baseChildren)); StructureViewFactoryEx structureViewFactory = StructureViewFactoryEx.getInstanceEx(element.getProject()); Class aClass = element.getClass(); for (StructureViewExtension extension : structureViewFactory.getAllExtensions(aClass)) {