diff --git a/json/src/com/intellij/json/formatter/JsonBlock.java b/json/src/com/intellij/json/formatter/JsonBlock.java index 85bbe545f2bb..307e4a7fbc59 100644 --- a/json/src/com/intellij/json/formatter/JsonBlock.java +++ b/json/src/com/intellij/json/formatter/JsonBlock.java @@ -1,7 +1,6 @@ package com.intellij.json.formatter; import com.intellij.formatting.*; -import com.intellij.json.JsonElementTypes; import com.intellij.json.JsonLanguage; import com.intellij.json.psi.JsonArray; import com.intellij.json.psi.JsonObject; @@ -22,17 +21,19 @@ import org.jetbrains.annotations.Nullable; import java.util.List; +import static com.intellij.json.JsonElementTypes.*; import static com.intellij.json.JsonParserDefinition.*; import static com.intellij.json.formatter.JsonCodeStyleSettings.PropertyAlignment.ALIGN_ON_COLON; import static com.intellij.json.formatter.JsonCodeStyleSettings.PropertyAlignment.ALIGN_ON_VALUE; +import static com.intellij.json.psi.JsonPsiUtil.hasElementType; /** * @author Mikhail Golubev */ public class JsonBlock implements ASTBlock { - private static final TokenSet OPEN_BRACES = TokenSet.create(JsonElementTypes.L_BRACKET, JsonElementTypes.L_CURLY); - private static final TokenSet CLOSE_BRACES = TokenSet.create(JsonElementTypes.R_BRACKET, JsonElementTypes.R_CURLY); - private static final TokenSet BRACES = TokenSet.orSet(OPEN_BRACES, CLOSE_BRACES); + private static final TokenSet JSON_OPEN_BRACES = TokenSet.create(L_BRACKET, L_CURLY); + private static final TokenSet JSON_CLOSE_BRACES = TokenSet.create(R_BRACKET, R_CURLY); + private static final TokenSet JSON_ALL_BRACES = TokenSet.orSet(JSON_OPEN_BRACES, JSON_CLOSE_BRACES); private final JsonBlock myParent; @@ -107,20 +108,18 @@ public class JsonBlock implements ASTBlock { } private Block makeSubBlock(@NotNull ASTNode childNode) { - final IElementType childNodeType = childNode.getElementType(); - Indent indent = Indent.getNoneIndent(); Alignment alignment = null; Wrap wrap = null; final JsonCodeStyleSettings customSettings = getCustomSettings(); - if (isContainer()) { - if (childNodeType != JsonElementTypes.COMMA && !BRACES.contains(childNodeType)) { + if (hasElementType(myNode, JSON_CONTAINERS)) { + if (!hasElementType(childNode, COMMA) && !hasElementType(childNode, JSON_ALL_BRACES)) { assert myChildWrap != null; wrap = myChildWrap; indent = Indent.getNormalIndent(); } - else if (OPEN_BRACES.contains(childNodeType)) { + else if (hasElementType(childNode, JSON_OPEN_BRACES)) { if (JsonPsiUtil.isPropertyValue(myPsiElement) && customSettings.PROPERTY_ALIGNMENT == ALIGN_ON_VALUE) { // WEB-13587 Align compound values on opening brace/bracket, not the whole block assert myParent != null && myParent.myParent != null && myParent.myParent.myPropertyValueAlignment != null; @@ -129,13 +128,13 @@ public class JsonBlock implements ASTBlock { } } // Handle properties alignment - else if (myNode.getElementType() == JsonElementTypes.PROPERTY) { + else if (hasElementType(myNode, PROPERTY) ) { assert myParent != null && myParent.myPropertyValueAlignment != null; - if (childNode.getElementType() == JsonElementTypes.COLON && customSettings.PROPERTY_ALIGNMENT == ALIGN_ON_COLON) { + if (hasElementType(childNode, COLON) && customSettings.PROPERTY_ALIGNMENT == ALIGN_ON_COLON) { alignment = myParent.myPropertyValueAlignment; } else if (JsonPsiUtil.isPropertyValue(childNode.getPsi()) && customSettings.PROPERTY_ALIGNMENT == ALIGN_ON_VALUE) { - if (!JSON_CONTAINERS.contains(childNodeType)) { + if (!hasElementType(childNode, JSON_CONTAINERS)) { alignment = myParent.myPropertyValueAlignment; } } @@ -165,17 +164,17 @@ public class JsonBlock implements ASTBlock { @Override public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { final CommonCodeStyleSettings commonSettings = getCommonSettings(); - final IElementType leftChildType = child1 instanceof JsonBlock ? ((JsonBlock)child1).myNode.getElementType() : null; - final IElementType rightChildType = child2 instanceof JsonBlock ? ((JsonBlock)child2).myNode.getElementType() : null; + final ASTNode leftChild = child1 instanceof JsonBlock ? ((JsonBlock)child1).myNode : null; + final ASTNode rightChild = child2 instanceof JsonBlock ? ((JsonBlock)child2).myNode : null; // This causes braces/brackets to be on their own lines if whole object/array spans several lines. - if (leftChildType != null && rightChildType != null) { - if (JSON_BRACES.contains(leftChildType) ^ JSON_BRACES.contains(rightChildType)) { + if (leftChild != null && rightChild != null) { + if (hasElementType(leftChild, JSON_BRACES) ^ hasElementType(rightChild, JSON_BRACES)) { final int numSpaces = commonSettings.SPACE_WITHIN_BRACES ? 1 : 0; return Spacing.createDependentLFSpacing(numSpaces, numSpaces, myNode.getTextRange(), commonSettings.KEEP_LINE_BREAKS, commonSettings.KEEP_BLANK_LINES_IN_CODE); } - else if (JSON_BRACKETS.contains(leftChildType) ^ JSON_BRACKETS.contains(rightChildType)) { + else if (hasElementType(leftChild, JSON_BRACKETS) ^ hasElementType(rightChild, JSON_BRACKETS)) { final int numSpaces = commonSettings.SPACE_WITHIN_BRACKETS ? 1 : 0; return Spacing.createDependentLFSpacing(numSpaces, numSpaces, myNode.getTextRange(), commonSettings.KEEP_LINE_BREAKS, @@ -188,7 +187,7 @@ public class JsonBlock implements ASTBlock { @NotNull @Override public ChildAttributes getChildAttributes(int newChildIndex) { - if (isContainer()) { + if (hasElementType(myNode, JSON_CONTAINERS)) { // WEB-13675: For some reason including alignment in child attributes causes // indents to consist solely of spaces when both USE_TABS and SMART_TAB // options are enabled. @@ -200,15 +199,14 @@ public class JsonBlock implements ASTBlock { @Override public boolean isIncomplete() { - final IElementType nodeType = myNode.getElementType(); final ASTNode lastChildNode = myNode.getLastChildNode(); - if (nodeType == JsonElementTypes.OBJECT) { - return lastChildNode != null && lastChildNode.getElementType() != JsonElementTypes.R_CURLY; + if (hasElementType(myNode, OBJECT)) { + return lastChildNode != null && lastChildNode.getElementType() != R_CURLY; } - else if (nodeType == JsonElementTypes.ARRAY) { - return lastChildNode != null && lastChildNode.getElementType() != JsonElementTypes.R_BRACKET; + else if (hasElementType(myNode, ARRAY)) { + return lastChildNode != null && lastChildNode.getElementType() != R_BRACKET; } - else if (myPsiElement instanceof JsonProperty) { + else if (hasElementType(myNode, PROPERTY)) { return ((JsonProperty)myPsiElement).getValue() == null; } return false; @@ -223,10 +221,6 @@ public class JsonBlock implements ASTBlock { return node.getElementType() == TokenType.WHITE_SPACE || node.getTextLength() == 0; } - private boolean isContainer() { - return JSON_CONTAINERS.contains(myNode.getElementType()); - } - private JsonCodeStyleSettings getCustomSettings() { return mySettings.getCustomSettings(JsonCodeStyleSettings.class); } diff --git a/json/src/com/intellij/json/psi/JsonPsiUtil.java b/json/src/com/intellij/json/psi/JsonPsiUtil.java index e3520f7526b1..0b9a151212e6 100644 --- a/json/src/com/intellij/json/psi/JsonPsiUtil.java +++ b/json/src/com/intellij/json/psi/JsonPsiUtil.java @@ -5,6 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import com.intellij.psi.TokenType; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; import static com.intellij.json.JsonParserDefinition.JSON_COMMENTARIES; @@ -86,4 +87,35 @@ public class JsonPsiUtil { } return lastSeen.getPsi(); } + + /** + * Check that element type of the given AST node belongs to the token set. + *
+ * It slightly less verbose than {@code set.contains(node.getElementType())} and overloaded methods with the same name + * allow check ASTNode/PsiElement against both concrete element types and token sets in uniform way. + */ + public static boolean hasElementType(@NotNull ASTNode node, @NotNull TokenSet set) { + return set.contains(node.getElementType()); + } + + /** + * @see #hasElementType(com.intellij.lang.ASTNode, com.intellij.psi.tree.TokenSet) + */ + public static boolean hasElementType(@NotNull ASTNode node, IElementType... types) { + return hasElementType(node, TokenSet.create(types)); + } + + /** + * @see #hasElementType(com.intellij.lang.ASTNode, com.intellij.psi.tree.TokenSet) + */ + public static boolean hasElementType(@NotNull PsiElement element, @NotNull TokenSet set) { + return element.getNode() != null && hasElementType(element.getNode(), set); + } + + /** + * @see #hasElementType(com.intellij.lang.ASTNode, com.intellij.psi.tree.IElementType...) + */ + public static boolean hasElementType(@NotNull PsiElement element, IElementType... types) { + return element.getNode() != null && hasElementType(element.getNode(), types); + } }