Java tutorial
/* * Copyright (c) 2018, WSO2 Inc. (http://wso2.com) All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.ballerinalang.langserver.formatting; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Node tree visitor for formatting. */ public class FormattingNodeTree { /** * format abort node. * * @param node {JsonObject} node as json object */ public void formatAbortNode(JsonObject node) { modifyBranchingStatement(node); } /** * format annotation node. * * @param node {JsonObject} node as json object */ public void formatAnnotationNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); boolean isPublic = node.has(FormattingConstants.PUBLIC) && node.get(FormattingConstants.PUBLIC).getAsBoolean(); String indentation = this.getIndentation(formatConfig, false); this.preserveHeight(ws, indentation); int attachPointCounter = 0; for (int i = 0; i < ws.size(); i++) { JsonObject annotationWS = ws.get(i).getAsJsonObject(); String text = annotationWS.get(FormattingConstants.TEXT).getAsString(); if (this.noHeightAvailable(annotationWS.get(FormattingConstants.WS).getAsString())) { if (i == 0) { // If annotation or documentation attachments exists add only one new line. // Else add given number of new lines. String whiteSpace = ((node.has("annotationAttachments") && node.getAsJsonArray("annotationAttachments").size() > 0) || node.has("markdownDocumentationAttachment") || (node.has("deprecatedAttachments") && node.getAsJsonArray("deprecatedAttachments").size() > 0)) ? (FormattingConstants.NEW_LINE + indentation) : (this.getNewLines(formatConfig .get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); annotationWS.addProperty(FormattingConstants.WS, whiteSpace); } else if (isPublic && text.equals("annotation")) { annotationWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (text.equals("<")) { annotationWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); ++attachPointCounter; } else if (text.equals(",")) { annotationWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else if (text.equals(">")) { annotationWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); attachPointCounter = 0; } else { if (attachPointCounter == 1) { annotationWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); ++attachPointCounter; } else if (attachPointCounter > 1) { annotationWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); ++attachPointCounter; } else { if (text.equals(";")) { annotationWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else { annotationWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } } } // Update whitespaces for type node. if (node.has("typeNode")) { JsonObject typeNode = node.getAsJsonObject("typeNode"); JsonObject typeNodeFormattingConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), false); typeNode.add(FormattingConstants.FORMATTING_CONFIG, typeNodeFormattingConfig); } } } /** * format annotation attachment node. * * @param node {JsonObject} node as json object */ public void formatAnnotationAttachmentNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentWithParentIndentation = this.getParentIndentation(formatConfig); // Preserve any comments or new lines that already available. this.preserveHeight(node.getAsJsonArray(FormattingConstants.WS), indentWithParentIndentation); // Update whitespace for annotation symbol, @. JsonObject annotationSymbolWhitespace = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(annotationSymbolWhitespace.get(FormattingConstants.WS).getAsString())) { annotationSymbolWhitespace.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentWithParentIndentation); } else if (this.noNewLine( annotationSymbolWhitespace.get(FormattingConstants.WS).getAsString().charAt(0) + "")) { annotationSymbolWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentWithParentIndentation); } // Update whitespace for annotation identifier. JsonObject identifierWhitespace = ws.get(ws.size() - 1).getAsJsonObject(); if (this.noHeightAvailable(identifierWhitespace.get(FormattingConstants.WS).getAsString())) { identifierWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } // Update whitespace for expression. if (node.has("expression") && node.getAsJsonObject("expression").has(FormattingConstants.WS)) { JsonObject expression = node.getAsJsonObject("expression"); JsonObject expressionFormatConfig = this.getFormattingConfig(0, 1, this.getWhiteSpaceCount(indentation), false, this.getWhiteSpaceCount(indentWithParentIndentation), false); expression.add(FormattingConstants.FORMATTING_CONFIG, expressionFormatConfig); } } } /** * format Array Literal Expr node. * * @param node {JsonObject} node as json object */ public void formatArrayLiteralExprNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentWithParentIndentation = this.getParentIndentation(formatConfig); this.preserveHeight(ws, indentWithParentIndentation); // Update opening bracket whitespace. JsonObject openingBracketWS = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(openingBracketWS.get(FormattingConstants.WS).getAsString())) { openingBracketWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt()) + indentation); } // Update whitespace for the separator. for (JsonElement item : ws) { JsonObject wsItem = item.getAsJsonObject(); String text = wsItem.get(FormattingConstants.TEXT).getAsString(); if (text.equals(",") && this.noHeightAvailable(wsItem.get(FormattingConstants.WS).getAsString())) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } // Update closing bracket whitespace. JsonObject closingBracketWS = ws.get(ws.size() - 1).getAsJsonObject(); if (this.noHeightAvailable(closingBracketWS.get(FormattingConstants.WS).getAsString())) { closingBracketWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } // Update expressions whitespaces. modifyExpressions(node, indentWithParentIndentation); } } /** * format Array Type node. * * @param node {JsonObject} node as json object */ public void formatArrayTypeNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentWithParentIndentation = this.getParentIndentation(formatConfig); String indentation = this.getIndentation(formatConfig, false); // Update whitespace for element type. if (node.has("elementType")) { if (node.has(FormattingConstants.GROUPED) && node.get(FormattingConstants.GROUPED).getAsBoolean()) { JsonObject elementTypeFormatConfig = this.getFormattingConfig(0, 0, 0, false, this.getWhiteSpaceCount(indentWithParentIndentation), false); node.getAsJsonObject("elementType").add(FormattingConstants.FORMATTING_CONFIG, elementTypeFormatConfig); } else { node.getAsJsonObject("elementType").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } } if (node.has(FormattingConstants.WS)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentWithParentIndentation : indentation); for (int i = 0; i < ws.size(); i++) { JsonObject wsItem = ws.get(i).getAsJsonObject(); if (this.noHeightAvailable(wsItem.get(FormattingConstants.WS).getAsString())) { String text = wsItem.get(FormattingConstants.TEXT).getAsString(); if (text.equals("(") && i == 0) { // Update grouped opening parentheses whitespace. if (node.has(FormattingConstants.GROUPED) && node.get(FormattingConstants.GROUPED).getAsBoolean()) { wsItem.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + this.getWhiteSpaces( formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt()) + indentation); } } else { // Update rest of the token whitespaces. wsItem.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } } } } /** * format Assignment node. * * @param node {JsonObject} node as json object */ public void formatAssignmentNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); // Get the indentation for the node. String indentation = this.getIndentation(formatConfig, false); String indentWithParentIndentation = this.getParentIndentation(formatConfig); // Preserve comments and new lines that already available. this.preserveHeight(ws, indentWithParentIndentation); if (node.has("declaredWithVar") && node.get("declaredWithVar").getAsBoolean()) { // Update whitespaces for var. JsonObject varWhitespace = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(varWhitespace.get(FormattingConstants.WS).getAsString())) { // If declared with var add new line varWhitespace.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } // Update whitespace for variable when declared with var. if (node.has("variable")) { JsonObject variable = node.getAsJsonObject("variable"); JsonObject variableFormatConfig = this.getFormattingConfig(0, 1, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), false, this.getWhiteSpaceCount(indentation), false); variable.add(FormattingConstants.FORMATTING_CONFIG, variableFormatConfig); } // Update whitespace for = JsonObject equalWhitespace = ws.get(1).getAsJsonObject(); if (this.noHeightAvailable(equalWhitespace.get(FormattingConstants.WS).getAsString())) { equalWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update whitespace for ; JsonObject semicolonWhitespace = ws.get(2).getAsJsonObject(); if (this.noHeightAvailable(semicolonWhitespace.get(FormattingConstants.WS).getAsString())) { semicolonWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } else { // Update whitespace for variable when not declared with var. if (node.has("variable")) { JsonObject variable = node.getAsJsonObject("variable"); JsonObject variableFormatConfig = this.getFormattingConfig( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt(), 0, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), formatConfig.get(FormattingConstants.DO_INDENT).getAsBoolean(), this.getWhiteSpaceCount(indentation), false); variable.add(FormattingConstants.FORMATTING_CONFIG, variableFormatConfig); } // Update whitespace for = JsonObject equalWhitespace = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(equalWhitespace.get(FormattingConstants.WS).getAsString())) { equalWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update whitespace for ; JsonObject semicolonWhitespace = ws.get(1).getAsJsonObject(); if (this.noHeightAvailable(semicolonWhitespace.get(FormattingConstants.WS).getAsString())) { semicolonWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } // Update whitespaces for the expression. if (node.has("expression") && node.getAsJsonObject("expression").has(FormattingConstants.WS)) { JsonObject expression = node.getAsJsonObject("expression"); JsonObject expressionFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), true); expression.add(FormattingConstants.FORMATTING_CONFIG, expressionFormatConfig); } } } /** * format arrow expr node. * * @param node {JsonObject} node as json object */ public void formatArrowExprNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentWithParentIndentation = this.getParentIndentation(formatConfig); // Preserve line separations that already available. this.preserveHeight(ws, indentWithParentIndentation); for (JsonElement wsItem : ws) { JsonObject arrowExprWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(arrowExprWS.get(FormattingConstants.WS).getAsString())) { String text = arrowExprWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("(")) { arrowExprWS.addProperty(FormattingConstants.WS, this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } if (text.equals(",")) { arrowExprWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } if (text.equals(")")) { arrowExprWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } if (text.equals("=>")) { arrowExprWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } // Update whitespaces of parameters. if (node.has("parameters")) { JsonArray parameters = node.getAsJsonArray("parameters"); boolean hasParentheses = node.has("hasParantheses") && node.get("hasParantheses").getAsBoolean(); for (int i = 0; i < parameters.size(); i++) { JsonObject param = parameters.get(i).getAsJsonObject(); JsonObject paramFormatConfig; // If parentheses available first param should fronted with empty space // Else first param should fronted with space count parent provided. if (i == 0) { if (hasParentheses) { paramFormatConfig = this.getFormattingConfig(0, 0, 0, false, this.getWhiteSpaceCount(indentWithParentIndentation), false); } else { paramFormatConfig = this.getFormattingConfig(0, formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt(), 0, false, this.getWhiteSpaceCount(indentWithParentIndentation), false); } } else { paramFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentWithParentIndentation), false); } param.add(FormattingConstants.FORMATTING_CONFIG, paramFormatConfig); } } // Update whitespace of expression. if (node.has(FormattingConstants.EXPRESSION)) { JsonObject expression = node.getAsJsonObject(FormattingConstants.EXPRESSION); JsonObject expressionFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentWithParentIndentation), false); expression.add(FormattingConstants.FORMATTING_CONFIG, expressionFormatConfig); } } } /** * format Binary Expr node. * * @param node {JsonObject} node as json object */ public void formatBinaryExprNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentWithParentIndentation = this.getParentIndentation(formatConfig); // Preserve line separations that already available. this.preserveHeight(ws, indentWithParentIndentation); // Update the operator symbol whitespace. JsonObject operatorSymbolWS = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(operatorSymbolWS.get(FormattingConstants.WS).getAsString())) { operatorSymbolWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Handle left expression whitespaces. if (node.has("leftExpression")) { node.getAsJsonObject("leftExpression").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } // Handle right expression whitespaces. if (node.has("rightExpression")) { JsonObject rightExpression = node.getAsJsonObject("rightExpression"); JsonObject rightExprFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentWithParentIndentation), true); rightExpression.add(FormattingConstants.FORMATTING_CONFIG, rightExprFormatConfig); } } } /** * format Block node. * * @param node {JsonObject} node as json object */ public void formatBlockNode(JsonObject node) { JsonObject position = new JsonObject(); // TODO: revisit code of how block node is handled. JsonObject formatConfig = node.has(FormattingConstants.FORMATTING_CONFIG) ? node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG) : null; // Get the start column of the parent. position.addProperty(FormattingConstants.START_COLUMN, node.get("parent").getAsJsonObject().get(FormattingConstants.POSITION).getAsJsonObject() .get(FormattingConstants.START_COLUMN).getAsInt()); // Add block position to be the parent's position. node.add(FormattingConstants.POSITION, position); // Update the statements whitespaces. for (int i = 0; i < node.getAsJsonArray(FormattingConstants.STATEMENTS).size(); i++) { JsonElement child = node.getAsJsonArray(FormattingConstants.STATEMENTS).get(i); JsonObject childFormatConfig = formatConfig; if (formatConfig == null) { childFormatConfig = this.getFormattingConfig(1, 0, node.get(FormattingConstants.POSITION).getAsJsonObject() .get(FormattingConstants.START_COLUMN).getAsInt(), true, node.get(FormattingConstants.POSITION).getAsJsonObject() .get(FormattingConstants.START_COLUMN).getAsInt(), false); } child.getAsJsonObject().add(FormattingConstants.FORMATTING_CONFIG, childFormatConfig); } // If this is a else block continue to following. if (node.has(FormattingConstants.WS) && node.getAsJsonArray(FormattingConstants.WS).get(0).getAsJsonObject() .get(FormattingConstants.TEXT).getAsString().equals("else")) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); this.preserveHeight(ws, this.getWhiteSpaces(node.getAsJsonObject(FormattingConstants.POSITION) .get(FormattingConstants.START_COLUMN).getAsInt())); // Update the else keyword whitespace. JsonObject elseKeywordWS = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(elseKeywordWS.get(FormattingConstants.WS).getAsString())) { elseKeywordWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update the opening brace whitespace. JsonObject openingBraceWS = ws.get(ws.size() - 2).getAsJsonObject(); if (this.noHeightAvailable(openingBraceWS.get(FormattingConstants.WS).getAsString())) { openingBraceWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update the closing brace whitespace. JsonObject closingBraceWS = ws.get(ws.size() - 1).getAsJsonObject(); if (node.getAsJsonArray(FormattingConstants.STATEMENTS).size() <= 0) { if (this.noHeightAvailable(closingBraceWS.get(FormattingConstants.WS).getAsString())) { closingBraceWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + this.getWhiteSpaces(node.getAsJsonObject(FormattingConstants.POSITION) .get(FormattingConstants.START_COLUMN).getAsInt()) + FormattingConstants.NEW_LINE + this.getWhiteSpaces(node.getAsJsonObject(FormattingConstants.POSITION) .get(FormattingConstants.START_COLUMN).getAsInt())); } } else if (this.noHeightAvailable(closingBraceWS.get(FormattingConstants.WS).getAsString())) { closingBraceWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + this.getWhiteSpaces(node.getAsJsonObject(FormattingConstants.POSITION) .get(FormattingConstants.START_COLUMN).getAsInt())); } } } /** * format Braced Tuple Expr node. * * @param node {JsonObject} node as json object */ public void formatBracedTupleExprNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); // Get the indentation for the node. String indentation = this.getIndentation(formatConfig, true); String indentationOfParent = this.getParentIndentation(formatConfig); this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); // Update opening parentheses whitespace. JsonObject openingParenthesesWS = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(openingParenthesesWS.get(FormattingConstants.WS).getAsString())) { openingParenthesesWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } // Update expressions' whitespaces. modifyExpressions(node, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); // Update closing parentheses whitespace. JsonObject closingParenthesesWS = ws.get(ws.size() - 1).getAsJsonObject(); if (this.noHeightAvailable(closingParenthesesWS.get(FormattingConstants.WS).getAsString())) { closingParenthesesWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } /** * format Break node. * * @param node {JsonObject} node as json object */ public void formatBreakNode(JsonObject node) { modifyBranchingStatement(node); } /** * format built in ref type. * * @param node {JsonObject} node as json object */ public void formatBuiltInRefTypeNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); // Get the indentation for the node. String indentation = this.getIndentation(formatConfig, true); // Preserve the line separators that already available. this.preserveHeight(ws, indentation); // Update the ref type whitespace. JsonObject refTypeWhitespace = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(refTypeWhitespace.get(FormattingConstants.WS).getAsString())) { refTypeWhitespace.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } } } /** * format Check Expr node. * * @param node {JsonObject} node as json object */ public void formatCheckExprNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG) && node.has(FormattingConstants.WS)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); boolean isExpression = node.has("isExpression") && node.get("isExpression").getAsBoolean(); // Get the indentation for the node. String indentation = this.getIndentation(formatConfig, false); // Get the indentation for the node. String indentationWithParent = this.getParentIndentation(formatConfig); if (isExpression) { this.preserveHeight(ws, indentationWithParent); } else { this.preserveHeight(ws, indentation); } // Update whitespaces for check. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("check")) { if (isExpression) { currentWS.addProperty(FormattingConstants.WS, this .getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } else { currentWS.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } } } } // Handle whitespace for expression. if (node.has(FormattingConstants.EXPRESSION)) { node.getAsJsonObject(FormattingConstants.EXPRESSION).add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(isExpression ? indentationWithParent : indentation), false)); } } } /** * format Compensate node. * * @param node {JsonObject} node as json object */ public void formatCompensateNode(JsonObject node) { // TODO: fix formatting for check expression. this.skipFormatting(node, true); } /** * format Compilation Unit node. * * @param node {JsonObject} node as json object */ public void formatCompilationUnitNode(JsonObject node) { // Update whitespaces for top level nodes. JsonArray topLevelNodes = node.get("topLevelNodes").getAsJsonArray(); // TODO: Fix import sorting. // Handle import sorting according to the alphabetical order. // int i, j; // boolean swapped; // for (i = 0; i < topLevelNodes.size() - 1; i++) { // swapped = false; // for (j = 0; j < topLevelNodes.size() - i - 1; j++) { // if (topLevelNodes.get(j).getAsJsonObject() // .get("kind").getAsString().equals("Import") // && topLevelNodes.get(j + 1).getAsJsonObject() // .get("kind").getAsString().equals("Import")) { // String refImportName = topLevelNodes.get(j).getAsJsonObject() // .get("orgName").getAsJsonObject().get("value").getAsString() + "/" // + topLevelNodes.get(j).getAsJsonObject().get("packageName") // .getAsJsonArray().get(0).getAsJsonObject().get("value").getAsString(); // // String compImportName = topLevelNodes.get(j + 1).getAsJsonObject() // .get("orgName").getAsJsonObject().get("value").getAsString() + "/" // + topLevelNodes.get(j + 1).getAsJsonObject().get("packageName") // .getAsJsonArray().get(0).getAsJsonObject().get("value").getAsString(); // // int comparisonResult = refImportName.compareTo(compImportName); // // Swap if the comparison value is positive. // if (comparisonResult > 0) { // // Swap ws to keep the formatting in level. // String refWS = topLevelNodes.get(j).getAsJsonObject().get(FormattingConstants.WS) // .getAsJsonArray().get(0).getAsJsonObject().get(FormattingConstants.WS).getAsString(); // // String compWS = topLevelNodes.get(j + 1).getAsJsonObject().get(FormattingConstants.WS) // .getAsJsonArray().get(0).getAsJsonObject().get(FormattingConstants.WS).getAsString(); // // JsonElement tempLowNode = topLevelNodes.get(j); // JsonElement tempTopNode = topLevelNodes.get(j + 1); // // int topNodeStartPosition = tempLowNode.getAsJsonObject().getAsJsonArray("ws") // .get(0).getAsJsonObject().get("i").getAsInt(); // // Reconcile whitespaces of the node to be replaced the current node at index j before adding. // FormattingSourceGen.reconcileWS(tempTopNode.getAsJsonObject(), topLevelNodes, node, // topNodeStartPosition); // topLevelNodes.set(j, tempTopNode); // // tempLowNode.getAsJsonObject().get(FormattingConstants.WS).getAsJsonArray().get(0) // .getAsJsonObject().addProperty(FormattingConstants.WS, compWS); // // topLevelNodes.get(j).getAsJsonObject().get(FormattingConstants.WS).getAsJsonArray() // .get(0).getAsJsonObject().addProperty(FormattingConstants.WS, refWS); // // int lowNodeStartPosition = topLevelNodes.size() >= (j + 2 + 1) // ? FormattingSourceGen.extractWS(topLevelNodes.get(j + 2) // .getAsJsonObject()).get(0).getAsJsonObject().get("i").getAsInt() : -1; // // Reconcile whitespace of the node to be added to the next node at index j+1 before adding. // FormattingSourceGen.reconcileWS(tempLowNode.getAsJsonObject(), topLevelNodes, node, // lowNodeStartPosition); // topLevelNodes.set(j + 1, tempLowNode); // // swapped = true; // } // } // } // // If not swapped, break. // if (!swapped) { // break; // } // } int movedFirstIndex = 0; for (int index = 0; index < topLevelNodes.size(); index++) { JsonObject child = topLevelNodes.get(index).getAsJsonObject(); JsonObject formatConfig; // Skip any anon types available in the top level before picking the first top level block. movedFirstIndex = child.has(FormattingConstants.WS) ? movedFirstIndex : ++movedFirstIndex; if (index == movedFirstIndex) { formatConfig = this.getFormattingConfig(0, 0, this.getWhiteSpaceCount(FormattingConstants.EMPTY_SPACE), false, this.getWhiteSpaceCount(FormattingConstants.EMPTY_SPACE), false); movedFirstIndex = 0; } else if (child.has("kind") && child.get("kind").getAsString().equals("Import")) { formatConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(FormattingConstants.EMPTY_SPACE), false, this.getWhiteSpaceCount(FormattingConstants.EMPTY_SPACE), false); } else { formatConfig = this.getFormattingConfig(2, 0, this.getWhiteSpaceCount(FormattingConstants.EMPTY_SPACE), false, this.getWhiteSpaceCount(FormattingConstants.EMPTY_SPACE), false); } child.add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } // Update EOF whitespace. if (node.has(FormattingConstants.WS) && topLevelNodes.size() > 0) { JsonArray ws = node.get(FormattingConstants.WS).getAsJsonArray(); // preserve comment available before EOF. this.preserveHeight(ws, null); // Handle adding a new line at the EOF. JsonObject eofWS = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(eofWS.get(FormattingConstants.WS).getAsString())) { eofWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE); } else if (this.noNewLine(eofWS.get(FormattingConstants.WS).getAsString() .charAt(eofWS.get(FormattingConstants.WS).getAsString().length() - 1) + "")) { eofWS.addProperty(FormattingConstants.WS, (eofWS.get(FormattingConstants.WS).getAsString() + FormattingConstants.NEW_LINE)); } } } /** * format Compound Assignment node. * * @param node {JsonObject} node as json object */ public void formatCompoundAssignmentNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String compoundOperator = node.get("compoundOperator").getAsString(); String indentation = this.getIndentation(formatConfig, false); // Preserve line separations that already available. this.preserveHeight(ws, indentation); // Iterate and format compound assignment whitespaces. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals(compoundOperator)) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (text.equals(";")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } // Handle variable whitespaces. if (node.has("variable")) { node.getAsJsonObject("variable").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } // Handle expression whitespaces. if (node.has("expression")) { node.getAsJsonObject("expression").add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), false)); } } } /** * format constant node. * * @param node {JsonObject} node as json object */ public void formatConstantNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); boolean isPublic = node.has(FormattingConstants.PUBLIC) && node.get(FormattingConstants.PUBLIC).getAsBoolean(); // Preserve line separators that already available. this.preserveHeight(ws, indentation); // Iterate and update whitespaces for constant node. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("public")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } else if (text.equals("const")) { if (isPublic) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else { currentWS.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } } else if (text.equals("=")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (text.equals(";")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } if (node.has("typeNode")) { node.getAsJsonObject("typeNode").add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), false)); } if (node.has("value")) { node.getAsJsonObject("value").add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), false)); } } } /** * format Constrained Type node. * * @param node {JsonObject} node as json object */ public void formatConstrainedTypeNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, true); // Preserve line separations that already available. this.preserveHeight(ws, indentation); // Update whitespace for type node. if (node.has("type")) { node.getAsJsonObject("type").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } // Update whitespace for constraint. if (node.has("constraint")) { JsonObject constraintFormatConfig = this.getFormattingConfig(0, 0, 0, false, this.getWhiteSpaceCount(indentation), false); node.getAsJsonObject("constraint").add(FormattingConstants.FORMATTING_CONFIG, constraintFormatConfig); } // Update whitespace for open constraint symbol. for (JsonElement item : ws) { JsonObject wsItem = item.getAsJsonObject(); if (this.noHeightAvailable(wsItem.get(FormattingConstants.WS).getAsString())) { String text = wsItem.get(FormattingConstants.TEXT).getAsString(); if (text.equals("<") || text.equals(">")) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } } } /** * Format continue node. * * @param node {JsonObject} node as a json object */ public void formatNextNode(JsonObject node) { modifyBranchingStatement(node); } /** * format Deprecated node. * * @param node {JsonObject} node as json object */ public void formatDeprecatedNode(JsonObject node) { // TODO: fix formatting for deprecated. this.skipFormatting(node, true); } /** * format documentation parameter node. * * @param node {JsonObject} node as json object */ public void formatDocumentationParameterNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); // Calculate indentation for the documentation parameter. String indentation = this.getParentIndentation(formatConfig); // Save new lines of a whitespace if available. this.preserveHeight(ws, indentation); // Iterate through whitespaces and update accordingly. for (int i = 0; i < ws.size(); i++) { JsonObject currentWS = ws.get(i).getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); String[] splitText = text.split(" "); // If text equals `#` or has `#` and `+` in order or has `#`, `+`, `return` and `-` // Change the whitespace for the current whitespace. if (text.equals("#") || (splitText.length == 2 && splitText[0].equals("#") && splitText[1].equals("+")) || (splitText.length == 4 && splitText[0].equals("#") && splitText[1].equals("+") && splitText[2].equals("return") && splitText[3].equals("-"))) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } } } } } /** * format markdown documentation node. * * @param node {JsonObject} node as json object */ public void formatMarkdownDocumentationNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); // Calculate indentation for the documentation parameter. String indentation = this.getParentIndentation(formatConfig); // Save new lines of a whitespace if available. this.preserveHeight(ws, indentation); // Iterate through whitespaces and update accordingly. for (int i = 0; i < ws.size(); i++) { JsonObject currentWS = ws.get(i).getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("#")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } } } if (node.has("parameters") && node.getAsJsonArray("parameters").size() > 0) { JsonArray parameters = node.getAsJsonArray("parameters"); for (JsonElement parameter : parameters) { parameter.getAsJsonObject().add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } } if (node.has("returnParameter")) { JsonObject returnParameter = node.getAsJsonObject("returnParameter"); returnParameter.getAsJsonObject().add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } } } /** * format Elvis Expr node. * * @param node {JsonObject} node as json object */ public void formatElvisExprNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentationOfParent = this.getParentIndentation(formatConfig); this.preserveHeight(ws, indentationOfParent); // Iterate and update whitespaces for elvis. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("?:")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } // Handle left hand side expression whitespaces. if (node.has("leftExpression")) { node.getAsJsonObject("leftExpression").add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), formatConfig.get(FormattingConstants.DO_INDENT).getAsBoolean(), formatConfig.get(FormattingConstants.INDENTED_START_COLUMN).getAsInt(), true)); } // Handle right hand side expression whitespaces. if (node.has("rightExpression")) { node.getAsJsonObject("rightExpression").add(FormattingConstants.FORMATTING_CONFIG, this .getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } } } /** * format Error Constructor node. * * @param node {JsonObject} node as json object */ public void formatErrorConstructorNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentationOfParent = this.getParentIndentation(formatConfig); // Preserve already available line separators. this.preserveHeight(ws, indentationOfParent); // Iterate available ws items in error constructor. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("error")) { currentWS.addProperty(FormattingConstants.WS, this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } else if (text.equals("(") || text.equals(",") || text.equals(")")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } // Handle reason expression whitespaces. if (node.has("reasonExpression")) { node.getAsJsonObject("reasonExpression").add(FormattingConstants.FORMATTING_CONFIG, this .getFormattingConfig(0, 0, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } // Handle details expression whitespaces. if (node.has("detailsExpression")) { node.getAsJsonObject("detailsExpression").add(FormattingConstants.FORMATTING_CONFIG, this .getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } } } /** * format Error Destructure node. * * @param node {JsonObject} node as json object */ public void formatErrorDestructureNode(JsonObject node) { // TODO: fix formatting for Error Destructure node. this.skipFormatting(node, true); } /** * format Error type node. * * @param node {JsonObject} node as json object */ public void formatErrorTypeNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); // Preserve comments and new line that already available. this.preserveHeight(ws, indentation); // Update reference whitespace. JsonObject referenceWS = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(referenceWS.get(FormattingConstants.WS).getAsString())) { if (formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt() > 0) { referenceWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } else if (formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt() > 0) { referenceWS.addProperty(FormattingConstants.WS, this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } else { referenceWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } } /** * format Error Variable Ref node. * * @param node {JsonObject} node as json object */ public void formatErrorVariableRefNode(JsonObject node) { // TODO: fix formatting for Error Variable Ref. this.skipFormatting(node, true); } /** * format Expression Statement node. * * @param node {JsonObject} node as json object */ public void formatExpressionStatementNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); // Preserve comments and new lines that already available. this.preserveHeight(ws, indentation); // Update whitespaces for expression. if (node.has("expression")) { JsonObject expression = node.getAsJsonObject("expression"); expression.add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } // Update whitespace for semicolon. JsonObject semicolonWhitespace = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(semicolonWhitespace.get(FormattingConstants.WS).getAsString())) { semicolonWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } /** * format Field Based Access Expr node. * * @param node {JsonObject} node as json object */ public void formatFieldBasedAccessExprNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentWithParentIndentation = this.getParentIndentation(formatConfig); // Preserve line separations that already available. this.preserveHeight(ws, indentWithParentIndentation); // Update the expression whitespaces. if (node.has(FormattingConstants.EXPRESSION)) { JsonObject expression = node.getAsJsonObject(FormattingConstants.EXPRESSION); if (node.has("isExpression") && node.get("isExpression").getAsBoolean()) { expression.addProperty("isExpression", true); } JsonObject expressionFormatConfig = this.getFormattingConfig( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), formatConfig.get(FormattingConstants.DO_INDENT).getAsBoolean(), this.getWhiteSpaceCount(indentation.isEmpty() ? indentWithParentIndentation : indentation), formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean()); expression.add(FormattingConstants.FORMATTING_CONFIG, expressionFormatConfig); } // Update rest of the whitespaces. for (JsonElement jsonElement : ws) { if (this.noHeightAvailable( jsonElement.getAsJsonObject().get(FormattingConstants.WS).getAsString())) { jsonElement.getAsJsonObject().addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } } /** * format Finite type node. * * @param node {JsonObject} node as json object */ public void formatFiniteTypeNodeNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.get(FormattingConstants.WS).getAsJsonArray(); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); // Preserve line separation that already available. this.preserveHeight(ws, indentation); // Update whitespace for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("|")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } if (node.has("valueSet")) { JsonArray valueSet = node.getAsJsonArray("valueSet"); for (JsonElement valueItem : valueSet) { JsonObject value = valueItem.getAsJsonObject(); JsonObject valueFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), false); value.add(FormattingConstants.FORMATTING_CONFIG, valueFormatConfig); } } } } /** * format Foreach node. * * @param node {JsonObject} node as json object */ public void formatForeachNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentWithParentIndentation = formatConfig.get(FormattingConstants.DO_INDENT).getAsBoolean() ? this.getWhiteSpaces(formatConfig.get(FormattingConstants.INDENTED_START_COLUMN).getAsInt()) + FormattingConstants.SPACE_TAB : this.getWhiteSpaces(formatConfig.get(FormattingConstants.INDENTED_START_COLUMN).getAsInt()); node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentWithParentIndentation)); this.preserveHeight(ws, indentWithParentIndentation); // Update whitespace for the foreach signature. for (JsonElement item : ws) { JsonObject wsItem = item.getAsJsonObject(); if (this.noHeightAvailable(wsItem.get(FormattingConstants.WS).getAsString())) { String text = wsItem.get(FormattingConstants.TEXT).getAsString(); // Update whitespace for the foreach keyword. if (text.equals("foreach")) { wsItem.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentWithParentIndentation); } // Update whitespace for the opening parentheses. if (text.equals("(")) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update whitespace for the param separator. if (text.equals(",")) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } // Update the whitespace for in keyword. if (text.equals("in")) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update whitespace for the closing parentheses. if (text.equals(")")) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } // Update the whitespace for opening bracket. if (text.equals("{")) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update the whitespace for closing bracket. if (text.equals("}")) { if (node.has(FormattingConstants.BODY) && node.getAsJsonObject(FormattingConstants.BODY) .has(FormattingConstants.STATEMENTS) && node.getAsJsonObject(FormattingConstants.BODY) .getAsJsonArray(FormattingConstants.STATEMENTS).size() <= 0) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentWithParentIndentation + FormattingConstants.NEW_LINE + indentWithParentIndentation); } else { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentWithParentIndentation); } } } } // Handle whitespace for variables if (node.has("variables")) { JsonArray variables = node.getAsJsonArray("variables"); for (int i = 0; i < variables.size(); i++) { JsonObject variable = variables.get(i).getAsJsonObject(); JsonObject variableFormatConfig; if (i == 0 && node.has("withParantheses") && node.get("withParantheses").getAsBoolean()) { variableFormatConfig = this.getFormattingConfig(0, 0, 0, false, this.getWhiteSpaceCount(indentWithParentIndentation), false); } else { variableFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentWithParentIndentation), false); } variable.add(FormattingConstants.FORMATTING_CONFIG, variableFormatConfig); } } // Handle whitespace for collection. if (node.has("collection")) { JsonObject collection = node.getAsJsonObject("collection"); JsonObject collectionFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentWithParentIndentation), false); collection.add(FormattingConstants.FORMATTING_CONFIG, collectionFormatConfig); } } } /** * format Forever node. * * @param node {JsonObject} node as json object */ public void formatForeverNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); // Preserve available line separators. this.preserveHeight(ws, indentation); // Update whitespaces for forever node. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("forever")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } else if (text.equals("{")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (text.equals("}")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation); } } } // Handle streaming query statements' whitespaces if (node.has("streamingQueryStatements")) { JsonArray queryStmts = node.getAsJsonArray("streamingQueryStatements"); for (JsonElement queryStmtItem : queryStmts) { JsonObject queryStmtFormatConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), true, this.getWhiteSpaceCount(indentation), true); queryStmtItem.getAsJsonObject().add(FormattingConstants.FORMATTING_CONFIG, queryStmtFormatConfig); } } } } /** * format Fork Join node. * * @param node {JsonObject} node as json object */ public void formatForkJoinNode(JsonObject node) { // TODO: fix formatting for fork join node. this.skipFormatting(node, true); } /** * format Function node. * * @param node {JsonObject} node as json object */ public void formatFunctionNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); boolean isLambda = node.has("lambda") && node.get("lambda").getAsBoolean(); boolean isWorker = node.has("worker") && node.get("worker").getAsBoolean(); String indentation = this.getIndentation(formatConfig, false); String indentWithParentIndentation = this.getParentIndentation(formatConfig); // Update the function node's start column. node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentWithParentIndentation)); // Preserve the new lines and characters available in node's whitespaces. this.preserveHeight(ws, indentWithParentIndentation); // Get the node's index if it is in a list of statements of parent array. int functionIndex = this.findIndex(node); // Update whitespaces for function/public keyword. JsonObject functionKeywordWs = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(functionKeywordWs.get(FormattingConstants.WS).getAsString())) { // If function is a lambda and not a worker, add spaces. if (isLambda && !isWorker) { functionKeywordWs.addProperty(FormattingConstants.WS, this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } else { // If annotation or documentation attachments exists add only one new line. // Else add given number of new lines. String whiteSpace = ((node.has("annotationAttachments") && node.getAsJsonArray("annotationAttachments").size() > 0) || node.has("markdownDocumentationAttachment") || (node.has("deprecatedAttachments") && node.getAsJsonArray("deprecatedAttachments").size() > 0)) ? (FormattingConstants.NEW_LINE + indentation) : (this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); functionKeywordWs.addProperty(FormattingConstants.WS, whiteSpace); } } else if (this.noNewLine(functionKeywordWs.get(FormattingConstants.WS).getAsString().charAt(0) + "") && functionIndex != 0) { // TODO: revisit logic. functionKeywordWs.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + functionKeywordWs.get(FormattingConstants.WS).getAsString()); } for (int i = 0; i < ws.size(); i++) { JsonObject functionWS = ws.get(i).getAsJsonObject(); if (this.noHeightAvailable(functionWS.get(FormattingConstants.WS).getAsString())) { String wsText = functionWS.get(FormattingConstants.TEXT).getAsString(); if (wsText.equals("(")) { if (!isLambda) { functionWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } if (wsText.equals(",")) { functionWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } if (wsText.equals("=>")) { functionWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } if (wsText.equals(")")) { functionWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } // Update whitespace for returns keyword. if (wsText.equals("returns")) { functionWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update whitespaces for the opening brace. if (wsText.equals("{")) { functionWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update whitespaces for closing brace of the function. if (wsText.equals("}")) { if (node.has(FormattingConstants.BODY) && node.getAsJsonObject(FormattingConstants.BODY) .getAsJsonArray(FormattingConstants.STATEMENTS).size() <= 0 && node.getAsJsonArray("endpointNodes").size() <= 0 && node.getAsJsonArray("workers").size() <= 0) { if (this.noHeightAvailable(functionWS.get(FormattingConstants.WS).getAsString())) { functionWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentWithParentIndentation + FormattingConstants.NEW_LINE + indentWithParentIndentation); } } else if (this.noHeightAvailable(functionWS.get(FormattingConstants.WS).getAsString())) { functionWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentWithParentIndentation); } } if (wsText.equals(";")) { functionWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } // Update whitespaces of parameters. if (node.has("parameters")) { JsonArray parameters = node.getAsJsonArray("parameters"); iterateAndFormatMembers(indentation.isEmpty() ? indentWithParentIndentation : indentation, parameters); } // Update whitespaces of defaultable parameters if (node.has("defaultableParameters")) { JsonArray defaulableParameters = node.getAsJsonArray("defaultableParameters"); for (JsonElement defaulableParameter : defaulableParameters) { // TODO: fix formatting for defaultable parameters. this.skipFormatting(defaulableParameter.getAsJsonObject(), true); } } // Update whitespaces of endpoint. modifyEndpoints(node, indentation); // Update whitespaces of workers. modifyWorkers(node, indentation); // Update whitespaces of annotation attachments. modifyAnnotationAttachments(node, formatConfig, indentation); // Update whitespaces of markdown documentation attachments. modifyMarkdownDocumentation(node, formatConfig, indentation); // Update whitespaces for rest parameters. if (node.has("restParameters")) { JsonObject restParam = node.getAsJsonObject("restParameters"); JsonObject restParamFormatConfig; if (node.has("parameters") && node.getAsJsonArray("parameters").size() > 0) { restParamFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount( indentation.isEmpty() ? indentWithParentIndentation : indentation), true); } else { restParamFormatConfig = this.getFormattingConfig(0, 0, 0, false, this.getWhiteSpaceCount( indentation.isEmpty() ? indentWithParentIndentation : indentation), true); } restParam.add(FormattingConstants.FORMATTING_CONFIG, restParamFormatConfig); } // Update whitespaces for return parameters. if (node.has("returnTypeNode") && node.has("hasReturns") && node.get("hasReturns").getAsBoolean()) { // Handle whitespace for return type node. JsonObject returnTypeNode = node.getAsJsonObject("returnTypeNode"); JsonObject returnTypeFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation.isEmpty() ? indentWithParentIndentation : indentation), true); returnTypeNode.add(FormattingConstants.FORMATTING_CONFIG, returnTypeFormatConfig); } // Update whitespaces for return type annotation attachments. modifyReturnTypeAnnotations(node, indentation); } } /** * format Function Clause node. * * @param node {JsonObject} node as json object */ public void formatFunctionClauseNode(JsonObject node) { // TODO: fix formatting for function clause node. this.skipFormatting(node, true); } /** * format Function Type node. * * @param node {JsonObject} node as json object */ public void formatFunctionTypeNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); boolean isGrouped = node.has("grouped") && node.get("grouped").getAsBoolean(); boolean returnKeywordExists = node.has("returnKeywordExists") && node.get("returnKeywordExists").getAsBoolean(); String indentation = this.getIndentation(formatConfig, true); String indentWithParentIndentation = this .getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt()) + this.getWhiteSpaces(formatConfig.get(FormattingConstants.INDENTED_START_COLUMN).getAsInt()); this.preserveHeight(ws, indentWithParentIndentation); // Update whitespace for function keyword or parentheses. JsonObject firstKeywordWS = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(firstKeywordWS.get(FormattingConstants.WS).getAsString())) { firstKeywordWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } JsonObject openingParenthesesWS; JsonObject closingParenthesesWS; if (isGrouped) { // Update function keyword. JsonObject functionKeywordWS = ws.get(1).getAsJsonObject(); if (this.noHeightAvailable(functionKeywordWS.get(FormattingConstants.WS).getAsString())) { functionKeywordWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } // Set opening parentheses whitespaces. openingParenthesesWS = ws.get(2).getAsJsonObject(); // Set closing parentheses whitespaces. if (returnKeywordExists) { closingParenthesesWS = ws.get(ws.size() - 3).getAsJsonObject(); } else { closingParenthesesWS = ws.get(ws.size() - 2).getAsJsonObject(); } // Update group closing parentheses whitespace. JsonObject closeGroupParenWS = ws.get(ws.size() - 1).getAsJsonObject(); if (this.noHeightAvailable(closingParenthesesWS.get(FormattingConstants.WS).getAsString())) { closeGroupParenWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } else { // Set opening parentheses whitespaces. openingParenthesesWS = ws.get(1).getAsJsonObject(); // Set closing parentheses whitespace. if (returnKeywordExists) { closingParenthesesWS = ws.get(ws.size() - 2).getAsJsonObject(); } else { closingParenthesesWS = ws.get(ws.size() - 1).getAsJsonObject(); } } // Update opening parentheses whitespaces. if (this.noHeightAvailable(openingParenthesesWS.get(FormattingConstants.WS).getAsString())) { openingParenthesesWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update closing parentheses whitespaces. if (this.noHeightAvailable(closingParenthesesWS.get(FormattingConstants.WS).getAsString())) { closingParenthesesWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } // Update whitespaces for the function type. for (int i = 0; i < ws.size(); i++) { JsonObject functionTypeWS = ws.get(i).getAsJsonObject(); if (this.noHeightAvailable(functionTypeWS.get(FormattingConstants.WS).getAsString())) { String text = functionTypeWS.get(FormattingConstants.TEXT).getAsString(); // Update whitespace for parameter separator and closing parentheses. if (text.equals(",")) { functionTypeWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } // Update whitespace for returns keyword. if (text.equals("returns")) { functionTypeWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } // Update whitespaces for the parameters. if (node.has("params")) { JsonArray parameters = node.getAsJsonArray("params"); iterateAndFormatMembers(indentation, parameters); } if (returnKeywordExists) { JsonObject returnType = node.getAsJsonObject("returnTypeNode"); JsonObject returnTypeFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), false); returnType.add(FormattingConstants.FORMATTING_CONFIG, returnTypeFormatConfig); modifyReturnTypeAnnotations(node, indentation); } } } /** * format Group By node. * * @param node {JsonObject} node as json object */ public void formatGroupByNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); // Preserve available line separations. this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); // Iterate through and format node's whitespaces. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("group")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } else if (text.equals("by")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } // Handle variable formatting. if (node.has("variables")) { JsonArray variables = node.getAsJsonArray("variables"); for (JsonElement variableItem : variables) { variableItem.getAsJsonObject().add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } } } } /** * format Having node. * * @param node {JsonObject} node as json object */ public void formatHavingNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); // Preserve available line separators. this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("having")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } } } // Handle formatting for expression. if (node.has("expression")) { node.getAsJsonObject("expression").add(FormattingConstants.FORMATTING_CONFIG, this .getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } } } /** * format Is assignable expr node. * * @param node {JsonObject} node as json object */ public void formatIsAssignableExprNode(JsonObject node) { // TODO: fix formatting for having node. this.skipFormatting(node, true); } /** * format Identifier node. * * @param node {JsonObject} node as json object */ public void formatIdentifierNode(JsonObject node) { // TODO: fix formatting for identifier node. this.skipFormatting(node, true); } /** * format If node. * * @param node {JsonObject} node as json object */ public void formatIfNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentWithParentIndentation = this.getParentIndentation(formatConfig); // Set the start column to the position of the node. node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentWithParentIndentation)); this.preserveHeight(ws, indentWithParentIndentation); // Update if or else if keyword. JsonObject firstKeywordWS = ws.get(0).getAsJsonObject(); if (node.has("isElseIfBlock") && node.get("isElseIfBlock").getAsBoolean()) { if (this.noHeightAvailable(firstKeywordWS.get(FormattingConstants.WS).getAsString())) { firstKeywordWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update if keyword whitespace. JsonObject ifKeywordWS = ws.get(1).getAsJsonObject(); if (this.noHeightAvailable(ifKeywordWS.get(FormattingConstants.WS).getAsString())) { ifKeywordWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } else { if (this.noHeightAvailable(firstKeywordWS.get(FormattingConstants.WS).getAsString())) { firstKeywordWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentWithParentIndentation); } } // Update opening brace whitespace. JsonObject openingBraceWS = ws.get(ws.size() - 2).getAsJsonObject(); if (this.noHeightAvailable(openingBraceWS.get(FormattingConstants.WS).getAsString())) { openingBraceWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update closing brace whitespace JsonObject closingBraceWS = ws.get(ws.size() - 1).getAsJsonObject(); modifyBlockBody(node, indentWithParentIndentation, closingBraceWS, FormattingConstants.BODY); if (node.has("elseStatement") && !node.getAsJsonObject("elseStatement").get("kind").getAsString().equals("Block")) { JsonObject elseStatement = node.getAsJsonObject("elseStatement"); JsonObject elseStatementFormatConfig = this.getFormattingConfig(0, 1, this.getWhiteSpaceCount(indentation), false, this.getWhiteSpaceCount(indentWithParentIndentation), false); elseStatement.add(FormattingConstants.FORMATTING_CONFIG, elseStatementFormatConfig); } if (node.has("condition")) { JsonObject conditionWs = node.getAsJsonObject("condition"); JsonObject conditionFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentWithParentIndentation), true); conditionWs.add(FormattingConstants.FORMATTING_CONFIG, conditionFormatConfig); } } } /** * format Import node. * * @param node {JsonObject} node as json object */ public void formatImportNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.get(FormattingConstants.WS).getAsJsonArray(); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); this.preserveHeight(ws, indentation); // Update whitespaces for import keyword if (this.noHeightAvailable(ws.get(0).getAsJsonObject().get(FormattingConstants.WS).getAsString())) { ws.get(0).getAsJsonObject().addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt()) + indentation); } // Update whitespace for semicolon JsonObject semicolonWhitespace = ws.get(ws.size() - 1).getAsJsonObject(); if (this.noHeightAvailable(semicolonWhitespace.get(FormattingConstants.WS).getAsString())) { semicolonWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } /** * format Index Based Access Expr node. * * @param node {JsonObject} node as json object */ public void formatIndexBasedAccessExprNode(JsonObject node) { // TODO: fix formatting for index based access expression. this.skipFormatting(node, true); } /** * format Int Range Expr node. * * @param node {JsonObject} node as json object */ public void formatIntRangeExprNode(JsonObject node) { // TODO: fix formatting for int range expression. this.skipFormatting(node, true); } /** * format Invocation node. * * @param node {JsonObject} node as json object */ public void formatInvocationNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentWithParentIndentation = this.getParentIndentation(formatConfig); boolean isExpressionAvailable = node.has(FormattingConstants.EXPRESSION) && node.getAsJsonObject(FormattingConstants.EXPRESSION).has(FormattingConstants.WS); boolean isAsync = false; boolean isCheck = false; boolean isActionOrFieldInvocation = false; JsonObject identifierWhitespace = null; // Preserve new lines and comments that already available. this.preserveHeight(ws, indentWithParentIndentation); if (isExpressionAvailable) { JsonObject expression = node.getAsJsonObject(FormattingConstants.EXPRESSION); expression.add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } for (int i = 0; i < ws.size(); i++) { JsonObject invocationWS = ws.get(i).getAsJsonObject(); if (this.noHeightAvailable(invocationWS.get(FormattingConstants.WS).getAsString())) { String text = invocationWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("check")) { invocationWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + this.getWhiteSpaces( formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt()) + indentation); isCheck = true; } else if (text.equals("start")) { if (isCheck) { invocationWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else { invocationWS.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + this.getWhiteSpaces( formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt()) + indentation); } isAsync = true; } else if (text.equals(".") || text.equals("->")) { invocationWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); isActionOrFieldInvocation = true; } else if (text.equals("(")) { invocationWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else if (text.equals(",")) { invocationWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else if (text.equals(")")) { invocationWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else if (text.equals(":")) { // Handle colon whitespaces. invocationWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); // Handle package alias. JsonObject packageAliasWhitespace = ws.get(i - 1).getAsJsonObject(); if (this.noHeightAvailable( packageAliasWhitespace.get(FormattingConstants.WS).getAsString())) { if (isAsync || isCheck) { packageAliasWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else { packageAliasWhitespace.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + this.getWhiteSpaces( formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt()) + indentation); } } // Identifier whitespace. identifierWhitespace = ws.get(i + 1).getAsJsonObject(); if (this.noHeightAvailable( identifierWhitespace.get(FormattingConstants.WS).getAsString())) { identifierWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } else if (identifierWhitespace == null && !ws.get(i + 1).getAsJsonObject().get("text").getAsString().equals(":")) { if (isAsync || isCheck) { invocationWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (isActionOrFieldInvocation) { invocationWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else { invocationWS.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + this.getWhiteSpaces( formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt()) + indentation); } } } } // Update argument expressions whitespaces. if (node.has("argumentExpressions")) { JsonArray argumentExpressions = node.getAsJsonArray("argumentExpressions"); iterateAndFormatMembers(indentation.isEmpty() ? indentWithParentIndentation : indentation, argumentExpressions); } } } /** * format Is Like node. * * @param node {JsonObject} node as json object */ public void formatIsLikeNode(JsonObject node) { // TODO: fix formatting for Is Like. this.skipFormatting(node, true); } /** * format Join Streaming Input node. * * @param node {JsonObject} node as json object */ public void formatJoinStreamingInputNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); // Preserve already existing line separators. this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); boolean firstKeywordUpdated = false; // Iterate through whitespaces and format. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("left") || text.equals("right") || text.equals("full") || text.equals("outer") || text.equals("inner") || text.equals("join")) { if (firstKeywordUpdated && this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else { if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } firstKeywordUpdated = true; } } else if (text.equals("unidirectional")) { if (node.get("unidirectionalAfterJoin").getAsBoolean() && this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (node.get("unidirectionalBeforeJoin").getAsBoolean()) { if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } firstKeywordUpdated = true; } } else if (text.equals("on") && this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } // Handles streaming input formatting. if (node.has("streamingInput")) { node.getAsJsonObject("streamingInput").add(FormattingConstants.FORMATTING_CONFIG, this .getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } // Handles on expression's formatting. if (node.has("onExpression")) { node.getAsJsonObject("onExpression").add(FormattingConstants.FORMATTING_CONFIG, this .getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } } } /** * format Lambda node. * * @param node {JsonObject} node as json object */ public void formatLambdaNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG) && node.has("functionNode")) { JsonObject functionNode = node.getAsJsonObject("functionNode"); functionNode.add(FormattingConstants.FORMATTING_CONFIG, node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG)); } } /** * format Limit node. * * @param node {JsonObject} node as json object */ public void formatLimitNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); // Preserve available line separation. this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); // Iterate and update node's whitespaces. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("limit")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } else { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } } } /** * format Literal node. * * @param node {JsonObject} node as json object */ public void formatLiteralNode(JsonObject node) { this.modifyLiteralNode(node); } /** * format Lock node. * * @param node {JsonObject} node as json object */ public void formatLockNode(JsonObject node) { // TODO: fix formatting for lock node. this.skipFormatting(node, true); } /** * format Match node. * * @param node {JsonObject} node as json object */ public void formatMatchNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); // Get the indentation for the node. String indentation = this.getIndentation(formatConfig, false); this.preserveHeight(ws, indentation); // Update match whitespaces. for (JsonElement item : ws) { JsonObject wsItem = item.getAsJsonObject(); if (this.noHeightAvailable(wsItem.get(FormattingConstants.WS).getAsString())) { String text = wsItem.get(FormattingConstants.TEXT).getAsString(); // Update match keyword whitespaces. if (text.equals("match")) { wsItem.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } // Update opening bracket whitespace. if (text.equals("{")) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update opening bracket whitespace. if (text.equals("}")) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation); } } } // Update expression whitespace. if (node.has(FormattingConstants.EXPRESSION)) { JsonObject expression = node.getAsJsonObject(FormattingConstants.EXPRESSION); JsonObject expressionFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), false); expression.add(FormattingConstants.FORMATTING_CONFIG, expressionFormatConfig); } // Update pattern clauses whitespace. modifyPatternClauses(node, indentation); } } /** * format Match structured pattern clause node. * * @param node {JsonObject} node as json object */ public void formatMatchStructuredPatternClauseNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); boolean withCurlies = node.has("withCurlies") && node.get("withCurlies").getAsBoolean(); // Get the indentation for the node. String indentation = this.getIndentation(formatConfig, false); node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentation)); this.preserveHeight(ws, indentation); // Handle whitespace for if (node.has("variableNode")) { if (ws.get(0).getAsJsonObject().get(FormattingConstants.TEXT).getAsString().equals("var")) { node.getAsJsonObject("variableNode").add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), false)); } else { node.getAsJsonObject("variableNode").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } } // Update the match pattern whitespace. for (JsonElement item : ws) { JsonObject wsItem = item.getAsJsonObject(); if (this.noHeightAvailable(wsItem.get(FormattingConstants.WS).getAsString())) { String text = wsItem.get(FormattingConstants.TEXT).getAsString(); // Update the => whitespace. if (text.equals("=>")) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update the opening brace whitespace. if (text.equals("{")) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update the closing brace whitespace. if (text.equals("}")) { if (node.has("statement") && node.getAsJsonObject("statement").has(FormattingConstants.STATEMENTS) && node.getAsJsonObject("statement").getAsJsonArray(FormattingConstants.STATEMENTS) .size() <= 0) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation + FormattingConstants.NEW_LINE + indentation); } else { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation); } } } } if (node.has("statement") && !withCurlies) { JsonObject statementFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), false); node.getAsJsonObject("statement").add(FormattingConstants.FORMATTING_CONFIG, statementFormatConfig); } } } /** * format Match static pattern clause node. * * @param node {JsonObject} node as json object */ public void formatMatchStaticPatternClauseNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); boolean withCurlies = node.has("withCurlies") && node.get("withCurlies").getAsBoolean(); // Get the indentation for the node. String indentation = this.getIndentation(formatConfig, false); node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentation)); this.preserveHeight(ws, indentation); // Handle whitespace for if (node.has("literal")) { node.getAsJsonObject("literal").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } // Update the match pattern whitespace. for (JsonElement item : ws) { JsonObject wsItem = item.getAsJsonObject(); if (this.noHeightAvailable(wsItem.get(FormattingConstants.WS).getAsString())) { String text = wsItem.get(FormattingConstants.TEXT).getAsString(); // Update the => whitespace. if (text.equals("=>")) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update the opening brace whitespace. if (text.equals("{")) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update the closing brace whitespace. if (text.equals("}")) { if (node.has("statement") && node.getAsJsonObject("statement").has(FormattingConstants.STATEMENTS) && node.getAsJsonObject("statement").getAsJsonArray(FormattingConstants.STATEMENTS) .size() <= 0) { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation + FormattingConstants.NEW_LINE + indentation); } else { wsItem.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation); } } } } if (node.has("statement") && !withCurlies) { JsonObject statementFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), false); node.getAsJsonObject("statement").add(FormattingConstants.FORMATTING_CONFIG, statementFormatConfig); } } } /** * format Match Typed Pattern Clause node. * * @param node {JsonObject} node as json object */ public void formatMatchTypedPatternClauseNode(JsonObject node) { // TODO: fix formatting for Match Typed Pattern Clause. this.skipFormatting(node, true); } /** * format Named Args Expr node. * * @param node {JsonObject} node as json object */ public void formatNamedArgsExprNode(JsonObject node) { // TODO: fix formatting for named argument expressions. this.skipFormatting(node, true); } /** * format Numeric Literal node. * * @param node {JsonObject} node as json object */ public void formatNumericLiteralNode(JsonObject node) { this.modifyLiteralNode(node); } /** * format Object Type node. * * @param node {JsonObject} node as json object */ public void formatObjectTypeNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); if (node.has(FormattingConstants.FIELDS)) { JsonArray fields = node.getAsJsonArray(FormattingConstants.FIELDS); for (int i = 0; i < fields.size(); i++) { JsonObject fieldFormatConfig = this.getFormattingConfig(1, 0, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), true, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), false); fields.get(i).getAsJsonObject().add(FormattingConstants.FORMATTING_CONFIG, fieldFormatConfig); } } if (node.has("initFunction")) { JsonObject initFunction = node.getAsJsonObject("initFunction"); JsonObject functionFormatConfig = this.getFormattingConfig(2, 0, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), true, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), false); initFunction.add(FormattingConstants.FORMATTING_CONFIG, functionFormatConfig); } if (node.has("functions")) { JsonArray functions = node.getAsJsonArray("functions"); for (int i = 0; i < functions.size(); i++) { JsonObject functionFormatConfig = this.getFormattingConfig(2, 0, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), true, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), false); functions.get(i).getAsJsonObject().add(FormattingConstants.FORMATTING_CONFIG, functionFormatConfig); } } if (node.has(FormattingConstants.WS)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); String indentation = this .getWhiteSpaces(formatConfig.get(FormattingConstants.START_COLUMN).getAsInt()); this.preserveHeight(ws, indentation); for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { if (text.equals("{")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (text.equals("}")) { if (node.getAsJsonArray(FormattingConstants.FIELDS).size() <= 0 && node.getAsJsonArray("functions").size() <= 0) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation + FormattingConstants.NEW_LINE + indentation); } else { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation); } } } } } } } /** * format Order By node. * * @param node {JsonObject} node as json object */ public void formatOrderByNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG) && node.has(FormattingConstants.WS)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("order")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } else if (text.equals("by")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (text.equals(",")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } // Handle order by variable formatting. if (node.has("variables")) { JsonArray variables = node.getAsJsonArray("variables"); for (JsonElement variableElement : variables) { variableElement.getAsJsonObject().add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } } } } /** * format Order By Variable node. * * @param node {JsonObject} node as json object */ public void formatOrderByVariableNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); // Handle variable reference formatting. if (node.has("variableReference")) { node.getAsJsonObject("variableReference").add(FormattingConstants.FORMATTING_CONFIG, this .getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } // If whitespaces available iterate and update whitespaces. if (node.has(FormattingConstants.WS)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString()) && text.equals(node.get("typeString").getAsString())) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } } } /** * format Output Rate Limit node. * * @param node {JsonObject} node as json object */ public void formatOutputRateLimitNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("output")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } else { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } } } /** * format panic node. * * @param node {JsonObject} node as json object */ public void formatPanicNode(JsonObject node) { // TODO: fix formatting for panic. this.skipFormatting(node, true); } /** * format Pattern Clause node. * * @param node {JsonObject} node as json object */ public void formatPatternClauseNode(JsonObject node) { // TODO: fix formatting for pattern clause. this.skipFormatting(node, true); } /** * format Pattern Streaming Edge Input node. * * @param node {JsonObject} node as json object */ public void formatPatternStreamingEdgeInputNode(JsonObject node) { // TODO: fix formatting for pattern streaming edge input. this.skipFormatting(node, true); } /** * format Pattern Streaming Input node. * * @param node {JsonObject} node as json object */ public void formatPatternStreamingInputNode(JsonObject node) { // TODO: fix formatting for pattern streaming input. this.skipFormatting(node, true); } /** * format Record destructor node. * * @param node {JsonObject} node as json object */ public void formatRecordDestructureNode(JsonObject node) { // TODO: fix formatting for Record Destructure. this.skipFormatting(node, true); } /** * format Record Literal Expr node. * * @param node {JsonObject} node as json object */ public void formatRecordLiteralExprNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentWithParentIndentation = this.getParentIndentation(formatConfig); String parentKind = node.getAsJsonObject(FormattingConstants.PARENT).get("kind").getAsString(); boolean isTable = parentKind.equals("Table"); boolean isExpression = parentKind.equals("Endpoint") || parentKind.equals("AnnotationAttachment") || parentKind.equals("Service") || parentKind.equals("Variable") || parentKind.equals("Invocation") || parentKind.equals("ErrorConstructor") || parentKind.equals("RecordLiteralExpr") || parentKind.equals("RecordLiteralKeyValue") || parentKind.equals("Return"); if (isExpression) { node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, indentation); } // Preserve line separation that already available. this.preserveHeight(ws, indentWithParentIndentation); // Iterate and update Whitespaces for the node. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); // Update whitespace for opening brace. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("{") && this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { if (isExpression) { currentWS.addProperty(FormattingConstants.WS, this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } else if (isTable) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentWithParentIndentation); } } // Update whitespace for closing brace. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("}") && this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { if (isExpression) { if (node.has("keyValuePairs") && node.getAsJsonArray("keyValuePairs").size() <= 0) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentWithParentIndentation + FormattingConstants.NEW_LINE + indentWithParentIndentation); } else { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentWithParentIndentation); } } else if (isTable) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } // Update whitespaces for the key value pair separator , or ;. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals(",") || currentWS.get(FormattingConstants.TEXT).getAsString().equals(";")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } // Update the key value pair of a record. if (node.has("keyValuePairs")) { JsonArray keyValuePairs = node.getAsJsonArray("keyValuePairs"); for (int i = 0; i < keyValuePairs.size(); i++) { JsonObject keyValue = keyValuePairs.get(i).getAsJsonObject(); JsonObject keyValueFormatting; if (i == 0 && isTable) { keyValueFormatting = this.getFormattingConfig(0, 0, this.getWhiteSpaceCount(indentWithParentIndentation), true, this.getWhiteSpaceCount(indentWithParentIndentation), false); } else if (isExpression) { keyValueFormatting = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentWithParentIndentation), true, this.getWhiteSpaceCount(indentWithParentIndentation), false); } else { keyValueFormatting = this.getFormattingConfig(0, 1, this.getWhiteSpaceCount(indentWithParentIndentation), true, this.getWhiteSpaceCount(indentWithParentIndentation), false); } keyValue.getAsJsonObject().add(FormattingConstants.FORMATTING_CONFIG, keyValueFormatting); } } } } /** * format record literal key value. * * @param node {JsonObject} node as json object */ public void formatRecordLiteralKeyValueNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); // Update whitespace for key value of record literal. if (node.has("key")) { JsonObject keyNode = node.getAsJsonObject("key"); JsonObject keyNodeFormatConfig = this.getFormattingConfig( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), true, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), false); keyNode.add(FormattingConstants.FORMATTING_CONFIG, keyNodeFormatConfig); } // Update whitespace for colon of the record literal key value pair. this.preserveHeight(ws, indentation); if (this.noHeightAvailable(ws.get(0).getAsJsonObject().get(FormattingConstants.WS).getAsString())) { ws.get(0).getAsJsonObject().addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } // Update whitespace for value of record literal. if (node.has("value")) { JsonObject valueNode = node.getAsJsonObject("value"); JsonObject valueNodeFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), true); valueNode.add(FormattingConstants.FORMATTING_CONFIG, valueNodeFormatConfig); } } } /** * format Record Type node. * * @param node {JsonObject} node as json object */ public void formatRecordTypeNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); // Update the fields whitespace. JsonArray fields = node.getAsJsonArray(FormattingConstants.FIELDS); for (int i = 0; i < fields.size(); i++) { JsonObject child = fields.get(i).getAsJsonObject(); JsonObject childFormatConfig = this.getFormattingConfig(1, 0, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), true, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), false); child.add(FormattingConstants.FORMATTING_CONFIG, childFormatConfig); } if (node.has(FormattingConstants.WS)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); // Update the restField whitespace. if (node.has("restFieldType") && node.get("restFieldType").getAsJsonObject().has(FormattingConstants.WS)) { JsonObject restFieldType = node.getAsJsonObject("restFieldType"); JsonObject restFieldTypeFormatConfig = this.getFormattingConfig(1, 0, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), true, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), false); restFieldType.add(FormattingConstants.FORMATTING_CONFIG, restFieldTypeFormatConfig); // Update the ... symbol whitespace. JsonObject restWS = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(restWS.get(FormattingConstants.WS).getAsString())) { restWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } // Update the whitespaces for sealed type. if (node.has("sealed") && node.get("sealed").getAsBoolean()) { String indentation = this.getIndentation(formatConfig, true); this.preserveHeight(ws, indentation); // Update the ! symbol whitespace. JsonObject sealedWS = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(sealedWS.get(FormattingConstants.WS).getAsString())) { sealedWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation); } // Update the ... symbol whitespace. JsonObject restWS = ws.get(1).getAsJsonObject(); if (this.noHeightAvailable(restWS.get(FormattingConstants.WS).getAsString())) { restWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } } } /** * format Record Variable node. * * @param node {JsonObject} node as json object */ public void formatRecordVariableNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG) && node.has(FormattingConstants.WS)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); String indentation = this.getIndentation(formatConfig, false); String indentWithParentIndentation = this.getParentIndentation(formatConfig); node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentation)); this.preserveHeight(ws, indentWithParentIndentation); // Update whitespaces of the variable first keyword. boolean frontedWithKeyword = false; for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if ((text.equals("final") || text.equals("public") || text.equals("var") || text.equals("client") || text.equals("listener") || text.equals("abstract") || text.equals("channel") || text.equals("const"))) { if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } frontedWithKeyword = true; } } for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("{")) { if (frontedWithKeyword || node.has("typeNode")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else { currentWS.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + this.getWhiteSpaces( formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt()) + indentation); } } else if (text.equals("}")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else if (text.equals(",")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } if (node.has("typeNode") && !frontedWithKeyword) { JsonObject typeNode = node.getAsJsonObject("typeNode"); JsonObject typeFormatConfig; if (!(node.has("annotationAttachments") && node.getAsJsonArray("annotationAttachments").size() > 0)) { typeFormatConfig = this.getFormattingConfig( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), formatConfig.get(FormattingConstants.DO_INDENT).getAsBoolean(), this.getWhiteSpaceCount(indentation), false); typeNode.add(FormattingConstants.FORMATTING_CONFIG, typeFormatConfig); } } } } /** * format Record Variable Ref node. * * @param node {JsonObject} node as json object */ public void formatRecordVariableRefNode(JsonObject node) { // TODO: fix formatting for Record Variable Ref. this.skipFormatting(node, true); } /** * format Resource node. * * @param node {JsonObject} node as json object */ public void formatResourceNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentWithParentIndentation = this.getParentIndentation(formatConfig); node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentWithParentIndentation)); this.preserveHeight(ws, indentWithParentIndentation); // Update whitespaces of resource name. JsonObject resourceNameWhitespace = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(resourceNameWhitespace.get(FormattingConstants.WS).getAsString())) { String whiteSpace = ((node.has("annotationAttachments") && node.getAsJsonArray("annotationAttachments").size() > 0) || (node.has("documentationAttachments") && node.getAsJsonArray("documentationAttachments").size() > 0) || (node.has("deprecatedAttachments") && node.getAsJsonArray("deprecatedAttachments").size() > 0)) ? (FormattingConstants.NEW_LINE + indentation) : (this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); resourceNameWhitespace.addProperty(FormattingConstants.WS, whiteSpace); } // Update whitespace of opening parentheses. JsonObject openingParenthesesWhitespace = ws.get(1).getAsJsonObject(); if (this.noHeightAvailable(openingParenthesesWhitespace.get(FormattingConstants.WS).getAsString())) { openingParenthesesWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } // TODO update whitespaces of parameter separators. // Update whitespace of closing parentheses. JsonObject closingParenthesesWhitespace = ws.get(ws.size() - 3).getAsJsonObject(); if (this.noHeightAvailable(closingParenthesesWhitespace.get(FormattingConstants.WS).getAsString())) { closingParenthesesWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } // Update opening bracket whitespaces. JsonObject openingBracketWhitespace = ws.get(ws.size() - 2).getAsJsonObject(); if (this.noHeightAvailable(openingBracketWhitespace.get(FormattingConstants.WS).getAsString())) { openingBracketWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update closing bracket whitespace. JsonObject closingBracketWhitespace = ws.get(ws.size() - 1).getAsJsonObject(); if (node.has(FormattingConstants.BODY) && node.getAsJsonObject(FormattingConstants.BODY).getAsJsonArray(FormattingConstants.STATEMENTS) .size() <= 0 && node.getAsJsonArray("workers").size() <= 0 && node.getAsJsonArray("endpointNodes").size() <= 0) { if (this.noHeightAvailable(closingBracketWhitespace.get(FormattingConstants.WS).getAsString())) { closingBracketWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation + FormattingConstants.NEW_LINE + indentation); } } else if (this.noHeightAvailable(closingBracketWhitespace.get(FormattingConstants.WS).getAsString())) { closingBracketWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + this.getWhiteSpaces(node.getAsJsonObject(FormattingConstants.POSITION) .get(FormattingConstants.START_COLUMN).getAsInt())); } // update the parameter whitespace in resource. if (node.has("parameters")) { JsonArray parameters = node.getAsJsonArray("parameters"); iterateAndFormatMembers(indentation, parameters); } // Update endpoint whitespaces in resource. if (node.has("endpointNodes")) { JsonArray endpointNodes = node.getAsJsonArray("endpointNodes"); for (int i = 0; i < endpointNodes.size(); i++) { JsonObject endpointNode = endpointNodes.get(i).getAsJsonObject(); JsonObject endpointFormatConfig; if (i == 0) { endpointFormatConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), true, this.getWhiteSpaceCount(indentWithParentIndentation), false); } else { endpointFormatConfig = this.getFormattingConfig(2, 0, this.getWhiteSpaceCount(indentation), true, this.getWhiteSpaceCount(indentWithParentIndentation), false); } endpointNode.add(FormattingConstants.FORMATTING_CONFIG, endpointFormatConfig); } } // Update annotation whitespaces in resource. modifyAnnotationAttachments(node, formatConfig, indentation); // Update workers whitespace in resource. modifyWorkers(node, indentation); } } /** * format Rest Args Expr node. * * @param node {JsonObject} node as json object */ public void formatRestArgsExprNode(JsonObject node) { // TODO: fix formatting for rest arguments expression. this.skipFormatting(node, true); } /** * format Retry node. * * @param node {JsonObject} node as json object */ public void formatRetryNode(JsonObject node) { modifyBranchingStatement(node); } /** * format Return node. * * @param node {JsonObject} node as json object */ public void formatReturnNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentWithParentIndentation = this.getParentIndentation(formatConfig); this.preserveHeight(ws, indentWithParentIndentation); // Update return keyword. JsonObject returnKeywordWhitespace = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(returnKeywordWhitespace.get(FormattingConstants.WS).getAsString())) { if (formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt() > 0) { returnKeywordWhitespace.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } else if (formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt() > 0) { returnKeywordWhitespace.addProperty(FormattingConstants.WS, this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } } // Update expression whitespaces. if (node.has(FormattingConstants.EXPRESSION)) { JsonObject expression = node.getAsJsonObject(FormattingConstants.EXPRESSION); JsonObject expressionFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), true); expression.add(FormattingConstants.FORMATTING_CONFIG, expressionFormatConfig); } // Update semicolon whitespace. JsonObject semicolonWhitespace = ws.get(1).getAsJsonObject(); if (this.noHeightAvailable(semicolonWhitespace.get(FormattingConstants.WS).getAsString())) { semicolonWhitespace.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } /** * format Select Clause node. * * @param node {JsonObject} node as json object */ public void formatSelectClauseNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("select")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } else if (text.equals("*")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (text.equals(",")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } if (node.has("selectExpressions")) { JsonArray selectExpressions = node.getAsJsonArray("selectExpressions"); for (JsonElement expr : selectExpressions) { JsonObject selectExpression = expr.getAsJsonObject(); selectExpression.add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount( formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation), true)); } } if (node.has("groupBy")) { node.getAsJsonObject("groupBy").add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), false, this.getWhiteSpaceCount(indentationOfParent), true)); } if (node.has("having")) { node.getAsJsonObject("having").add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), false, this.getWhiteSpaceCount(indentationOfParent), true)); } } } /** * format Select Expression node. * * @param node {JsonObject} node as json object */ public void formatSelectExpressionNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); // If whitespaces available iterate and update whitespaces. if (node.has(FormattingConstants.WS)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } if (node.has("expression")) { node.getAsJsonObject("expression").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } } } /** * format Service node. * * @param node {JsonObject} node as json object */ public void formatServiceNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { if (node.has("anonymousService") && node.get("anonymousService").getAsBoolean()) { // Skip service expression this.skipFormatting(node, true); } else { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); this.preserveHeight(ws, indentation); // Update whitespaces for service definition. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { if (text.equals("service")) { String whiteSpace = ((node.has("annotationAttachments") && node.getAsJsonArray("annotationAttachments").size() > 0) || (node.has("documentationAttachments") && node.getAsJsonArray("documentationAttachments").size() > 0) || (node.has("deprecatedAttachments") && node.getAsJsonArray("deprecatedAttachments").size() > 0)) ? (FormattingConstants.NEW_LINE + indentation) : (this.getNewLines(formatConfig .get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); currentWS.addProperty(FormattingConstants.WS, whiteSpace); } else { // Update service identifier whitespaces and on keyword. currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } // Update whitespaces for body. if (node.has("typeDefinition") && node.getAsJsonObject("typeDefinition").has("typeNode")) { JsonObject typeNode = node.getAsJsonObject("typeDefinition").getAsJsonObject("typeNode"); String typeNodeIndentation = this .getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt()) + (formatConfig.get(FormattingConstants.DO_INDENT).getAsBoolean() ? (this.getWhiteSpaces( formatConfig.get(FormattingConstants.START_COLUMN).getAsInt()) + FormattingConstants.SPACE_TAB) : this.getWhiteSpaces( formatConfig.get(FormattingConstants.START_COLUMN).getAsInt())); JsonObject typeDefFormatConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(typeNodeIndentation), true, this.getWhiteSpaceCount(typeNodeIndentation), false); typeNode.add(FormattingConstants.FORMATTING_CONFIG, typeDefFormatConfig); } // Update whitespaces for resources. if (node.has("resources")) { JsonArray resources = node.getAsJsonArray("resources"); iterateAndFormatBlockStatements(formatConfig, indentation, resources); } modifyAnnotationAttachments(node, formatConfig, indentation); if (node.has("attachedExprs")) { JsonArray boundEndpoints = node.getAsJsonArray("boundEndpoints"); for (JsonElement boundEndpoint : boundEndpoints) { // TODO: fix formatting for bound endpoint in service. this.skipFormatting(boundEndpoint.getAsJsonObject(), true); } } } } } /** * format Service Constructor node. * * @param node {JsonObject} node as json object */ public void formatServiceConstructorNode(JsonObject node) { // TODO: fix formatting for Service Constructor. this.skipFormatting(node, true); } /** * format Set Assignment Clause node. * * @param node {JsonObject} node as json object */ public void formatSetAssignmentClauseNode(JsonObject node) { // TODO: fix formatting for Set Assignment Clause. this.skipFormatting(node, true); } /** * format Simple Variable Ref node. * * @param node {JsonObject} node as json object */ public void formatSimpleVariableRefNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); String indentation = this.getIndentation(formatConfig, false); // Preserve comments and new line that already available. this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? this.getParentIndentation(formatConfig) : indentation); // Update reference whitespace. JsonObject referenceWS = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(referenceWS.get(FormattingConstants.WS).getAsString())) { if (formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt() > 0) { referenceWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } else if (formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt() > 0) { referenceWS.addProperty(FormattingConstants.WS, this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } else { referenceWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } } /** * format Statement Expression node. * * @param node {JsonObject} node as json object */ public void formatStatementExpressionNode(JsonObject node) { // TODO: fix formatting for statement expression. this.skipFormatting(node, true); } /** * format Stream Action node. * * @param node {JsonObject} node as json object */ public void formatStreamActionNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); // Preserve existing line separation. this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); // Iterate through ws and update whitespace. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("=>")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } else if (text.equals("(")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (text.equals(")")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else if (text.equals("{")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (text.equals("}")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } } } // Handle invokable body formatting if (node.has("invokableBody")) { node.getAsJsonObject("invokableBody").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } } } /** * format Streaming Input node. * * @param node {JsonObject} node as json object */ public void formatStreamingInputNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); // Handle stream reference formatting. if (node.has("streamReference")) { node.getAsJsonObject("streamReference").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } if (node.has("beforeStreamingCondition")) { node.getAsJsonObject("beforeStreamingCondition").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } if (node.has("preFunctionInvocations")) { node.getAsJsonObject("preFunctionInvocations").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } if (node.has("windowClause")) { node.getAsJsonObject("windowClause").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } if (node.has("postFunctionInvocations")) { node.getAsJsonObject("postFunctionInvocations").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } if (node.has("afterStreamingCondition")) { node.getAsJsonObject("afterStreamingCondition").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } if (node.has("alias")) { if (node.has(FormattingConstants.WS)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); String indentationOfParent = this.getParentIndentation(formatConfig); this.preserveHeight(ws, indentationOfParent); for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("as")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } } node.getAsJsonObject("alias").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } } } /** * format Streaming Query node. * * @param node {JsonObject} node as json object */ public void formatStreamingQueryNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); // Preserve available line separation. this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); // Iterate and update node's whitespaces. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("from")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } } } // Handle streaming input formatting. if (node.has("streamingInput")) { JsonObject streamingInput = node.getAsJsonObject("streamingInput"); JsonObject streamingInputFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), true); streamingInput.add(FormattingConstants.FORMATTING_CONFIG, streamingInputFormatConfig); } if (node.has("joiningInput")) { JsonObject joiningInput = node.getAsJsonObject("joiningInput"); JsonObject joiningInputFormatConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), false, this.getWhiteSpaceCount(indentationOfParent), true); joiningInput.add(FormattingConstants.FORMATTING_CONFIG, joiningInputFormatConfig); } // Handle pattern clause formatting. if (node.has("patternClause")) { JsonObject patternClause = node.getAsJsonObject("patternClause"); JsonObject patternClauseFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), false); patternClause.add(FormattingConstants.FORMATTING_CONFIG, patternClauseFormatConfig); } // Handle select clause formatting. if (node.has("selectClause")) { JsonObject selectClause = node.getAsJsonObject("selectClause"); JsonObject selectClauseFormatConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), false, this.getWhiteSpaceCount(indentationOfParent), true); selectClause.add(FormattingConstants.FORMATTING_CONFIG, selectClauseFormatConfig); } // Handle order by clause formatting. if (node.has("orderbyClause")) { JsonObject orderbyClause = node.getAsJsonObject("orderbyClause"); JsonObject orderbyClauseFormatConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), false, this.getWhiteSpaceCount(indentationOfParent), true); orderbyClause.add(FormattingConstants.FORMATTING_CONFIG, orderbyClauseFormatConfig); } // Handle output rate limit node formatting. if (node.has("outputRateLimitNode")) { JsonObject outputRateLimitNode = node.getAsJsonObject("outputRateLimitNode"); JsonObject outputRateLimitNodeFormatConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), false, this.getWhiteSpaceCount(indentationOfParent), true); outputRateLimitNode.add(FormattingConstants.FORMATTING_CONFIG, outputRateLimitNodeFormatConfig); } if (node.has("streamingAction")) { JsonObject streamingAction = node.getAsJsonObject("streamingAction"); JsonObject streamingActionFormatConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), false, this.getWhiteSpaceCount(indentationOfParent), true); streamingAction.add(FormattingConstants.FORMATTING_CONFIG, streamingActionFormatConfig); } } } /** * format String Template Literal node. * * @param node {JsonObject} node as json object */ public void formatStringTemplateLiteralNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); // Iterate through whitespace and format. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.contains("string") && text.contains("`")) { if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } // Since template literal start is in a single text formatting it to the correct format // is done by replacing the text. currentWS.addProperty(FormattingConstants.TEXT, "string `"); } else if (text.equals("`") && this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } // Handle expressions format if (node.has("expressions")) { JsonArray expressions = node.getAsJsonArray("expressions"); // Every three expression is related to // Start of the template expression // expression of the template expression // end brace of the template expression for (JsonElement expressionItem : expressions) { JsonObject expression = expressionItem.getAsJsonObject(); expression.add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(0, 0, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } } } } /** * format Table Column node. * * @param node {JsonObject} node as json object */ public void formatTableColumnNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentWithParentIndentation = this.getParentIndentation(formatConfig); this.preserveHeight(ws, indentWithParentIndentation); if (ws.size() > 1) { JsonObject primaryKeyWS = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(primaryKeyWS.get(FormattingConstants.WS).getAsString())) { primaryKeyWS.addProperty(FormattingConstants.WS, this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } JsonObject identifierWS = ws.get(1).getAsJsonObject(); if (this.noHeightAvailable(identifierWS.get(FormattingConstants.WS).getAsString())) { identifierWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } else { JsonObject identifierWS = ws.get(1).getAsJsonObject(); if (this.noHeightAvailable(identifierWS.get(FormattingConstants.WS).getAsString())) { identifierWS.addProperty(FormattingConstants.WS, this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } } } } /** * format table literal node. * * @param node {JsonObject} node as json object */ public void formatTableNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentWithParentIndentation = this.getParentIndentation(formatConfig); String indentation = indentWithParentIndentation + FormattingConstants.SPACE_TAB; node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentWithParentIndentation)); this.preserveHeight(ws, indentWithParentIndentation); // Iterate and update whitespaces for the node. int openBracesCount = 0; for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); // Update whitespace for table keyword. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("table")) { if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } if (currentWS.get(FormattingConstants.TEXT).getAsString().equals(",")) { if (openBracesCount == 1) { if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else { this.preserveHeightForWS(currentWS, indentation); } } else { if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else { this.preserveHeightForWS(currentWS, indentation + FormattingConstants.SPACE_TAB); } } } // Update whitespace for opening brace or bracket. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("{") || currentWS.get(FormattingConstants.TEXT).getAsString().equals("[")) { if (openBracesCount > 0) { if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation); } else { this.preserveHeightForWS(currentWS, indentation); } } else { if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } // Update whitespace for closing brace. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("}")) { if (openBracesCount == 1) { if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { if (node.has("dataRows") && node.has("tableColumns") && node.getAsJsonArray("dataRows").size() <= 0 && node.getAsJsonArray("tableColumns").size() <= 0) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentWithParentIndentation + FormattingConstants.NEW_LINE + indentWithParentIndentation); } else { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentWithParentIndentation); } } } else { if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else { preserveHeightForWS(currentWS, indentation); } } } // Update whitespace for closing bracket. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("]")) { if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { if (node.has("dataRows") && node.getAsJsonArray("dataRows").size() <= 0) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation); } } else { this.preserveHeightForWS(currentWS, indentation); } } if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("{") || currentWS.get(FormattingConstants.TEXT).getAsString().equals("[")) { if (openBracesCount > 0) { openBracesCount++; } else { openBracesCount = 1; } } if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("}") || currentWS.get(FormattingConstants.TEXT).getAsString().equals("]")) { if (openBracesCount > 1) { openBracesCount--; } } } if (node.has("dataRows")) { JsonArray dataRows = node.getAsJsonArray("dataRows"); for (JsonElement dataRowItem : dataRows) { JsonObject dataRow = dataRowItem.getAsJsonObject(); JsonObject rowFormatConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), true, this.getWhiteSpaceCount(indentation), false); dataRow.add(FormattingConstants.FORMATTING_CONFIG, rowFormatConfig); } } if (node.has("tableColumns")) { JsonArray tableColumns = node.getAsJsonArray("tableColumns"); this.iterateAndFormatMembers(indentation + FormattingConstants.SPACE_TAB, tableColumns); } } } /** * format Table Query node. * * @param node {JsonObject} node as json object */ public void formatTableQueryNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, true); String indentationOfParent = this.getParentIndentation(formatConfig); // Preserve available line separators. this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); // Iterate and update whitespaces for the node. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("from")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } } } // Handle select clause node formatting. if (node.has("selectClauseNode")) { node.getAsJsonObject("selectClauseNode").add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentationOfParent), false, this.getWhiteSpaceCount(indentationOfParent), true)); } // Handle streaming input node formatting. if (node.has("streamingInput")) { node.getAsJsonObject("streamingInput").add(FormattingConstants.FORMATTING_CONFIG, this .getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } // Handle join streaming input formatting. if (node.has("joinStreamingInput")) { node.getAsJsonObject("joinStreamingInput").add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentationOfParent), false, this.getWhiteSpaceCount(indentationOfParent), true)); } // Handle order by node formatting. if (node.has("orderByNode")) { node.getAsJsonObject("orderByNode").add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentationOfParent), false, this.getWhiteSpaceCount(indentationOfParent), true)); } // Handle order by node formatting. if (node.has("limitClause")) { node.getAsJsonObject("limitClause").add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentationOfParent), false, this.getWhiteSpaceCount(indentationOfParent), true)); } } } /** * format Table Query Expression node. * * @param node {JsonObject} node as json object */ public void formatTableQueryExpressionNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); if (node.has("tableQuery")) { if (node.has("isExpression")) { node.getAsJsonObject("tableQuery").addProperty("isExpression", node.get("isExpression").getAsBoolean()); } node.getAsJsonObject("tableQuery").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } } } /** * format Ternary Expr node. * * @param node {JsonObject} node as json object */ public void formatTernaryExprNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); // Iterate through whitespaces and format. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("?") || text.equals(":")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } // Handle condition's formatting. if (node.has("condition")) { node.getAsJsonObject("condition").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } // Handle then expression's formatting. if (node.has("thenExpression")) { node.getAsJsonObject("thenExpression").add(FormattingConstants.FORMATTING_CONFIG, this .getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } // Handle else expression's formatting. if (node.has("elseExpression")) { node.getAsJsonObject("elseExpression").add(FormattingConstants.FORMATTING_CONFIG, this .getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } } } /** * format Throw node. * * @param node {JsonObject} node as json object */ public void formatThrowNode(JsonObject node) { // TODO: fix formatting for throw. this.skipFormatting(node, true); } /** * format Transaction node. * * @param node {JsonObject} node as json object */ public void formatTransactionNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, true); node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentation)); this.preserveHeight(ws, indentation); // Update transaction and retry whitespaces. boolean isRetryBody = false; for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("transaction")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("onretry")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); isRetryBody = true; } if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("{")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("}")) { if (isRetryBody) { modifyBlockBody(node, indentation, currentWS, "onRetryBody"); } else { modifyBlockBody(node, indentation, currentWS, "transactionBody"); } } if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("with")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("retries")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("=")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } if (currentWS.get(FormattingConstants.TEXT).getAsString().equals(",")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("onabort")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("oncommit")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } // Update whitespaces for retryCount. if (node.has("retryCount")) { this.skipFormatting(node.getAsJsonObject("retryCount"), true); } // Update whitespaces for onAbort function. if (node.has("onAbortFunction")) { this.skipFormatting(node.getAsJsonObject("onAbortFunction"), true); } // Update whitespaces for onCommit function. if (node.has("onCommitFunction")) { this.skipFormatting(node.getAsJsonObject("onCommitFunction"), true); } } } /** * format Trap Expr node. * * @param node {JsonObject} node as json object */ public void formatTrapExprNode(JsonObject node) { // TODO: fix formatting for Trap Expr. this.skipFormatting(node, true); } /** * format Tuple Destructure node. * * @param node {JsonObject} node as json object */ public void formatTupleDestructureNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, true); this.preserveHeight(ws, indentation); if (node.has("declaredWithVar") && node.get("declaredWithVar").getAsBoolean()) { JsonObject varWS = ws.get(0).getAsJsonObject(); JsonObject openingParenthesesWS = ws.get(1).getAsJsonObject(); if (this.noHeightAvailable(varWS.get(FormattingConstants.WS).getAsString())) { varWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } if (this.noHeightAvailable(openingParenthesesWS.get(FormattingConstants.WS).getAsString())) { openingParenthesesWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } else { JsonObject openingParenthesesWS = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(openingParenthesesWS.get(FormattingConstants.WS).getAsString())) { openingParenthesesWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } } // Update variable references' whitespaces. if (node.has("variableRefs")) { JsonArray varRefs = node.getAsJsonArray("variableRefs"); modifyVariableReferences(formatConfig, indentation, varRefs); } // Update closing parentheses whitespace. JsonObject closingParenWS = ws.get(ws.size() - 3).getAsJsonObject(); if (this.noHeightAvailable(closingParenWS.get(FormattingConstants.WS).getAsString())) { closingParenWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } // Update assignment sign for tuple destruct. JsonObject equalWS = ws.get(ws.size() - 2).getAsJsonObject(); if (this.noHeightAvailable(equalWS.get(FormattingConstants.WS).getAsString())) { equalWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update whitespace for expression. if (node.has(FormattingConstants.EXPRESSION)) { JsonObject expression = node.getAsJsonObject(FormattingConstants.EXPRESSION); JsonObject expressionFormatConfig = this.getFormattingConfig(0, 1, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), false, this.getWhiteSpaceCount(indentation), false); expression.add(FormattingConstants.FORMATTING_CONFIG, expressionFormatConfig); } // Update semicolon whitespace JsonObject semicolonWS = ws.get(ws.size() - 1).getAsJsonObject(); if (this.noHeightAvailable(semicolonWS.get(FormattingConstants.WS).getAsString())) { semicolonWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } /** * format Tuple Type node. * * @param node {JsonObject} node as json object */ public void formatTupleTypeNodeNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, true); this.preserveHeight(ws, indentation); // Update the whitespace for the opening parentheses. JsonObject openingParentheses = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(openingParentheses.get(FormattingConstants.WS).getAsString())) { openingParentheses.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } // Update the whitespaces for member types in tuple. if (node.has("memberTypeNodes")) { JsonArray memberTypeNodes = node.getAsJsonArray("memberTypeNodes"); JsonObject memberFormatConfig = this.getFormattingConfig(0, 0, 0, false, this.getWhiteSpaceCount(indentation), false); modifyVariableReferences(memberFormatConfig, indentation, memberTypeNodes); } // Update the whitespace for closing parentheses. JsonObject closingParentheses = ws.get(ws.size() - 1).getAsJsonObject(); if (this.noHeightAvailable(closingParentheses.get(FormattingConstants.WS).getAsString())) { closingParentheses.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } /** * format Tuple variable node. * * @param node {JsonObject} node as json object */ public void formatTupleVariableNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); if (node.has(FormattingConstants.WS)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); String indentation = this.getIndentation(formatConfig, true); String indentWithParentIndentation = this.getParentIndentation(formatConfig); node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentation)); this.preserveHeight(ws, indentWithParentIndentation); // Update the record or public keyword whitespaces. JsonObject firstKeywordWS = ws.get(0).getAsJsonObject(); // Format type node if (node.has("typeNode")) { JsonObject typeNode = node.getAsJsonObject("typeNode"); JsonObject typeFormatConfig; if ((node.has(FormattingConstants.FINAL) && node.get(FormattingConstants.FINAL).getAsBoolean()) || (node.has(FormattingConstants.PUBLIC) && node.get(FormattingConstants.PUBLIC).getAsBoolean() && firstKeywordWS.get(FormattingConstants.TEXT).getAsString() .equals(FormattingConstants.PUBLIC)) || firstKeywordWS.get(FormattingConstants.TEXT).getAsString().equals("const") || firstKeywordWS.get(FormattingConstants.TEXT).getAsString().equals("var")) { if (this.noHeightAvailable(firstKeywordWS.get(FormattingConstants.WS).getAsString())) { firstKeywordWS.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } } else { typeFormatConfig = this.getFormattingConfig( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), formatConfig.get(FormattingConstants.DO_INDENT).getAsBoolean(), this.getWhiteSpaceCount(indentation), false); typeNode.add(FormattingConstants.FORMATTING_CONFIG, typeFormatConfig); } } else { if ((node.has(FormattingConstants.FINAL) && node.get(FormattingConstants.FINAL).getAsBoolean()) || (node.has(FormattingConstants.PUBLIC) && node.get(FormattingConstants.PUBLIC).getAsBoolean() && firstKeywordWS.get(FormattingConstants.TEXT).getAsString() .equals(FormattingConstants.PUBLIC)) || firstKeywordWS.get(FormattingConstants.TEXT).getAsString().equals("const") || firstKeywordWS.get(FormattingConstants.TEXT).getAsString().equals("var")) { if (this.noHeightAvailable(firstKeywordWS.get(FormattingConstants.WS).getAsString())) { firstKeywordWS.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } } } // Update whitespaces of parameters. if (node.has("variables")) { JsonArray variables = node.getAsJsonArray("variables"); iterateAndFormatMembers(indentation, variables); } if (node.has("annotationAttachments")) { JsonArray annotationAttachments = node.getAsJsonArray("annotationAttachments"); for (JsonElement annotationAttachment : annotationAttachments) { JsonObject annotationAttachmentFormattingConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), false, this.getWhiteSpaceCount(indentation), false); annotationAttachment.getAsJsonObject().add(FormattingConstants.FORMATTING_CONFIG, annotationAttachmentFormattingConfig); } } } else if (node.has("typeNode")) { node.getAsJsonObject("typeNode").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } } } /** * format Tuple Variable Ref node. * * @param node {JsonObject} node as json object */ public void formatTupleVariableRefNode(JsonObject node) { // TODO: fix formatting for Tuple Variable Ref. this.skipFormatting(node, true); } /** * format Type Conversion Expr node. * * @param node {JsonObject} node as json object */ public void formatTypeConversionExprNode(JsonObject node) { // TODO: fix formatting for type conversion expression. this.skipFormatting(node, true); } /** * format Type Definition node. * * @param node {JsonObject} node as json object */ public void formatTypeDefinitionNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, true); this.preserveHeight(ws, indentation); boolean isEnum = true; // Handles whitespace for type def. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { // Update the type or public keywords whitespace. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("public")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } // Update type keyword whitespace. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("type")) { if (node.has(FormattingConstants.PUBLIC) && node.get(FormattingConstants.PUBLIC).getAsBoolean()) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else { currentWS.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } } // Update record or object keyword whitespace. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("object") || currentWS.get(FormattingConstants.TEXT).getAsString().equals("record")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update identifier whitespace. if (currentWS.get(FormattingConstants.TEXT).getAsString() .equals(node.getAsJsonObject("name").get("valueWithBar").getAsString())) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update opening bracket whitespace. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("{")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); isEnum = false; } // Update the closing bracket whitespaces. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("}")) { if (node.has("typeNode") && node.getAsJsonObject("typeNode") .getAsJsonArray(FormattingConstants.FIELDS).size() <= 0) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation + FormattingConstants.NEW_LINE + indentation); } else { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation); } } // Update the semicolon whitespace. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals(";")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } // Handle the whitespace for type node. if (node.has("typeNode")) { if (isEnum) { JsonObject typeNodeFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), false); node.getAsJsonObject("typeNode").add(FormattingConstants.FORMATTING_CONFIG, typeNodeFormatConfig); } else { JsonObject typeNodeFormatConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), true, this.getWhiteSpaceCount(indentation), false); node.getAsJsonObject("typeNode").add(FormattingConstants.FORMATTING_CONFIG, typeNodeFormatConfig); } } // Update whitespaces of annotation attachments. modifyAnnotationAttachments(node, formatConfig, indentation); // Update whitespaces of markdown documentation attachments. modifyMarkdownDocumentation(node, formatConfig, indentation); } } /** * format Typedesc Expression node. * * @param node {JsonObject} node as json object */ public void formatTypedescExpressionNode(JsonObject node) { // TODO: fix formatting for type desc expression. this.skipFormatting(node, true); } /** * format Type Init Expr node. * * @param node {JsonObject} node as json object */ public void formatTypeInitExprNode(JsonObject node) { // TODO: fix formatting for type init expression this.skipFormatting(node, true); } /** * format Type Test Expr node. * * @param node {JsonObject} node as json object */ public void formatTypeTestExprNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); // Iterate through whitespaces for this node and update. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("is")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } // Handle expression's formatting. if (node.has("expression")) { node.getAsJsonObject("expression").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } // Handle typeNode's formatting. if (node.has("typeNode")) { node.getAsJsonObject("typeNode").add(FormattingConstants.FORMATTING_CONFIG, this .getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } } } /** * format Unary Expr node. * * @param node {JsonObject} node as json object */ public void formatUnaryExprNode(JsonObject node) { // TODO: fix formatting for unary expression. this.skipFormatting(node, true); } /** * format Union Type node. * * @param node {JsonObject} node as json object */ public void formatUnionTypeNodeNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); boolean isGrouped = node.has(FormattingConstants.GROUPED) && node.get(FormattingConstants.GROUPED).getAsBoolean(); String indentation = this.getIndentation(formatConfig, true); if (node.has(FormattingConstants.WS)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); this.preserveHeight(ws, indentation); // Iterate through WS to update horizontal whitespaces. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { // Update opening parentheses whitespace. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("(")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } // Update pipe symbol whitespace. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals("|")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update closing parentheses whitespace. if (currentWS.get(FormattingConstants.TEXT).getAsString().equals(")")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } } // Update member types whitespaces. if (node.has("memberTypeNodes")) { JsonArray memberTypeNodes = node.getAsJsonArray("memberTypeNodes"); for (int i = 0; i < memberTypeNodes.size(); i++) { JsonObject memberType = memberTypeNodes.get(i).getAsJsonObject(); JsonObject memberTypeFormatConfig; if (i == 0 && !node.getAsJsonObject(FormattingConstants.PARENT).get("kind").getAsString() .equals("TypeDefinition")) { if (isGrouped) { memberTypeFormatConfig = this.getFormattingConfig(0, 0, 0, false, this.getWhiteSpaceCount(indentation), true); } else { memberTypeFormatConfig = this.getFormattingConfig( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), formatConfig.get(FormattingConstants.DO_INDENT).getAsBoolean(), this.getWhiteSpaceCount(indentation), false); } } else { memberTypeFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), true); } memberType.add(FormattingConstants.FORMATTING_CONFIG, memberTypeFormatConfig); } } } } /** * format User Defined Type node. * * @param node {JsonObject} node as json object */ public void formatUserDefinedTypeNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); if (node.has(FormattingConstants.WS) && !node.has(FormattingConstants.IS_ANON_TYPE)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); String indentation = this.getIndentation(formatConfig, false); node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentation + this .getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt()))); this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? getParentIndentation(formatConfig) : indentation); boolean isPackageAliasExist = false; boolean isGrouped = node.has("grouped") && node.get("grouped").getAsBoolean(); for (int i = 0; i < ws.size(); i++) { JsonObject currentWS = ws.get(i).getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (i == 0) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation + this.getWhiteSpaces( formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } else { if (text.equals(":")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); isPackageAliasExist = true; } else if (text.equals("?") || (text.equals(")") && isGrouped)) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else { if (isPackageAliasExist) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); isPackageAliasExist = false; } else if (isGrouped) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } } } } else if (node.has(FormattingConstants.IS_ANON_TYPE) && node.get(FormattingConstants.IS_ANON_TYPE).getAsBoolean()) { JsonObject anonType = node.getAsJsonObject(FormattingConstants.ANON_TYPE); JsonObject anonTypeFormatConfig = this.getFormattingConfig( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), formatConfig.get(FormattingConstants.DO_INDENT).getAsBoolean(), formatConfig.get(FormattingConstants.INDENTED_START_COLUMN).getAsInt(), false); anonType.add(FormattingConstants.FORMATTING_CONFIG, anonTypeFormatConfig); } } } /** * format Value Type node. * * @param node {JsonObject} node as json object */ public void formatValueTypeNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentation)); this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? this.getParentIndentation(formatConfig) : indentation); // Update whitespaces for type. JsonObject typeWhitespace = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(typeWhitespace.get(FormattingConstants.WS).getAsString())) { typeWhitespace.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt()) + indentation); } } } /** * format Variable Def node. * * @param node {JsonObject} node as json object */ public void formatVariableDefNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); if (node.has("variable")) { node.getAsJsonObject("variable").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } if (node.has(FormattingConstants.WS)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); String indentation = this.getIndentation(formatConfig, false); this.preserveHeight(ws, indentation); // Iterate and update whitespaces for variable def. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { if (text.equals("var")) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } if (text.equals("=")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } if (text.equals(";")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } } // Update whitespaces for semicolon. // if (this.noHeightAvailable(node.getAsJsonArray(FormattingConstants.WS).get(0) // .getAsJsonObject().get(FormattingConstants.WS).getAsString())) { // node.getAsJsonArray(FormattingConstants.WS).get(0).getAsJsonObject() // .addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); // } } } /** * format Variable node. * * @param node {JsonObject} node as json object */ public void formatVariableNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); if (node.has(FormattingConstants.WS)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); String indentation = this.getIndentation(formatConfig, true); String indentWithParentIndentation = this.getParentIndentation(formatConfig); node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentation)); this.preserveHeight(ws, indentWithParentIndentation); // Update the record or public keyword whitespaces. boolean hasFirstKeyword = false; JsonObject firstKeywordWS = ws.get(0).getAsJsonObject(); String firstKeyword = firstKeywordWS.get(FormattingConstants.TEXT).getAsString(); if (firstKeyword.equals(FormattingConstants.FINAL) || firstKeyword.equals(FormattingConstants.PUBLIC) || firstKeyword.equals("private") || firstKeyword.equals("const") || firstKeyword.equals("var") || firstKeyword.equals("client") || firstKeyword.equals("listener") || firstKeyword.equals("abstract") || firstKeyword.equals("channel") || firstKeyword.equals("record") || firstKeyword.equals("object")) { hasFirstKeyword = true; } boolean updatedFirstKeyword = false; for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals(FormattingConstants.FINAL) || text.equals(FormattingConstants.PUBLIC) || text.equals("private") || text.equals("const") || text.equals("var") || text.equals("client") || text.equals("listener") || text.equals("abstract") || text.equals("channel") || text.equals("record") || text.equals("object")) { if (updatedFirstKeyword) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (text.equals(firstKeywordWS.get(FormattingConstants.TEXT).getAsString())) { currentWS.addProperty(FormattingConstants.WS, this.getNewLines( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); updatedFirstKeyword = true; } else { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } else if (text.equals(";") || text.equals("?") || text.equals(",")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else if (text.equals("{")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (text.equals("}")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation); } else if (text.equals("...")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else if (text.equals("=")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else { if (node.has(FormattingConstants.IS_ANON_TYPE) && node.get(FormattingConstants.IS_ANON_TYPE).getAsBoolean()) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if ((!node.has("typeNode") && !hasFirstKeyword) || (node.has("arrowExprParam") && node.get("arrowExprParam").getAsBoolean())) { currentWS.addProperty(FormattingConstants.WS, this.getWhiteSpaces( formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } else { currentWS.addProperty(FormattingConstants.WS, formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt() > 0 ? this.getWhiteSpaces(formatConfig .get(FormattingConstants.SPACE_COUNT).getAsInt()) : FormattingConstants.SINGLE_SPACE); } } } } // Format type node if (node.has("typeNode")) { JsonObject typeNode = node.getAsJsonObject("typeNode"); JsonObject typeFormatConfig; if (node.has(FormattingConstants.IS_ANON_TYPE) && node.get(FormattingConstants.IS_ANON_TYPE).getAsBoolean()) { // Update type node whitespace. typeFormatConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), true, this.getWhiteSpaceCount( formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentWithParentIndentation : indentation), formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean()); typeNode.add(FormattingConstants.FORMATTING_CONFIG, typeFormatConfig); } else { if ((node.has(FormattingConstants.FINAL) && node.get(FormattingConstants.FINAL).getAsBoolean()) || (node.has(FormattingConstants.PUBLIC) && node.get(FormattingConstants.PUBLIC).getAsBoolean() && firstKeywordWS.get(FormattingConstants.TEXT).getAsString() .equals(FormattingConstants.PUBLIC)) || firstKeywordWS.get(FormattingConstants.TEXT).getAsString().equals("private") || firstKeywordWS.get(FormattingConstants.TEXT).getAsString().equals("const") || firstKeywordWS.get(FormattingConstants.TEXT).getAsString().equals("var") || firstKeywordWS.get(FormattingConstants.TEXT).getAsString().equals("client") || firstKeywordWS.get(FormattingConstants.TEXT).getAsString().equals("listener") || firstKeywordWS.get(FormattingConstants.TEXT).getAsString().equals("abstract") || firstKeywordWS.get(FormattingConstants.TEXT).getAsString().equals("channel")) { typeFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount( formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentWithParentIndentation : indentation), formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean()); typeNode.add(FormattingConstants.FORMATTING_CONFIG, typeFormatConfig); } else { if (!(node.has("annotationAttachments") && node.getAsJsonArray("annotationAttachments").size() > 0)) { typeFormatConfig = this.getFormattingConfig( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt(), formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), formatConfig.get(FormattingConstants.DO_INDENT).getAsBoolean(), this.getWhiteSpaceCount( formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION) .getAsBoolean() ? indentWithParentIndentation : indentation), formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION) .getAsBoolean()); typeNode.add(FormattingConstants.FORMATTING_CONFIG, typeFormatConfig); } } } } if (node.has("initialExpression")) { JsonObject initialExprFormattingConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentWithParentIndentation), true); node.getAsJsonObject("initialExpression").add(FormattingConstants.FORMATTING_CONFIG, initialExprFormattingConfig); } if (node.has("annotationAttachments")) { JsonArray annotationAttachments = node.getAsJsonArray("annotationAttachments"); for (int i = 0; i < annotationAttachments.size(); i++) { JsonObject annotationAttachment = annotationAttachments.get(i).getAsJsonObject(); JsonObject annotationAttachmentFormattingConfig; if (node.has("param") && node.get("param").getAsBoolean()) { if (i == 0) { annotationAttachmentFormattingConfig = this.getFormattingConfig(0, 0, this.getWhiteSpaceCount(indentation), false, this.getWhiteSpaceCount(indentation), false); } else { annotationAttachmentFormattingConfig = this.getFormattingConfig(0, 1, this.getWhiteSpaceCount(indentation), false, this.getWhiteSpaceCount(indentation), false); } } else { annotationAttachmentFormattingConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), false, this.getWhiteSpaceCount(indentation), false); } annotationAttachment.getAsJsonObject().add(FormattingConstants.FORMATTING_CONFIG, annotationAttachmentFormattingConfig); } } } else if (node.has("typeNode")) { node.getAsJsonObject("typeNode").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } else if (node.has("worker") && node.get("worker").getAsBoolean()) { if (node.has("initialExpression") && node.getAsJsonObject("initialExpression").get("kind").getAsString().equals("Lambda")) { node.getAsJsonObject("initialExpression").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } } } } /** * format Wait Expr node. * * @param node {JsonObject} node as json object */ public void formatWaitExprNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentWithParentIndentation = this.getParentIndentation(formatConfig); this.preserveHeight(ws, indentWithParentIndentation); // Update whitespaces for wait. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("wait") || text.equals("{")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (text.equals("}") || text.equals(",")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } // Update key value pairs' whitespaces. if (node.has("keyValuePairs")) { JsonArray keyValuePairs = node.getAsJsonArray("keyValuePairs"); this.iterateAndFormatMembers(indentWithParentIndentation, keyValuePairs); } } } /** * format Where node. * * @param node {JsonObject} node as json object */ public void formatWhereNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG) && node.has(FormattingConstants.WS)) { JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); // Preserve available line separators. this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); // Iterate and update whitespaces for the node. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("where")) { currentWS.addProperty(FormattingConstants.WS, this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } } } // Handle expression formatting. if (node.has("expression")) { node.getAsJsonObject("expression").add(FormattingConstants.FORMATTING_CONFIG, this .getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentationOfParent), true)); } } } /** * format While node. * * @param node {JsonObject} node as json object */ public void formatWhileNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, true); node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentation)); this.preserveHeight(ws, indentation); // Update while keyword whitespace. JsonObject whileKeywordWS = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(whileKeywordWS.get(FormattingConstants.WS).getAsString())) { whileKeywordWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } // Update opening brace whitespace. JsonObject openingBraceWS = ws.get(ws.size() - 2).getAsJsonObject(); if (this.noHeightAvailable(openingBraceWS.get(FormattingConstants.WS).getAsString())) { openingBraceWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update closing brace whitespace. JsonObject closingBraceWS = ws.get(ws.size() - 1).getAsJsonObject(); modifyBlockBody(node, indentation, closingBraceWS, FormattingConstants.BODY); // Update condition whitespace. if (node.has("condition")) { JsonObject whileCondition = node.getAsJsonObject("condition"); JsonObject whileConditionFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), false); whileCondition.add(FormattingConstants.FORMATTING_CONFIG, whileConditionFormatConfig); } } } /** * format Window Clause node. * * @param node {JsonObject} node as json object */ public void formatWindowClauseNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); String indentationOfParent = this.getParentIndentation(formatConfig); this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? indentationOfParent : indentation); for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("window")) { currentWS.addProperty(FormattingConstants.WS, this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } } } if (node.has("functionInvocation")) { node.getAsJsonObject("functionInvocation").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } } } /** * format Within node. * * @param node {JsonObject} node as json object */ public void formatWithinNode(JsonObject node) { // TODO: fix formatting for Within node. this.skipFormatting(node, true); } /** * format Worker node. * * @param node {JsonObject} node as json object */ public void formatWorkerNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); // Update the position start column of the node as to the indentation. node.getAsJsonObject(FormattingConstants.POSITION).addProperty(FormattingConstants.START_COLUMN, this.getWhiteSpaceCount(indentation)); // Preserve height and comments that already available. this.preserveHeight(ws, indentation); // Update whitespace for worker keyword. JsonObject workerKeywordWhitespace = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(workerKeywordWhitespace.get(FormattingConstants.WS).getAsString())) { workerKeywordWhitespace.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentation); } // Update whitespace for worker identifier. JsonObject workerIdentifier = ws.get(ws.size() - 3).getAsJsonObject(); if (this.noHeightAvailable(workerIdentifier.get(FormattingConstants.WS).getAsString())) { workerIdentifier.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update whitespace for worker opening brace. JsonObject openingBrace = ws.get(ws.size() - 2).getAsJsonObject(); if (this.noHeightAvailable(openingBrace.get(FormattingConstants.WS).getAsString())) { openingBrace.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } // Update whitespace for worker closing brace. JsonObject closingBrace = ws.get(ws.size() - 1).getAsJsonObject(); if (node.has(FormattingConstants.BODY) && node.getAsJsonObject(FormattingConstants.BODY).getAsJsonArray(FormattingConstants.STATEMENTS) .size() <= 0 && node.getAsJsonArray("workers").size() <= 0 && node.getAsJsonArray("endpointNodes").size() <= 0) { if (this.noHeightAvailable(closingBrace.get(FormattingConstants.WS).getAsString())) { closingBrace.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation + FormattingConstants.NEW_LINE + indentation); } } else if (this.noHeightAvailable( ws.get(ws.size() - 1).getAsJsonObject().get(FormattingConstants.WS).getAsString())) { closingBrace.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation); } } } /** * format Worker Flush node. * * @param node {JsonObject} node as json object */ public void formatWorkerFlushNode(JsonObject node) { // TODO: fix formatting for Worker Flush node. this.skipFormatting(node, true); } /** * format Worker Receive node. * * @param node {JsonObject} node as json object */ public void formatWorkerReceiveNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentationFromParent = this.getParentIndentation(formatConfig); this.preserveHeight(ws, indentationFromParent); // Iterate through ws accordingly. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("<-")) { currentWS.addProperty(FormattingConstants.WS, this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt())); } else if (text.equals(",")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } if (node.has("keyExpression")) { node.getAsJsonObject("keyExpression").add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentationFromParent), false)); } } } /** * format Worker Send node. * * @param node {JsonObject} node as json object */ public void formatWorkerSendNode(JsonObject node) { if (node.has(FormattingConstants.FORMATTING_CONFIG) && node.has(FormattingConstants.WS)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); this.preserveHeight(ws, indentation); // Iterate through ws and update accordingly. for (JsonElement wsItem : ws) { JsonObject currentWS = wsItem.getAsJsonObject(); if (this.noHeightAvailable(currentWS.get(FormattingConstants.WS).getAsString())) { String text = currentWS.get(FormattingConstants.TEXT).getAsString(); if (text.equals("->")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } else if (text.equals(";") || text.equals(",")) { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } else { currentWS.addProperty(FormattingConstants.WS, FormattingConstants.SINGLE_SPACE); } } } if (node.has("keyExpression")) { node.getAsJsonObject("keyExpression").add(FormattingConstants.FORMATTING_CONFIG, this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), false)); } if (node.has("expression")) { node.getAsJsonObject("expression").add(FormattingConstants.FORMATTING_CONFIG, formatConfig); } } } /** * format Worker Sync Send node. * * @param node {JsonObject} node as json object */ public void formatWorkerSyncSendNode(JsonObject node) { // TODO: fix formatting for Worker Sync Send. this.skipFormatting(node, true); } /** * format XML Attribute node. * * @param node {JsonObject} node as json object */ public void formatXmlAttributeNode(JsonObject node) { // TODO: fix formatting for XML Attribute. this.skipFormatting(node, true); } /** * format XML Attribute Access Expr node. * * @param node {JsonObject} node as json object */ public void formatXmlAttributeAccessExprNode(JsonObject node) { // TODO: fix formatting for XML Attribute Access Expr. this.skipFormatting(node, true); } /** * format XML Comment Literal node. * * @param node {JsonObject} node as json object */ public void formatXmlCommentLiteralNode(JsonObject node) { // TODO: fix formatting for XML Comment Literal. this.skipFormatting(node, true); } /** * format XML Element Literal node. * * @param node {JsonObject} node as json object */ public void formatXmlElementLiteralNode(JsonObject node) { // TODO: fix formatting for XML Element Literal. this.skipFormatting(node, true); } /** * format XMLNS node. * * @param node {JsonObject} node as json object */ public void formatXmlnsNode(JsonObject node) { // TODO: fix formatting for where node. this.skipFormatting(node, true); } /** * format XML PI Literal node. * * @param node {JsonObject} node as json object */ public void formatXmlPiLiteralNode(JsonObject node) { // TODO: fix formatting for XML PI Literal. this.skipFormatting(node, true); } /** * format XML Qname node. * * @param node {JsonObject} node as json object */ public void formatXmlQnameNode(JsonObject node) { // TODO: fix formatting for XML Qname. this.skipFormatting(node, true); } /** * format XML Quoted String node. * * @param node {JsonObject} node as json object */ public void formatXmlQuotedStringNode(JsonObject node) { // TODO: fix formatting for XML Quoted String. this.skipFormatting(node, true); } /** * format Xml Sequence Literal node. * * @param node {JsonObject} node as json object */ public void formatXmlSequenceLiteralNode(JsonObject node) { // TODO: fix formatting for Xml Sequence Literal. this.skipFormatting(node, true); } /** * format XML Text Literal node. * * @param node {JsonObject} node as json object */ public void formatXmlTextLiteralNode(JsonObject node) { // TODO: fix formatting for XML Text Literal. this.skipFormatting(node, true); } // --------- Util functions for the modifying node tree -------- private void modifyLiteralNode(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentation = this.getIndentation(formatConfig, false); // Update whitespace for literal value. this.preserveHeight(ws, formatConfig.get(FormattingConstants.USE_PARENT_INDENTATION).getAsBoolean() ? this.getParentIndentation(formatConfig) : indentation); if (this.noHeightAvailable(ws.get(0).getAsJsonObject().get(FormattingConstants.WS).getAsString())) { ws.get(0).getAsJsonObject().addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt()) + indentation); } } } private void modifyReturnTypeAnnotations(JsonObject node, String indentation) { if (node.has("returnTypeAnnotationAttachments")) { JsonArray returnTypeAnnotations = node.getAsJsonArray("returnTypeAnnotationAttachments"); iterateAndFormatMembers(indentation, returnTypeAnnotations); } } private void modifyExpressions(JsonObject node, String indentWithParentIndentation) { if (node.has("expressions")) { JsonArray expressions = node.getAsJsonArray("expressions"); iterateAndFormatMembers(indentWithParentIndentation, expressions); } } private void modifyBlockBody(JsonObject node, String indentation, JsonObject closingBraceWS, String block) { if (node.has(block) && node.getAsJsonObject(block).getAsJsonArray(FormattingConstants.STATEMENTS).size() <= 0) { if (this.noHeightAvailable(closingBraceWS.get(FormattingConstants.WS).getAsString())) { closingBraceWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation + FormattingConstants.NEW_LINE + indentation); } } else if (this.noHeightAvailable(closingBraceWS.get(FormattingConstants.WS).getAsString())) { closingBraceWS.addProperty(FormattingConstants.WS, FormattingConstants.NEW_LINE + indentation); } } private void modifyBranchingStatement(JsonObject node) { if (node.has(FormattingConstants.WS) && node.has(FormattingConstants.FORMATTING_CONFIG)) { JsonArray ws = node.getAsJsonArray(FormattingConstants.WS); JsonObject formatConfig = node.getAsJsonObject(FormattingConstants.FORMATTING_CONFIG); String indentWithParentIndentation = formatConfig.get(FormattingConstants.DO_INDENT).getAsBoolean() ? this.getWhiteSpaces(formatConfig.get(FormattingConstants.INDENTED_START_COLUMN).getAsInt()) + FormattingConstants.SPACE_TAB : this.getWhiteSpaces(formatConfig.get(FormattingConstants.INDENTED_START_COLUMN).getAsInt()); this.preserveHeight(ws, indentWithParentIndentation); // Update done keyword whitespace. JsonObject doneWS = ws.get(0).getAsJsonObject(); if (this.noHeightAvailable(doneWS.get(FormattingConstants.WS).getAsString())) { doneWS.addProperty(FormattingConstants.WS, this.getNewLines(formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt()) + indentWithParentIndentation); } // Update semicolon whitespace. JsonObject semicolonWS = ws.get(ws.size() - 1).getAsJsonObject(); if (this.noHeightAvailable(semicolonWS.get(FormattingConstants.WS).getAsString())) { semicolonWS.addProperty(FormattingConstants.WS, FormattingConstants.EMPTY_SPACE); } } } private void modifyAnnotationAttachments(JsonObject node, JsonObject formatConfig, String indentation) { if (node.has("annotationAttachments")) { JsonArray annotationAttachments = node.getAsJsonArray("annotationAttachments"); for (int i = 0; i < annotationAttachments.size(); i++) { JsonObject annotationAttachment = annotationAttachments.get(i).getAsJsonObject(); JsonObject annotationFormattingConfig; if (i == 0) { annotationFormattingConfig = this.getFormattingConfig( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt(), 0, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), false, this.getWhiteSpaceCount(indentation), false); } else { annotationFormattingConfig = this.getFormattingConfig(1, 0, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), false, this.getWhiteSpaceCount(indentation), false); } annotationAttachment.add(FormattingConstants.FORMATTING_CONFIG, annotationFormattingConfig); } } } private void modifyMarkdownDocumentation(JsonObject node, JsonObject formatConfig, String indentation) { if (node.has("markdownDocumentationAttachment")) { JsonObject markdownDocumentationAttachment = node.getAsJsonObject("markdownDocumentationAttachment"); JsonObject markdownDocumentationAttachmentConfig = this.getFormattingConfig( formatConfig.get(FormattingConstants.NEW_LINE_COUNT).getAsInt(), 0, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), false, this.getWhiteSpaceCount(indentation), false); markdownDocumentationAttachment.add(FormattingConstants.FORMATTING_CONFIG, markdownDocumentationAttachmentConfig); } } private void modifyWorkers(JsonObject node, String indentation) { if (node.has("workers")) { JsonArray workers = node.getAsJsonArray("workers"); iterateAndFormatBlockStatements(node.getAsJsonObject(FormattingConstants.POSITION), indentation, workers); } } private void modifyEndpoints(JsonObject node, String indentation) { if (node.has("endpointNodes")) { JsonArray endpointNodes = node.getAsJsonArray("endpointNodes"); iterateAndFormatBlockStatements(node.getAsJsonObject(FormattingConstants.POSITION), indentation, endpointNodes); } } private void modifyPatternClauses(JsonObject node, String indentation) { if (node.has("patternClauses")) { JsonArray patternClauses = node.getAsJsonArray("patternClauses"); for (JsonElement patternClause : patternClauses) { JsonObject patternFormatConfig = this.getFormattingConfig(1, 0, this.getWhiteSpaceCount(indentation), true, this.getWhiteSpaceCount(indentation), false); patternClause.getAsJsonObject().add(FormattingConstants.FORMATTING_CONFIG, patternFormatConfig); } } } private void modifyVariableReferences(JsonObject formatConfig, String indentation, JsonArray variableReferences) { for (int i = 0; i < variableReferences.size(); i++) { JsonObject memberType = variableReferences.get(i).getAsJsonObject(); JsonObject memberTypeFormatConfig; if (i == 0) { memberTypeFormatConfig = this.getFormattingConfig(0, 0, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), false, this.getWhiteSpaceCount(indentation), false); } else { memberTypeFormatConfig = this.getFormattingConfig(0, 1, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), false, this.getWhiteSpaceCount(indentation), false); } memberType.add(FormattingConstants.FORMATTING_CONFIG, memberTypeFormatConfig); } } private void iterateAndFormatBlockStatements(JsonObject formatConfig, String indentation, JsonArray blockStatementNodes) { for (int i = 0; i < blockStatementNodes.size(); i++) { JsonObject endpointNode = blockStatementNodes.get(i).getAsJsonObject(); JsonObject endpointFormatConfig; if (i == 0) { endpointFormatConfig = this.getFormattingConfig(1, 0, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), true, this.getWhiteSpaceCount(indentation), false); } else { endpointFormatConfig = this.getFormattingConfig(2, 0, formatConfig.get(FormattingConstants.START_COLUMN).getAsInt(), true, this.getWhiteSpaceCount(indentation), false); } endpointNode.add(FormattingConstants.FORMATTING_CONFIG, endpointFormatConfig); } } private void iterateAndFormatMembers(String indentation, JsonArray members) { for (int i = 0; i < members.size(); i++) { JsonObject member = members.get(i).getAsJsonObject(); JsonObject memberFormatConfig; if (i == 0) { memberFormatConfig = this.getFormattingConfig(0, 0, 0, false, this.getWhiteSpaceCount(indentation), true); } else { memberFormatConfig = this.getFormattingConfig(0, 1, 0, false, this.getWhiteSpaceCount(indentation), true); } member.add(FormattingConstants.FORMATTING_CONFIG, memberFormatConfig); } } private String getWhiteSpaces(int column) { StringBuilder whiteSpaces = new StringBuilder(); for (int i = 0; i <= (column - 1); i++) { whiteSpaces.append(" "); } return whiteSpaces.toString(); } private String getNewLines(int column) { StringBuilder newLines = new StringBuilder(); for (int i = 0; i < column; i++) { newLines.append("\n"); } return newLines.toString(); } private int getWhiteSpaceCount(String ws) { return ws.length(); } private List<String> tokenizer(String text) { List<String> tokens = new ArrayList<>(); StringBuilder comment = new StringBuilder(); for (int i = 0; i < text.length(); i++) { String character = text.charAt(i) + ""; if (!character.contains("\n")) { comment.append(text.charAt(i)); } else { if (!comment.toString().trim().equals("")) { tokens.add(comment.toString().trim()); comment = new StringBuilder(); } tokens.add(character); } if (i == (text.length() - 1) && !comment.toString().trim().equals("")) { tokens.add(comment.toString().trim()); comment = new StringBuilder(); } } return tokens; } private String getTextFromTokens(List<String> tokens, String indent) { StringBuilder text = new StringBuilder(); for (String token : tokens) { if (!token.contains("\n")) { text.append(indent != null ? indent + token : token); } else { text.append(token); } } return indent != null ? (text + indent) : text.toString(); } private void preserveHeight(JsonArray ws, String indent) { for (int i = 0; i < ws.size(); i++) { if (ws.get(i).isJsonObject()) { preserveHeightForWS(ws.get(i).getAsJsonObject(), indent); } } } private void preserveHeightForWS(JsonObject ws, String indent) { if (ws.has(FormattingConstants.WS) && (ws.get(FormattingConstants.WS).getAsString().trim().length() > 0 || ws.get(FormattingConstants.WS).getAsString().contains("\n"))) { List<String> tokens = this.tokenizer(ws.get(FormattingConstants.WS).getAsString()); ws.addProperty(FormattingConstants.WS, this.getTextFromTokens(tokens, indent)); } } private boolean noHeightAvailable(String ws) { return ws.trim().length() <= 0 && !ws.contains("\n"); } private boolean noNewLine(String text) { return !text.contains("\n"); } private int findIndex(JsonObject node) { int index = -1; JsonObject parent = node.getAsJsonObject("parent"); for (Map.Entry<String, JsonElement> entry : parent.entrySet()) { if (entry.getValue().isJsonArray() && !entry.getKey().equals(FormattingConstants.WS)) { for (int i = 0; i < entry.getValue().getAsJsonArray().size(); i++) { JsonElement element = entry.getValue().getAsJsonArray().get(i); if (element.isJsonObject() && element.getAsJsonObject().has("id") && element.getAsJsonObject() .get("id").getAsString().equals(node.get("id").getAsString())) { index = i; } } } } return index; } private void skipFormatting(JsonObject node, boolean doSkip) { // Add skipFormatting field as a property to the node. node.addProperty(FormattingConstants.SKIP_FORMATTING, doSkip); for (Map.Entry<String, JsonElement> child : node.entrySet()) { // If child element is not parent, position or ws continue. if (!child.getKey().equals("parent") && !child.getKey().equals(FormattingConstants.POSITION) && !child.getKey().equals(FormattingConstants.WS)) { // If child is a object and has a kind, do skip formatting // else if child is a array iterate and skip formatting for child items. if (child.getValue().isJsonObject() && child.getValue().getAsJsonObject().has("kind")) { skipFormatting(child.getValue().getAsJsonObject(), doSkip); } else if (child.getValue().isJsonArray()) { for (int i = 0; i < child.getValue().getAsJsonArray().size(); i++) { JsonElement childItem = child.getValue().getAsJsonArray().get(i); if (childItem.isJsonObject() && childItem.getAsJsonObject().has("kind")) { skipFormatting(childItem.getAsJsonObject(), doSkip); } } } } } } private JsonObject getFormattingConfig(int newLineCount, int spacesCount, int startColumn, boolean doIndent, int indentedStartColumn, boolean userParentIndentation) { JsonObject formattingConfig = new JsonObject(); formattingConfig.addProperty(FormattingConstants.NEW_LINE_COUNT, newLineCount); formattingConfig.addProperty(FormattingConstants.SPACE_COUNT, spacesCount); formattingConfig.addProperty(FormattingConstants.START_COLUMN, startColumn); formattingConfig.addProperty(FormattingConstants.DO_INDENT, doIndent); formattingConfig.addProperty(FormattingConstants.INDENTED_START_COLUMN, indentedStartColumn); formattingConfig.addProperty(FormattingConstants.USE_PARENT_INDENTATION, userParentIndentation); return formattingConfig; } private String getIndentation(JsonObject formatConfig, boolean addSpaces) { String indentation = formatConfig.get(FormattingConstants.DO_INDENT).getAsBoolean() ? (this.getWhiteSpaces(formatConfig.get(FormattingConstants.START_COLUMN).getAsInt()) + FormattingConstants.SPACE_TAB) : this.getWhiteSpaces(formatConfig.get(FormattingConstants.START_COLUMN).getAsInt()); // If add space is true add spaces to the // indentation as provided by the format config return addSpaces ? this.getWhiteSpaces(formatConfig.get(FormattingConstants.SPACE_COUNT).getAsInt()) + indentation : indentation; } private String getParentIndentation(JsonObject formatConfig) { return formatConfig.get(FormattingConstants.DO_INDENT).getAsBoolean() ? this.getWhiteSpaces(formatConfig.get(FormattingConstants.INDENTED_START_COLUMN).getAsInt()) + FormattingConstants.SPACE_TAB : this.getWhiteSpaces(formatConfig.get(FormattingConstants.INDENTED_START_COLUMN).getAsInt()); } }