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 5f8c82e9c8 GROOVY-10855: normalized annotation metadata (pt.2)
5f8c82e9c8 is described below
commit 5f8c82e9c88bb7087bdf134f2864d7ca9008b9e7
Author: Eric Milles <[email protected]>
AuthorDate: Tue Aug 8 16:52:10 2023 -0500
GROOVY-10855: normalized annotation metadata (pt.2)
---
src/main/java/groovy/lang/DelegatesTo.java | 52 +++++++++++++---------
.../java/groovy/transform/stc/ClosureParams.java | 2 +
.../stc/ClosureParamTypeInferenceSTCTest.groovy | 28 ++++++------
3 files changed, 48 insertions(+), 34 deletions(-)
diff --git a/src/main/java/groovy/lang/DelegatesTo.java
b/src/main/java/groovy/lang/DelegatesTo.java
index c3c650de9e..3b57d3f423 100644
--- a/src/main/java/groovy/lang/DelegatesTo.java
+++ b/src/main/java/groovy/lang/DelegatesTo.java
@@ -22,12 +22,10 @@ import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
/**
- * This annotation can be used by API or DSL writers to document parameters
which accept a closure.
- * In that case, using this annotation, you can specify what the delegate type
of the closure will
- * be. This is important for IDE support.
+ * This annotation can be used by API or DSL writers to specify what the
delegate
+ * type of a closure will be. This is important for IDE support.
* <p>
* This annotation can also be used to help the type checker ({@link
groovy.transform.TypeChecked})
* which would not report errors then if the delegate is of the documented
type. Of course, it is
@@ -35,7 +33,7 @@ import java.lang.annotation.Target;
* <p>
* Example:
* <pre>
- * // Document the fact that the delegate of the closure will be an ExecSpec
+ * // Declare that the delegate of the closure will be an ExecSpec
* ExecResult exec(@DelegatesTo(ExecSpec) Closure closure) { ... }
* </pre>
*
@@ -43,12 +41,22 @@ import java.lang.annotation.Target;
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.PARAMETER, ElementType.METHOD})
[email protected](ElementType.PARAMETER)
public @interface DelegatesTo {
- Class value() default Target.class;
/**
- * The {@link Closure#resolveStrategy} used by the closure.
+ * The closure's delegate type, if not using {@code DelegatesTo.Target} or
{@link #type()}.
+ */
+ Class value() default DelegatesTo.Target.class;
+
+ /**
+ * The closure's resolve strategy.
+ *
+ * @see Closure#DELEGATE_FIRST
+ * @see Closure#DELEGATE_ONLY
+ * @see Closure#OWNER_FIRST
+ * @see Closure#OWNER_ONLY
+ * @see Closure#TO_SELF
*/
int strategy() default Closure.OWNER_FIRST;
@@ -66,29 +74,33 @@ public @interface DelegatesTo {
String target() default "";
/**
- * The type member should be used when the type of the delegate cannot
- * be represented with {@link #value()}, {@link #genericTypeIndex()} or
- * {@link #target()}. In this case, it is possible to use a String to
represent
- * the type, at the cost of potential uncaught errors at compile time if
the
- * type is invalid and increased compile time.
+ * The type member should be used when the type of the delegate cannot be
+ * represented by {@link #value()} or {@link #target()}. In this case, it
+ * is possible to use a string to represent the type, at the cost of more
+ * compile time and potential uncaught load errors if the type is invalid.
*
- * @return a String representation of a type
* @since 2.4.0
*/
String type() default "";
/**
- * Parameter annotation used to specify the delegate for a {@code
@DelegatesTo} annotated
- * parameter of the same method.
+ * Specifies the delegate for a {@code @DelegatesTo} annotated parameter
of the same method.
+ * <p>
+ * Example:
+ * <pre>
+ * // Declare that the delegate of the closure will be the "spec" argument
+ * ExecResult exec(@DelegatesTo.Target ExecSpec spec, @DelegatesTo Closure
closure) { ... }
+ * </pre>
*/
+ @Documented
@Retention(RetentionPolicy.RUNTIME)
- @java.lang.annotation.Target({ElementType.PARAMETER})
+ @java.lang.annotation.Target(ElementType.PARAMETER)
@interface Target {
/**
- * An identifier that should be used to disambiguate targets when
there are
- * multiple {@code @DelegatesTo.Target} annotated parameters.
+ * An identifier used to disambiguate targets when there are multiple
+ * {@code @DelegatesTo.Target} annotated parameters.
*/
String value() default "";
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/groovy/transform/stc/ClosureParams.java
b/src/main/java/groovy/transform/stc/ClosureParams.java
index e788d4457a..d5cd7ead8b 100644
--- a/src/main/java/groovy/transform/stc/ClosureParams.java
+++ b/src/main/java/groovy/transform/stc/ClosureParams.java
@@ -18,6 +18,7 @@
*/
package groovy.transform.stc;
+import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -55,6 +56,7 @@ import java.lang.annotation.Target;
* <p>Which uses the {@link FirstParam.FirstGenericType} first generic type of
the first argument</p> hint to tell that the only expected
* argument type corresponds to the type of the first generic argument type of
the first method parameter.
*/
+@Documented
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClosureParams {
diff --git
a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
index b99bdd63c1..9aa74d2317 100644
--- a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
@@ -248,7 +248,7 @@ class ClosureParamTypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
void testFromStringWithTypeParameterFromClass() {
assertScript '''
class Foo<T> {
- void foo(@ClosureParams(value=FromString,
options="java.util.List<T>") Closure cl) { cl.call(['hey','ya']) }
+ void foo(@ClosureParams(value=FromString,
options="java.util.List<T>") Closure c) { c.call(['hey','ya']) }
}
def foo = new Foo<String>()
foo.foo { List<String> str -> str.each { println it.toUpperCase()
} }
@@ -258,7 +258,7 @@ class ClosureParamTypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
void testFromStringWithTypeParameterFromClassWithTwoGenerics() {
assertScript '''
class Foo<T,U> {
- void foo(@ClosureParams(value=FromString,
options="java.util.List<U>") Closure cl) { cl.call(['hey','ya']) }
+ void foo(@ClosureParams(value=FromString,
options="java.util.List<U>") Closure c) { c.call(['hey','ya']) }
}
def foo = new Foo<Integer,String>()
foo.foo { List<String> str -> str.each { println it.toUpperCase()
} }
@@ -268,7 +268,7 @@ class ClosureParamTypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
void
testFromStringWithTypeParameterFromClassWithTwoGenericsAndNoExplicitSignature()
{
assertScript '''
class Foo<T,U> {
- public void foo(@ClosureParams(value=FromString,
options="java.util.List<U>") Closure cl) { cl.call(['hey','ya']) }
+ void foo(@ClosureParams(value=FromString,
options="java.util.List<U>") Closure c) { c.call(['hey','ya']) }
}
def foo = new Foo<Integer,String>()
foo.foo { it.each { println it.toUpperCase() } }
@@ -278,7 +278,7 @@ class ClosureParamTypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
void
testFromStringWithTypeParameterFromClassWithTwoGenericsAndNoExplicitSignatureAndNoFQN()
{
assertScript '''
class Foo<T,U> {
- public void foo(@ClosureParams(value=FromString,
options="List<U>") Closure cl) { cl.call(['hey','ya']) }
+ void foo(@ClosureParams(value=FromString, options="List<U>")
Closure c) { c.call(['hey','ya']) }
}
def foo = new Foo<Integer,String>()
foo.foo { it.each { println it.toUpperCase() } }
@@ -293,7 +293,7 @@ class ClosureParamTypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
}
}
class Tor<D,U> {
- public void foo(@ClosureParams(value=FromString,
options="List<U>") Closure cl) { cl.call([new Foo(), new Foo()]) }
+ void foo(@ClosureParams(value=FromString, options="List<U>")
Closure c) { c.call([new Foo(), new Foo()]) }
}
def tor = new Tor<Integer,Foo>()
tor.foo { it.each { it.bar() } }
@@ -308,7 +308,7 @@ class ClosureParamTypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
}
}
class Tor<D,U> {
- public void foo(@ClosureParams(value=FromString,
options=["D,List<U>"]) Closure cl) { cl.call(3, [new Foo(), new Foo()]) }
+ void foo(@ClosureParams(value=FromString,
options=["D,List<U>"]) Closure c) { c.call(3, [new Foo(), new Foo()]) }
}
def tor = new Tor<Integer,Foo>()
tor.foo { r, e -> r.times { e.each { it.bar() } } }
@@ -323,11 +323,11 @@ class ClosureParamTypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
}
}
class Tor<D,U> {
- public void foo(@ClosureParams(value=FromString,
options=["D,List<U>","D"]) Closure cl) {
- if (cl.maximumNumberOfParameters==2) {
- cl.call(3, [new Foo(), new Foo()])
+ void foo(@ClosureParams(value=FromString,
options=["D,List<U>","D"]) Closure c) {
+ if (c.maximumNumberOfParameters==2) {
+ c.call(3, [new Foo(), new Foo()])
} else {
- cl.call(3)
+ c.call(3)
}
}
}
@@ -339,11 +339,11 @@ class ClosureParamTypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
void testFromStringWithConflictResolutionStrategy() {
assertScript '''
- def transform(value, @ClosureParams(value=FromString,
options=["Integer","String"], conflictResolutionStrategy=PickFirstResolver)
Closure condition) {
- if (condition.parameterTypes[0].simpleName == 'String') {
- condition(value.toString())
+ def transform(value, @ClosureParams(value=FromString,
options=["Integer","String"], conflictResolutionStrategy=PickFirstResolver)
Closure c) {
+ if (c.parameterTypes[0].simpleName == 'String') {
+ c(value.toString())
} else {
- condition(value instanceof Integer ? value :
value.toString().size())
+ c(value instanceof Integer ? value :
value.toString().size())
}
}