You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2021/07/14 13:10:21 UTC
[groovy] 01/09: GROOVY-9272: Support switch expression
This is an automated email from the ASF dual-hosted git repository.
paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit b4298c727089e790782a6a995208fdf8cb223071
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sun Jun 27 22:21:32 2021 +0800
GROOVY-9272: Support switch expression
---
src/antlr/GroovyLexer.g4 | 1 +
src/antlr/GroovyParser.g4 | 34 ++-
.../apache/groovy/parser/antlr4/AstBuilder.java | 309 ++++++++++++++++++++-
.../groovy/parser/antlr4/SemanticPredicates.java | 3 +-
.../core/SwitchExpression_01x.groovy} | 32 +--
.../core/SwitchExpression_02x.groovy} | 35 +--
.../core/SwitchExpression_03x.groovy} | 32 +--
.../core/SwitchExpression_04x.groovy} | 33 +--
.../core/SwitchExpression_05x.groovy} | 31 +--
.../core/SwitchExpression_06x.groovy} | 35 +--
.../core/SwitchExpression_07x.groovy} | 42 ++-
.../core/SwitchExpression_08x.groovy} | 45 ++-
.../core/SwitchExpression_09x.groovy} | 32 +--
.../core/SwitchExpression_10x.groovy} | 58 ++--
.../core/SwitchExpression_11x.groovy | 111 ++++++++
.../core/SwitchExpression_12x.groovy} | 37 +--
.../core/SwitchExpression_13x.groovy} | 30 +-
.../core/SwitchExpression_14x.groovy | 79 ++++++
.../core/SwitchExpression_15x.groovy} | 35 +--
.../core/SwitchExpression_16x.groovy} | 39 ++-
.../core/SwitchExpression_17x.groovy} | 37 +--
.../core/SwitchExpression_18x.groovy} | 33 +--
.../core/SwitchExpression_19x.groovy} | 33 +--
.../core/SwitchExpression_20x.groovy} | 39 ++-
.../core/SwitchExpression_21x.groovy} | 39 ++-
.../core/SwitchExpression_22x.groovy} | 36 +--
.../core/SwitchExpression_23x.groovy} | 40 ++-
.../core/SwitchExpression_24x.groovy} | 49 ++--
.../fail/SwitchExpression_01x.groovy} | 31 +--
.../fail/SwitchExpression_02x.groovy} | 31 +--
.../fail/SwitchExpression_03x.groovy} | 32 +--
.../fail/SwitchExpression_04x.groovy} | 32 +--
.../fail/SwitchExpression_05x.groovy} | 31 +--
.../fail/SwitchExpression_06x.groovy} | 31 +--
.../fail/SwitchExpression_07x.groovy} | 31 +--
.../fail/SwitchExpression_08x.groovy} | 31 +--
src/test/groovy/MethodInBadPositionTest.groovy | 2 +-
.../groovy/parser/antlr4/GroovyParserTest.groovy | 47 +++-
.../groovy/parser/antlr4/SyntaxErrorTest.groovy | 13 +-
.../apache/groovy/parser/antlr4/TestUtils.groovy | 5 +-
.../console/ui/text/SmartDocumentFilter.java | 3 +-
.../groovy-ginq/src/spec/doc/ginq-userguide.adoc | 7 +
.../test/org/apache/groovy/ginq/GinqTest.groovy | 16 ++
43 files changed, 925 insertions(+), 777 deletions(-)
diff --git a/src/antlr/GroovyLexer.g4 b/src/antlr/GroovyLexer.g4
index 53532b1..2c58768 100644
--- a/src/antlr/GroovyLexer.g4
+++ b/src/antlr/GroovyLexer.g4
@@ -417,6 +417,7 @@ fragment
BOOLEAN : 'boolean';
BREAK : 'break';
+YIELD : 'yield';
fragment
BYTE : 'byte';
diff --git a/src/antlr/GroovyParser.g4 b/src/antlr/GroovyParser.g4
index 07f1fae..3faf7ad 100644
--- a/src/antlr/GroovyParser.g4
+++ b/src/antlr/GroovyParser.g4
@@ -45,6 +45,7 @@ options {
}
@members {
+ private int inSwitchExpressionLevel = 0;
public static class GroovyParserRuleContext extends ParserRuleContext implements NodeMetaDataHandler {
private Map metaDataMap = null;
@@ -614,6 +615,11 @@ breakStatement
identifier?
;
+yieldStatement
+ : YIELD
+ expression
+ ;
+
tryCatchStatement
: TRY resources? nls block
(nls catchClause)*
@@ -634,6 +640,8 @@ statement
| THROW expression #throwStmtAlt
| breakStatement #breakStmtAlt
| continueStatement #continueStmtAlt
+ | { inSwitchExpressionLevel > 0 }?
+ yieldStatement #yieldStmtAlt
| identifier COLON nls statement #labeledStmtAlt
| assertStatement #assertStmtAlt
| localVariableDeclaration #localVariableDeclarationStmtAlt
@@ -717,7 +725,7 @@ expressionInPar
;
expressionList[boolean canSpread]
- : expressionListElement[$canSpread] (COMMA expressionListElement[$canSpread])*
+ : expressionListElement[$canSpread] (COMMA nls expressionListElement[$canSpread])*
;
expressionListElement[boolean canSpread]
@@ -737,6 +745,26 @@ postfixExpression
: pathExpression op=(INC | DEC)?
;
+switchExpression
+@init {
+ inSwitchExpressionLevel++;
+}
+@after {
+ inSwitchExpressionLevel--;
+}
+ : SWITCH expressionInPar nls LBRACE nls switchBlockStatementExpressionGroup* nls RBRACE
+ ;
+
+switchBlockStatementExpressionGroup
+ : (switchExpressionLabel nls)+ blockStatements
+ ;
+
+switchExpressionLabel
+ : ( CASE expressionList[true]
+ | DEFAULT
+ ) ac=(ARROW | COLON)
+ ;
+
expression
// must come before postfixExpression to resovle the ambiguities between casting and call on parentheses expression, e.g. (int)(1 / 2)
: castParExpression castOperandExpression #castExprAlt
@@ -744,6 +772,8 @@ expression
// qualified names, array expressions, method invocation, post inc/dec
| postfixExpression #postfixExprAlt
+ | switchExpression #switchExprAlt
+
// ~(BNOT)/!(LNOT) (level 1)
| (BITNOT | NOT) nls expression #unaryNotExprAlt
@@ -1177,6 +1207,7 @@ identifier
// | DEF
| TRAIT
| AS
+ | YIELD
;
builtInType
@@ -1229,6 +1260,7 @@ keywords
| VAR
| VOLATILE
| WHILE
+ | YIELD
| NullLiteral
| BooleanLiteral
diff --git a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index 3505867..eea1e49 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -214,6 +214,7 @@ import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.CodeVisitorSupport;
import org.codehaus.groovy.ast.ConstructorNode;
import org.codehaus.groovy.ast.EnumConstantClassNode;
import org.codehaus.groovy.ast.FieldNode;
@@ -314,6 +315,13 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import static groovy.lang.Tuple.tuple;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ARROW;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.SwitchBlockStatementExpressionGroupContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.SwitchExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.SwitchExpressionContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.SwitchExpressionLabelContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.YieldStatementContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.YieldStmtAltContext;
import static org.apache.groovy.parser.antlr4.GroovyParser.ADD;
import static org.apache.groovy.parser.antlr4.GroovyParser.AS;
import static org.apache.groovy.parser.antlr4.GroovyParser.CASE;
@@ -339,11 +347,14 @@ import static org.apache.groovy.parser.antlr4.GroovyParser.STATIC;
import static org.apache.groovy.parser.antlr4.GroovyParser.SUB;
import static org.apache.groovy.parser.antlr4.GroovyParser.VAR;
import static org.apache.groovy.parser.antlr4.util.PositionConfigureUtils.configureAST;
+import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveVoid;
import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.closureX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
import static org.codehaus.groovy.classgen.asm.util.TypeUtil.isPrimitiveType;
-import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveVoid;
import static org.codehaus.groovy.runtime.DefaultGroovyMethods.asBoolean;
import static org.codehaus.groovy.runtime.DefaultGroovyMethods.last;
@@ -351,7 +362,6 @@ import static org.codehaus.groovy.runtime.DefaultGroovyMethods.last;
* Builds the AST from the parse tree generated by Antlr4.
*/
public class AstBuilder extends GroovyParserBaseVisitor<Object> {
-
public AstBuilder(final SourceUnit sourceUnit, final boolean groovydocEnabled, final boolean runtimeGroovydocEnabled) {
this.sourceUnit = sourceUnit;
this.moduleNode = new ModuleNode(sourceUnit);
@@ -1009,6 +1019,11 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
@Override
public ReturnStatement visitReturnStmtAlt(final ReturnStmtAltContext ctx) {
+ GroovyParserRuleContext gprc = switchExpressionRuleContextStack.peek();
+ if (gprc instanceof SwitchExpressionContext) {
+ throw createParsingFailedException("switch expression does not support `return`", ctx);
+ }
+
return configureAST(new ReturnStatement(asBoolean(ctx.expression())
? (Expression) this.visit(ctx.expression())
: ConstantExpression.EMPTY_EXPRESSION),
@@ -1037,6 +1052,11 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
throw createParsingFailedException("break statement is only allowed inside loops or switches", ctx);
}
+ GroovyParserRuleContext gprc = switchExpressionRuleContextStack.peek();
+ if (gprc instanceof SwitchExpressionContext) {
+ throw createParsingFailedException("switch expression does not support `break`", ctx);
+ }
+
String label = asBoolean(ctx.identifier())
? this.visitIdentifier(ctx.identifier())
: null;
@@ -1045,11 +1065,28 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
}
@Override
+ public ReturnStatement visitYieldStatement(YieldStatementContext ctx) {
+ ReturnStatement returnStatement = (ReturnStatement) returnS((Expression) this.visit(ctx.expression()));
+ returnStatement.putNodeMetaData(IS_YIELD_STATEMENT, true);
+ return configureAST(returnStatement, ctx);
+ }
+
+ @Override
+ public ReturnStatement visitYieldStmtAlt(YieldStmtAltContext ctx) {
+ return configureAST(this.visitYieldStatement(ctx.yieldStatement()), ctx);
+ }
+
+ @Override
public ContinueStatement visitContinueStatement(final ContinueStatementContext ctx) {
if (visitingLoopStatementCount == 0) {
throw createParsingFailedException("continue statement is only allowed inside loops", ctx);
}
+ GroovyParserRuleContext gprc = switchExpressionRuleContextStack.peek();
+ if (gprc instanceof SwitchExpressionContext) {
+ throw createParsingFailedException("switch expression does not support `continue`", ctx);
+ }
+
String label = asBoolean(ctx.identifier())
? this.visitIdentifier(ctx.identifier())
: null;
@@ -1058,6 +1095,238 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
}
+ @Override
+ public Expression visitSwitchExprAlt(SwitchExprAltContext ctx) {
+ return configureAST(this.visitSwitchExpression(ctx.switchExpression()), ctx);
+ }
+
+ /**
+ * <pre>
+ * switch(a) {
+ * case 0, 1 -> 'a';
+ * case 2 -> 'b';
+ * default -> 'z';
+ * }
+ * </pre>
+ * the above code will be transformed to:
+ * <pre>
+ * {->
+ * switch(a) {
+ * case 0:
+ * case 1: return 'a';
+ * case 2: return 'b';
+ * default: return 'z';
+ * }
+ * }()
+ * </pre>
+ *
+ * @param ctx the parse tree
+ * @return {@link MethodCallExpression} instance
+ */
+ @Override
+ public MethodCallExpression visitSwitchExpression(SwitchExpressionContext ctx) {
+ switchExpressionRuleContextStack.push(ctx);
+ try {
+ validateSwitchExpressionLabels(ctx);
+ List<Statement> statementList =
+ ctx.switchBlockStatementExpressionGroup().stream()
+ .map(e -> this.visitSwitchBlockStatementExpressionGroup(e))
+ .reduce(new LinkedList<>(), (r, e) -> {
+ r.addAll(e);
+ return r;
+ });
+
+ List<CaseStatement> caseStatementList = new LinkedList<>();
+ List<Statement> defaultStatementList = new LinkedList<>();
+
+ statementList.forEach(e -> {
+ if (e instanceof CaseStatement) {
+ caseStatementList.add((CaseStatement) e);
+ } else if (isTrue(e, IS_SWITCH_DEFAULT)) {
+ defaultStatementList.add(e);
+ }
+ });
+
+ int defaultStatementListSize = defaultStatementList.size();
+ if (defaultStatementListSize > 1) {
+ throw createParsingFailedException("switch expression should have only one default case, which should appear at last", defaultStatementList.get(0));
+ }
+
+ if (defaultStatementListSize > 0 && last(statementList) instanceof CaseStatement) {
+ throw createParsingFailedException("default case should appear at last", defaultStatementList.get(0));
+ }
+
+ SwitchStatement switchStatement = configureAST(
+ new SwitchStatement(
+ this.visitExpressionInPar(ctx.expressionInPar()),
+ caseStatementList,
+ defaultStatementListSize == 0 ? EmptyStatement.INSTANCE : defaultStatementList.get(0)
+ ),
+ ctx);
+
+ MethodCallExpression callClosure = callX(
+ configureAST(
+ closureX(null, createBlockStatement(switchStatement)),
+ ctx
+ ), "call");
+ callClosure.setImplicitThis(false);
+
+ return configureAST(callClosure, ctx);
+ } finally {
+ switchExpressionRuleContextStack.pop();
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public List<Statement> visitSwitchBlockStatementExpressionGroup(SwitchBlockStatementExpressionGroupContext ctx) {
+ int labelCnt = ctx.switchExpressionLabel().size();
+ List<Token> firstLabelHolder = new ArrayList<>(1);
+ final int[] arrowCntHolder = new int[1];
+
+ return (List<Statement>) ctx.switchExpressionLabel().stream()
+ .map(e -> (Object) this.visitSwitchExpressionLabel(e))
+ .reduce(new ArrayList<Statement>(4), (r, e) -> {
+ List<Statement> statementList = (List<Statement>) r;
+ Tuple3<Token, List<Expression>, Integer> tuple = (Tuple3<Token, List<Expression>, Integer>) e;
+
+ boolean isArrow = ARROW == tuple.getV3();
+ if (isArrow) {
+ if (++arrowCntHolder[0] > 1 && !firstLabelHolder.isEmpty()) {
+ throw createParsingFailedException("`case ... ->` does not support falling through cases", firstLabelHolder.get(0));
+ }
+ }
+
+ boolean isLast = labelCnt - 1 == statementList.size();
+
+ BlockStatement codeBlock = this.visitBlockStatements(ctx.blockStatements());
+ List<Statement> statements = codeBlock.getStatements();
+ int statementsCnt = statements.size();
+ if (0 == statementsCnt) {
+ throw createParsingFailedException("`yield` is expected", ctx.blockStatements());
+ }
+
+ if (statementsCnt > 1) {
+ throw new GroovyBugError("statements count should be 1, but the count is actually: " + statementsCnt);
+ }
+
+ if (!isArrow) {
+ boolean[] hasYieldHolder = new boolean[1];
+ boolean[] hasThrowHolder = new boolean[1];
+ codeBlock.visit(new CodeVisitorSupport() {
+ @Override
+ public void visitReturnStatement(ReturnStatement statement) {
+ if (isTrue(statement, IS_YIELD_STATEMENT)) {
+ hasYieldHolder[0] = true;
+ return;
+ }
+
+ super.visitReturnStatement(statement);
+ }
+
+ @Override
+ public void visitThrowStatement(ThrowStatement statement) {
+ hasThrowHolder[0] = true;
+ }
+ });
+ if (!(hasYieldHolder[0] || hasThrowHolder[0])) {
+ throw createParsingFailedException("`yield` or `throw` is expected", ctx.blockStatements());
+ }
+ }
+
+ Statement exprOrBlockStatement = statements.get(0);
+ if (exprOrBlockStatement instanceof BlockStatement) {
+ BlockStatement blockStatement = (BlockStatement) exprOrBlockStatement;
+ List<Statement> branchStatementList = blockStatement.getStatements();
+ if (1 == branchStatementList.size()) {
+ exprOrBlockStatement = branchStatementList.get(0);
+ }
+ }
+
+ if (!(exprOrBlockStatement instanceof ReturnStatement || exprOrBlockStatement instanceof ThrowStatement)) {
+ MethodCallExpression callClosure = callX(
+ configureAST(
+ closureX(null, exprOrBlockStatement),
+ exprOrBlockStatement
+ ), "call");
+ callClosure.setImplicitThis(false);
+
+ codeBlock = configureAST(
+ createBlockStatement(configureAST(
+ returnS(
+ exprOrBlockStatement instanceof ExpressionStatement
+ ? ((ExpressionStatement) exprOrBlockStatement).getExpression()
+ : callClosure
+ ),
+ exprOrBlockStatement
+ )),
+ exprOrBlockStatement
+ );
+ }
+
+ switch (tuple.getV1().getType()) {
+ case CASE: {
+ if (!asBoolean(statementList)) {
+ firstLabelHolder.add(tuple.getV1());
+ }
+
+ for (int i = 0, n = tuple.getV2().size(); i < n; i++) {
+ Expression expr = tuple.getV2().get(i);
+
+ statementList.add(
+ configureAST(
+ new CaseStatement(
+ expr,
+
+ // check whether processing the last label. if yes, block statement should be attached.
+ (isLast && i == n - 1) ? codeBlock
+ : EmptyStatement.INSTANCE
+ ),
+ firstLabelHolder.get(0)));
+ }
+
+ break;
+ }
+ case DEFAULT: {
+ codeBlock.putNodeMetaData(IS_SWITCH_DEFAULT, true);
+
+ statementList.add(
+ // this.configureAST(codeBlock, tuple.getKey())
+ codeBlock
+ );
+
+ break;
+ }
+ }
+
+ return statementList;
+ });
+ }
+
+ private void validateSwitchExpressionLabels(SwitchExpressionContext ctx) {
+ Map<String, List<SwitchExpressionLabelContext>> acMap =
+ ctx.switchBlockStatementExpressionGroup().stream()
+ .flatMap(e -> e.switchExpressionLabel().stream())
+ .collect(Collectors.groupingBy(e -> e.ac.getText()));
+ if (acMap.size() > 1) {
+ List<SwitchExpressionLabelContext> lastSelcList = acMap.values().stream().reduce((prev, next) -> next).orElse(null);
+ throw createParsingFailedException(acMap.keySet().stream().collect(Collectors.joining("` and `", "`", "`")) + " cannot be used together", lastSelcList.get(0).ac);
+ }
+ }
+
+ @Override
+ public Tuple3<Token, List<Expression>, Integer> visitSwitchExpressionLabel(SwitchExpressionLabelContext ctx) {
+ final Integer acType = ctx.ac.getType();
+ if (asBoolean(ctx.CASE())) {
+ return tuple(ctx.CASE().getSymbol(), this.visitExpressionList(ctx.expressionList()), acType);
+ } else if (asBoolean(ctx.DEFAULT())) {
+ return tuple(ctx.DEFAULT().getSymbol(), Collections.singletonList(EmptyExpression.INSTANCE), acType);
+ }
+
+ throw createParsingFailedException("Unsupported switch expression label: " + ctx.getText(), ctx);
+ }
+
+
// } statement -------------------------------------------------------------
@Override
@@ -3619,7 +3888,12 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
@Override
public LambdaExpression visitStandardLambdaExpression(final StandardLambdaExpressionContext ctx) {
- return configureAST(this.createLambda(ctx.standardLambdaParameters(), ctx.lambdaBody()), ctx);
+ switchExpressionRuleContextStack.push(ctx);
+ try {
+ return configureAST(this.createLambda(ctx.standardLambdaParameters(), ctx.lambdaBody()), ctx);
+ } finally {
+ switchExpressionRuleContextStack.pop();
+ }
}
private LambdaExpression createLambda(final StandardLambdaParametersContext standardLambdaParametersContext, final LambdaBodyContext lambdaBodyContext) {
@@ -3656,22 +3930,27 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
@Override
public ClosureExpression visitClosure(final ClosureContext ctx) {
- visitingClosureCount += 1;
+ switchExpressionRuleContextStack.push(ctx);
+ try {
+ visitingClosureCount += 1;
- Parameter[] parameters = asBoolean(ctx.formalParameterList())
- ? this.visitFormalParameterList(ctx.formalParameterList())
- : null;
+ Parameter[] parameters = asBoolean(ctx.formalParameterList())
+ ? this.visitFormalParameterList(ctx.formalParameterList())
+ : null;
- if (!asBoolean(ctx.ARROW())) {
- parameters = Parameter.EMPTY_ARRAY;
- }
+ if (!asBoolean(ctx.ARROW())) {
+ parameters = Parameter.EMPTY_ARRAY;
+ }
- Statement code = this.visitBlockStatementsOpt(ctx.blockStatementsOpt());
- ClosureExpression result = configureAST(new ClosureExpression(parameters, code), ctx);
+ Statement code = this.visitBlockStatementsOpt(ctx.blockStatementsOpt());
+ ClosureExpression result = configureAST(new ClosureExpression(parameters, code), ctx);
- visitingClosureCount -= 1;
+ visitingClosureCount -= 1;
- return result;
+ return result;
+ } finally {
+ switchExpressionRuleContextStack.pop();
+ }
}
@Override
@@ -4664,6 +4943,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
private final List<ClassNode> classNodeList = new LinkedList<>();
private final Deque<ClassNode> classNodeStack = new ArrayDeque<>();
private final Deque<List<InnerClassNode>> anonymousInnerClassesDefinedInMethodStack = new ArrayDeque<>();
+ private final Deque<GroovyParserRuleContext> switchExpressionRuleContextStack = new ArrayDeque<>();
private Tuple2<GroovyParserRuleContext, Exception> numberFormatError;
@@ -4725,4 +5005,5 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
private static final String INTEGER_LITERAL_TEXT = "_INTEGER_LITERAL_TEXT";
private static final String FLOATING_POINT_LITERAL_TEXT = "_FLOATING_POINT_LITERAL_TEXT";
private static final String ENCLOSING_INSTANCE_EXPRESSION = "_ENCLOSING_INSTANCE_EXPRESSION";
+ private static final String IS_YIELD_STATEMENT = "_IS_YIELD_STATEMENT";
}
diff --git a/src/main/java/org/apache/groovy/parser/antlr4/SemanticPredicates.java b/src/main/java/org/apache/groovy/parser/antlr4/SemanticPredicates.java
index 78e5877..addfd47 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/SemanticPredicates.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/SemanticPredicates.java
@@ -42,6 +42,7 @@ import static org.apache.groovy.parser.antlr4.GroovyParser.PathExpressionContext
import static org.apache.groovy.parser.antlr4.GroovyParser.PostfixExprAltContext;
import static org.apache.groovy.parser.antlr4.GroovyParser.PostfixExpressionContext;
import static org.apache.groovy.parser.antlr4.GroovyParser.StringLiteral;
+import static org.apache.groovy.parser.antlr4.GroovyParser.YIELD;
import static org.apache.groovy.parser.antlr4.util.StringUtils.matches;
/**
@@ -141,7 +142,7 @@ public class SemanticPredicates {
public static boolean isInvalidMethodDeclaration(TokenStream ts) {
int tokenType = ts.LT(1).getType();
- return (Identifier == tokenType || CapitalizedIdentifier == tokenType || StringLiteral == tokenType)
+ return (Identifier == tokenType || CapitalizedIdentifier == tokenType || StringLiteral == tokenType || YIELD == tokenType)
&& LPAREN == (ts.LT(2).getType());
}
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_01x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_01x.groovy
index 3b288ca..448719e 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_01x.groovy
@@ -16,30 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+def a = 6
+def result = switch(a) {
+ case 8 -> 'b'
+ default -> 'z'
+}
+assert 'z' == result
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_02x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_02x.groovy
index 3b288ca..5574d94 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_02x.groovy
@@ -16,30 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
+def a = 6
+def result = switch(a) {
+ case 6 -> 'a'
+}
+assert 'a' == result
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+a = 9
+result = switch(a) {
+ case 6 -> 'a'
+}
+assert null == result
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_03x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_03x.groovy
index 3b288ca..ef46adb 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_03x.groovy
@@ -16,30 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+def a = 6
+def result = switch(a) {
+ case 6, 8 -> 'b'
+ default -> 'z'
+}
+assert 'b' == result
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_04x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_04x.groovy
index 3b288ca..8b773cb 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_04x.groovy
@@ -16,30 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+def a = 9
+def result = switch(a) {
+ case 6, 8 -> 'b'
+ case 9 -> 'c'
+ default -> 'z'
+}
+assert 'c' == result
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_05x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_05x.groovy
index 3b288ca..5a52c93 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_05x.groovy
@@ -16,30 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+def a = 6
+def result = switch(a) {
+ case 6, 8 -> 1 + 2
+}
+assert 3 == result
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_06x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_06x.groovy
index 3b288ca..f864a24 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_06x.groovy
@@ -16,30 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
+def a = 6
+def result = switch(a) {
+ case 6, 8 -> 1.plus 2
+}
+assert 3 == result
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+a = 8
+result = switch(a) {
+ case 6, 8 -> 1.plus 2
+}
+assert 3 == result
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_07x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_07x.groovy
index 3b288ca..07e375b 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_07x.groovy
@@ -16,30 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
+def a = 9
+def result = switch(a) {
+ case 6, 8 -> 1.plus 2
+ default -> 1.plus 5
+}
+assert 6 == result
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
+a = 6
+result = switch(a) {
+ case 6, 8 -> 1.plus 2
+ default -> 1.plus 5
+}
+assert 3 == result
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+a = 8
+result = switch(a) {
+ case 6, 8 -> 1.plus 2
+ default -> 1.plus 5
+}
+assert 3 == result
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_08x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_08x.groovy
index 3b288ca..0b171f2 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_08x.groovy
@@ -16,30 +16,27 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
+def a = 6
+def result = switch(a) {
+ case 6 -> { 'a' }
+}
+assert 'a' == result
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
+a = 6
+result = switch(a) {
+ case 6 -> { yield 'a' }
+}
+assert 'a' == result
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+a = 8
+result = switch(a) {
+ case 6, 8 -> { yield 'a' }
+}
+assert 'a' == result
+
+a = 9
+result = switch(a) {
+ case 6, 8 -> { yield 'a' }
+}
+assert null == result
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_09x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_09x.groovy
index 3b288ca..14e0dd0 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_09x.groovy
@@ -16,30 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
+def a = 9
+def result = switch(a) {
+ case 6 -> { yield 'a' }
+ default -> { yield 'z' }
+}
+assert 'z' == result
+
+
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_10x.groovy
similarity index 52%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_10x.groovy
index 3b288ca..450fb24 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_10x.groovy
@@ -16,30 +16,44 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
+def a = 6
+def result = switch(a) {
+ case 6 -> {
+ def n = 1
+ yield 'a' + n
+ }
+ default -> { yield 'z' }
+}
+assert 'a1' == result
+
+a = 8
+result = switch(a) {
+ case 6, 8 -> {
+ def n = 1
+ yield 'a' + n
+ }
+ default -> { yield 'z' }
+}
+assert 'a1' == result
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
+a = 9
+result = switch(a) {
+ case 6, 8 -> {
+ def n = 1
+ yield 'a' + n
}
+ default -> { yield 'z' }
+}
+assert 'z' == result
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
+a = 9
+result = switch(a) {
+ case 6, 8 -> {
+ def n = 1
+ yield 'a' + n
}
-}
\ No newline at end of file
+ default -> yield 'z'
+}
+assert 'z' == result
+
diff --git a/src/test-resources/core/SwitchExpression_11x.groovy b/src/test-resources/core/SwitchExpression_11x.groovy
new file mode 100644
index 0000000..b8d55f1
--- /dev/null
+++ b/src/test-resources/core/SwitchExpression_11x.groovy
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+try {
+ def a = 6
+ def result = switch(a) {
+ case 6 : throw new RuntimeException('a')
+ }
+} catch (e) {
+ assert 'a' == e.message
+}
+
+a = 6
+result = switch(a) {
+ case 6 : yield 'a'
+}
+assert 'a' == result
+
+a = 8
+result = switch(a) {
+ case 6 : yield 'a'
+ default: yield 'b'
+}
+assert 'b' == result
+
+a = 9
+result = switch(a) {
+ case 6, 9 : yield 'a'
+ default: yield 'b'
+}
+assert 'a' == result
+
+a = 7
+result = switch(a) {
+ case 7:
+ case 6, 9 : yield 'a'
+ default: yield 'b'
+}
+assert 'a' == result
+
+
+a = 10
+result = switch(a) {
+ case 7:
+ case 6, 9 : yield 'a'
+ case 10:
+ case 11: yield 'c'
+ default: yield 'b'
+}
+assert 'c' == result
+
+a = 10
+result = switch(a) {
+ case 7:
+ case 6, 9 : yield 'a'
+ case 10:
+ case 11: {
+ def x = 1
+ yield 'c' + x
+ }
+ default: yield 'b'
+}
+assert 'c1' == result
+
+
+a = 6
+result = switch(a) {
+ case 6 : yield 'a'
+}
+assert 'a' == result
+
+a = 6
+result = switch(a) {
+ default : yield 'b'
+}
+assert 'b' == result
+
+a = 6
+result = switch(a) {
+ case 6 : { yield 'a' }
+}
+assert 'a' == result
+
+a = 6
+result = switch(a) {
+ default : { yield 'b' }
+}
+assert 'b' == result
+
+a = 6
+result = switch(a) {
+ case 6 : yield 'a'
+ default : yield 'b'
+}
+assert 'a' == result
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_12x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_12x.groovy
index 3b288ca..bbe8342 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_12x.groovy
@@ -16,30 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
+def a = 6
+def result = switch(a) {
+ case 6 -> 'a'
+ default-> yield 'b'
+}
+assert 'a' == result
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+a = 6
+result = switch(a) {
+ case 6 -> 'a'
+ default -> yield 'b'
+}
+assert 'a' == result
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_13x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_13x.groovy
index 3b288ca..4a2a7c8 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_13x.groovy
@@ -16,30 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
+def yield (String msg) { return msg }
+def yield () { return 'b' }
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+def result = yield 'a'
+assert 'a' == result
+assert 'b'== yield()
diff --git a/src/test-resources/core/SwitchExpression_14x.groovy b/src/test-resources/core/SwitchExpression_14x.groovy
new file mode 100644
index 0000000..0a8a661
--- /dev/null
+++ b/src/test-resources/core/SwitchExpression_14x.groovy
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+def test() {
+ def a = 2
+ def b = 1
+ def c = 0
+ def d = 99
+ def r = switch (a) {
+ case 0 -> 'a'
+ case 1 -> 'b'
+ case 2 -> 'c'
+ default -> 'z'
+ } + switch (b) {
+ case 0 -> 'a'
+ case 1 -> 'b'
+ case 2 -> 'c'
+ default -> 'z'
+ } + switch (c) {
+ case 0 -> 'a'
+ case 1 -> 'b'
+ case 2 -> 'c'
+ default -> 'z'
+ } + switch (d) {
+ case 0 -> 'a'
+ case 1 -> 'b'
+ case 2 -> 'c'
+ default -> 'z'
+ }
+ assert 'cbaz' == r
+}
+test()
+
+@groovy.transform.CompileStatic
+def testCS() {
+ def a = 2
+ def b = 1
+ def c = 0
+ def d = 99
+ def r = switch (a) {
+ case 0 -> 'a'
+ case 1 -> 'b'
+ case 2 -> 'c'
+ default -> 'z'
+ } + switch (b) {
+ case 0 -> 'a'
+ case 1 -> 'b'
+ case 2 -> 'c'
+ default -> 'z'
+ } + switch (c) {
+ case 0 -> 'a'
+ case 1 -> 'b'
+ case 2 -> 'c'
+ default -> 'z'
+ } + switch (d) {
+ case 0 -> 'a'
+ case 1 -> 'b'
+ case 2 -> 'c'
+ default -> 'z'
+ }
+ assert 'cbaz' == r
+}
+testCS()
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_15x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_15x.groovy
index 3b288ca..58b3a12 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_15x.groovy
@@ -16,30 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
+def a = 9
+def b = 8
+def result = switch(a) {
+ case 8 -> 'a'
+ case 9 -> switch(b) {
+ case 8 -> 'b'
+ default -> 'c'
}
-}
\ No newline at end of file
+ default -> 'd'
+}
+assert 'b' == result
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_16x.groovy
similarity index 52%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_16x.groovy
index 3b288ca..028d624 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_16x.groovy
@@ -16,30 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
+def a = 6
+try {
+ switch(a) {
+ case 8 -> 'b'
+ default -> throw new RuntimeException('z')
}
+} catch (e) {
+ assert 'z' == e.message
+}
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
+def r = switch(a) {
+ case 6 -> {
+ def x = 'a'
+ yield x
}
-}
\ No newline at end of file
+ default -> throw new RuntimeException('z')
+}
+assert 'a' == r
+
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_17x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_17x.groovy
index 3b288ca..aff965b 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_17x.groovy
@@ -16,30 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
+def a = '123'
+def r = switch (a) {
+ case String -> 1
+ default -> 2
+}
+assert 1 == r
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+a = 123
+r = switch (a) {
+ case String -> 1
+ default -> 2
+}
+assert 2 == r
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_18x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_18x.groovy
index 3b288ca..ba57d6b 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_18x.groovy
@@ -16,30 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+cnt = 0
+void prt() { cnt++ }
+def a = '123'
+switch (a) {
+ case String -> { prt() }
+}
+assert 1 == cnt
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_19x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_19x.groovy
index 3b288ca..f65840e 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_19x.groovy
@@ -16,30 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+cnt = 0
+void prt() { cnt++ }
+def a = '123'
+switch (a) {
+ case String -> prt()
+}
+assert 1 == cnt
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_20x.groovy
similarity index 52%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_20x.groovy
index 3b288ca..f0eec8d 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_20x.groovy
@@ -16,30 +16,25 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
+import groovy.transform.CompileStatic
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
+@CompileStatic
+String same(String s) { s }
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
+@CompileStatic
+def meth() {
+ def a = 1
+ def r = switch (a) {
+ case 1 -> {
+ if (true) {
+ same 'a'
+ } else {
+ same 'b'
}
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
+ }
}
-}
\ No newline at end of file
+ r + 'z'
+}
+
+assert 'az' == meth()
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_21x.groovy
similarity index 52%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_21x.groovy
index 3b288ca..55bac5a 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_21x.groovy
@@ -16,30 +16,25 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
+import groovy.transform.CompileStatic
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
+@CompileStatic
+String same(String s) { s }
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
+@CompileStatic
+def meth() {
+ def a = 1
+ def r = switch (a) {
+ case 1 -> {
+ if (2 == 2) {
+ yield 'hello'
}
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
+ yield 'hi'
+ }
+ case 2 -> 'Hello'
}
-}
\ No newline at end of file
+ r + ', Daniel'
+}
+
+assert 'hello, Daniel' == meth()
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_22x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_22x.groovy
index 3b288ca..ae410da 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_22x.groovy
@@ -16,30 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
+import java.time.Month
+import static java.time.Month.*
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+Month month = JUNE
+String quarter = switch (month) {
+ case JANUARY, FEBRUARY, MARCH -> "First Quarter"
+ case APRIL, MAY, JUNE -> "Second Quarter"
+ case JULY, AUGUST, SEPTEMBER -> "Third Quarter"
+ case OCTOBER, NOVEMBER, DECEMBER -> "Forth Quarter"
+ default -> "Unknown Quarter"
+}
+assert 'Second Quarter' == quarter
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_23x.groovy
similarity index 52%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_23x.groovy
index 3b288ca..31b5a14 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_23x.groovy
@@ -16,30 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
+import java.time.Month
+import static java.time.Month.*
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
+Month month = JUNE
+String quarter = switch (month) {
+ case JANUARY,
+ FEBRUARY,
+ MARCH -> {
+ yield "First Quarter"
+ }
+ case APRIL, MAY, JUNE -> {
+ yield "Second Quarter"
}
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
+ case JULY, AUGUST, SEPTEMBER -> "Third Quarter"
+ case OCTOBER, NOVEMBER, DECEMBER -> {
+ yield "Forth Quarter"
}
-}
\ No newline at end of file
+ default -> "Unknown Quarter"
+}
+assert 'Second Quarter' == quarter
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/core/SwitchExpression_24x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/core/SwitchExpression_24x.groovy
index 3b288ca..785008e 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/core/SwitchExpression_24x.groovy
@@ -16,30 +16,29 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
+import java.time.Month
+import static java.time.Month.*
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+Month month = JUNE
+String quarter = switch (month) {
+ case JANUARY:
+ case FEBRUARY:
+ case MARCH:
+ yield "First Quarter"
+ case APRIL:
+ case MAY:
+ case JUNE:
+ yield "Second Quarter"
+ case JULY:
+ case AUGUST:
+ case SEPTEMBER:
+ yield "Third Quarter"
+ case OCTOBER:
+ case NOVEMBER:
+ case DECEMBER:
+ yield "Forth Quarter"
+ default:
+ yield "Unknown Quarter"
+}
+assert 'Second Quarter' == quarter
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/fail/SwitchExpression_01x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/fail/SwitchExpression_01x.groovy
index 3b288ca..df57b27 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/fail/SwitchExpression_01x.groovy
@@ -16,30 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+def a = 6
+switch(a) {
+ case 8 ->
+ case 9 -> 'a'
+}
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/fail/SwitchExpression_02x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/fail/SwitchExpression_02x.groovy
index 3b288ca..8112793 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/fail/SwitchExpression_02x.groovy
@@ -16,30 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+def a = 6
+switch(a) {
+ case 8 ->
+ default -> 'b'
+}
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/fail/SwitchExpression_03x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/fail/SwitchExpression_03x.groovy
index 3b288ca..64ddad8 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/fail/SwitchExpression_03x.groovy
@@ -16,30 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+def a = 6
+switch(a) {
+ case 6 ->
+ case 8 ->
+ default -> 'b'
+}
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/fail/SwitchExpression_04x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/fail/SwitchExpression_04x.groovy
index 3b288ca..82d52da 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/fail/SwitchExpression_04x.groovy
@@ -16,30 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+def a = 6
+switch(a) {
+ case 6 -> 'a'
+ case 8 : yield 'b'
+ default -> 'c'
+}
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/fail/SwitchExpression_05x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/fail/SwitchExpression_05x.groovy
index 3b288ca..13fbb69 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/fail/SwitchExpression_05x.groovy
@@ -16,30 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+def a = 6
+def r = switch(a) {
+ case 6 : 'a'
+ default : 'c'
+}
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/fail/SwitchExpression_06x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/fail/SwitchExpression_06x.groovy
index 3b288ca..a799824 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/fail/SwitchExpression_06x.groovy
@@ -16,30 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-}
\ No newline at end of file
+def a = 6
+def r = switch(a) {
+ case 6 : return 'a'
+ default : return 'c'
+}
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/fail/SwitchExpression_07x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/fail/SwitchExpression_07x.groovy
index 3b288ca..592051c 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/fail/SwitchExpression_07x.groovy
@@ -16,30 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
+def a = 7
+while (a-- > 0) {
+ def r = switch(a) {
+ case 6 : break
+ default : return 'c'
}
-}
\ No newline at end of file
+}
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test-resources/fail/SwitchExpression_08x.groovy
similarity index 51%
copy from src/test/groovy/MethodInBadPositionTest.groovy
copy to src/test-resources/fail/SwitchExpression_08x.groovy
index 3b288ca..3c61cfd 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test-resources/fail/SwitchExpression_08x.groovy
@@ -16,30 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package groovy
-import gls.CompilableTestSupport
-
-class MethodInBadPositionTest extends CompilableTestSupport {
- /** GROOVY-4215 */
- void testMethodDefinitionInClosure() {
- def msg = shouldNotCompile('''
- { ->
- def say(String msg) {
- println(msg)
- }
- }()
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
- }
-
- /** GROOVY-4215 */
- void testXMethodDefinitionInSwitch() {
- def msg = shouldNotCompile('''
- switch(1) {
- case 1: def say(){}
- }
- ''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
+def a = 7
+while (a-- > 0) {
+ def r = switch(a) {
+ case 6 : continue
+ default : return 'c'
}
-}
\ No newline at end of file
+}
diff --git a/src/test/groovy/MethodInBadPositionTest.groovy b/src/test/groovy/MethodInBadPositionTest.groovy
index 3b288ca..453d75c 100644
--- a/src/test/groovy/MethodInBadPositionTest.groovy
+++ b/src/test/groovy/MethodInBadPositionTest.groovy
@@ -40,6 +40,6 @@ class MethodInBadPositionTest extends CompilableTestSupport {
case 1: def say(){}
}
''')
- assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('")
+ assert msg.contains('Method definition not expected here') || msg.contains("Unexpected input: '('") || msg.contains("Unexpected input: 'switch(1)")
}
}
\ No newline at end of file
diff --git a/src/test/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy b/src/test/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
index f7f0e59..506d6c0 100644
--- a/src/test/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
+++ b/src/test/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
@@ -412,15 +412,42 @@ final class GroovyParserTest extends GroovyTestCase {
}
void "test groovy core - var"() {
- doRunAndTestAntlr4('core/Var_01x.groovy');
+ doRunAndTestAntlr4('core/Var_01x.groovy')
}
void "test groovy core - String"() {
- doRunAndTestAntlr4('core/String_01x.groovy');
+ doRunAndTestAntlr4('core/String_01x.groovy')
}
void "test groovy core - NonStaticClass"() {
- doRunAndTestAntlr4('core/NonStaticClass_01x.groovy');
+ doRunAndTestAntlr4('core/NonStaticClass_01x.groovy')
+ }
+
+ void "test groovy core - SwitchExpression"() {
+ doRunAndTestAntlr4('core/SwitchExpression_01x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_02x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_03x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_04x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_05x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_06x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_07x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_08x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_09x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_10x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_11x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_12x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_13x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_14x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_15x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_16x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_17x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_18x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_19x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_20x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_21x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_22x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_23x.groovy')
+ doRunAndTestAntlr4('core/SwitchExpression_24x.groovy')
}
void "test groovy core - BUG"() {
@@ -445,30 +472,30 @@ final class GroovyParserTest extends GroovyTestCase {
}
void "test groovy core - GROOVY-9427"() {
- doTest('bugs/BUG-GROOVY-9427.groovy');
+ doTest('bugs/BUG-GROOVY-9427.groovy')
}
void "test groovy core - GROOVY-9433"() {
- doTest('bugs/BUG-GROOVY-9433.groovy');
+ doTest('bugs/BUG-GROOVY-9433.groovy')
}
void "test groovy core - GROOVY-9449"() {
- doTest('bugs/BUG-GROOVY-9449.groovy');
+ doTest('bugs/BUG-GROOVY-9449.groovy')
}
void "test groovy core - GROOVY-9511"() {
- doTest('bugs/BUG-GROOVY-9511.groovy', [MethodNode]);
+ doTest('bugs/BUG-GROOVY-9511.groovy', [MethodNode])
}
void "test groovy core - GROOVY-9507"() {
- doTest('bugs/BUG-GROOVY-9507.groovy');
+ doTest('bugs/BUG-GROOVY-9507.groovy')
}
void "test groovy core - GROOVY-9522"() {
- doTest('bugs/BUG-GROOVY-9522.groovy');
+ doTest('bugs/BUG-GROOVY-9522.groovy')
}
void "test groovy core - GROOVY-9692"() {
- doTest('bugs/BUG-GROOVY-9692.groovy');
+ doTest('bugs/BUG-GROOVY-9692.groovy')
}
}
diff --git a/src/test/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy b/src/test/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
index 3b993f7..e5ecbae 100644
--- a/src/test/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
+++ b/src/test/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
@@ -241,7 +241,7 @@ final class SyntaxErrorTest extends GroovyTestCase {
}
void 'test groovy core - AnnotationDeclaration 1'() {
- TestUtils.doRunAndShouldFail('fail/AnnotationDeclaration_01x.groovy');
+ TestUtils.doRunAndShouldFail('fail/AnnotationDeclaration_01x.groovy')
}
void 'test groovy core - AnnotationDeclaration 2'() {
@@ -420,6 +420,17 @@ final class SyntaxErrorTest extends GroovyTestCase {
TestUtils.doRunAndShouldFail('fail/Array_02x.groovy')
}
+ void "test groovy core - SwitchExpression"() {
+ TestUtils.doRunAndShouldFail('fail/SwitchExpression_01x.groovy')
+ TestUtils.doRunAndShouldFail('fail/SwitchExpression_02x.groovy')
+ TestUtils.doRunAndShouldFail('fail/SwitchExpression_03x.groovy')
+ TestUtils.doRunAndShouldFail('fail/SwitchExpression_04x.groovy')
+ TestUtils.doRunAndShouldFail('fail/SwitchExpression_05x.groovy')
+ TestUtils.doRunAndShouldFail('fail/SwitchExpression_06x.groovy')
+ TestUtils.doRunAndShouldFail('fail/SwitchExpression_07x.groovy')
+ TestUtils.doRunAndShouldFail('fail/SwitchExpression_08x.groovy')
+ }
+
@NotYetImplemented
void 'test error alternative - Missing ")" 1'() {
def err = expectParseError '''\
diff --git a/src/test/org/apache/groovy/parser/antlr4/TestUtils.groovy b/src/test/org/apache/groovy/parser/antlr4/TestUtils.groovy
index 3310447..c8aae4b 100644
--- a/src/test/org/apache/groovy/parser/antlr4/TestUtils.groovy
+++ b/src/test/org/apache/groovy/parser/antlr4/TestUtils.groovy
@@ -198,7 +198,7 @@ final class TestUtils {
}
static void doRunAndTestAntlr4(String path, CompilerConfiguration compilerConfiguration = CompilerConfiguration.DEFAULT) {
- assert executeScript(createAntlr4Shell(compilerConfiguration), "$RESOURCES_PATH/$path")
+ assert executeScript(createAntlr4Shell(compilerConfiguration), path)
}
static void doRunAndTestAntlr2(String path, CompilerConfiguration compilerConfiguration = CompilerConfiguration.DEFAULT) {
@@ -255,7 +255,8 @@ final class TestUtils {
}
private static boolean executeScript(GroovyShell shell, String path) {
- def file = new File(path)
+ File file = new File("$RESOURCES_PATH/$path")
+ assert file.exists() : "Test resource not found: $file.absolutePath"
try {
shell.evaluate(file.text)
return true
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/SmartDocumentFilter.java b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/SmartDocumentFilter.java
index 4496873..cdf55b2 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/SmartDocumentFilter.java
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/SmartDocumentFilter.java
@@ -108,6 +108,7 @@ import static org.apache.groovy.parser.antlr4.GroovyLexer.VAR;
import static org.apache.groovy.parser.antlr4.GroovyLexer.VOID;
import static org.apache.groovy.parser.antlr4.GroovyLexer.VOLATILE;
import static org.apache.groovy.parser.antlr4.GroovyLexer.WHILE;
+import static org.apache.groovy.parser.antlr4.GroovyLexer.YIELD;
/**
@@ -378,7 +379,7 @@ public class SmartDocumentFilter extends DocumentFilter {
VAR, BuiltInPrimitiveType, ABSTRACT, ASSERT, BREAK, CASE, CATCH, CLASS, CONST, CONTINUE, DEFAULT, DO,
ELSE, ENUM, EXTENDS, FINAL, FINALLY, FOR, IF, GOTO, IMPLEMENTS, IMPORT, INSTANCEOF, INTERFACE,
NATIVE, NEW, PACKAGE, PRIVATE, PROTECTED, PUBLIC, RETURN, STATIC, STRICTFP, SUPER, SWITCH, SYNCHRONIZED,
- THIS, THROW, THROWS, TRANSIENT, TRY, VOID, VOLATILE, WHILE, NullLiteral, BooleanLiteral)) {
+ THIS, THROW, THROWS, TRANSIENT, TRY, VOID, VOLATILE, WHILE, YIELD, NullLiteral, BooleanLiteral)) {
Style style = createDefaultStyleByTokenType(t);
StyleConstants.setBold(style, true);
StyleConstants.setForeground(style, Color.BLUE.darker().darker());
diff --git a/subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc b/subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc
index 51dedae..fae4474 100644
--- a/subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc
+++ b/subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc
@@ -912,6 +912,13 @@ GINQ does not support `with` clause for now. We could define a temporary variabl
include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_tips_12,indent=0]
----
+==== Alternative for `case-when`
+`case-when` of SQL could be replaced with switch expression:
+[source, groovy]
+----
+include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_tips_13,indent=0]
+----
+
==== Query JSON
[source, groovy]
----
diff --git a/subprojects/groovy-ginq/src/spec/test/org/apache/groovy/ginq/GinqTest.groovy b/subprojects/groovy-ginq/src/spec/test/org/apache/groovy/ginq/GinqTest.groovy
index 92bf5bc..18182f1 100644
--- a/subprojects/groovy-ginq/src/spec/test/org/apache/groovy/ginq/GinqTest.groovy
+++ b/subprojects/groovy-ginq/src/spec/test/org/apache/groovy/ginq/GinqTest.groovy
@@ -5886,6 +5886,22 @@ class GinqTest {
}
@Test
+ void "testGinq - switch - 1"() {
+ assertGinqScript '''
+// tag::ginq_tips_13[]
+ assert ['a', 'b', 'c', 'c'] == GQ {
+ from n in [1, 2, 3, 4]
+ select switch (n) {
+ case 1 -> 'a'
+ case 2 -> 'b'
+ default -> 'c'
+ }
+ }.toList()
+// end::ginq_tips_13[]
+ '''
+ }
+
+ @Test
void "testGinq - shutdown - 0"() {
assertScript '''
import org.apache.groovy.ginq.provider.collection.runtime.QueryableHelper