You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2019/04/08 12:59:08 UTC
[groovy] 16/20: Support reference on the RHS
This is an automated email from the ASF dual-hosted git repository.
paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit febc0673aff58f559a9dcfa7c62f4e83448e853e
Author: Daniel Sun <su...@apache.org>
AuthorDate: Mon Mar 25 23:51:20 2019 +0800
Support reference on the RHS
---
.../transform/stc/StaticTypeCheckingVisitor.java | 35 ++++++++++++++++++--
.../groovy/transform/stc/StaticTypesMarker.java | 3 +-
.../transform/stc/MethodReferenceTest.groovy | 37 ++++++++++++++++++++++
3 files changed, 71 insertions(+), 4 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 9294b7e..18a42a3 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -265,6 +265,7 @@ import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.toMeth
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.typeCheckMethodArgumentWithGenerics;
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.typeCheckMethodsWithGenerics;
import static org.codehaus.groovy.transform.stc.StaticTypesMarker.CLOSURE_ARGUMENTS;
+import static org.codehaus.groovy.transform.stc.StaticTypesMarker.CONSTRUCTED_LAMBDA_EXPRESSION;
import static org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_TYPE;
//import static org.codehaus.groovy.syntax.Types.COMPARE_NOT_INSTANCEOF;
@@ -827,7 +828,26 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
} else {
lType = getType(leftExpression);
- inferParameterAndReturnTypesOfClosureOnRHS(lType, rightExpression, op);
+
+ Expression constructedRightExpression = rightExpression;
+
+ boolean isMrExprRHS = rightExpression instanceof MethodReferenceExpression && ClassHelper.isFunctionalInterface(lType);
+ if (isMrExprRHS) {
+ constructedRightExpression = constructLambdaExpressionForMethodReference(lType);
+ }
+
+ inferParameterAndReturnTypesOfClosureOnRHS(lType, constructedRightExpression, op);
+
+ if (isMrExprRHS) {
+ LambdaExpression lambdaExpression = (LambdaExpression) constructedRightExpression;
+ ClassNode[] argumentTypes =
+ Arrays.stream(lambdaExpression.getParameters())
+ .map(Parameter::getType)
+ .toArray(ClassNode[]::new);
+
+ rightExpression.putNodeMetaData(CLOSURE_ARGUMENTS, argumentTypes);
+ rightExpression.putNodeMetaData(CONSTRUCTED_LAMBDA_EXPRESSION, lambdaExpression);
+ }
rightExpression.visit(this);
}
@@ -4355,8 +4375,17 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
// ex : def foos = ['a','b','c']
return right;
}
- if (rightRedirect.isDerivedFrom(CLOSURE_TYPE) && isSAMType(leftRedirect) && rightExpression instanceof ClosureExpression) {
- return inferSAMTypeGenericsInAssignment(left, findSAM(left), right, (ClosureExpression) rightExpression);
+ if (rightRedirect.isDerivedFrom(CLOSURE_TYPE) && isSAMType(leftRedirect)) {
+ ClosureExpression closureExpression = null;
+ if (rightExpression instanceof ClosureExpression) {
+ closureExpression = (ClosureExpression) rightExpression;
+ } else if (rightExpression instanceof MethodReferenceExpression) {
+ closureExpression = rightExpression.getNodeMetaData(CONSTRUCTED_LAMBDA_EXPRESSION);
+ }
+
+ if (null != closureExpression) {
+ return inferSAMTypeGenericsInAssignment(left, findSAM(left), right, closureExpression);
+ }
}
if (leftExpression instanceof VariableExpression) {
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypesMarker.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypesMarker.java
index 03b678c..6f7d6d3 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypesMarker.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypesMarker.java
@@ -39,5 +39,6 @@ public enum StaticTypesMarker {
DYNAMIC_RESOLUTION, // call recognized by a type checking extension as a dynamic method call
SUPER_MOP_METHOD_REQUIRED, // used to store the list of MOP methods that still have to be generated
PARAMETER_TYPE, // used to store the parameter type information of method invocation on an expression
- INFERRED_FUNCTIONAL_INTERFACE_TYPE // used to store the function interface type information on an expression
+ INFERRED_FUNCTIONAL_INTERFACE_TYPE, // used to store the function interface type information on an expression
+ CONSTRUCTED_LAMBDA_EXPRESSION // used to store the constructed lambda expression for method reference and constructor reference
}
diff --git a/src/test/groovy/transform/stc/MethodReferenceTest.groovy b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
index ffe7297..70b1f7f 100644
--- a/src/test/groovy/transform/stc/MethodReferenceTest.groovy
+++ b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
@@ -272,4 +272,41 @@ class MethodReferenceTest extends GroovyTestCase {
'''
}
+
+ // class::staticMethod
+ void testFunctionCS_RHS() {
+ assertScript '''
+ import java.util.function.Function
+ import java.util.stream.Stream
+ import java.util.stream.Collectors
+
+ @groovy.transform.CompileStatic
+ void p() {
+ Function<Integer, Integer> f = Math::abs
+ def result = [1, -2, 3].stream().map(f).collect(Collectors.toList())
+
+ assert [1, 2, 3] == result
+ }
+
+ p()
+ '''
+ }
+
+ // class::new
+ void testFunctionCN_RHS() {
+ assertScript '''
+ import java.util.function.Function
+ import java.util.stream.Stream
+ import java.util.stream.Collectors
+
+ @groovy.transform.CompileStatic
+ void p() {
+ Function<String, Integer> f = Integer::new
+ assert [1, 2, 3] == ["1", "2", "3"].stream().map(f).collect(Collectors.toList())
+ }
+
+ p()
+
+ '''
+ }
}