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 2021/05/02 23:12:39 UTC
[groovy] 02/02: GROOVY-10072: SC/STC: support "def c = { p =
defaultValue -> return p }"
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
commit 356a7a2c58915af24d105d96d98a17ae1f86d7cb
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun May 2 16:49:41 2021 -0500
GROOVY-10072: SC/STC: support "def c = { p = defaultValue -> return p }"
---
.../groovy/classgen/asm/ClosureWriter.java | 4 +-
.../classgen/asm/sc/StaticTypesClosureWriter.java | 4 +-
...StaticTypesMethodReferenceExpressionWriter.java | 4 +-
.../transform/stc/StaticTypeCheckingVisitor.java | 44 ++++++++++++----------
.../groovy/transform/stc/ClosuresSTCTest.groovy | 17 ++++++++-
.../groovy/transform/stc/GenericsSTCTest.groovy | 1 -
6 files changed, 47 insertions(+), 27 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
index 607d6e3..dda126d 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
@@ -31,7 +31,6 @@ import org.codehaus.groovy.ast.Variable;
import org.codehaus.groovy.ast.VariableScope;
import org.codehaus.groovy.ast.expr.ClassExpression;
import org.codehaus.groovy.ast.expr.ClosureExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.FieldExpression;
@@ -54,6 +53,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorSuperX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
@@ -196,7 +196,7 @@ public class ClosureWriter {
parameters = Parameter.EMPTY_ARRAY;
} else if (parameters.length == 0) {
// let's create a default 'it' parameter
- Parameter it = param(ClassHelper.OBJECT_TYPE, "it", ConstantExpression.NULL);
+ Parameter it = param(ClassHelper.OBJECT_TYPE, "it", nullX());
parameters = new Parameter[]{it};
Variable ref = expression.getVariableScope().getDeclaredVariable("it");
if (ref != null) it.setClosureSharedVariable(ref.isClosureSharedVariable());
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesClosureWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesClosureWriter.java
index 89020f1..a1ad0da 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesClosureWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesClosureWriter.java
@@ -96,7 +96,9 @@ public class StaticTypesClosureWriter extends ClosureWriter {
private static Expression defaultArgument(final Parameter parameter) {
Expression argument;
- if (parameter.getType().isArray()) {
+ if (parameter.hasInitialExpression()) {
+ argument = parameter.getInitialExpression();
+ } else if (parameter.getType().isArray()) {
ClassNode elementType = parameter.getType().getComponentType();
argument = new ArrayExpression(elementType, null, Collections.singletonList(constX(0, true)));
} else {
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
index 6294174..222e9ee 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
@@ -28,7 +28,6 @@ import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.expr.ArgumentListExpression;
import org.codehaus.groovy.ast.expr.ArrayExpression;
import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.expr.MethodReferenceExpression;
@@ -53,6 +52,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
import static org.codehaus.groovy.ast.tools.ParameterUtils.parametersCompatible;
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.filterMethodsByVisibility;
@@ -173,7 +173,7 @@ public class StaticTypesMethodReferenceExpressionWriter extends MethodReferenceE
private MethodNode addSyntheticMethodForDGSM(final MethodNode mn) {
Parameter[] parameters = removeFirstParameter(mn.getParameters());
ArgumentListExpression args = args(parameters);
- args.getExpressions().add(0, ConstantExpression.NULL);
+ args.getExpressions().add(0, nullX());
MethodCallExpression returnValue = callX(classX(mn.getDeclaringClass()), mn.getName(), args);
returnValue.putNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET, mn);
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 3aad94a..d3d5159 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -238,7 +238,7 @@ import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.Matche
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.NUMBER_OPS;
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.UNKNOWN_PARAMETER_TYPE;
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.addMethodLevelDeclaredGenerics;
-import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.allParametersAndArgumentsMatch;
+import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.allParametersAndArgumentsMatchWithDefaultParams;
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsConnections;
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext;
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContextToParameterClass;
@@ -1852,30 +1852,32 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
typeCheckingContext.isInStaticContext = node.isInStaticContext();
currentField = node;
visitAnnotations(node);
- Expression init = node.getInitialExpression();
- if (init != null) {
- ClassNode lType = getType(node);
- if (isFunctionalInterface(lType)) { // GROOVY-9977
- processFunctionalInterfaceAssignment(lType, init);
- } else if (isClosureWithType(lType) && init instanceof ClosureExpression) {
- storeInferredReturnType(init, getCombinedBoundType(lType.getGenericsTypes()[0]));
- }
- init.visit(this);
- ClassNode rType = getType(init);
- if (init instanceof ConstructorCallExpression) {
- inferDiamondType((ConstructorCallExpression) init, lType);
- }
-
- FieldExpression left = new FieldExpression(node);
- BinaryExpression bexp = assignX(left, init, node);
- typeCheckAssignment(bexp, left, lType, init, getResultType(lType, ASSIGN, rType, bexp));
- }
+ visitInitialExpression(node.getInitialExpression(), new FieldExpression(node), node);
} finally {
currentField = null;
typeCheckingContext.isInStaticContext = osc;
}
}
+ private void visitInitialExpression(final Expression value, final Expression target, final ASTNode position) {
+ if (value != null) {
+ ClassNode lType = target.getType();
+ if (isFunctionalInterface(lType)) { // GROOVY-9977
+ processFunctionalInterfaceAssignment(lType, value);
+ } else if (isClosureWithType(lType) && value instanceof ClosureExpression) {
+ storeInferredReturnType(value, getCombinedBoundType(lType.getGenericsTypes()[0]));
+ }
+ value.visit(this);
+ ClassNode rType = getType(value);
+ if (value instanceof ConstructorCallExpression) {
+ inferDiamondType((ConstructorCallExpression) value, lType);
+ }
+
+ BinaryExpression bexp = assignX(target, value, position);
+ typeCheckAssignment(bexp, target, lType, value, getResultType(lType, ASSIGN, rType, bexp));
+ }
+ }
+
@Override
public void visitForLoop(final ForStatement forLoop) {
// collect every variable expression used in the loop body
@@ -2405,6 +2407,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
typeCheckingContext.isInStaticContext = oldStaticContext;
for (Parameter parameter : getParametersSafe(expression)) {
typeCheckingContext.controlStructureVariables.remove(parameter);
+ // GROOVY-10071: visit param default argument expression if present
+ visitInitialExpression(parameter.getInitialExpression(), varX(parameter), parameter);
}
}
@@ -3880,7 +3884,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
protected void typeCheckClosureCall(final Expression arguments, final ClassNode[] argumentTypes, final Parameter[] parameters) {
- if (allParametersAndArgumentsMatch(parameters, argumentTypes) < 0 && lastArgMatchesVarg(parameters, argumentTypes) < 0) {
+ if (allParametersAndArgumentsMatchWithDefaultParams(parameters, argumentTypes) < 0 && lastArgMatchesVarg(parameters, argumentTypes) < 0) {
addStaticTypeError("Cannot call closure that accepts " + formatArgumentList(extractTypesFromParameters(parameters)) + " with " + formatArgumentList(argumentTypes), arguments);
}
}
diff --git a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
index 3af0ba9..fb6ffe9 100644
--- a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
@@ -55,6 +55,21 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
'''
}
+ // GROOVY-10072
+ void testClosureWithoutArguments5() {
+ assertScript '''
+ def c = { p = 'foo' -> return p }
+ assert c('bar') == 'bar'
+ assert c() == 'foo'
+ '''
+
+ assertScript '''
+ def c = { p, q = 'baz' -> '' + p + q }
+ assert c('foo', 'bar') == 'foobar'
+ assert c('foo') == 'foobaz'
+ '''
+ }
+
void testClosureWithArguments1() {
assertScript '''
def c = { int a, int b -> a + b }
@@ -62,7 +77,7 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
'''
shouldFailWithMessages '''
- def c = { int a, int b -> print a + b }
+ def c = { int a, int b -> a + b }
c('5', '7')
''',
'Cannot call closure that accepts [int, int] with [java.lang.String, java.lang.String]'
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index b1ae721..811a5d9 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -650,7 +650,6 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
- @NotYetImplemented
void testDiamondInferrenceFromConstructor9b() {
assertScript '''
@groovy.transform.TupleConstructor(defaults=false)