You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by jo...@apache.org on 2021/10/28 21:42:01 UTC
[royale-compiler] 02/02: formatter: MXML attribute whitespace
options
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 <jo...@apache.org>
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