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 2019/07/02 14:17:16 UTC
[groovy] 01/02: GROOVY-9184 (clone of GROOVY-4438): enumConstants:
reduce ambiguity within loop (closes #940)
This is an automated email from the ASF dual-hosted git repository.
paulk pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit c159feba2126d746a23cc57dbc50467b9331777a
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Jun 1 10:50:20 2019 -0500
GROOVY-9184 (clone of GROOVY-4438): enumConstants: reduce ambiguity within loop (closes #940)
---
src/main/antlr2/org/codehaus/groovy/antlr/groovy.g | 10 +-
src/test/groovy/bugs/Groovy4438.groovy | 50 ++++++
.../groovy/antlr/EnumSourceParsingTest.java | 179 +++++++++++++--------
3 files changed, 166 insertions(+), 73 deletions(-)
diff --git a/src/main/antlr2/org/codehaus/groovy/antlr/groovy.g b/src/main/antlr2/org/codehaus/groovy/antlr/groovy.g
index 105059a..4458bc7 100644
--- a/src/main/antlr2/org/codehaus/groovy/antlr/groovy.g
+++ b/src/main/antlr2/org/codehaus/groovy/antlr/groovy.g
@@ -1191,13 +1191,13 @@ enumConstantsStart
enumConstants
:
enumConstant
- ( options {generateAmbigWarnings=false;} :
- (nls (SEMI! | RCURLY | classField)) => { break; /* leave ()* loop */ }
- | nls! COMMA!
- (
+ ( options {generateAmbigWarnings=false;} :
+ (nls ( options {generateAmbigWarnings=false;} : SEMI! | RCURLY | declarationStart | constructorStart)) => {break;}
+ |
+ nls! COMMA! (
(nls annotationsOpt IDENT) => nls! enumConstant
|
- (nls (SEMI! | RCURLY | classField)) => { break; /* leave ()* loop */ }
+ (nls (RCURLY | classField)) => {break;}
)
)*
;
diff --git a/src/test/groovy/bugs/Groovy4438.groovy b/src/test/groovy/bugs/Groovy4438.groovy
new file mode 100644
index 0000000..9e3e3fc
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy4438.groovy
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package groovy.bugs
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+import static org.codehaus.groovy.control.ParserPluginFactory.antlr2
+
+@CompileStatic
+@RunWith(JUnit4)
+final class Groovy4438 {
+
+ @Test(timeout=1500L)
+ void testEnumWithinEnum() {
+ def config = new CompilerConfiguration(pluginFactory: antlr2())
+
+ new GroovyShell(config).evaluate('''\
+ enum Outer {
+ A, B
+ enum Inner {
+ X, Y
+ }
+ }
+ assert Outer.A.name() == 'A'
+ assert Outer.A.ordinal() == 0
+ assert Outer.Inner.Y.name() == 'Y'
+ assert Outer.Inner.Y.ordinal() == 1
+ ''')
+ }
+}
diff --git a/src/test/org/codehaus/groovy/antlr/EnumSourceParsingTest.java b/src/test/org/codehaus/groovy/antlr/EnumSourceParsingTest.java
index ad0d23e..8a6d2a3 100644
--- a/src/test/org/codehaus/groovy/antlr/EnumSourceParsingTest.java
+++ b/src/test/org/codehaus/groovy/antlr/EnumSourceParsingTest.java
@@ -20,108 +20,151 @@ package org.codehaus.groovy.antlr;
import java.io.StringReader;
-
/**
* Parser tests for Enum definitions.
*/
-public class EnumSourceParsingTest extends SourceParserTest {
+public final class EnumSourceParsingTest extends SourceParserTest {
+
public void testParseEnumConstants() {
- StringReader reader = new StringReader(
- "enum One {\n"
- + " ONE, TWO, THREE\n"
- + "}");
- parse("testParseEnumConstants", reader);
+ parse(getMethodName(), new StringReader(
+ "enum E {\n" +
+ " ONE, TWO, THREE\n" +
+ "}"));
}
- public void testParseEnumMultiLine() {
- StringReader reader = new StringReader(
- "enum ParseCode\n" +
- "{\n" +
- " COMPLETE,\n" +
- " INCOMPLETE,\n" +
- " ERROR\n" +
- "}");
- parse("testParseEnumMultiLine", reader);
+ public void testParseEnumConstantsMultiLine() {
+ parse(getMethodName(), new StringReader(
+ "enum E {\n" +
+ " ONE,\n" +
+ " TWO,\n" +
+ " THREE,\n" +
+ "}"));
+ }
+
+ public void testParseEnumConstantsMultiLine2() {
+ parse(getMethodName(), new StringReader(
+ "enum ParseCode\n" +
+ "{\n" +
+ " COMPLETE,\n" +
+ " INCOMPLETE,\n" +
+ " ERROR\n" +
+ "}"));
}
-
+
public void testParseEnumImplementsMultiLine() {
- StringReader reader = new StringReader(
+ parse(getMethodName(), new StringReader(
"enum ParseCode implements I\n" +
"{\n" +
" COMPLETE,\n" +
" INCOMPLETE,\n" +
" ERROR\n" +
- "}");
- parse("testParseEnumImplementsMultiLine", reader);
+ "}"));
}
-
+
public void testParseEnumImplementsMultiLine2() {
- StringReader reader = new StringReader(
+ parse(getMethodName(), new StringReader(
"enum ParseCode\n" +
"implements I\n" +
"{\n" +
" COMPLETE,\n" +
" INCOMPLETE,\n" +
" ERROR\n" +
- "}");
- parse("testParseEnumImplementsMultiLine2", reader);
+ "}"));
}
-
+
public void testParseEnumConstantsOneLiner() {
- StringReader reader = new StringReader(
- "enum One { ONE, TWO, THREE }");
- parse("testParseEnumConstantsOneLiner", reader);
+ parse(getMethodName(), new StringReader(
+ "enum One { ONE, TWO, THREE }"));
}
public void testParseEnumImplements() {
- StringReader reader = new StringReader(
- "enum Two implements I1 {\n"
- + "ONE, TWO, THREE\n"
- + "}");
- parse("testParseEnumImplements", reader);
+ parse(getMethodName(), new StringReader(
+ "enum Two implements I1 {\n" +
+ "ONE, TWO, THREE\n" +
+ "}"));
}
public void testParseEnumWithValues() {
- StringReader reader = new StringReader(
- "enum Three1 {\n"
- + " ONE(1), TWO(2)\n\n"
- + " Three1(val) {\n"
- + " value = val\n"
- + " }\n\n"
- + " private final int value"
- + "}");
- parse("testParseEnumWithValues", reader);
-
- reader = new StringReader(
- "enum Three1 {\n"
- + " @Annotation ONE(1), TWO(2)\n\n"
- + " Three1(val) {\n"
- + " value = val\n"
- + " }\n\n"
- + " private final int value"
- + "}");
- parse("testParseEnumWithValues2", reader);
+ parse(getMethodName(), new StringReader(
+ "enum Three1 {\n" +
+ " ONE(1), TWO(2)\n\n" +
+ " Three1(val) {\n" +
+ " value = val\n" +
+ " }\n\n" +
+ " private final int value" +
+ "}"));
+ }
+
+ public void testParseEnumWithValues2() {
+ parse(getMethodName(), new StringReader(
+ "enum Three1 {\n" +
+ " @Annotation ONE(1), TWO(2)\n\n" +
+ " Three1(val) {\n" +
+ " value = val\n" +
+ " }\n\n" +
+ " private final int value" +
+ "}"));
+ }
+
+ public void testParseEnumWithValues3() {
+ parse(getMethodName(), new StringReader(
+ "enum NonFinal {\n" +
+ " One(1), Two(2)\n" +
+ " Object value\n" + // different parsing without leading keyword
+ " NonFinal(value) {\n" +
+ " this.value = value\n" +
+ " }\n" +
+ "}\n"));
+ }
+
+ public void testParseEnumWithValues4() {
+ parse(getMethodName(), new StringReader(
+ "enum Color {\n" +
+ " RED,\n" +
+ " BLACK\n" +
+ "}\n" +
+ "enum Suit {\n" +
+ " CLUBS(Color.BLACK),\n" +
+ " DIAMONDS(Color.RED),\n" +
+ " HEARTS(Color.RED),\n" +
+ " SPADES(Color.BLACK),\n" +
+ " \n" +
+ " final Color color\n" +
+ " Suit(Color color) {\n" +
+ " this.color = color\n" +
+ " }\n" +
+ "}\n"));
}
public void testParseEnumWithMethodDefinitions() {
- StringReader reader = new StringReader(
- "enum Four {\n"
- + " ONE, TWO, THREE\n\n"
- + " def someMethod() { }\n"
- + " public m2(args) { }\n"
- + " int m3(String arg) { }\n"
- + "}");
- parse("testParseEnumWithMethodDefinitions", reader);
+ parse(getMethodName(), new StringReader(
+ "enum Four {\n" +
+ " ONE, TWO, THREE\n\n" +
+ " def someMethod() { }\n" +
+ " public m2(args) { }\n" +
+ " int m3(String arg) { }\n" +
+ "}"));
+ }
+
+ public void testParseEnumWithAnnotatedMethodDefinition() {
+ parse(getMethodName(), new StringReader(
+ "enum Orientation {\n" +
+ " LANDSCAPE, PORTRAIT\n" +
+ " \n" +
+ " @Override\n" +
+ " String toString() {\n" +
+ " name().toLowerCase().capitalize()\n" +
+ " }\n" +
+ "}\n"));
}
public void testParseCompleteEnum() {
- StringReader reader = new StringReader(
- "enum Five {\n"
- + " ONE { double eval(int v) { return (double) v } }, \n"
- + " TWO {\n"
- + " double eval(int v) { return (double) v + 1 }\n"
- + " }, THREE\n"
- + "}");
- parse("testParseCompleteEnum", reader);
+ parse(getMethodName(), new StringReader(
+ "enum Five {\n" +
+ " ONE { double eval(int v) { return (double) v } }, \n" +
+ " TWO {\n" +
+ " double eval(int v) { return (double) v + 1 }\n" +
+ " }, THREE\n" +
+ "}"));
}
}