groovy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pa...@apache.org
Subject [groovy] 08/20: Clone the parameters to avoid impacting the original parameter type of SAM
Date Mon, 08 Apr 2019 12:59:00 GMT
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 100db21fc938440f9ed691c81c9847c7afad9232
Author: Daniel Sun <sunlan@apache.org>
AuthorDate: Sat Mar 9 02:52:13 2019 +0800

    Clone the parameters to avoid impacting the original parameter type of SAM
---
 .../codehaus/groovy/ast/tools/GenericsUtils.java   | 84 ++++------------------
 ...StaticTypesMethodReferenceExpressionWriter.java |  6 +-
 src/test/groovy/transform/stc/LambdaTest.groovy    | 15 +++-
 .../groovy/ast/tools/GenericsUtilsTest.groovy      | 44 +-----------
 4 files changed, 34 insertions(+), 115 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
index 7a68d35..b28771a 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -20,7 +20,6 @@ package org.codehaus.groovy.ast.tools;
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
-import groovy.lang.Tuple;
 import groovy.lang.Tuple2;
 import groovy.transform.stc.IncorrectTypeHintException;
 import org.apache.groovy.util.SystemUtil;
@@ -961,82 +960,25 @@ public class GenericsUtils {
      */
     public static Tuple2<ClassNode[], ClassNode> parameterizeSAM(ClassNode sam) {
         MethodNode methodNode = ClassHelper.findSAM(sam);
-        return parameterizeMethodNode(methodNode, sam);
-    }
-
-    /**
-     * Get the parameter and return types of the specified method node
-     *
-     * @param parameterizedClassNode the class node which contains the specified method node
-     * @param methodNode the specified method node to parameterize
-     * @return the parameter and return types
-     * @since 3.0.0
-     */
-    public static Tuple2<ClassNode[], ClassNode> parameterizeMethodNode(MethodNode
methodNode, ClassNode parameterizedClassNode) {
-        final Map<GenericsType, GenericsType> map = makeDeclaringAndActualGenericsTypeMapOfExactType(methodNode.getDeclaringClass(),
parameterizedClassNode);
+        final Map<GenericsType, GenericsType> map = makeDeclaringAndActualGenericsTypeMapOfExactType(methodNode.getDeclaringClass(),
sam);
 
         ClassNode[] parameterTypes =
                 Arrays.stream(methodNode.getParameters())
-                    .map(e -> findActualType(e.getType(), map))
+                    .map(e -> {
+                        ClassNode originalParameterType = e.getType();
+                        return originalParameterType.isGenericsPlaceHolder()
+                                ? findActualTypeByGenericsPlaceholderName(originalParameterType.getUnresolvedName(),
map)
+                                : originalParameterType;
+                    })
                     .toArray(ClassNode[]::new);
 
-        ClassNode returnType = findActualType(methodNode.getReturnType(), map);
-        return tuple(parameterTypes, returnType);
-    }
-
-    private static ClassNode findActualType(ClassNode originalParameterType, Map<GenericsType,
GenericsType> map) {
-        if (originalParameterType.isGenericsPlaceHolder()) {
-            return findActualTypeByGenericsPlaceholderName(originalParameterType.getUnresolvedName(),
map);
-        }
-
-        if (null != originalParameterType.getGenericsTypes()) {
-            return findGenericsActualType(originalParameterType, map);
-        }
-
-        return originalParameterType;
-    }
+        ClassNode originalReturnType = methodNode.getReturnType();
+        ClassNode returnType =
+                originalReturnType.isGenericsPlaceHolder()
+                        ? findActualTypeByGenericsPlaceholderName(originalReturnType.getUnresolvedName(),
map)
+                        : originalReturnType;
 
-    private static ClassNode findGenericsActualType(ClassNode classNodeWithGenerics, Map<GenericsType,
GenericsType> map) {
-        Tuple2<ClassNode, Boolean> genericsActualTypeTuple = doFindGenericsActualType(classNodeWithGenerics,
map);
-        return genericsActualTypeTuple.getV1();
-    }
-
-    private static Tuple2<ClassNode, Boolean> doFindGenericsActualType(ClassNode classNodeWithGenerics,
Map<GenericsType, GenericsType> map) {
-        GenericsType[] genericsTypes = classNodeWithGenerics.getGenericsTypes();
-        if (null != genericsTypes) {
-            List<GenericsType> newGenericsTypeList = new LinkedList<>();
-            boolean hasPlaceHolders = false;
-            for (GenericsType gt : genericsTypes) {
-                ClassNode type;
-                if (gt.isPlaceholder()) {
-                    type = findActualTypeByGenericsPlaceholderName(gt.getType().getUnresolvedName(),
map);
-                    hasPlaceHolders = true;
-                } else {
-                    Tuple2<ClassNode, Boolean> genericsActualTypeTuple = doFindGenericsActualType(gt.getType(),
map);
-                    type = genericsActualTypeTuple.getV1();
-                    hasPlaceHolders = genericsActualTypeTuple.getV2();
-                }
-
-                if (null == type) { // TODO handle method generics, e.g. Stream.map
-                    return Tuple.tuple(classNodeWithGenerics, hasPlaceHolders);
-                }
-
-                GenericsType genericsType = new GenericsType(type);
-                genericsType.setSourcePosition(gt);
-                newGenericsTypeList.add(genericsType);
-            }
-
-            if (hasPlaceHolders) {
-                ClassNode newClassNodeWithGenerics = ClassHelper.makeWithoutCaching(classNodeWithGenerics.getTypeClass(),
false);
-                newClassNodeWithGenerics.setGenericsTypes(newGenericsTypeList.toArray(GenericsType.EMPTY_ARRAY));
-                newClassNodeWithGenerics.setRedirect(classNodeWithGenerics.redirect());
-                newClassNodeWithGenerics.setSourcePosition(classNodeWithGenerics);
-
-                return Tuple.tuple(newClassNodeWithGenerics, true);
-            }
-        }
-
-        return Tuple.tuple(classNodeWithGenerics, false);
+        return tuple(parameterTypes, returnType);
     }
 
     /**
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 20a3d63..a64b604 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
@@ -24,6 +24,7 @@ import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.expr.MethodReferenceExpression;
+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.MethodReferenceExpressionWriter;
@@ -83,7 +84,10 @@ public class StaticTypesMethodReferenceExpressionWriter extends MethodReferenceE
     }
 
     private Parameter[] createParametersWithExactType(MethodNode abstractMethodNode, ClassNode[]
inferredParameterTypes) {
-        Parameter[] parameters = abstractMethodNode.getParameters();
+        Parameter[] originalParameters = abstractMethodNode.getParameters();
+
+        // We MUST clone the parameters to avoid impacting the original parameter type of
SAM
+        Parameter[] parameters = GeneralUtils.cloneParams(originalParameters);
         if (parameters == null) {
             parameters = Parameter.EMPTY_ARRAY;
         }
diff --git a/src/test/groovy/transform/stc/LambdaTest.groovy b/src/test/groovy/transform/stc/LambdaTest.groovy
index 7bf7fff..24cb562 100644
--- a/src/test/groovy/transform/stc/LambdaTest.groovy
+++ b/src/test/groovy/transform/stc/LambdaTest.groovy
@@ -892,5 +892,18 @@ class LambdaTest extends GroovyTestCase {
         '''
     }
 
-
+    void testMixingLambdaAndMethodReference() {
+        assertScript '''
+            import java.util.stream.Collectors
+            
+            @groovy.transform.CompileStatic
+            void p() {
+                assert ['1', '2', '3'] == [1, 2, 3].stream().map(Object::toString).collect(Collectors.toList())
+                assert [2, 3, 4] == [1, 2, 3].stream().map(e -> e.plus 1).collect(Collectors.toList())
+                assert ['1', '2', '3'] == [1, 2, 3].stream().map(Object::toString).collect(Collectors.toList())
+            }
+            
+            p()
+        '''
+    }
 }
diff --git a/src/test/org/codehaus/groovy/ast/tools/GenericsUtilsTest.groovy b/src/test/org/codehaus/groovy/ast/tools/GenericsUtilsTest.groovy
index 8484648..1373f4f 100644
--- a/src/test/org/codehaus/groovy/ast/tools/GenericsUtilsTest.groovy
+++ b/src/test/org/codehaus/groovy/ast/tools/GenericsUtilsTest.groovy
@@ -22,12 +22,13 @@ package org.codehaus.groovy.ast.tools
 import org.codehaus.groovy.ast.ClassHelper
 import org.codehaus.groovy.ast.ClassNode
 import org.codehaus.groovy.ast.GenericsType
-import org.codehaus.groovy.ast.MethodNode
 import org.codehaus.groovy.control.CompilationUnit
 import org.codehaus.groovy.control.Phases
 
 import java.util.function.BiFunction
 
+import static groovy.lang.Tuple.tuple
+
 class GenericsUtilsTest extends GroovyTestCase {
     void testFindParameterizedType1() {
         def code = '''
@@ -320,45 +321,4 @@ class GenericsUtilsTest extends GroovyTestCase {
         assert ClassHelper.Integer_TYPE == typeInfo.getV1()[1]
         assert ClassHelper.Integer_TYPE == typeInfo.getV2()
     }
-
-    void testParameterizeMethodNode() {
-        def code = '''
-        import java.util.function.*
-        interface T extends Function<String, Integer> {}
-        '''
-        def ast = new CompilationUnit().tap {
-            addSource 'hello.groovy', code
-            compile Phases.SEMANTIC_ANALYSIS
-        }.ast
-
-        def classNodeList = ast.getModules()[0].getClasses()
-        ClassNode parameterizedClassNode = findClassNode('T', classNodeList).getAllInterfaces().find
{ it.name.equals('java.util.function.Function') }
-        MethodNode methodNode = parameterizedClassNode.getMethods('apply')[0]
-        Tuple2<ClassNode[], ClassNode> typeInfo = GenericsUtils.parameterizeMethodNode(methodNode,
parameterizedClassNode)
-        assert 1 == typeInfo.getV1().length
-        assert ClassHelper.STRING_TYPE == typeInfo.getV1()[0]
-        assert ClassHelper.Integer_TYPE == typeInfo.getV2()
-    }
-
-    void testParameterizeMethodNode2() {
-        def code = '''
-        import java.util.stream.*
-        interface T extends Stream<Integer> {}
-        '''
-        def ast = new CompilationUnit().tap {
-            addSource 'hello.groovy', code
-            compile Phases.SEMANTIC_ANALYSIS
-        }.ast
-
-        def classNodeList = ast.getModules()[0].getClasses()
-        ClassNode parameterizedClassNode = findClassNode('T', classNodeList).getAllInterfaces().find
{ it.name.equals('java.util.stream.Stream') }
-        MethodNode methodNode = parameterizedClassNode.getMethods('reduce')[0]
-        Tuple2<ClassNode[], ClassNode> typeInfo = GenericsUtils.parameterizeMethodNode(methodNode,
parameterizedClassNode)
-//        println typeInfo
-        assert 2 == typeInfo.getV1().length
-        assert ClassHelper.Integer_TYPE == typeInfo.getV1()[0]
-        assert ClassHelper.make(java.util.function.BinaryOperator) == typeInfo.getV1()[1]
-        assert ClassHelper.Integer_TYPE == typeInfo.getV1()[1].getGenericsTypes()[0].getType()
-        assert ClassHelper.Integer_TYPE == typeInfo.getV2()
-    }
 }


Mime
View raw message