Skip to content

Commit

Permalink
GROOVY-9306: accept trailing comma for constants-only enum declaration
Browse files Browse the repository at this point in the history
`enum E1 {}`
`enum E2 {A}`
`enum E3 {A,}`
`enum E4 {A,B,}`
`enum E5 {A,B;}`
`enum E6 {A,B,;}`
`enum E7 {A,B,;char c}`
`enum E8 {A,B\nchar c}`

but not:

`enum E9 { A, B,\ndef x;}`
  • Loading branch information
eric-milles committed Oct 28, 2024
1 parent d5760cf commit 65506f4
Show file tree
Hide file tree
Showing 13 changed files with 582 additions and 685 deletions.
25 changes: 15 additions & 10 deletions src/antlr/GroovyParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -219,12 +219,12 @@ typeList
*/
classDeclaration
locals[ int t ]
: ( CLASS { $t = 0; }
| INTERFACE { $t = 1; }
| ENUM { $t = 2; }
: ( CLASS { $t = 0; }
| INTERFACE { $t = 1; }
| ENUM { $t = 2; }
| AT INTERFACE { $t = 3; }
| TRAIT { $t = 4; }
| RECORD { $t = 5; }
| TRAIT { $t = 4; }
| RECORD { $t = 5; }
)
identifier
(nls typeParameters)?
Expand All @@ -235,16 +235,21 @@ locals[ int t ]
nls classBody[$t]
;

// t see the comment of classDeclaration
classBody[int t]
: LBRACE nls
(
/* Only enum can have enum constants */
{ 2 == $t }?
enumConstants (nls COMMA)? sep?
{ $t == 2 }?
enumConstants (
(nls COMMA)?
|
// GROOVY-7773, GROOVY-9306:
((nls COMMA)? nls SEMI)? nls
classBodyDeclaration[$t] (sep classBodyDeclaration[$t])*
)
|
(classBodyDeclaration[$t] (sep classBodyDeclaration[$t])* )?
)
(classBodyDeclaration[$t] (sep classBodyDeclaration[$t])*)? sep? RBRACE
sep? RBRACE
;

enumConstants
Expand Down
76 changes: 36 additions & 40 deletions src/test-resources/core/EnumDeclaration_01.groovy
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import H.I

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
Expand All @@ -16,59 +18,53 @@
* specific language governing permissions and limitations
* under the License.
*/
enum AAAA {}
public enum AAAA2 {}
public enum AAAA3 implements A {}

enum e1{}
enum e2 { }
public enum E3 {}
public enum E4 implements A {}
@Test2
public enum AAAA4 implements A,B {}
enum BBBB {A}
enum CCCC {A, B}
enum CCCC2 {A, B
public enum E5 implements A,B {}
enum E6 implements I<T> {}

enum E10 {A}
enum E11 {A, B}
enum E12 {A, B
}
enum CCCC3 {
enum E13 {
A, B
}
enum DDDD {A, B,}
enum EEEE {
enum E14 {A, B,}
enum E15 {
A,
B}
enum FFFF {
enum E16 {
A,
B,}
enum GGGG
enum E17
{A,
B,}

enum E1 {
A(111,'aa'), B(222,'bb')
enum E18
{
A
,
B
,
}

@Test2
enum E2 {
A2,
B2,C2,
D2
private void a() {}
def c;
enum E19
{
A
,
B
,
;
}

enum E3 {
A(1), B(2)

public static final String SOME_CONSTANT = '123';
private String name;
private int age = 2;
String title = "title"
public E9(int x) {}
enum E20 {
@Test2
A
}



enum e {}

enum Enum1 {
A, B;
enum E21 {
A(111,'aa'), B(222,'bb')
}
enum Enum2 {
A, B;}
enum Enum3 {A, B;}
215 changes: 166 additions & 49 deletions src/test-resources/core/EnumDeclaration_02.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -16,80 +16,197 @@
* specific language governing permissions and limitations
* under the License.
*/
enum E {
A() {}, B(1) {{}},
C(1, 2) {
public void prt() {
println "$x, $y"
}

void prt2() {
println "$x, $y"
}
@Test2
enum E1 {
A,
B,C,
D
private void proc() {}
def prop;
}

@Test2 prt3() {
println "$x, $y"
}
enum E2 {
A(1), B(2)

public static final String SOME_CONSTANT = '123';
private final String name;
private final int age = 2;
final String title='title'
public E2(int x) {}
}

private void prt4() {
println "$x, $y"
}
enum E3 {
A, B
enum E4{X, Y}
}

private prt5() {
println "$x, $y"
class C {
enum E5 {
A
enum E6 {
B
}
},
D {
void hello() {}
}
}

protected int x;
protected int y;
enum E7 {
A(1), B(2)
E7(value) {
this.value = value
}
private final int value
}

E() {}
E(int x) {
this.x = x;
enum E8 {
@Test2 A(1), B(2)
E8(value) {
this.value = value
}
E(int x, y) {
this(x)
this.y = y;
private final int value
}

enum E9 {
A(1), B(2)
Object value // different parsing without leading keyword
E9(value) {
this.value = value
}
}

void prt() {
println "123"
// GROOVY-9301
enum E10 {
X(1), Y(2), // trailing comma
;
Object value
E10(value) {
this.value = value
}
}

enum F {
@Test2
A
enum E11 {
X, Y, Z
def m1() { }
public m2(args) { }
int m3(String arg) { }
}

enum G implements I<T> {
enum E12 {
X, Y, Z
def <T> T m() { }
}

enum E13 {
X, Y, Z
final <T> T m() { }
}

enum J {
A,
B,
enum E14 {
X, Y, Z
public <T> T m() { }
}

enum K {
A,
B,
enum E15 {
X { double eval(int v) { return (double) v } },
Y {
double eval(int v) { return (double) v + 1 }
}, Z
}

enum E16 {
X, Y, Z
class C { }
}

// GROOVY-8507
enum E17 {
X, Y, Z, // trailing comma
;
class C { }
}

enum Outer {
A, B
enum Inner{X, Y}
enum E18 {
X, Y, Z
enum E2 { A, B, C }
}

class TestClass {
enum OuterEnum {
VALUE,
enum InnerEnum {
A
}
// GROOVY-8507
enum E19 {
X, Y, Z, // trailing comma
;
enum Another { A, B, C }
}

enum E20 {
X, Y, Z
interface I { }
}

// GROOVY-8507
enum E21 {
X, Y, Z, // trailing comma
;
interface I { }
}

enum E22 {
X, Y, Z
@interface A { }
}

enum E23 {
X, Y, Z, // trailing comma
;
@interface A { }
}

enum E24 {
X, Y, Z
trait T { }
}

enum E25 {
X, Y, Z;
trait T { }
}

enum Color {
RED, BLACK
}
enum Suit {
CLUBS(Color.BLACK),
DIAMONDS(Color.RED),
HEARTS(Color.RED),
SPADES(Color.BLACK), // trailing comma
;
final Color color
Suit(Color color) {
this.color = color
}
}

enum Orientation1 {
LANDSCAPE, PORTRAIT

@Override
String toString() {
name().toLowerCase().capitalize()
}
}

// GROOVY-9306
enum Orientation2 {
LANDSCAPE, PORTRAIT, // trailing comma
;
@Override
String toString() {
name().toLowerCase().capitalize()
}
}

// GROOVY-9306
enum Orientation3 {
LANDSCAPE, PORTRAIT, // trailing comma
;
@Deprecated <T> T whatever() { }
}
Loading

0 comments on commit 65506f4

Please sign in to comment.