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 2020/02/23 11:53:27 UTC
[groovy] branch GROOVY_3_0_X updated: Tweak `classDeclaration` rule
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
new ea468d3 Tweak `classDeclaration` rule
ea468d3 is described below
commit ea468d342b58ec41fd06d2cd89c0e5b574c702ae
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sun Feb 23 19:02:18 2020 +0800
Tweak `classDeclaration` rule
(cherry picked from commit 907ec453f595b7e907b6730cbe53b3b20dd7999f)
---
src/antlr/GroovyParser.g4 | 35 +------
src/test/gls/generics/GenericsUsageTest.groovy | 4 +-
.../apache/groovy/parser/antlr4/AstBuilder.java | 53 +++++++++-
.../groovy/parser/antlr4/SyntaxErrorTest.groovy | 107 +++++++++++++++++++++
4 files changed, 162 insertions(+), 37 deletions(-)
diff --git a/src/antlr/GroovyParser.g4 b/src/antlr/GroovyParser.g4
index f075237..ef6cd79 100644
--- a/src/antlr/GroovyParser.g4
+++ b/src/antlr/GroovyParser.g4
@@ -221,36 +221,11 @@ locals[ int t ]
| AT INTERFACE { $t = 3; }
| TRAIT { $t = 4; }
)
- identifier nls
-
- (
- { 3 != $t }?
- (typeParameters nls)?
- (
- { 2 != $t }?
- EXTENDS nls
- (
- // Only interface can extend more than one super class
- {1 == $t}? scs=typeList
- |
- sc=type
- )
- nls
- |
- /* enum should not have type parameters and extends */
- )
-
- (
- {1 != $t}?
- IMPLEMENTS nls is=typeList nls
- |
- /* interface should not implement other interfaces */
- )
- |
- /* annotation should not have implements and extends*/
- )
-
- classBody[$t]
+ identifier
+ (nls typeParameters)?
+ (nls EXTENDS nls scs=typeList)?
+ (nls IMPLEMENTS nls is=typeList)?
+ nls classBody[$t]
;
// t see the comment of classDeclaration
diff --git a/src/test/gls/generics/GenericsUsageTest.groovy b/src/test/gls/generics/GenericsUsageTest.groovy
index 3b07463..8ef2e56 100644
--- a/src/test/gls/generics/GenericsUsageTest.groovy
+++ b/src/test/gls/generics/GenericsUsageTest.groovy
@@ -214,7 +214,7 @@ final class GenericsUsageTest extends CompilableTestSupport {
shouldFailCompilationWithMessage """
abstract class ArrayList2<E> extends AbstractList<E implements List<E> {}
- """, "Unexpected input: 'AbstractList<E implements'"
+ """, "Unexpected input: '<'"
shouldFailCompilationWithMessage """
abstract class ArrayList3<E> extends AbstractList<E> implements List<E {}
@@ -312,7 +312,7 @@ final class GenericsUsageTest extends CompilableTestSupport {
} else {
shouldFailCompilationWithMessages '''
class MyList extends ArrayList<> {}
- ''', ['Unexpected input: \'ArrayList<>\'']
+ ''', ['Unexpected input: \'<\'']
}
shouldFailCompilationWithMessages '''
diff --git a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index 9b2780e..82baee7 100644
--- a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -1082,6 +1082,39 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
throw createParsingFailedException("var cannot be used for type declarations", ctx.identifier());
}
+ boolean isAnnotation = asBoolean(ctx.AT());
+ if (isAnnotation) {
+ if (asBoolean(ctx.typeParameters())) {
+ throw createParsingFailedException("annotation declaration cannot have type parameters", ctx.typeParameters());
+ }
+
+ if (asBoolean(ctx.EXTENDS())) {
+ throw createParsingFailedException("No extends clause allowed for annotation declaration", ctx.EXTENDS());
+ }
+
+ if (asBoolean(ctx.IMPLEMENTS())) {
+ throw createParsingFailedException("No implements clause allowed for annotation declaration", ctx.IMPLEMENTS());
+ }
+ }
+
+ boolean isEnum = asBoolean(ctx.ENUM());
+ if (isEnum) {
+ if (asBoolean(ctx.typeParameters())) {
+ throw createParsingFailedException("enum declaration cannot have type parameters", ctx.typeParameters());
+ }
+
+ if (asBoolean(ctx.EXTENDS())) {
+ throw createParsingFailedException("No extends clause allowed for enum declaration", ctx.EXTENDS());
+ }
+ }
+
+ boolean isInterface = (asBoolean(ctx.INTERFACE()) && !isAnnotation);
+ if (isInterface) {
+ if (asBoolean(ctx.IMPLEMENTS())) {
+ throw createParsingFailedException("No implements clause allowed for interface declaration", ctx.IMPLEMENTS());
+ }
+ }
+
List<ModifierNode> modifierNodeList = ctx.getNodeMetaData(TYPE_DECLARATION_MODIFIERS);
Objects.requireNonNull(modifierNodeList, "modifierNodeList should not be null");
ModifierManager modifierManager = new ModifierManager(this, modifierNodeList);
@@ -1091,7 +1124,8 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
modifiers &= ~Opcodes.ACC_SYNTHETIC;
ClassNode classNode, outerClass = classNodeStack.peek();
- if (asBoolean(ctx.ENUM())) {
+
+ if (isEnum) {
classNode = EnumHelper.makeEnumNode(
asBoolean(outerClass) ? className : packageName + className,
modifiers,
@@ -1117,7 +1151,6 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
configureAST(classNode, ctx);
classNode.setSyntheticPublic(syntheticPublic);
classNode.setGenericsTypes(this.visitTypeParameters(ctx.typeParameters()));
- boolean isInterface = (asBoolean(ctx.INTERFACE()) && !asBoolean(ctx.AT()));
boolean isInterfaceWithDefaultMethods = (isInterface && this.containsDefaultMethods(ctx));
if (isInterfaceWithDefaultMethods || asBoolean(ctx.TRAIT())) {
@@ -1131,7 +1164,17 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
classNode.putNodeMetaData(CLASS_NAME, className);
if (asBoolean(ctx.CLASS()) || asBoolean(ctx.TRAIT()) || isInterfaceWithDefaultMethods) {
- classNode.setSuperClass(this.visitType(ctx.sc));
+ ClassNode superClass;
+ if (asBoolean(ctx.scs)) {
+ ClassNode[] scs = this.visitTypeList(ctx.scs);
+ if (scs.length > 1) {
+ throw createParsingFailedException("Cannot extend multiple classes", ctx.EXTENDS());
+ }
+ superClass = scs[0];
+ } else {
+ superClass = ClassHelper.OBJECT_TYPE;
+ }
+ classNode.setSuperClass(superClass);
classNode.setInterfaces(this.visitTypeList(ctx.is));
this.initUsingGenerics(classNode);
@@ -1142,12 +1185,12 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
this.initUsingGenerics(classNode);
this.hackMixins(classNode);
- } else if (asBoolean(ctx.ENUM())) {
+ } else if (isEnum) {
classNode.setModifiers(classNode.getModifiers() | Opcodes.ACC_ENUM | Opcodes.ACC_FINAL);
classNode.setInterfaces(this.visitTypeList(ctx.is));
this.initUsingGenerics(classNode);
- } else if (asBoolean(ctx.AT())) {
+ } else if (isAnnotation) {
classNode.setModifiers(classNode.getModifiers() | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_ANNOTATION);
classNode.addInterface(ClassHelper.Annotation_TYPE);
this.hackMixins(classNode);
diff --git a/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy b/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
index 98d2a1c..fc7cebd 100644
--- a/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
+++ b/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
@@ -284,6 +284,113 @@ test.groovy: 2: Missing ')' @ line 2, column 22.
'''
}
+
+ void "test groovy core - AnnotationDeclaration 1"() {
+ def err = expectFail '''\
+@interface A<T> {}
+ '''
+
+ assert err == '''\
+startup failed:
+test.groovy: 1: annotation declaration cannot have type parameters @ line 1, column 13.
+ @interface A<T> {}
+ ^
+
+1 error
+'''
+ }
+
+ void "test groovy core - AnnotationDeclaration 2"() {
+ def err = expectFail '''\
+@interface A extends Object {}
+ '''
+
+ assert err == '''\
+startup failed:
+test.groovy: 1: No extends clause allowed for annotation declaration @ line 1, column 14.
+ @interface A extends Object {}
+ ^
+
+1 error
+'''
+ }
+
+ void "test groovy core - AnnotationDeclaration 3"() {
+ def err = expectFail '''\
+@interface A implements Serializable {}
+ '''
+
+ assert err == '''\
+startup failed:
+test.groovy: 1: No implements clause allowed for annotation declaration @ line 1, column 14.
+ @interface A implements Serializable {}
+ ^
+
+1 error
+'''
+ }
+
+ void "test groovy core - EnumDeclaration 1"() {
+ def err = expectFail '''\
+enum E<T> {}
+ '''
+
+ assert err == '''\
+startup failed:
+test.groovy: 1: enum declaration cannot have type parameters @ line 1, column 7.
+ enum E<T> {}
+ ^
+
+1 error
+'''
+ }
+
+ void "test groovy core - EnumDeclaration 2"() {
+ def err = expectFail '''\
+enum E extends Object {}
+ '''
+
+ assert err == '''\
+startup failed:
+test.groovy: 1: No extends clause allowed for enum declaration @ line 1, column 8.
+ enum E extends Object {}
+ ^
+
+1 error
+'''
+ }
+
+ void "test groovy core - InterfaceDeclaration 1"() {
+ def err = expectFail '''\
+interface I implements Serializable {}
+ '''
+
+ assert err == '''\
+startup failed:
+test.groovy: 1: No implements clause allowed for interface declaration @ line 1, column 13.
+ interface I implements Serializable {}
+ ^
+
+1 error
+'''
+ }
+
+ void "test test groovy core - ClassDeclaration 1"() {
+ def err = expectFail '''\
+class C extends Object, Number {}
+ '''
+
+ assert err == '''\
+startup failed:
+test.groovy: 1: Cannot extend multiple classes @ line 1, column 9.
+ class C extends Object, Number {}
+ ^
+
+1 error
+'''
+ }
+
+
//--------------------------------------------------------------------------
def expectFail(String code) {
try {