This is an automated email from the ASF dual-hosted git repository. joshtynjala pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/royale-compiler.git
commit 16ffb9e46941ccb7c1d48df6c5f4bae21bd47728 Author: Josh Tynjala <[email protected]> AuthorDate: Thu Oct 28 14:41:39 2021 -0700 formatter: MXML attribute whitespace options --- .../org/apache/royale/formatter/FORMATTER.java | 103 +++++++++++++-------- .../royale/formatter/config/Configuration.java | 36 +++++++ .../org/apache/royale/formatter/TestMXMLTag.java | 60 ++++++++++++ 3 files changed, 160 insertions(+), 39 deletions(-) diff --git a/formatter/src/main/java/org/apache/royale/formatter/FORMATTER.java b/formatter/src/main/java/org/apache/royale/formatter/FORMATTER.java index 132c246..9f8d1bc 100644 --- a/formatter/src/main/java/org/apache/royale/formatter/FORMATTER.java +++ b/formatter/src/main/java/org/apache/royale/formatter/FORMATTER.java @@ -120,6 +120,8 @@ public class FORMATTER { public Semicolons semicolons = Semicolons.INSERT; public boolean ignoreProblems = false; public boolean collapseEmptyBlocks = false; + public boolean mxmlAlignAttributes = false; + public boolean mxmlInsertNewLineBetweenAttributes = false; private ProblemQuery problems; private List<File> inputFiles = new ArrayList<File>(); @@ -324,6 +326,8 @@ public class FORMATTER { insertSpaceBeforeAndAfterBinaryOperators = configuration.getInsertSpaceBeforeAndAfterBinaryOperators(); insertSpaceAtStartOfLineComment = configuration.getInsertSpaceAtStartOfLineComment(); insertSpaces = configuration.getInsertSpaces(); + mxmlInsertNewLineBetweenAttributes = configuration.getMxmlInsertNewLineBetweenAttributes(); + mxmlAlignAttributes = configuration.getMxmlAlignAttributes(); listChangedFiles = configuration.getListFiles(); maxPreserveNewLines = configuration.getMaxPreserveNewLines(); placeOpenBraceOnNewLine = configuration.getPlaceOpenBraceOnNewLine(); @@ -1573,15 +1577,37 @@ public class FORMATTER { return Math.max(0, indent - 1); } + private String getIndent() { + if (insertSpaces) { + String result = ""; + for (int j = 0; j < tabSize; j++) { + result += " "; + } + return result; + } + return "\t"; + } + + private String getAttributeIndent(IMXMLToken openTagToken) { + if (!mxmlAlignAttributes) { + return getIndent(); + } + int indentSize = openTagToken.getText().length() + 1; + String result = ""; + while (indentSize >= tabSize) { + result += getIndent(); + indentSize -= tabSize; + } + for (int i = 0; i < indentSize; i++) { + result += " "; + } + return result; + } + private void appendIndent(StringBuilder builder, int indent) { + String indentString = getIndent(); for (int i = 0; i < indent; i++) { - if (insertSpaces) { - for (int j = 0; j < tabSize; j++) { - builder.append(" "); - } - } else { - builder.append("\t"); - } + builder.append(indentString); } } @@ -1634,8 +1660,7 @@ public class FORMATTER { IMXMLToken[] originalTokens = null; try { originalTokens = mxmlTokenizer.getTokens(textReader); - } - finally { + } finally { IOUtils.closeQuietly(textReader); IOUtils.closeQuietly(mxmlTokenizer); } @@ -1653,7 +1678,7 @@ public class FORMATTER { boolean requiredSpace = false; boolean inOpenTag = false; boolean inCloseTag = false; - boolean indentedAttributes = false; + String attributeIndent = ""; IMXMLToken prevToken = null; IMXMLToken prevTokenOrExtra = null; IMXMLToken token = null; @@ -1677,10 +1702,9 @@ public class FORMATTER { prevTokenOrExtra = token; continue; } else if (token.getType() == MXMLTokenTypes.TOKEN_WHITESPACE) { - if(elementStack.isEmpty() || !elementStack.get(elementStack.size() - 1).containsText) { + if (elementStack.isEmpty() || !elementStack.get(elementStack.size() - 1).containsText) { numRequiredNewLines = Math.max(numRequiredNewLines, countNewLinesInExtra(token)); - } - else { + } else { // if the parent element contains text, treat whitespace // the same as text, and don't reformat it // text is never reformatted because some components use it @@ -1734,12 +1758,13 @@ public class FORMATTER { case MXMLTokenTypes.TOKEN_OPEN_TAG_START: { inOpenTag = true; // if the parent contains text, children should be the same - boolean containsText = !elementStack.isEmpty() && elementStack.get(elementStack.size() - 1).containsText; + boolean containsText = !elementStack.isEmpty() + && elementStack.get(elementStack.size() - 1).containsText; elementStack.add(new ElementStackItem(token, token.getText().substring(1), containsText)); break; } case MXMLTokenTypes.TOKEN_CLOSE_TAG_START: { - if(elementStack.isEmpty() || !elementStack.get(elementStack.size() - 1).containsText) { + if (elementStack.isEmpty() || !elementStack.get(elementStack.size() - 1).containsText) { indent = decreaseIndent(indent); } inCloseTag = true; @@ -1753,12 +1778,11 @@ public class FORMATTER { if (prevToken != null) { if (numRequiredNewLines > 0) { - if (inOpenTag && token.getType() != MXMLTokenTypes.TOKEN_OPEN_TAG_START && !indentedAttributes) { - indentedAttributes = true; - indent = increaseIndent(indent); - } appendNewLines(builder, numRequiredNewLines); appendIndent(builder, indent); + if (attributeIndent.length() > 0) { + builder.append(attributeIndent); + } } else if (requiredSpace) { builder.append(' '); } @@ -1798,6 +1822,7 @@ public class FORMATTER { case MXMLTokenTypes.TOKEN_OPEN_TAG_START: { if (nextToken != null && nextToken.getType() != MXMLTokenTypes.TOKEN_TAG_END && nextToken.getType() != MXMLTokenTypes.TOKEN_EMPTY_TAG_END) { + attributeIndent = getAttributeIndent(token); requiredSpace = true; } break; @@ -1808,43 +1833,43 @@ public class FORMATTER { if (!element.containsText) { element.containsText = elementContainsText(tokens, i + 1, element.token); } - if(elementStack.isEmpty() || !elementStack.get(elementStack.size() - 1).containsText) { + if (elementStack.isEmpty() || !elementStack.get(elementStack.size() - 1).containsText) { indent = increaseIndent(indent); } - } - else { - if(elementStack.isEmpty() || !elementStack.get(elementStack.size() - 1).containsText) { + } else { + if (elementStack.isEmpty() || !elementStack.get(elementStack.size() - 1).containsText) { numRequiredNewLines = Math.max(numRequiredNewLines, 1); } } inOpenTag = false; - if (indentedAttributes) { - indentedAttributes = false; - indent = decreaseIndent(indent); - } + attributeIndent = ""; inCloseTag = false; break; } case MXMLTokenTypes.TOKEN_EMPTY_TAG_END: { if (inOpenTag) { elementStack.remove(elementStack.size() - 1); - } - else { - if(elementStack.isEmpty() || !elementStack.get(elementStack.size() - 1).containsText) { + } else { + if (elementStack.isEmpty() || !elementStack.get(elementStack.size() - 1).containsText) { numRequiredNewLines = Math.max(numRequiredNewLines, 1); } } inOpenTag = false; // no need to change nested indent after this tag // however, we may need to remove attribute indent - if (indentedAttributes) { - indentedAttributes = false; - indent = decreaseIndent(indent); - } + attributeIndent = ""; // we shouldn't find an empty close tag, but clear flag anyway inCloseTag = false; break; } + case MXMLTokenTypes.TOKEN_STRING: { + if (inOpenTag && mxmlInsertNewLineBetweenAttributes && nextToken != null + && nextToken.getType() != MXMLTokenTypes.TOKEN_TAG_END + && nextToken.getType() != MXMLTokenTypes.TOKEN_EMPTY_TAG_END) { + numRequiredNewLines = Math.max(numRequiredNewLines, 1); + } + break; + } } prevToken = token; @@ -1857,11 +1882,11 @@ public class FORMATTER { private boolean elementContainsText(List<IMXMLToken> tokens, int startIndex, IMXMLToken openTagToken) { ArrayList<IMXMLToken> elementStack = new ArrayList<IMXMLToken>(); elementStack.add(openTagToken); - for(int i = startIndex; i < tokens.size(); i++) { + for (int i = startIndex; i < tokens.size(); i++) { IMXMLToken token = tokens.get(i); - switch(token.getType()) { + switch (token.getType()) { case MXMLTokenTypes.TOKEN_TEXT: - if(elementStack.size() == 1) { + if (elementStack.size() == 1) { return true; } break; @@ -1870,13 +1895,13 @@ public class FORMATTER { break; case MXMLTokenTypes.TOKEN_EMPTY_TAG_END: elementStack.remove(elementStack.size() - 1); - if(elementStack.size() == 0) { + if (elementStack.size() == 0) { return false; } break; case MXMLTokenTypes.TOKEN_CLOSE_TAG_START: elementStack.remove(elementStack.size() - 1); - if(elementStack.size() == 0) { + if (elementStack.size() == 0) { return false; } break; diff --git a/formatter/src/main/java/org/apache/royale/formatter/config/Configuration.java b/formatter/src/main/java/org/apache/royale/formatter/config/Configuration.java index 440be23..dd5c0ac 100644 --- a/formatter/src/main/java/org/apache/royale/formatter/config/Configuration.java +++ b/formatter/src/main/java/org/apache/royale/formatter/config/Configuration.java @@ -471,4 +471,40 @@ public class Configuration { { this.ignoreParsingProblems = b; } + + // + // 'mxml-align-attributes' option + // + + private boolean mxmlAlignAttributes = false; + + public boolean getMxmlAlignAttributes() + { + return mxmlAlignAttributes; + } + + @Config(advanced = true) + @Mapping("mxml-align-attributes") + public void setMxmlAlignAttributes(ConfigurationValue cv, boolean b) + { + this.mxmlAlignAttributes = b; + } + + // + // 'mxml-insert-new-line-attributes' option + // + + private boolean mxmlInsertNewLineBetweenAttributes = false; + + public boolean getMxmlInsertNewLineBetweenAttributes() + { + return mxmlInsertNewLineBetweenAttributes; + } + + @Config(advanced = true) + @Mapping("mxml-insert-new-line-attributes") + public void setMxmlInsertNewLineBetweenAttributes(ConfigurationValue cv, boolean b) + { + this.mxmlInsertNewLineBetweenAttributes = b; + } } diff --git a/formatter/src/test/java/org/apache/royale/formatter/TestMXMLTag.java b/formatter/src/test/java/org/apache/royale/formatter/TestMXMLTag.java index 8096322..20c85f7 100644 --- a/formatter/src/test/java/org/apache/royale/formatter/TestMXMLTag.java +++ b/formatter/src/test/java/org/apache/royale/formatter/TestMXMLTag.java @@ -211,4 +211,64 @@ public class TestMXMLTag extends BaseFormatterTests { // @formatter:on result); } + + @Test + public void testMultipleAttributes() { + FORMATTER formatter = new FORMATTER(); + formatter.insertSpaces = false; + formatter.mxmlInsertNewLineBetweenAttributes = false; + formatter.mxmlAlignAttributes = false; + String result = formatter.formatMXMLText( + // @formatter:off + "<s:Tag one=\"1\" two=\"2\"/>", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "<s:Tag one=\"1\" two=\"2\"/>", + // @formatter:on + result); + } + + @Test + public void testMultipleAttributesOnePerLine() { + FORMATTER formatter = new FORMATTER(); + formatter.insertSpaces = false; + formatter.mxmlInsertNewLineBetweenAttributes = true; + formatter.mxmlAlignAttributes = false; + String result = formatter.formatMXMLText( + // @formatter:off + "<s:Tag one=\"1\" two=\"2\"/>", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "<s:Tag one=\"1\"\n" + + "\ttwo=\"2\"/>", + // @formatter:on + result); + } + + @Test + public void testMXMLAlignAttributes() { + FORMATTER formatter = new FORMATTER(); + formatter.insertSpaces = false; + formatter.mxmlInsertNewLineBetweenAttributes = true; + formatter.mxmlAlignAttributes = true; + String result = formatter.formatMXMLText( + // @formatter:off + "<s:Tag one=\"1\" two=\"2\" three=\"3\"/>", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "<s:Tag one=\"1\"\n" + + "\t two=\"2\"\n" + + "\t three=\"3\"/>", + // @formatter:on + result); + } } \ No newline at end of file
