You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/06/27 13:50:31 UTC
[groovy] branch GROOVY-9272 updated (166fbbb -> 24fcf32)
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a change to branch GROOVY-9272
in repository https://gitbox.apache.org/repos/asf/groovy.git.
omit 166fbbb GROOVY-9272: Support switch expression
add d7f9edc Trivial refactoring: extract common variables
add d3d06f7 GROOVY-10112: IndexedProperty AST transform should only provide the getter for immutable fields
add a556398 GROOVY-5239: prefer outer class method over static import method
add cfd5ef0 refactor interface collect methods
add 61df54b refactor
add 26a28be GROOVY-8638: erase generics for no-signature fields/methods like bridges
add c125919 GROOVY-8111: lowestUpperBound: primitives and self-referential types fix
add 9a4df4d GROOVY-10122: stubgen: find type of helper method in special ctor call
add 445e0f6 GROOVY-5453: order category methods before taking first getter/setter
add 0bdad76 GROOVY-10107: STC: check assign null before type parameter compatibility
add 00fc7a4 Trivial tweak for hash table of hash-joins
add 89f148f Make Travis CI build work again(closes #1589)
add eef2a82 GROOVY-10113: check class cycle for outer types and type parameters
add 05a3963 GROOVY-3421: evaluate spread-map value only once
add f48bb09 GROOVY-10125: fix for type parameter cycle false positive
add 09979f9 undo edit
add b3fd3e8 GROOVY-10126: Support parsing multiple YAML documents
add 8ea882a Trivial refactoring: inline variable
add f230608 Correct a typo in quote type
add c0b5b23 GROOVY-5245: bean-style property access for boolean "is" category method
add 80895bc GROOVY-8678: allow floating point literals without leading zeroes
add 8ad3f0e Merge pull request #1588 from nineninesevenfour/GROOVY-8678
add bf7bb95 GROOVY-8678: extend test case
add b76a929 try to fix dist build
add efcfd33 GROOVY-10132: XmlUtil.serialize() Emoji bug
add 73e6c82 GROOVY-10134: Groovy console can not highlight token properly sometimes
add bd56a6b Trivial tweak: avoid redundant operations when text updated
add 32099f6 Trivial refactoring: extract common variable
add f62e403 Trivial tweak: avoid reading preferences frequently
add c21fe1f GROOVY-10135: Bump jansi to 2.3.3
add 134ed00 Trivial tweak for setting preferred size of numbers panel
add 1e521a8 Apply thread factory to ginq thread pool
add 051c130 Try to workaround javadoc bug
add 6e041d3 Install graphviz
add 7f4edba Workaround javadoc bug
add 8dce303 Fix javadoc issues
add 07907ff Tweak javadoc
add b3bba1c Fix javadoc issues
add 6af09d3 GROOVY-10141: retain parse order of anon. inner types in module classes
add 0b4b51a GROOVY-10143: add test case
add 0fffd2c Trivial refactoring: remove redundant type casting
add 9eed7a8 Trivial refactoring: extract common variable
add eec31fa Update GINQ user guide
add cdb8083 minor refactor: optimize imports
add 8ba70f6 GROOVY-10146: Groovy 3 compilation errors are less accurate than Groovy 2
add 571e36f Tweak syntax highlighter of groovy console
add d4f1636 GROOVY-10145: Support JDK16 (#1598)
add c51cb71 Add license header
add 9087a3e Avoid caching method repeatedly
add 0c44604 Access more methods if "spy" found
add 180e201 Trivial refactoring: simplify code
add 0dfa029 Add a test for `GroovyObjectHelper`
add 8c794fd GROOVY-10150: Eliminate ambiguities while parsing non-static class creator
add 237f107 Tweak `GroovyObjectHelperTest`
add 2d0f332 Tweak `GroovyObjectHelperTest` further
add 1bf1d6c GROOVY-10151: Bump gradle to 6.9
new 24fcf32 GROOVY-9272: Support switch expression
This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version. This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:
* -- * -- B -- O -- O -- O (166fbbb)
\
N -- N -- N refs/heads/GROOVY-9272 (24fcf32)
You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.
Any revisions marked "omit" are not gone; other references still
refer to them. Any revisions marked "discard" are gone forever.
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.github/workflows/gradle-snapshot-distribution.yml | 4 +-
.travis.yml | 6 +-
build.gradle | 4 +-
.../src/main/groovy/org.apache.groovy-core.gradle | 14 +-
.../main/groovy/org.apache.groovy-tested.gradle | 7 +
gradle.properties | 2 +-
gradle/verification-metadata.xml | 7 +
gradle/wrapper/gradle-wrapper.jar | Bin 55741 -> 59203 bytes
gradle/wrapper/gradle-wrapper.properties | 2 +-
gradlew | 53 +++--
gradlew.bat | 43 ++--
src/antlr/GroovyLexer.g4 | 21 +-
src/antlr/GroovyParser.g4 | 6 +-
src/main/java/groovy/lang/MetaClassImpl.java | 236 ++++++++++++++++-----
.../java/groovy/transform/IndexedProperty.java | 3 +-
.../org/apache/groovy/lang/GroovyObjectHelper.java | 127 +++++++++++
.../apache/groovy/parser/antlr4/AstBuilder.java | 3 +-
.../groovy/ast/decompiled/AsmDecompiler.java | 165 +++++++-------
.../ast/decompiled/MemberSignatureParser.java | 113 +++++-----
.../groovy/ast/expr/MethodCallExpression.java | 4 +-
.../codehaus/groovy/ast/tools/GeneralUtils.java | 14 +-
.../groovy/ast/tools/WideningCategories.java | 153 +++++++------
.../groovy/classgen/AsmClassGenerator.java | 138 ++++++------
.../org/codehaus/groovy/classgen/Verifier.java | 39 +++-
.../groovy/control/CompilerConfiguration.java | 2 +-
.../codehaus/groovy/control/ResolveVisitor.java | 87 ++++----
.../groovy/control/StaticImportVisitor.java | 20 +-
.../groovy/reflection/ReflectionUtils.java | 63 ++++--
.../org/codehaus/groovy/runtime/ArrayUtil.java | 7 +-
.../groovy/runtime/GroovyCategorySupport.java | 44 ++--
.../groovy/runtime/ProxyGeneratorAdapter.java | 4 +-
.../groovy/runtime/StreamGroovyMethods.java | 12 +-
.../groovy/tools/javac/JavaStubGenerator.java | 78 +++----
.../transform/ImmutableASTTransformation.java | 2 +
.../IndexedPropertyASTTransformation.java | 8 +-
.../transform/stc/StaticTypeCheckingSupport.java | 46 ++--
.../transform/stc/StaticTypeCheckingVisitor.java | 2 +-
.../codehaus/groovy/vmplugin/VMPluginFactory.java | 1 +
.../org/codehaus/groovy/vmplugin/v10/Java10.java | 5 +
.../org/codehaus/groovy/vmplugin/v16/Java16.java | 116 ++++++++++
.../vmplugin/v16/PluginDefaultGroovyMethods.java | 13 +-
.../vmplugin/v16/ProxyDefaultMethodHandle.java | 56 +++++
.../org/codehaus/groovy/vmplugin/v8/Java8.java | 23 +-
.../vmplugin/v8/PluginDefaultGroovyMethods.java | 5 +-
.../org/codehaus/groovy/vmplugin/v9/Java9.java | 10 +-
src/spec/doc/core-differences-java.adoc | 2 +-
src/spec/test/SyntaxTest.groovy | 1 +
src/test/gls/innerClass/InnerClassTest.groovy | 20 ++
src/test/groovy/CategoryTest.groovy | 52 ++++-
src/test/groovy/IllegalAccessTests.groovy | 4 +-
src/test/groovy/bugs/Groovy10113.groovy | 114 ++++++++++
src/test/groovy/bugs/Groovy10143.groovy | 111 ++++++++++
.../{Groovy1465Bug.groovy => Groovy1465.groovy} | 39 ++--
.../{Groovy3904Bug.groovy => Groovy3904.groovy} | 55 ++---
src/test/groovy/bugs/Groovy5239.groovy | 100 +++++++++
.../{Groovy8048Bug.groovy => Groovy8048.groovy} | 32 +--
src/test/groovy/bugs/Groovy8678.groovy | 218 +++++++++++++++++++
src/test/groovy/bugs/Groovy8815.groovy | 7 +
src/test/groovy/bugs/Groovy8947.groovy | 5 +
.../groovy/operator/SpreadMapOperatorTest.groovy | 26 ++-
.../groovy/transform/stc/GenericsSTCTest.groovy | 33 ++-
.../groovy/lang/GroovyObjectHelperTest.groovy | 52 +++++
.../groovy/parser/antlr4/SyntaxErrorTest.groovy | 23 +-
.../groovy/ast/decompiled/AsmDecompilerTest.groovy | 32 ++-
.../ast/decompiled/AsmDecompilerTestData.java | 1 +
.../groovy/ast/tools/WideningCategoriesTest.groovy | 41 +++-
.../groovy/classgen/TransientMetaClassTest.groovy | 4 +-
.../codehaus/groovy/classgen/VerifierTest.groovy | 72 +++++++
.../codehaus/groovy/reflection/SecurityTest.java | 3 +
.../runtime/typehandling/NumberMathTest.groovy | 2 +-
.../{Groovy7306.groovy => Groovy10122.groovy} | 25 +--
.../transform/IndexedPropertyTransformTest.groovy | 30 ++-
.../TransformsAndCustomClassLoadersTest.groovy | 5 +-
.../groovy/console/ui/ConsoleTextEditor.java | 27 ++-
.../console/ui/text/SmartDocumentFilter.java | 24 +--
.../collection/runtime/QueryableCollection.java | 29 ++-
.../collection/runtime/QueryableHelper.groovy | 8 +-
.../groovy-ginq/src/spec/doc/ginq-userguide.adoc | 2 +-
.../StreamingMarkupWriter.java | 5 +-
.../groovy/xml/GpathSyntaxTestSupport.groovy | 12 +-
.../src/test/groovy/groovy/xml/XmlUtilTest.groovy | 9 +
.../org/apache/groovy/yaml/util/YamlConverter.java | 8 +-
.../spec/test/groovy/yaml/YamlParserTest.groovy | 17 ++
versions.properties | 2 +-
84 files changed, 2237 insertions(+), 783 deletions(-)
create mode 100644 src/main/java/org/apache/groovy/lang/GroovyObjectHelper.java
create mode 100644 src/main/java/org/codehaus/groovy/vmplugin/v16/Java16.java
copy subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroStub.java => src/main/java/org/codehaus/groovy/vmplugin/v16/PluginDefaultGroovyMethods.java (80%)
create mode 100644 src/main/java/org/codehaus/groovy/vmplugin/v16/ProxyDefaultMethodHandle.java
create mode 100644 src/test/groovy/bugs/Groovy10113.groovy
create mode 100644 src/test/groovy/bugs/Groovy10143.groovy
rename src/test/groovy/bugs/{Groovy1465Bug.groovy => Groovy1465.groovy} (63%)
rename src/test/groovy/bugs/{Groovy3904Bug.groovy => Groovy3904.groovy} (62%)
create mode 100644 src/test/groovy/bugs/Groovy5239.groovy
rename src/test/groovy/bugs/{Groovy8048Bug.groovy => Groovy8048.groovy} (65%)
create mode 100644 src/test/groovy/bugs/Groovy8678.groovy
create mode 100644 src/test/org/apache/groovy/lang/GroovyObjectHelperTest.groovy
create mode 100644 src/test/org/codehaus/groovy/classgen/VerifierTest.groovy
copy src/test/org/codehaus/groovy/tools/stubgenerator/{Groovy7306.groovy => Groovy10122.groovy} (67%)
[groovy] 01/01: GROOVY-9272: Support switch expression
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY-9272
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 24fcf3289b9dbaffc8ca8ed0afe0f8ccb6bee33e
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sat May 22 13:49:17 2021 +0800
GROOVY-9272: Support switch expression
---
src/antlr/GroovyLexer.g4 | 1 +
src/antlr/GroovyParser.g4 | 32 +++
.../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 ++-
.../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 | 44 ++-
.../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 ++
40 files changed, 869 insertions(+), 703 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..839ce88 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
@@ -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/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..e15fb98 100644
--- a/src/test/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
+++ b/src/test/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
@@ -412,15 +412,39 @@ 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')
}
void "test groovy core - BUG"() {
@@ -445,30 +469,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