You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2019/12/19 19:15:13 UTC
[groovy] branch GROOVY-9340 updated: GROOVY-9342: support I super
T> i = lambda/closure
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY-9340
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY-9340 by this push:
new bcbaa09 GROOVY-9342: support I<? super T> i = lambda/closure
bcbaa09 is described below
commit bcbaa0951be4301f83f2878305b87609eef9589b
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Dec 19 13:14:37 2019 -0600
GROOVY-9342: support I<? super T> i = lambda/closure
---
.../codehaus/groovy/ast/tools/GenericsUtils.java | 55 ++++++++++++----------
src/test/groovy/transform/stc/LambdaTest.groovy | 15 ++++++
2 files changed, 45 insertions(+), 25 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
index 3ce6be7..19261e7 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -48,6 +48,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.function.Function;
import java.util.function.Predicate;
import static groovy.lang.Tuple.tuple;
@@ -925,7 +926,7 @@ public class GenericsUtils {
}
/**
- * Get the parameter and return types of the abstract method of SAM
+ * Gets the parameter and return types of the abstract method of SAM.
*
* If the abstract method is not parameterized, we will get generics placeholders, e.g. T, U
* For example, the abstract method of {@link java.util.function.Function} is
@@ -942,31 +943,23 @@ public class GenericsUtils {
* we can get parameter types and return type of the above abstract method,
* i.e. ClassNode {@code ClassHelper.STRING_TYPE} and {@code ClassHelper.Integer_TYPE}
*
- * @param sam the class node which contains only one abstract method
- * @return the parameter and return types
- * @since 3.0.0
+ * @param samType the class node which contains only one abstract method
*
+ * @since 3.0.0
*/
- public static Tuple2<ClassNode[], ClassNode> parameterizeSAM(ClassNode sam) {
- MethodNode methodNode = ClassHelper.findSAM(sam);
- final Map<GenericsType, GenericsType> map = makeDeclaringAndActualGenericsTypeMapOfExactType(methodNode.getDeclaringClass(), sam);
-
- ClassNode[] parameterTypes =
- Arrays.stream(methodNode.getParameters())
- .map(e -> {
- ClassNode originalParameterType = e.getType();
- return originalParameterType.isGenericsPlaceHolder()
- ? findActualTypeByGenericsPlaceholderName(originalParameterType.getUnresolvedName(), map)
- : originalParameterType;
- })
- .toArray(ClassNode[]::new);
-
- ClassNode originalReturnType = methodNode.getReturnType();
- ClassNode returnType =
- originalReturnType.isGenericsPlaceHolder()
- ? findActualTypeByGenericsPlaceholderName(originalReturnType.getUnresolvedName(), map)
- : originalReturnType;
+ public static Tuple2<ClassNode[], ClassNode> parameterizeSAM(final ClassNode samType) {
+ MethodNode abstractMethod = ClassHelper.findSAM(samType);
+
+ Map<GenericsType, GenericsType> generics = makeDeclaringAndActualGenericsTypeMapOfExactType(abstractMethod.getDeclaringClass(), samType);
+ Function<ClassNode, ClassNode> resolver = t -> {
+ if (t.isGenericsPlaceHolder()) {
+ return findActualTypeByGenericsPlaceholderName(t.getUnresolvedName(), generics);
+ }
+ return t;
+ };
+ ClassNode[] parameterTypes = Arrays.stream(abstractMethod.getParameters()).map(Parameter::getType).map(resolver).toArray(ClassNode[]::new);
+ ClassNode returnType = resolver.apply(abstractMethod.getReturnType());
return tuple(parameterTypes, returnType);
}
@@ -977,9 +970,21 @@ public class GenericsUtils {
* @param genericsPlaceholderAndTypeMap the result of {@link #makeDeclaringAndActualGenericsTypeMap(ClassNode, ClassNode)}
*/
public static ClassNode findActualTypeByGenericsPlaceholderName(final String placeholderName, final Map<GenericsType, GenericsType> genericsPlaceholderAndTypeMap) {
+ Function<GenericsType, ClassNode> resolver = gt -> {
+ if (gt.isWildcard()) {
+ if (gt.getLowerBound() != null) {
+ return gt.getLowerBound();
+ }
+ if (gt.getUpperBounds() != null) {
+ return gt.getUpperBounds()[0];
+ }
+ }
+ return gt.getType();
+ };
+
return genericsPlaceholderAndTypeMap.entrySet().stream()
- .filter(entry -> entry.getKey().getName().equals(placeholderName))
- .map(entry -> entry.getValue().getType()).findFirst().orElse(null);
+ .filter(e -> e.getKey().getName().equals(placeholderName))
+ .map(Map.Entry::getValue).map(resolver).findFirst().orElse(null);
}
private static class ParameterizedTypeCacheKey {
diff --git a/src/test/groovy/transform/stc/LambdaTest.groovy b/src/test/groovy/transform/stc/LambdaTest.groovy
index 4b2960b..bc2eb13 100644
--- a/src/test/groovy/transform/stc/LambdaTest.groovy
+++ b/src/test/groovy/transform/stc/LambdaTest.groovy
@@ -741,6 +741,21 @@ final class LambdaTest {
'''
}
+ @Test // GROOVY-9342
+ void testConsumer7() {
+ assertScript '''
+ @groovy.transform.CompileStatic
+ void test() {
+ int sum = 0
+ java.util.function.Consumer<? super Integer> add = i -> sum += i
+
+ [1, 2, 3].forEach(add)
+ assert sum == 6
+ }
+ test()
+ '''
+ }
+
@Test
void testFunctionalInterface1() {
assertScript '''