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 c8272f2bcba681589b317084b6610384a383ae44 Author: Daniel Sun <sun...@apache.org> AuthorDate: Mon Mar 18 22:45:46 2019 +0800 Support expression::instanceMethod and expression::staticMethod --- .../classgen/asm/sc/StaticTypesLambdaWriter.java | 2 +- ...StaticTypesMethodReferenceExpressionWriter.java | 27 ++--- .../transform/stc/MethodReferenceTest.groovy | 120 ++++++++------------- 3 files changed, 57 insertions(+), 92 deletions(-) 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 1f0524b..1a3c1c8 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 @@ -139,7 +139,7 @@ public class StaticTypesLambdaWriter extends LambdaWriter implements AbstractFun mv.visitInsn(DUP); loadEnclosingClassInstance(); - loadEnclosingClassInstance(); + controller.getOperandStack().dup(); loadSharedVariables(syntheticLambdaMethodNode); 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 9ea102c..9fd304d 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 @@ -19,7 +19,6 @@ package org.codehaus.groovy.classgen.asm.sc; import groovy.lang.GroovyRuntimeException; -import org.codehaus.groovy.GroovyBugError; import org.codehaus.groovy.ast.ClassHelper; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.MethodNode; @@ -29,14 +28,10 @@ import org.codehaus.groovy.ast.expr.ArrayExpression; import org.codehaus.groovy.ast.expr.ClassExpression; import org.codehaus.groovy.ast.expr.Expression; import org.codehaus.groovy.ast.expr.MethodReferenceExpression; -import org.codehaus.groovy.ast.expr.VariableExpression; import org.codehaus.groovy.ast.tools.GeneralUtils; import org.codehaus.groovy.ast.tools.ParameterUtils; import org.codehaus.groovy.classgen.asm.BytecodeHelper; -import org.codehaus.groovy.classgen.asm.BytecodeVariable; -import org.codehaus.groovy.classgen.asm.CompileStack; import org.codehaus.groovy.classgen.asm.MethodReferenceExpressionWriter; -import org.codehaus.groovy.classgen.asm.OperandStack; import org.codehaus.groovy.classgen.asm.WriterController; import org.codehaus.groovy.runtime.ArrayTypeUtils; import org.objectweb.asm.MethodVisitor; @@ -47,7 +42,6 @@ import java.util.Arrays; import java.util.LinkedList; import java.util.List; -import static org.codehaus.groovy.ast.ClassHelper.getWrapper; 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.ctorX; @@ -71,6 +65,12 @@ public class StaticTypesMethodReferenceExpressionWriter extends MethodReferenceE ClassNode functionalInterfaceType = getFunctionalInterfaceType(methodReferenceExpression); ClassNode redirect = functionalInterfaceType.redirect(); + if (null == functionalInterfaceType || !ClassHelper.isFunctionalInterface(redirect)) { + // if the parameter type is not real FunctionInterface or failed to be inferred, generate the default bytecode, which is actually a method closure + super.writeMethodReferenceExpression(methodReferenceExpression); + return; + } + MethodNode abstractMethodNode = ClassHelper.findSAM(redirect); String abstractMethodDesc = createMethodDescriptor(abstractMethodNode); @@ -113,20 +113,11 @@ public class StaticTypesMethodReferenceExpressionWriter extends MethodReferenceE ClassExpression classExpression = new ClassExpression(mrExprType); classExpression.setSourcePosition(mrExpr); mrExpr = classExpression; + isClassExpr = true; } - if (mrExpr instanceof VariableExpression) { - VariableExpression variableExpression = (VariableExpression) mrExpr; - - OperandStack operandStack = controller.getOperandStack(); - CompileStack compileStack = controller.getCompileStack(); - BytecodeVariable variable = compileStack.getVariable(variableExpression.getName(), true); - - operandStack.loadOrStoreVariable(variable, variableExpression.isUseReferenceDirectly()); - } else if (mrExpr instanceof ClassExpression) { - // DO NOTHING - } else { - throw new GroovyBugError("TODO: " + mrExpr.getClass()); + if (!isClassExpr) { + mrExpr.visit(controller.getAcg()); } } diff --git a/src/test/groovy/transform/stc/MethodReferenceTest.groovy b/src/test/groovy/transform/stc/MethodReferenceTest.groovy index f0a90d0..e620ddd 100644 --- a/src/test/groovy/transform/stc/MethodReferenceTest.groovy +++ b/src/test/groovy/transform/stc/MethodReferenceTest.groovy @@ -38,22 +38,6 @@ class MethodReferenceTest extends GroovyTestCase { } // class::instanceMethod - void testFunctionCI_STATICMETHOD() { - assertScript ''' - import java.util.stream.Collectors - - @groovy.transform.CompileStatic - static void p() { - def result = [1, 2, 3].stream().map(Object::toString).collect(Collectors.toList()) - assert 3 == result.size() - assert ['1', '2', '3'] == result - } - - p() - ''' - } - - // class::instanceMethod void testBinaryOperatorCI() { if (true) return @@ -71,22 +55,6 @@ class MethodReferenceTest extends GroovyTestCase { ''' } - // class::instanceMethod - void testBinaryOperatorCI_STATICMETHOD() { - assertScript ''' - import java.util.stream.Stream - - @groovy.transform.CompileStatic - static void p() { - def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), BigDecimal::add) - - assert new BigDecimal(6) == result - } - - p() - ''' - } - // class::staticMethod void testFunctionCS() { assertScript ''' @@ -104,33 +72,40 @@ class MethodReferenceTest extends GroovyTestCase { ''' } - // class::staticMethod - void testFunctionCS_STATICMETHOD() { + // instance::instanceMethod + void testBinaryOperatorII() { assertScript ''' import java.util.stream.Stream import java.util.stream.Collectors @groovy.transform.CompileStatic - static void p() { - def result = [1, -2, 3].stream().map(Math::abs).collect(Collectors.toList()) + void p() { + Adder adder = new Adder() + def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), adder::add) - assert [1, 2, 3] == result + assert new BigDecimal(6) == result } p() + + @groovy.transform.CompileStatic + class Adder { + public BigDecimal add(BigDecimal a, BigDecimal b) { + return a.add(b) + } + } ''' } - // instance::instanceMethod - void testBinaryOperatorII() { + // expression::instanceMethod + void testBinaryOperatorII_EXPRESSION() { assertScript ''' import java.util.stream.Stream import java.util.stream.Collectors @groovy.transform.CompileStatic void p() { - Adder adder = new Adder() - def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), adder::add) + def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), new Adder()::add) assert new BigDecimal(6) == result } @@ -146,16 +121,15 @@ class MethodReferenceTest extends GroovyTestCase { ''' } - // instance::instanceMethod - void testBinaryOperatorII_STATICMETHOD() { + // expression::instanceMethod + void testBinaryOperatorII_EXPRESSION2() { assertScript ''' import java.util.stream.Stream import java.util.stream.Collectors @groovy.transform.CompileStatic - static void p() { - Adder adder = new Adder() - def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), adder::add) + void p() { + def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), new Adder().getThis()::add) assert new BigDecimal(6) == result } @@ -167,6 +141,10 @@ class MethodReferenceTest extends GroovyTestCase { public BigDecimal add(BigDecimal a, BigDecimal b) { return a.add(b) } + + Adder getThis() { + return this + } } ''' } @@ -196,16 +174,15 @@ class MethodReferenceTest extends GroovyTestCase { ''' } - // instance::staticMethod - void testBinaryOperatorIS_STATICMETHOD() { + // expression::staticMethod + void testBinaryOperatorIS_EXPRESSION() { assertScript ''' import java.util.stream.Stream import java.util.stream.Collectors @groovy.transform.CompileStatic - static void p() { - Adder adder = new Adder() - def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), adder::add) + void p() { + def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), new Adder()::add) assert new BigDecimal(6) == result } @@ -221,28 +198,41 @@ class MethodReferenceTest extends GroovyTestCase { ''' } - // arrayClass::new - void testIntFunctionCN() { + // expression::staticMethod + void testBinaryOperatorIS_EXPRESSION2() { assertScript ''' import java.util.stream.Stream + import java.util.stream.Collectors @groovy.transform.CompileStatic void p() { - assert new Integer[] { 1, 2, 3 } == [1, 2, 3].stream().toArray(Integer[]::new) + def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), Adder.newInstance()::add) + + assert new BigDecimal(6) == result } p() - + + @groovy.transform.CompileStatic + class Adder { + public static BigDecimal add(BigDecimal a, BigDecimal b) { + return a.add(b) + } + + static Adder newInstance() { + return new Adder() + } + } ''' } // arrayClass::new - void testIntFunctionCN_STATICMETHOD() { + void testIntFunctionCN() { assertScript ''' import java.util.stream.Stream @groovy.transform.CompileStatic - static void p() { + void p() { assert new Integer[] { 1, 2, 3 } == [1, 2, 3].stream().toArray(Integer[]::new) } @@ -267,20 +257,4 @@ class MethodReferenceTest extends GroovyTestCase { ''' } - // class::new - void testFunctionCN_STATICMETHOD() { - assertScript ''' - import java.util.stream.Stream - import java.util.stream.Collectors - - @groovy.transform.CompileStatic - static void p() { - assert [1, 2, 3] == ["1", "2", "3"].stream().map(Integer::new).collect(Collectors.toList()) - } - - p() - - ''' - } - }