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 2022/01/30 20:43:23 UTC
[groovy] 01/04: GROOVY-10336: STC: handle method reference(s) supplied to variadic param
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 0864af26c811c4b866960d49d5d516d201be3089
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Nov 1 10:37:29 2021 -0500
GROOVY-10336: STC: handle method reference(s) supplied to variadic param
Conflicts:
src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
---
.../transform/stc/StaticTypeCheckingVisitor.java | 45 +++++++++++-----------
.../transform/stc/MethodReferenceTest.groovy | 20 ++++++++++
2 files changed, 42 insertions(+), 23 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 206b6bc..453040d 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -3629,39 +3629,38 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
Parameter[] parameters = selectedMethod.getParameters();
+ final int nthParameter = parameters.length - 1;
- List<Integer> methodReferenceParamIndexList = new LinkedList<>();
- List<Expression> newArgumentExpressionList = new LinkedList<>();
+ List<Integer> methodReferencePositions = new LinkedList<>();
+ List<Expression> newArgumentExpressions = new LinkedList<>();
for (int i = 0, n = argumentExpressions.size(); i < n; i += 1) {
Expression argumentExpression = argumentExpressions.get(i);
if (!(argumentExpression instanceof MethodReferenceExpression)) {
- newArgumentExpressionList.add(argumentExpression);
- continue;
- }
-
- Parameter param = parameters[i];
- ClassNode paramType = param.getType();
+ newArgumentExpressions.add(argumentExpression);
+ } else {
+ Parameter param = parameters[Math.min(i, nthParameter)]; // GROOVY-10336
+ ClassNode paramType = param.getType();
+ if (i >= nthParameter && paramType.isArray())
+ paramType = paramType.getComponentType();
- if (!isFunctionalInterface(paramType.redirect())) {
- addError("The argument is a method reference, but the parameter type is not a functional interface", argumentExpression);
- newArgumentExpressionList.add(argumentExpression);
- continue;
+ if (!isFunctionalInterface(paramType.redirect())) {
+ addError("The argument is a method reference, but the parameter type is not a functional interface", argumentExpression);
+ newArgumentExpressions.add(argumentExpression);
+ } else {
+ methodReferencePositions.add(i);
+ newArgumentExpressions.add(constructLambdaExpressionForMethodReference(paramType));
+ }
}
-
- LambdaExpression constructedLambdaExpression = constructLambdaExpressionForMethodReference(paramType);
-
- newArgumentExpressionList.add(constructedLambdaExpression);
- methodReferenceParamIndexList.add(i);
}
- if (methodReferenceParamIndexList.isEmpty()) return; // GROOVY-10269
+ if (methodReferencePositions.isEmpty()) return; // GROOVY-10269
- visitMethodCallArguments(receiver, new ArgumentListExpression(newArgumentExpressionList), true, selectedMethod);
+ visitMethodCallArguments(receiver, args(newArgumentExpressions), true, selectedMethod);
- for (Integer methodReferenceParamIndex : methodReferenceParamIndexList) {
- LambdaExpression lambdaExpression = (LambdaExpression) newArgumentExpressionList.get(methodReferenceParamIndex);
- ClassNode[] argumentTypes = lambdaExpression.getNodeMetaData(CLOSURE_ARGUMENTS);
- argumentExpressions.get(methodReferenceParamIndex).putNodeMetaData(CLOSURE_ARGUMENTS, argumentTypes);
+ for (int index : methodReferencePositions) {
+ Expression lambdaExpression = newArgumentExpressions.get(index);
+ Expression methodReferenceExpression = argumentExpressions.get(index);
+ methodReferenceExpression.putNodeMetaData(CLOSURE_ARGUMENTS, lambdaExpression.getNodeMetaData(CLOSURE_ARGUMENTS));
}
}
diff --git a/src/test/groovy/transform/stc/MethodReferenceTest.groovy b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
index 70ed133..7afcd0e 100644
--- a/src/test/groovy/transform/stc/MethodReferenceTest.groovy
+++ b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
@@ -692,4 +692,24 @@ final class MethodReferenceTest extends GroovyTestCase {
assert err =~ /The argument is a method reference, but the parameter type is not a functional interface/
}
+
+ // GROOVY-10336
+ void testNotFunctionalInterface2() {
+ def err = shouldFail '''
+ import java.util.function.Supplier
+
+ class C {
+ Integer m() { 1 }
+ }
+ @groovy.transform.CompileStatic
+ void test() {
+ Supplier<Long> outer = () -> {
+ Closure<Long> inner = (Object o, Supplier<Integer> s) -> 2L
+ inner(new Object(), new C()::m)
+ }
+ }
+ '''
+
+ assert err =~ /The argument is a method reference, but the parameter type is not a functional interface/
+ }
}