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 9241f0f3855e6ebdc35ae1b70bfef0cc4b893b77 Author: Josh Tynjala <[email protected]> AuthorDate: Wed Sep 27 14:38:48 2023 -0700 ASTokenFormatter: fix some issues with unary and arithmetic operators --- .../apache/royale/formatter/ASTokenFormatter.java | 57 +++++- .../royale/formatter/TestArithmeticOperators.java | 200 +++++++++++++++++++ .../royale/formatter/TestDecrementOperator.java | 176 ++++++++++++++++ .../royale/formatter/TestIncrementOperator.java | 222 +++++++++++++++++++++ 4 files changed, 644 insertions(+), 11 deletions(-) diff --git a/formatter/src/main/java/org/apache/royale/formatter/ASTokenFormatter.java b/formatter/src/main/java/org/apache/royale/formatter/ASTokenFormatter.java index 8fd808a28..30fa3c9f4 100644 --- a/formatter/src/main/java/org/apache/royale/formatter/ASTokenFormatter.java +++ b/formatter/src/main/java/org/apache/royale/formatter/ASTokenFormatter.java @@ -449,7 +449,7 @@ public class ASTokenFormatter extends BaseTokenFormatter { } case ASTokenTypes.TOKEN_OPERATOR_PLUS: case ASTokenTypes.TOKEN_OPERATOR_MINUS: { - boolean isUnary = checkTokenBeforeUnaryOperator(prevTokenNotComment); + boolean isUnary = checkTokenBeforePossibleUnaryOperator(prevTokenNotComment); if (!isUnary && settings.insertSpaceBeforeAndAfterBinaryOperators) { requiredSpace = true; } @@ -709,6 +709,10 @@ public class ASTokenFormatter extends BaseTokenFormatter { if (controlFlowParenStack <= 0) { endIndentedStatement(); inControlFlowStatement = false; + if (!blockStack.isEmpty()) { + BlockStackItem stackItem = blockStack.get(blockStack.size() - 1); + stackItem.controlFlowEnd = token.getEnd(); + } controlFlowParenStack = 0; blockOpenPending = true; if (nextToken != null && nextToken.getType() == ASTokenTypes.TOKEN_SEMICOLON) { @@ -735,9 +739,9 @@ public class ASTokenFormatter extends BaseTokenFormatter { } case ASTokenTypes.TOKEN_OPERATOR_INCREMENT: case ASTokenTypes.TOKEN_OPERATOR_DECREMENT: { - if (!inControlFlowStatement && prevToken != null - && prevToken.getType() != ASTokenTypes.TOKEN_SEMICOLON && nextToken != null - && nextToken.getType() != ASTokenTypes.TOKEN_SEMICOLON) { + if (!inControlFlowStatement + && !checkTokenBeforePossibleUnaryOperator(prevTokenNotComment) + && !checkTokenAfterPossibleUnaryOperator(nextTokenNotComment)) { requiredSpace = true; } break; @@ -986,7 +990,7 @@ public class ASTokenFormatter extends BaseTokenFormatter { } case ASTokenTypes.TOKEN_OPERATOR_PLUS: case ASTokenTypes.TOKEN_OPERATOR_MINUS: { - boolean isUnary = checkTokenBeforeUnaryOperator(prevTokenNotComment); + boolean isUnary = checkTokenBeforePossibleUnaryOperator(prevTokenNotComment); if (!isUnary && settings.insertSpaceBeforeAndAfterBinaryOperators && !skipWhitespaceBeforeSemicolon) { requiredSpace = true; @@ -1452,12 +1456,42 @@ public class ASTokenFormatter extends BaseTokenFormatter { && nextToken.getType() == ASTokenTypes.TOKEN_TYPED_LITERAL_CLOSE)); } - private boolean checkTokenBeforeUnaryOperator(IASToken token) { - return (token instanceof ASToken) ? ((ASToken) token).isOperator() - || token.getType() == ASTokenTypes.TOKEN_SQUARE_OPEN || token.getType() == ASTokenTypes.TOKEN_PAREN_OPEN - || token.getType() == ASTokenTypes.TOKEN_BLOCK_OPEN || token.getType() == ASTokenTypes.TOKEN_SEMICOLON - || token.getType() == ASTokenTypes.TOKEN_KEYWORD_RETURN || token.getType() == ASTokenTypes.TOKEN_COMMA - || token.getType() == ASTokenTypes.TOKEN_COLON : (token == null); + private boolean checkTokenBeforePossibleUnaryOperator(IASToken token) { + if (token instanceof ASToken) { + if (token.getType() == ASTokenTypes.TOKEN_PAREN_CLOSE && !blockStack.isEmpty()) { + BlockStackItem stackItem = blockStack.get(blockStack.size() - 1); + if (stackItem.controlFlowEnd == token.getEnd()) { + return true; + } + } + return ((ASToken) token).isOperator() + || token.getType() == ASTokenTypes.TOKEN_SQUARE_OPEN + // square close may not indicate unary operator: arr[x] + 3 + || token.getType() == ASTokenTypes.TOKEN_PAREN_OPEN + // paren close may not indicate unary operator: (1 + 2) + 3 + || token.getType() == ASTokenTypes.TOKEN_BLOCK_OPEN + // however, block close is more like semicolon than square/paren close + || token.getType() == ASTokenTypes.TOKEN_BLOCK_CLOSE + || token.getType() == ASTokenTypes.TOKEN_SEMICOLON + || token.getType() == ASTokenTypes.TOKEN_KEYWORD_RETURN + || token.getType() == ASTokenTypes.TOKEN_COMMA + || token.getType() == ASTokenTypes.TOKEN_COLON; + } + return token == null; + } + + private boolean checkTokenAfterPossibleUnaryOperator(IASToken token) { + if (token instanceof ASToken) { + return ((ASToken) token).isOperator() + || token.getType() == ASTokenTypes.TOKEN_SQUARE_CLOSE + // paren open may not indicate unary operator: 1 + (2 + 3) + || token.getType() == ASTokenTypes.TOKEN_PAREN_CLOSE + || token.getType() == ASTokenTypes.TOKEN_BLOCK_OPEN + || token.getType() == ASTokenTypes.TOKEN_BLOCK_CLOSE + || token.getType() == ASTokenTypes.TOKEN_SEMICOLON + || token.getType() == ASTokenTypes.TOKEN_COMMA; + } + return token == null; } private boolean isInForStatement(List<BlockStackItem> blockStack) { @@ -1563,6 +1597,7 @@ public class ASTokenFormatter extends BaseTokenFormatter { public boolean braces = true; public boolean indentedStatement = false; public boolean controlFlow = false; + public int controlFlowEnd = -1; } private static class ObjectLiteralBlockStackItem extends BlockStackItem { diff --git a/formatter/src/test/java/org/apache/royale/formatter/TestArithmeticOperators.java b/formatter/src/test/java/org/apache/royale/formatter/TestArithmeticOperators.java index 65aef259a..3e6525bac 100644 --- a/formatter/src/test/java/org/apache/royale/formatter/TestArithmeticOperators.java +++ b/formatter/src/test/java/org/apache/royale/formatter/TestArithmeticOperators.java @@ -223,4 +223,204 @@ public class TestArithmeticOperators extends BaseFormatterTests { // @formatter:on result); } + + @Test + public void testAdditionOperatorWithParentheses1() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceBeforeAndAfterBinaryOperators = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "(a+b)+c;", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "(a + b) + c;", + // @formatter:on + result); + } + + @Test + public void testAdditionOperatorWithParentheses2() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceBeforeAndAfterBinaryOperators = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "a+(b+c);", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "a + (b + c);", + // @formatter:on + result); + } + + @Test + public void testSubtractionOperatorWithParentheses1() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceBeforeAndAfterBinaryOperators = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "(a-b)-c;", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "(a - b) - c;", + // @formatter:on + result); + } + + @Test + public void testSubtractionOperatorWithParentheses2() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceBeforeAndAfterBinaryOperators = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "a-(b-c);", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "a - (b - c);", + // @formatter:on + result); + } + + @Test + public void testMultiplicationOperatorWithParentheses1() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceBeforeAndAfterBinaryOperators = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "(a*b)*c;", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "(a * b) * c;", + // @formatter:on + result); + } + + @Test + public void testMultiplicationOperatorWithParentheses2() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceBeforeAndAfterBinaryOperators = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "a*(b*c);", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "a * (b * c);", + // @formatter:on + result); + } + + @Test + public void testDivisionOperatorWithParentheses1() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceBeforeAndAfterBinaryOperators = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "(a/b)/c;", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "(a / b) / c;", + // @formatter:on + result); + } + + @Test + public void testDivisionOperatorWithParentheses2() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceBeforeAndAfterBinaryOperators = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "a/(b/c);", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "a / (b / c);", + // @formatter:on + result); + } + + @Test + public void testModuloOperatorWithParentheses1() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceBeforeAndAfterBinaryOperators = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "(a%b)%c;", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "(a % b) % c;", + // @formatter:on + result); + } + + @Test + public void testModuloOperatorWithParentheses2() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceBeforeAndAfterBinaryOperators = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "a%(b%c);", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "a % (b % c);", + // @formatter:on + result); + } } diff --git a/formatter/src/test/java/org/apache/royale/formatter/TestDecrementOperator.java b/formatter/src/test/java/org/apache/royale/formatter/TestDecrementOperator.java index 9833495a9..0a744d872 100644 --- a/formatter/src/test/java/org/apache/royale/formatter/TestDecrementOperator.java +++ b/formatter/src/test/java/org/apache/royale/formatter/TestDecrementOperator.java @@ -63,4 +63,180 @@ public class TestDecrementOperator extends BaseFormatterTests { // @formatter:on result); } + + @Test + public void testAfterWithPrecedingComment() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "// comment\n" + + "i--;", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "// comment\n" + + "i--;", + // @formatter:on + result); + } + + @Test + public void testAfterWithFollowingComment() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "i--;\n" + + "// comment", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "i--;\n" + + "// comment", + // @formatter:on + result); + } + + @Test + public void testAfterInsideBlock() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "{\n" + + "\ti--;\n" + + "}", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "{\n" + + "\ti--;\n" + + "}", + // @formatter:on + result); + } + + @Test + public void testAfterInsideParentheses() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "(i--);", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "(i--);", + // @formatter:on + result); + } + + @Test + public void testBeforeWithPrecedingComment() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "// comment\n" + + "--i;", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "// comment\n" + + "--i;", + // @formatter:on + result); + } + + @Test + public void testBeforeWithFollowingComment() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "--i;\n" + + "// comment", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "--i;\n" + + "// comment", + // @formatter:on + result); + } + + @Test + public void testBeforeInsideBlock() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "{\n" + + "\t--i;\n" + + "}", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "{\n" + + "\t--i;\n" + + "}", + // @formatter:on + result); + } + + @Test + public void testBeforeInsideParentheses() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "(--i);", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "(--i);", + // @formatter:on + result); + } } diff --git a/formatter/src/test/java/org/apache/royale/formatter/TestIncrementOperator.java b/formatter/src/test/java/org/apache/royale/formatter/TestIncrementOperator.java index 66573ab44..eddfe81d6 100644 --- a/formatter/src/test/java/org/apache/royale/formatter/TestIncrementOperator.java +++ b/formatter/src/test/java/org/apache/royale/formatter/TestIncrementOperator.java @@ -63,4 +63,226 @@ public class TestIncrementOperator extends BaseFormatterTests { // @formatter:on result); } + + @Test + public void testAfterWithPrecedingComment() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "// comment\n" + + "i++;", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "// comment\n" + + "i++;", + // @formatter:on + result); + } + + @Test + public void testAfterWithFollowingComment() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "i++;\n" + + "// comment", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "i++;\n" + + "// comment", + // @formatter:on + result); + } + + @Test + public void testAfterInsideBlock() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "{\n" + + "\ti++;\n" + + "}", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "{\n" + + "\ti++;\n" + + "}", + // @formatter:on + result); + } + + @Test + public void testAfterInsideParentheses() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "(i++);", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "(i++);", + // @formatter:on + result); + } + + @Test + public void testBeforeWithPrecedingComment() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "// comment\n" + + "++i;", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "// comment\n" + + "++i;", + // @formatter:on + result); + } + + @Test + public void testBeforeWithFollowingComment() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "++i;\n" + + "// comment", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "++i;\n" + + "// comment", + // @formatter:on + result); + } + + @Test + public void testBeforeInsideBlock() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "{\n" + + "\t++i;\n" + + "}", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "{\n" + + "\t++i;\n" + + "}", + // @formatter:on + result); + } + + @Test + public void testBeforeAfterBlock() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "{\n" + + "}\n" + + "++i;", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "{\n" + + "}\n" + + "++i;", + // @formatter:on + result); + } + + @Test + public void testBeforeInsideParentheses() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "(++i);", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "(++i);", + // @formatter:on + result); + } + + @Test + public void testBeforeAsStatementInsideIfWithoutBraces() { + FormatterSettings settings = new FormatterSettings(); + settings.insertSpaceAfterKeywordsInControlFlowStatements = true; + settings.placeOpenBraceOnNewLine = true; + settings.insertSpaces = false; + ASTokenFormatter formatter = new ASTokenFormatter(settings); + String result = formatter.format("file.as", + // @formatter:off + "if (condition)\n" + + "\t++i;", + // @formatter:on + problems + ); + assertEquals( + // @formatter:off + "if (condition)\n" + + "\t++i;", + // @formatter:on + result); + } }
