Repository: groovy Updated Branches: refs/heads/native-lambda 5965c5c07 -> d53fb4f8a
Support nested native lambda Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/d53fb4f8 Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/d53fb4f8 Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/d53fb4f8 Branch: refs/heads/native-lambda Commit: d53fb4f8a4d07811243f77c36980d153a9a23037 Parents: 5965c5c Author: sunlan <sun...@apache.org> Authored: Fri Jan 26 16:59:26 2018 +0800 Committer: sunlan <sun...@apache.org> Committed: Fri Jan 26 16:59:26 2018 +0800 ---------------------------------------------------------------------- .../asm/sc/StaticTypesLambdaWriter.java | 16 ++-- src/test/groovy/transform/stc/LambdaTest.groovy | 81 +++++++++++++++++++- 2 files changed, 88 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/d53fb4f8/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java index 121c8f6..899fd45 100644 --- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java +++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java @@ -107,7 +107,7 @@ public class StaticTypesLambdaWriter extends LambdaWriter { ClassNode classNode = controller.getClassNode(); boolean isInterface = classNode.isInterface(); - ClassNode lambdaClassNode = getOrAddLambdaClass(expression, ACC_PUBLIC | (isInterface ? ACC_STATIC : 0)); + ClassNode lambdaClassNode = getOrAddLambdaClass(expression, ACC_PUBLIC | (isInterface ? ACC_STATIC : 0), abstractMethodNode); MethodNode syntheticLambdaMethodNode = lambdaClassNode.getMethods(DO_CALL).get(0); newGroovyLambdaInstanceAndLoad(lambdaClassNode, syntheticLambdaMethodNode); @@ -259,10 +259,10 @@ public class StaticTypesLambdaWriter extends LambdaWriter { return parameterType.redirect().isInterface() && !parameterType.redirect().getAnnotations(ClassHelper.FunctionalInterface_Type).isEmpty(); } - public ClassNode getOrAddLambdaClass(LambdaExpression expression, int mods) { + public ClassNode getOrAddLambdaClass(LambdaExpression expression, int mods, MethodNode abstractMethodNode) { ClassNode lambdaClass = lambdaClassMap.get(expression); if (lambdaClass == null) { - lambdaClass = createLambdaClass(expression, mods); + lambdaClass = createLambdaClass(expression, mods, abstractMethodNode); lambdaClassMap.put(expression, lambdaClass); controller.getAcg().addInnerClass(lambdaClass); lambdaClass.addInterface(ClassHelper.GENERATED_LAMBDA_TYPE); @@ -271,7 +271,7 @@ public class StaticTypesLambdaWriter extends LambdaWriter { return lambdaClass; } - protected ClassNode createLambdaClass(LambdaExpression expression, int mods) { + protected ClassNode createLambdaClass(LambdaExpression expression, int mods, MethodNode abstractMethodNode) { ClassNode outerClass = controller.getOutermostClass(); ClassNode classNode = controller.getClassNode(); String name = genLambdaClassName(); @@ -290,7 +290,7 @@ public class StaticTypesLambdaWriter extends LambdaWriter { answer.setScriptBody(true); } - MethodNode syntheticLambdaMethodNode = addSyntheticLambdaMethodNode(expression, answer); + MethodNode syntheticLambdaMethodNode = addSyntheticLambdaMethodNode(expression, answer, abstractMethodNode); Parameter[] localVariableParameters = syntheticLambdaMethodNode.getNodeMetaData(LAMBDA_SHARED_VARIABLES); addFieldsAndGettersForLocalVariables(answer, localVariableParameters); @@ -312,9 +312,9 @@ public class StaticTypesLambdaWriter extends LambdaWriter { + controller.getContext().getNextLambdaInnerName(outerClass, classNode, methodNode); } - private MethodNode addSyntheticLambdaMethodNode(LambdaExpression expression, InnerClassNode answer) { + private MethodNode addSyntheticLambdaMethodNode(LambdaExpression expression, InnerClassNode answer, MethodNode abstractMethodNode) { Parameter[] parametersWithExactType = createParametersWithExactType(expression); // expression.getParameters(); - ClassNode returnType = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE); //abstractMethodNode.getReturnType(); +// ClassNode returnType = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE); //abstractMethodNode.getReturnType(); Parameter[] localVariableParameters = getLambdaSharedVariables(expression); removeInitialValues(localVariableParameters); @@ -325,7 +325,7 @@ public class StaticTypesLambdaWriter extends LambdaWriter { answer.addMethod( DO_CALL, Opcodes.ACC_PUBLIC, - returnType, + abstractMethodNode.getReturnType() /*ClassHelper.OBJECT_TYPE*/ /*returnType*/, methodParameterList.toArray(Parameter.EMPTY_ARRAY), ClassNode.EMPTY_ARRAY, expression.getCode() http://git-wip-us.apache.org/repos/asf/groovy/blob/d53fb4f8/src/test/groovy/transform/stc/LambdaTest.groovy ---------------------------------------------------------------------- diff --git a/src/test/groovy/transform/stc/LambdaTest.groovy b/src/test/groovy/transform/stc/LambdaTest.groovy index 7f28151..212ec11 100644 --- a/src/test/groovy/transform/stc/LambdaTest.groovy +++ b/src/test/groovy/transform/stc/LambdaTest.groovy @@ -485,7 +485,7 @@ TestScript0.groovy: 14: [Static type checking] - Cannot find matching method jav } public static void p() { - Function<Integer, String> f = (Integer e) -> 'a' + e + Function<Integer, String> f = (Integer e) -> 'a' + e // STC can not infer the type of `e`, so we have to specify the type `Integer` by ourselves assert ['a1', 'a2', 'a3'] == [1, 2, 3].stream().map(f).collect(Collectors.toList()) } } @@ -520,4 +520,83 @@ TestScript0.groovy: 14: [Static type checking] - Cannot find matching method jav ''' } + + void testFunctionWithNestedLambda() { + assertScript ''' + import groovy.transform.CompileStatic + import java.util.stream.Collectors + import java.util.stream.Stream + + @CompileStatic + public class Test1 { + public static void main(String[] args) { + p() + } + + public static void p() { + [1, 2].stream().forEach(e -> { + def list = ['a', 'b'].stream().map(f -> f + e).toList() + if (1 == e) { + assert ['a1', 'b1'] == list + } else if (2 == e) { + assert ['a2', 'b2'] == list + } + }) + + } + } + ''' + } + + void testFunctionWithNestedLambda2() { + assertScript ''' + import groovy.transform.CompileStatic + import java.util.stream.Collectors + import java.util.stream.Stream + + @CompileStatic + public class Test1 { + public static void main(String[] args) { + p() + } + + public static void p() { + def list = ['a', 'b'].stream() + .map(e -> { + [1, 2].stream().map(f -> e + f).toList() + }).toList() + + assert ['a1', 'a2'] == list[0] + assert ['b1', 'b2'] == list[1] + } + } + ''' + } + + void testFunctionWithNestedLambda3() { + assertScript ''' + import groovy.transform.CompileStatic + import java.util.stream.Collectors + import java.util.stream.Stream + import java.util.function.Function + + @CompileStatic + public class Test1 { + public static void main(String[] args) { + p() + } + + public static void p() { + def list = ['a', 'b'].stream() + .map(e -> { + Function<Integer, String> x = (Integer f) -> e + f + [1, 2].stream().map(x).toList() + }).toList() + + assert ['a1', 'a2'] == list[0] + assert ['b1', 'b2'] == list[1] + } + } + ''' + } }