This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new 5597fb6449 GROOVY-11208: `String m() default ""` only for annotation
declaration
5597fb6449 is described below
commit 5597fb6449aac8831378bb77dbd07d71edf7fe5c
Author: Eric Milles <[email protected]>
AuthorDate: Wed Jan 21 10:43:40 2026 -0600
GROOVY-11208: `String m() default ""` only for annotation declaration
---
src/antlr/GroovyParser.g4 | 9 ++--
..._10x.groovy => AnnotationDeclaration_02.groovy} | 29 +++++++------
.../fail/AnnotationDeclaration_01x.groovy | 22 ----------
.../fail/InterfaceDeclaration_01.groovy | 21 ----------
.../groovy/parser/antlr4/GroovyParserTest.groovy | 8 +---
.../groovy/parser/antlr4/SyntaxErrorTest.groovy | 48 +++++++++++++++++++---
6 files changed, 65 insertions(+), 72 deletions(-)
diff --git a/src/antlr/GroovyParser.g4 b/src/antlr/GroovyParser.g4
index b41faad333..e97417c651 100644
--- a/src/antlr/GroovyParser.g4
+++ b/src/antlr/GroovyParser.g4
@@ -275,15 +275,16 @@ memberDeclaration[int t]
/**
* t 0: *class member* all kinds of method declaration AND constructor
declaration,
- * 1: normal method declaration, 2: abstract method declaration
- * 3: normal method declaration OR abstract method declaration
+ * 1: normal method declaration,
+ * 2: abstract method declaration
+ * 3: method declaration OR abstract method declaration
* ct 9: script, other see the comment of classDeclaration
*/
methodDeclaration[int t, int ct]
: modifiersOpt typeParameters? (returnType[$ct] nls)?
methodName formalParameters
- (
- DEFAULT nls elementValue
+ ( { $ct == 3 }? // GROOVY-11208: @interface only
+ (DEFAULT nls elementValue)
|
(nls THROWS nls qualifiedClassNameList)?
(nls methodBody)?
diff --git a/src/test-resources/core/Annotation_10x.groovy
b/src/test-resources/core/AnnotationDeclaration_02.groovy
similarity index 71%
rename from src/test-resources/core/Annotation_10x.groovy
rename to src/test-resources/core/AnnotationDeclaration_02.groovy
index 1ee354bd4c..b520673302 100644
--- a/src/test-resources/core/Annotation_10x.groovy
+++ b/src/test-resources/core/AnnotationDeclaration_02.groovy
@@ -16,23 +16,26 @@
* specific language governing permissions and limitations
* under the License.
*/
-import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Retention
-
-def closureClass =
NestedAnnotationWithDefault.getAnnotation(AnnWithNestedAnnWithDefault).elem().elem()
-def closure = closureClass.newInstance(null, null)
-assert closure.call() == 3
-
-
-@AnnWithNestedAnnWithDefault(elem = @AnnWithDefaultValue())
-class NestedAnnotationWithDefault {}
+import java.lang.annotation.RetentionPolicy
@Retention(RetentionPolicy.RUNTIME)
-@interface AnnWithDefaultValue {
- Class elem() default { 1 + 2 }
+@interface ClassValueWithDefault {
+ Class value() default { 1 + 2 }
}
@Retention(RetentionPolicy.RUNTIME)
-@interface AnnWithNestedAnnWithDefault {
- AnnWithDefaultValue elem()
+@interface AnnotationValue {
+ ClassValueWithDefault value()
}
+
+@AnnotationValue(@ClassValueWithDefault())
+class TypeWithAnnotationWithAnnotationWithClosure {
+}
+
+def closureClass =
TypeWithAnnotationWithAnnotationWithClosure.getAnnotation(AnnotationValue).value().value()
+def closure = closureClass.newInstance(null, null)
+def value = closure.call()
+
+assert value instanceof Integer
+assert value == 3
diff --git a/src/test-resources/fail/AnnotationDeclaration_01x.groovy
b/src/test-resources/fail/AnnotationDeclaration_01x.groovy
deleted file mode 100644
index c32699ecac..0000000000
--- a/src/test-resources/fail/AnnotationDeclaration_01x.groovy
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-@interface A {
- void a()
-}
diff --git a/src/test-resources/fail/InterfaceDeclaration_01.groovy
b/src/test-resources/fail/InterfaceDeclaration_01.groovy
deleted file mode 100644
index 312818e086..0000000000
--- a/src/test-resources/fail/InterfaceDeclaration_01.groovy
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.
- */
-interface Foo {
- def doit( String param = "Groovy", int o )
-}
diff --git
a/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
b/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
index 60973387db..8dd54cf55b 100644
--- a/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
+++ b/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
@@ -145,7 +145,8 @@ final class GroovyParserTest {
doTest('core/Annotation_07.groovy')
doTest('core/Annotation_08.groovy')
doTest('core/Annotation_09.groovy')
- doRunAndTestAntlr4('core/Annotation_10x.groovy')
+ doTest('core/AnnotationDeclaration_01.groovy')
+ doRunAndTestAntlr4('core/AnnotationDeclaration_02.groovy')
}
@Test
@@ -413,11 +414,6 @@ final class GroovyParserTest {
doRunAndTestAntlr4('core/RecordDeclaration_14x.groovy')
}
- @Test
- void 'groovy core - AnnotationDeclaration'() {
- doTest('core/AnnotationDeclaration_01.groovy')
- }
-
@Test
void 'groovy core - SealedTypeDeclaration'() {
doRunAndTestAntlr4('core/SealedTypeDeclaration_01x.groovy')
diff --git
a/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
b/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
index 9d5b789773..788f47e8ef 100644
--- a/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
+++ b/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
@@ -22,8 +22,8 @@ import groovy.test.NotYetImplemented
import groovy.transform.AutoFinal
import org.codehaus.groovy.control.CompilationUnit
import org.codehaus.groovy.control.Phases
-import org.junit.Assert
-import org.junit.Test
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.Test
import static
org.apache.groovy.parser.antlr4.util.ASTComparatorCategory.LOCATION_IGNORE_LIST
@@ -285,7 +285,17 @@ final class SyntaxErrorTest {
@Test
void 'groovy core - AnnotationDeclaration 1'() {
- TestUtils.doRunAndShouldFail('fail/AnnotationDeclaration_01x.groovy')
+ expectParseError '''\
+ |@interface A {
+ | void a()
+ |}
+ |'''.stripMargin(), '''\
+ |annotation method cannot have void return type @ line 2, column 5.
+ | void a()
+ | ^
+ |
+ |1 error
+ |'''.stripMargin()
}
@Test
@@ -379,7 +389,17 @@ final class SyntaxErrorTest {
@Test
void 'groovy core - InterfaceDeclaration 1'() {
- TestUtils.shouldFail('fail/InterfaceDeclaration_01.groovy')
+ expectParseError '''\
+ |interface Foo {
+ | def doit( String param = "Groovy", int o )
+ |}
+ |'''.stripMargin(), '''\
+ |Cannot specify default value for method parameter 'param =
Groovy' inside an interface @ line 2, column 15.
+ | def doit( String param = "Groovy", int o )
+ | ^
+ |
+ |1 error
+ |'''.stripMargin()
}
@Test
@@ -395,6 +415,22 @@ final class SyntaxErrorTest {
|'''.stripMargin()
}
+ // GROOVY-11208
+ @Test
+ void 'groovy core - InterfaceDeclaration 3'() {
+ expectParseError '''\
+ |interface I {
+ | def m() default {1}
+ |}
+ |'''.stripMargin(), '''\
+ |Unexpected input: 'default' @ line 2, column 13.
+ | def m() default {1}
+ | ^
+ |
+ |1 error
+ |'''.stripMargin()
+ }
+
@Test
void 'groovy core - void'() {
TestUtils.doRunAndShouldFail('fail/Void_01x.groovy')
@@ -600,10 +636,10 @@ final class SyntaxErrorTest {
compile(Phases.CONVERSION)
getAST()
}
- Assert.fail('expected parse to fail')
+ Assertions.fail('expected parse to fail')
} catch (e) {
def line = (expect =~ /@ line (\d+),/)[0][1]
- Assert.assertEquals("startup failed:\ntest.groovy: $line:
$expect".toString(), e.message.replace('\r\n', '\n'))
+ Assertions.assertEquals("startup failed:\ntest.groovy: $line:
$expect".toString(), e.message.replace('\r\n', '\n'))
}
}