mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-14 18:05:27 +07:00
Add proper folding for line and block comments in JSON
Also line comments separated by more than one line feed are not moved together.
This commit is contained in:
@@ -1,16 +1,15 @@
|
||||
package com.intellij.json.editor.folding;
|
||||
|
||||
import com.intellij.json.JsonElementTypes;
|
||||
import com.intellij.json.psi.JsonLiteral;
|
||||
import com.intellij.json.psi.JsonObject;
|
||||
import com.intellij.json.psi.JsonProperty;
|
||||
import com.intellij.json.psi.JsonValue;
|
||||
import com.intellij.json.psi.*;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.folding.FoldingBuilder;
|
||||
import com.intellij.lang.folding.FoldingDescriptor;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -37,6 +36,18 @@ public class JsonFoldingBuilder implements FoldingBuilder, DumbAware {
|
||||
if ((type == JsonElementTypes.OBJECT || type == JsonElementTypes.ARRAY) && spanMultipleLines(node, document)) {
|
||||
descriptors.add(new FoldingDescriptor(node, node.getTextRange()));
|
||||
}
|
||||
else if (type == JsonElementTypes.BLOCK_COMMENT) {
|
||||
descriptors.add(new FoldingDescriptor(node, node.getTextRange()));
|
||||
}
|
||||
else if (type == JsonElementTypes.LINE_COMMENT) {
|
||||
final Couple<PsiElement> commentRange = JsonPsiUtil.expandLineCommentsRange(node.getPsi());
|
||||
final int startOffset = commentRange.getFirst().getTextRange().getStartOffset();
|
||||
final int endOffset = commentRange.getSecond().getTextRange().getEndOffset();
|
||||
if (document.getLineNumber(startOffset) != document.getLineNumber(endOffset)) {
|
||||
descriptors.add(new FoldingDescriptor(node, new TextRange(startOffset, endOffset)));
|
||||
}
|
||||
}
|
||||
|
||||
for (ASTNode child : node.getChildren(null)) {
|
||||
collectDescriptorsRecursively(child, document, descriptors);
|
||||
}
|
||||
@@ -72,6 +83,12 @@ public class JsonFoldingBuilder implements FoldingBuilder, DumbAware {
|
||||
else if (type == JsonElementTypes.ARRAY) {
|
||||
return "[...]";
|
||||
}
|
||||
else if (type == JsonElementTypes.LINE_COMMENT) {
|
||||
return "//...";
|
||||
}
|
||||
else if (type == JsonElementTypes.BLOCK_COMMENT) {
|
||||
return "/*...*/";
|
||||
}
|
||||
return "...";
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.intellij.codeInsight.editorActions.moveUpDown.LineMover;
|
||||
import com.intellij.codeInsight.editorActions.moveUpDown.LineRange;
|
||||
import com.intellij.json.JsonElementTypes;
|
||||
import com.intellij.json.psi.*;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -74,25 +73,9 @@ public class JsonLineMover extends LineMover {
|
||||
|
||||
@NotNull
|
||||
private Pair<PsiElement, PsiElement> expandCommentsInRange(@NotNull Pair<PsiElement, PsiElement> range) {
|
||||
final PsiElement firstElement = expandComment(range.first, true);
|
||||
final PsiElement lastElement = expandComment(range.second, false);
|
||||
return Pair.create(firstElement, lastElement);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PsiElement expandComment(@NotNull PsiElement first, boolean before) {
|
||||
ASTNode node = first.getNode();
|
||||
if (node.getElementType() != JsonElementTypes.LINE_COMMENT) {
|
||||
return first;
|
||||
}
|
||||
ASTNode sibling;
|
||||
do {
|
||||
sibling = node;
|
||||
node = before ? node.getTreePrev() : node.getTreeNext();
|
||||
}
|
||||
while (node != null && (node.getElementType() == JsonElementTypes.LINE_COMMENT ||
|
||||
sibling.getElementType() == JsonElementTypes.LINE_COMMENT));
|
||||
return (before ? sibling.getTreeNext() : sibling.getTreePrev()).getPsi();
|
||||
final PsiElement upper = JsonPsiUtil.findOutermostLineComment(range.getFirst(), false);
|
||||
final PsiElement lower = JsonPsiUtil.findOutermostLineComment(range.getSecond(), true);
|
||||
return Pair.create(upper, lower);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package com.intellij.json.psi;
|
||||
|
||||
import com.intellij.json.JsonElementTypes;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.TokenType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -46,4 +51,37 @@ public class JsonPsiUtil {
|
||||
final PsiElement parent = element.getParent();
|
||||
return parent instanceof JsonProperty && element == ((JsonProperty)parent).getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find largest region of successive line comments that includes given one.
|
||||
* @param anchor anchor line comment from which range will be expanded
|
||||
* @return specified range of comments or pair {@code (anchor, anchor)} if anchor is not line comment
|
||||
*/
|
||||
@NotNull
|
||||
public static Couple<PsiElement> expandLineCommentsRange(@NotNull PsiElement anchor) {
|
||||
return Couple.of(findOutermostLineComment(anchor, false), findOutermostLineComment(anchor, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Lowest or topmost successive line comment for given anchor element.
|
||||
* @param anchor start element (most probably another line comment)
|
||||
* @param below whether to scan through element forward or backward
|
||||
* @return described {@link com.intellij.psi.PsiComment} element or {@code anchor} if it's not a line comment
|
||||
*/
|
||||
@NotNull
|
||||
public static PsiElement findOutermostLineComment(@NotNull PsiElement anchor, boolean below) {
|
||||
ASTNode node = anchor.getNode();
|
||||
ASTNode lastSeenComment = node;
|
||||
while (node != null) {
|
||||
final IElementType elementType = node.getElementType();
|
||||
if (elementType == JsonElementTypes.LINE_COMMENT) {
|
||||
lastSeenComment = node;
|
||||
}
|
||||
else if (elementType != TokenType.WHITE_SPACE || node.getText().indexOf('\n', 1) != -1) {
|
||||
break;
|
||||
}
|
||||
node = below ? node.getTreeNext() : node.getTreePrev();
|
||||
}
|
||||
return lastSeenComment.getPsi();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,10 @@ public class JsonFoldingTest extends JsonTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testCommentaries() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// Moved from JavaScript
|
||||
|
||||
public void testObjectLiteral2() {
|
||||
|
||||
11
json/tests/testData/folding/Commentaries.json
Normal file
11
json/tests/testData/folding/Commentaries.json
Normal file
@@ -0,0 +1,11 @@
|
||||
// Single line comment is not folded.
|
||||
|
||||
<fold text='//...'>// But
|
||||
// several comments
|
||||
// are.</fold>
|
||||
<fold text='{"foo": 42...}'>{
|
||||
<fold text='/*...*/'>/* Block commentaries
|
||||
are always folded however.
|
||||
*/</fold>
|
||||
"foo": 42
|
||||
}</fold>
|
||||
@@ -1,5 +1,7 @@
|
||||
{
|
||||
"foo": true,
|
||||
// This line won't be moved
|
||||
|
||||
// Line<caret> 1
|
||||
// Line 2
|
||||
"bar": false
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{
|
||||
"foo": true,
|
||||
// This line won't be moved
|
||||
|
||||
"bar": false
|
||||
// Line 1
|
||||
// Line 2
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"foo": true,
|
||||
// This line won't be moved
|
||||
// Line 1
|
||||
// Line 2
|
||||
"foo": true,
|
||||
"bar": false
|
||||
}
|
||||
Reference in New Issue
Block a user