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
The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
new 7c62395 GROOVY-10033, GROOVY-10046, GROOVY-10047: refs for ctor and
static calls
7c62395 is described below
commit 7c6239554227201c86211006bd5193b138ab7889
Author: Eric Milles <[email protected]>
AuthorDate: Wed Apr 21 11:57:04 2021 -0500
GROOVY-10033, GROOVY-10046, GROOVY-10047: refs for ctor and static calls
Conflicts:
src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
src/test/groovy/transform/stc/MethodReferenceTest.groovy
---
.../java/org/codehaus/groovy/ast/ClassHelper.java | 2 +-
...StaticTypesMethodReferenceExpressionWriter.java | 123 ++++++-------
.../asm/sc/StaticTypesWriterController.java | 8 +-
.../transform/stc/StaticTypeCheckingVisitor.java | 26 ++-
.../transform/stc/MethodReferenceTest.groovy | 202 ++++++++++++++++-----
5 files changed, 222 insertions(+), 139 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
b/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
index 17bcc8d..413ac68 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
@@ -418,7 +418,7 @@ public class ClassHelper {
public static boolean isFunctionalInterface(final ClassNode type) {
// Functional interface must be an interface at first, or the
following exception will occur:
// java.lang.invoke.LambdaConversionException: Functional interface
SamCallable is not an interface
- return type.isInterface() && isSAMType(type);
+ return type != null && type.isInterface() && isSAMType(type);
}
/**
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 ebbfdb9..14af6ba 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
@@ -20,10 +20,7 @@ package org.codehaus.groovy.classgen.asm.sc;
import groovy.lang.Tuple;
import groovy.lang.Tuple2;
-import groovy.transform.CompileStatic;
-import groovy.transform.Generated;
import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.MethodNode;
@@ -31,17 +28,17 @@ 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;
import org.codehaus.groovy.ast.tools.GeneralUtils;
import org.codehaus.groovy.classgen.asm.BytecodeHelper;
import org.codehaus.groovy.classgen.asm.MethodReferenceExpressionWriter;
import org.codehaus.groovy.classgen.asm.WriterController;
-import org.codehaus.groovy.runtime.ArrayTypeUtils;
import org.codehaus.groovy.syntax.RuntimeParserException;
+import org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys;
import org.codehaus.groovy.transform.stc.ExtensionMethodNode;
-import org.objectweb.asm.MethodVisitor;
+import org.codehaus.groovy.transform.stc.StaticTypesMarker;
import org.objectweb.asm.Opcodes;
import java.util.Arrays;
@@ -49,27 +46,25 @@ import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
+import static org.apache.groovy.ast.tools.ClassNodeUtils.addGeneratedMethod;
import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
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;
import static
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.findDGMMethodsForClassNode;
import static
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.isAssignableTo;
-import static
org.codehaus.groovy.transform.stc.StaticTypesMarker.CLOSURE_ARGUMENTS;
/**
- * Writer responsible for generating method reference in statically compiled
mode.
+ * Generates bytecode for method reference expressions in statically-compiled
code.
*
* @since 3.0.0
*/
public class StaticTypesMethodReferenceExpressionWriter extends
MethodReferenceExpressionWriter implements AbstractFunctionalInterfaceWriter {
- private static final String METHODREF_EXPR_INSTANCE =
"__METHODREF_EXPR_INSTANCE";
- private static final ClassNode GENERATED_TYPE =
ClassHelper.make(Generated.class);
- private static final ClassNode COMPILE_STATIC_TYPE =
ClassHelper.make(CompileStatic.class);
public StaticTypesMethodReferenceExpressionWriter(WriterController
controller) {
super(controller);
@@ -103,7 +98,7 @@ public class StaticTypesMethodReferenceExpressionWriter
extends MethodReferenceE
ClassNode typeOrTargetRefType = isClassExpression ?
typeOrTargetRef.getType()
: controller.getTypeChooser().resolveType(typeOrTargetRef,
classNode);
- ClassNode[] methodReferenceParamTypes =
methodReferenceExpression.getNodeMetaData(CLOSURE_ARGUMENTS);
+ ClassNode[] methodReferenceParamTypes =
methodReferenceExpression.getNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS);
Parameter[] parametersWithExactType =
createParametersWithExactType(abstractMethodNode, methodReferenceParamTypes);
String methodRefName =
methodReferenceExpression.getMethodName().getText();
@@ -127,33 +122,30 @@ public class StaticTypesMethodReferenceExpressionWriter
extends MethodReferenceE
methodRefMethod = addSyntheticMethodForDGSM(methodRefMethod);
}
- ClassExpression classExpression = new
ClassExpression(methodRefMethod.getDeclaringClass());
+ typeOrTargetRefType = methodRefMethod.getDeclaringClass();
+ ClassExpression classExpression = classX(typeOrTargetRefType);
classExpression.setSourcePosition(typeOrTargetRef);
typeOrTargetRef = classExpression;
- typeOrTargetRefType = typeOrTargetRef.getType();
+ isClassExpression = true;
}
methodRefMethod.putNodeMetaData(ORIGINAL_PARAMETERS_WITH_EXACT_TYPE,
parametersWithExactType);
- MethodVisitor mv = controller.getMethodVisitor();
- boolean isClassExpr = isClassExpr(typeOrTargetRef);
- if (!isClassExpr) {
+ if (!isClassExpression) {
if (isConstructorReference) {
- // TODO move the checking code to the Parrot parser
+ // TODO: move the checking code to the Parrot parser
addFatalError("Constructor reference must be className::new",
methodReferenceExpression);
} else if (methodRefMethod.isStatic()) {
ClassExpression classExpression = classX(typeOrTargetRefType);
classExpression.setSourcePosition(typeOrTargetRef);
typeOrTargetRef = classExpression;
- isClassExpr = true;
- }
-
- if (!isClassExpr) {
+ isClassExpression = true;
+ } else {
typeOrTargetRef.visit(controller.getAcg());
}
}
- mv.visitInvokeDynamicInsn(
+ controller.getMethodVisitor().visitInvokeDynamicInsn(
abstractMethodNode.getName(),
createAbstractMethodDesc(functionalInterfaceType,
typeOrTargetRef),
createBootstrapMethod(isInterface, false),
@@ -164,7 +156,7 @@ public class StaticTypesMethodReferenceExpressionWriter
extends MethodReferenceE
methodRefMethod, false)
);
- if (isClassExpr) {
+ if (isClassExpression) {
controller.getOperandStack().push(redirect);
} else {
controller.getOperandStack().replace(redirect, 1);
@@ -194,55 +186,53 @@ public class StaticTypesMethodReferenceExpressionWriter
extends MethodReferenceE
private MethodNode addSyntheticMethodForDGSM(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);
+ returnValue.setMethodTarget(mn);
- MethodNode syntheticMethodNode =
controller.getClassNode().addSyntheticMethod(
- "dgsm$$" +
mn.getParameters()[0].getType().getName().replace(".", "$") + "$$" +
mn.getName(),
+ MethodNode delegateMethod =
addGeneratedMethod(controller.getClassNode(),
+ "dgsm$$" +
mn.getParameters()[0].getType().getName().replace('.', '$') + "$$" +
mn.getName(),
Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL |
Opcodes.ACC_SYNTHETIC,
mn.getReturnType(),
parameters,
ClassNode.EMPTY_ARRAY,
- block(
- returnS(
- callX(new
ClassExpression(mn.getDeclaringClass()), mn.getName(), args)
- )
- )
+ block(returnS(returnValue))
);
- syntheticMethodNode.addAnnotation(new AnnotationNode(GENERATED_TYPE));
- syntheticMethodNode.addAnnotation(new
AnnotationNode(COMPILE_STATIC_TYPE));
+
delegateMethod.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE,
Boolean.TRUE);
- return syntheticMethodNode;
+ return delegateMethod;
}
private MethodNode addSyntheticMethodForConstructorReference(String
syntheticMethodName, ClassNode returnType, Parameter[] parametersWithExactType)
{
ArgumentListExpression ctorArgs = args(parametersWithExactType);
- MethodNode syntheticMethodNode =
controller.getClassNode().addSyntheticMethod(
+ Expression returnValue;
+ if (returnType.isArray()) {
+ returnValue = new ArrayExpression(
+ returnType.getComponentType(),
+ null, ctorArgs.getExpressions());
+ } else {
+ returnValue = ctorX(returnType, ctorArgs);
+ }
+
+ MethodNode delegateMethod =
addGeneratedMethod(controller.getClassNode(),
syntheticMethodName,
Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL |
Opcodes.ACC_SYNTHETIC,
returnType,
parametersWithExactType,
ClassNode.EMPTY_ARRAY,
- block(
- returnS(
- returnType.isArray()
- ?
- new ArrayExpression(
-
ClassHelper.make(ArrayTypeUtils.elementType(returnType.getTypeClass())),
- null,
- ctorArgs.getExpressions()
- )
- :
- ctorX(returnType, ctorArgs)
- )
- )
+ block(returnS(returnValue))
);
- syntheticMethodNode.addAnnotation(new AnnotationNode(GENERATED_TYPE));
- syntheticMethodNode.addAnnotation(new
AnnotationNode(COMPILE_STATIC_TYPE));
+ // TODO: if StaticTypesMarker.DIRECT_METHOD_CALL_TARGET or
+ // OptimizingStatementWriter.StatementMeta.class metadatas
+ // can bet set for the ctorX above, then this can be TRUE:
+
delegateMethod.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE,
Boolean.FALSE);
- return syntheticMethodNode;
+ return delegateMethod;
}
private String genSyntheticMethodNameForConstructorReference() {
@@ -261,7 +251,7 @@ public class StaticTypesMethodReferenceExpressionWriter
extends MethodReferenceE
List<Parameter> methodReferenceSharedVariableList = new LinkedList<>();
if (!(methodRef instanceof ClassExpression)) {
- prependParameter(methodReferenceSharedVariableList,
METHODREF_EXPR_INSTANCE,
+ prependParameter(methodReferenceSharedVariableList,
"__METHODREF_EXPR_INSTANCE",
controller.getTypeChooser().resolveType(methodRef,
controller.getClassNode()));
}
@@ -269,29 +259,22 @@ public class StaticTypesMethodReferenceExpressionWriter
extends MethodReferenceE
}
private Parameter[] createParametersWithExactType(MethodNode
abstractMethodNode, ClassNode[] inferredParameterTypes) {
- Parameter[] originalParameters = abstractMethodNode.getParameters();
-
// We MUST clone the parameters to avoid impacting the original
parameter type of SAM
- Parameter[] parameters = GeneralUtils.cloneParams(originalParameters);
+ Parameter[] parameters =
GeneralUtils.cloneParams(abstractMethodNode.getParameters());
if (parameters == null) {
parameters = Parameter.EMPTY_ARRAY;
}
-
- for (int i = 0; i < parameters.length; i++) {
- Parameter parameter = parameters[i];
- ClassNode parameterType = parameter.getType();
- ClassNode inferredType = inferredParameterTypes[i];
-
- if (null == inferredType) {
- continue;
+ if (inferredParameterTypes != null) {
+ for (int i = 0, n = parameters.length; i < n; i += 1) {
+ ClassNode inferredParamType = inferredParameterTypes[i];
+ if (inferredParamType == null) continue;
+ Parameter parameter = parameters[i];
+
+ ClassNode type = convertParameterType(parameter.getType(),
inferredParamType);
+ parameter.setOriginType(type);
+ parameter.setType(type);
}
-
- ClassNode type = convertParameterType(parameterType, inferredType);
-
- parameter.setType(type);
- parameter.setOriginType(type);
}
-
return parameters;
}
diff --git
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
index 25bd2a0..8aa352c 100644
---
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
+++
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
@@ -100,10 +100,8 @@ public class StaticTypesWriterController extends
DelegatingController {
node = classNode.getOuterClass();
}
- boolean isStaticCompileNode =
classNode.getNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE) !=
null;
- isInStaticallyCheckedMethod =
- mn != null &&
(StaticCompilationVisitor.isStaticallyCompiled(node)
- ||
implementsGeneratedClosureOrGeneratedLambdaInterface && isStaticCompileNode);
+ isInStaticallyCheckedMethod = mn != null &&
(StaticCompilationVisitor.isStaticallyCompiled(node)
+ || implementsGeneratedClosureOrGeneratedLambdaInterface &&
Boolean.TRUE.equals(classNode.getNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE)));
}
@Override
@@ -121,7 +119,7 @@ public class StaticTypesWriterController extends
DelegatingController {
@Override
public CallSiteWriter getCallSiteWriter() {
MethodNode methodNode = getMethodNode();
- if (methodNode !=null &&
methodNode.getNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION)==Boolean.TRUE)
{
+ if (methodNode != null &&
Boolean.TRUE.equals(methodNode.getNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION)))
{
return super.getCallSiteWriter();
}
if (isInStaticallyCheckedMethod) {
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 897e5ba..ed0c92c 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -2724,6 +2724,9 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
if (nExpressions > 0 && expressions.get(0) instanceof MapExpression &&
params.length > 0) {
checkNamedParamsAnnotation(params[0], (MapExpression)
expressions.get(0));
}
+ if (visitClosures) {
+ inferMethodReferenceType(receiver, arguments, selectedMethod);
+ }
}
private void checkNamedParamsAnnotation(final Parameter param, final
MapExpression args) {
@@ -3564,8 +3567,6 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
}
}
}
-
- inferMethodReferenceType(call, receiver, argumentList);
} finally {
typeCheckingContext.popEnclosingMethodCall();
extension.afterMethodCall(call);
@@ -3583,28 +3584,23 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
return Closure.OWNER_FIRST;
}
- private void inferMethodReferenceType(final MethodCallExpression call,
final ClassNode receiver, final ArgumentListExpression argumentList) {
- if (call == null) return;
+ private void inferMethodReferenceType(final ClassNode receiver, final
ArgumentListExpression argumentList, final MethodNode selectedMethod) {
if (receiver == null) return;
if (argumentList == null) return;
+ if (selectedMethod == null) return;
- List<Expression> argumentExpressionList =
argumentList.getExpressions();
- if (argumentExpressionList == null) return;
-
- boolean noMethodReferenceParams =
argumentExpressionList.stream().noneMatch(e -> e instanceof
MethodReferenceExpression);
- if (noMethodReferenceParams) {
+ List<Expression> argumentExpressions = argumentList.getExpressions();
+ if (argumentExpressions == null || argumentExpressions.stream()
+ .noneMatch(e -> e instanceof MethodReferenceExpression)) {
return;
}
- MethodNode selectedMethod =
call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
- if (selectedMethod == null) return;
-
Parameter[] parameters = selectedMethod.getParameters();
List<Integer> methodReferenceParamIndexList = new LinkedList<>();
List<Expression> newArgumentExpressionList = new LinkedList<>();
- for (int i = 0, n = argumentExpressionList.size(); i < n; i++) {
- Expression argumentExpression = argumentExpressionList.get(i);
+ for (int i = 0, n = argumentExpressions.size(); i < n; i += 1) {
+ Expression argumentExpression = argumentExpressions.get(i);
if (!(argumentExpression instanceof MethodReferenceExpression)) {
newArgumentExpressionList.add(argumentExpression);
continue;
@@ -3630,7 +3626,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
for (Integer methodReferenceParamIndex :
methodReferenceParamIndexList) {
LambdaExpression lambdaExpression = (LambdaExpression)
newArgumentExpressionList.get(methodReferenceParamIndex);
ClassNode[] argumentTypes =
lambdaExpression.getNodeMetaData(CLOSURE_ARGUMENTS);
-
argumentExpressionList.get(methodReferenceParamIndex).putNodeMetaData(CLOSURE_ARGUMENTS,
argumentTypes);
+
argumentExpressions.get(methodReferenceParamIndex).putNodeMetaData(CLOSURE_ARGUMENTS,
argumentTypes);
}
}
diff --git a/src/test/groovy/transform/stc/MethodReferenceTest.groovy
b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
index 4e00072..4ff62ab 100644
--- a/src/test/groovy/transform/stc/MethodReferenceTest.groovy
+++ b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
@@ -44,21 +44,55 @@ class MethodReferenceTest extends GroovyTestCase {
@groovy.transform.CompileStatic
void p() {
def result = [1, 2,
3].stream().map(Integer::toString).collect(Collectors.toList())
- assert result ['1', '2', '3']
+ assert result == ['1', '2', '3']
}
p()
'''
}
- // class::instanceMethod
+ // class::instanceMethod -- GROOVY-10047
void testFunctionCI3() {
+ assertScript '''
+ import java.util.function.Function
+ import static java.util.stream.Collectors.toMap
+
+ @groovy.transform.CompileStatic
+ void p() {
+ List<String> list = ['a','bc','def']
+ Function<String,String> self = str -> str // help for toMap
+ def map = list.stream().collect(toMap(self, String::length))
+ assert map == [a: 1, bc: 2, 'def': 3]
+ }
+
+ p()
+ '''
+
+ assertScript '''
+ import java.util.function.Function
+ import static java.util.stream.Collectors.toMap
+
+ @groovy.transform.CompileStatic
+ void p() {
+ List<String> list = ['a','bc','def']
+ // TODO: inference for T in toMap(Function<? super T,...>,
Function<? super T,...>)
+ def map =
list.stream().collect(toMap(Function.<String>identity(), String::length))
+ assert map == [a: 1, bc: 2, 'def': 3]
+ }
+
+ p()
+ '''
+ }
+
+ // class::instanceMethod
+ void testFunctionCI4() {
def err = shouldFail '''
- import java.util.stream.Collectors
+ import static java.util.stream.Collectors.toList
@groovy.transform.CompileStatic
void p() {
- def result = [1, 2,
3].stream().map(String::toString).collect(Collectors.toList())
+ def result = [1, 2,
3].stream().map(String::toString).collect(toList())
+ assert result == ["1", "2", "3"]
}
p()
@@ -68,10 +102,10 @@ class MethodReferenceTest extends GroovyTestCase {
}
// class::instanceMethod -- GROOVY-9814
- void testFunctionCI4() {
+ void testFunctionCI5() {
assertScript '''
import java.util.function.*
- import groovy.transform.CompileStatic
+ import groovy.transform.*
@CompileStatic
class One { String id }
@@ -79,7 +113,7 @@ class MethodReferenceTest extends GroovyTestCase {
@CompileStatic
class Two extends One { }
- @CompileStatic
@groovy.transform.Immutable(knownImmutableClasses=[Function])
+ @CompileStatic @Immutable(knownImmutableClasses=[Function])
class FunctionHolder<T> {
Function<T, ?> extractor
@@ -122,41 +156,6 @@ class MethodReferenceTest extends GroovyTestCase {
'''
}
- // class::staticMethod
- void testFunctionCS() {
- assertScript '''
- import groovy.transform.CompileStatic
- import java.util.stream.Collectors
- @CompileStatic
- void p() {
- def result = [1, -2,
3].stream().map(Math::abs).collect(Collectors.toList())
- assert [1, 2, 3] == result
- }
- p()
- '''
- }
-
- // class::staticMethod -- GROOVY-9799
- void testFunctionCS2() {
- assertScript '''
- class C {
- String x
- }
- class D {
- String x
- static D from(C c) {
- new D(x: c.x)
- }
- }
- @groovy.transform.CompileStatic
- def test(C c) {
- Optional.of(c).map(D::from).get()
- }
- def d = test(new C(x: 'x'))
- assert d.x == 'x'
- '''
- }
-
// instance::instanceMethod
void testBinaryOperatorII() {
assertScript '''
@@ -316,30 +315,137 @@ class MethodReferenceTest extends GroovyTestCase {
}
// arrayClass::new
- void testIntFunctionCN() {
+ void testFunctionCN() {
assertScript '''
@groovy.transform.CompileStatic
void p() {
- assert new Integer[] { 1, 2, 3 } == [1, 2,
3].stream().toArray(Integer[]::new)
+ def result = [1, 2, 3].stream().toArray(Integer[]::new)
+ assert result == new Integer[] { 1, 2, 3 }
}
p()
-
'''
}
// class::new
- void testFunctionCN() {
+ void testFunctionCN2() {
assertScript '''
- import java.util.stream.Collectors
+ import static java.util.stream.Collectors.toList
+
+ @groovy.transform.CompileStatic
+ void p() {
+ def result = ["1", "2",
"3"].stream().map(Integer::new).collect(toList())
+ assert result == [1, 2, 3]
+ }
+
+ p()
+ '''
+ }
+
+ // class::new -- GROOVY-10033
+ void testFunctionCN3() {
+ assertScript '''
+ import java.util.function.Function
+
+ @groovy.transform.CompileStatic
+ class C {
+ C(Function<String,Integer> f) {
+ def i = f.apply('42')
+ assert i == 42
+ }
+ static test() {
+ new C(Integer::new)
+ }
+ }
+ C.test()
+ '''
+ }
+
+ // class::new -- GROOVY-10033
+ void testFunctionCN4() {
+ assertScript '''
+ import java.util.function.Function
+
+ class A {
+ A(Function<A,B> f) {
+ B b = f.apply(this)
+ assert b instanceof X.Y
+ }
+ }
+ class B {
+ B(A a) {
+ assert a != null
+ }
+ }
+ @groovy.transform.CompileStatic
+ class X extends A {
+ public X() {
+ super(Y::new)
+ }
+ private static class Y extends B {
+ Y(A a) {
+ super(a)
+ }
+ }
+ }
+
+ new X()
+ '''
+ }
+
+ // class::staticMethod
+ void testFunctionCS() {
+ assertScript '''
+ import static java.util.stream.Collectors.toList
@groovy.transform.CompileStatic
void p() {
- assert [1, 2, 3] == ["1", "2",
"3"].stream().map(Integer::new).collect(Collectors.toList())
+ def result = [1, -2,
3].stream().map(Math::abs).collect(toList())
+ assert [1, 2, 3] == result
}
p()
+ '''
+ }
+
+ // class::staticMethod
+ void testFunctionCS2() {
+ assertScript '''
+ import java.util.function.Function
+ import static java.util.stream.Collectors.toMap
+
+ @groovy.transform.CompileStatic
+ void p() {
+ List<String> list = ['x','y','z']
+ def map = list.stream().collect(toMap(Function.identity(),
Collections::singletonList))
+ assert map == [x: ['x'], y: ['y'], z: ['z']]
+ }
+
+ p()
+ '''
+ }
+
+ // class::staticMethod -- GROOVY-9799
+ void testFunctionCS3() {
+ assertScript '''
+ class C {
+ String x
+ }
+ class D {
+ String x
+ static D from(C c) {
+ new D(x: c.x)
+ }
+ }
+
+ @groovy.transform.CompileStatic
+ def test(C c) {
+ Optional.of(c).map(D::from).get()
+ }
+
+ def d = test(new C(x: 'x'))
+ assert d.x == 'x'
'''
}