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 2022/05/25 19:07:01 UTC

[groovy] branch master updated (5176ea3155 -> 74baecf4b3)

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


    from 5176ea3155 GROOVY-10143: super trait field access
     new 496748a118 GROOVY-6022, GROOVY-10636: STC: closure(s) for variadic parameter
     new 74baecf4b3 minor edits

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/groovy/parser/antlr4/AstBuilder.java    |  11 +-
 .../groovy/ast/ClassCodeVisitorSupport.java        |   1 +
 .../transform/stc/StaticTypeCheckingVisitor.java   | 143 +++++++++++----------
 .../stc/ClosureParamTypeInferenceSTCTest.groovy    |  14 ++
 .../groovy/transform/stc/ClosuresSTCTest.groovy    |  19 ++-
 .../groovy/transform/stc/DelegatesToSTCTest.groovy |  45 +++++++
 6 files changed, 154 insertions(+), 79 deletions(-)


[groovy] 02/02: minor edits

Posted by em...@apache.org.
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 74baecf4b3990f84003929c0c31ec150d5d305cf
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed May 25 14:05:10 2022 -0500

    minor edits
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 134 ++++++++++-----------
 1 file changed, 67 insertions(+), 67 deletions(-)

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 7afb96347f..5c4ba09dc2 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -597,30 +597,30 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
             if (enclosingClosure != null) {
                 switch (name) {
-                    case "delegate":
-                        DelegationMetadata dm = getDelegationMetadata(enclosingClosure.getClosureExpression());
-                        if (dm != null) {
-                            storeType(vexp, dm.getType());
-                            return;
-                        }
-                        // falls through
-                    case "owner":
-                        if (typeCheckingContext.getEnclosingClosureStack().size() > 1) {
-                            storeType(vexp, CLOSURE_TYPE);
-                            return;
-                        }
-                        // falls through
-                    case "thisObject":
-                        storeType(vexp, typeCheckingContext.getEnclosingClassNode());
+                  case "delegate":
+                    DelegationMetadata dm = getDelegationMetadata(enclosingClosure.getClosureExpression());
+                    if (dm != null) {
+                        storeType(vexp, dm.getType());
                         return;
-                    case "parameterTypes":
-                        storeType(vexp, CLASS_Type.makeArray());
-                        return;
-                    case "maximumNumberOfParameters":
-                    case "resolveStrategy":
-                    case "directive":
-                        storeType(vexp, int_TYPE);
+                    }
+                    // falls through
+                  case "owner":
+                    if (typeCheckingContext.getEnclosingClosureStack().size() > 1) {
+                        storeType(vexp, CLOSURE_TYPE);
                         return;
+                    }
+                    // falls through
+                  case "thisObject":
+                    storeType(vexp, typeCheckingContext.getEnclosingClassNode());
+                    return;
+                  case "parameterTypes":
+                    storeType(vexp, CLASS_Type.makeArray());
+                    return;
+                  case "maximumNumberOfParameters":
+                  case "resolveStrategy":
+                  case "directive":
+                    storeType(vexp, int_TYPE);
+                    return;
                 }
             }
 
@@ -1778,10 +1778,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             } else {
                 // map*.property syntax acts on Entry
                 switch (pexp.getPropertyAsString()) {
-                case "key":
+                  case "key":
                     pexp.putNodeMetaData(READONLY_PROPERTY,Boolean.TRUE); // GROOVY-10326
                     return makeClassSafe0(LIST_TYPE, gts[0]);
-                case "value":
+                  case "value":
                     GenericsType v = gts[1];
                     if (!v.isWildcard()
                             && !Modifier.isFinal(v.getType().getModifiers())
@@ -1789,7 +1789,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                         v = GenericsUtils.buildWildcardType(v.getType()); // GROOVY-10325
                     }
                     return makeClassSafe0(LIST_TYPE, v);
-                default:
+                  default:
                     addStaticTypeError("Spread operator on map only allows one of [key,value]", pexp);
                 }
             }
@@ -2708,7 +2708,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                     break;
                 }
             }
-            if (mn == null || mn.isEmpty()) {
+            if (mn.isEmpty()) {
                 mn = extension.handleMissingMethod(receiver, name, argumentList, args, call);
             }
             boolean callArgsVisited = false;
@@ -2720,10 +2720,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                     MethodNode directMethodCallCandidate = mn.get(0);
                     ClassNode returnType = getType(directMethodCallCandidate);
                     if (returnType.isUsingGenerics() && !returnType.isEnum()) {
-                        visitMethodCallArguments(receiver, argumentList, true, directMethodCallCandidate);
-                        ClassNode irtg = inferReturnTypeGenerics(chosenReceiver.getType(), directMethodCallCandidate, argumentList);
-                        returnType = irtg != null && implementsInterfaceOrIsSubclassOf(irtg, returnType) ? irtg : returnType;
-                        callArgsVisited = true;
+                        visitMethodCallArguments(receiver, argumentList, true, directMethodCallCandidate); callArgsVisited = true;
+                        ClassNode rt = inferReturnTypeGenerics(chosenReceiver.getType(), directMethodCallCandidate, argumentList);
+                        if (rt != null && implementsInterfaceOrIsSubclassOf(rt, returnType))
+                            returnType = rt;
                     }
                     storeType(call, returnType);
                     storeTargetMethod(call, directMethodCallCandidate);
@@ -3278,30 +3278,30 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     private static void addReceivers(final List<Receiver<String>> receivers, final Collection<Receiver<String>> owners, final DelegationMetadata dmd, final String path) {
         int strategy = dmd.getStrategy();
         switch (strategy) {
-            case Closure.DELEGATE_ONLY:
-            case Closure.DELEGATE_FIRST:
-                addDelegateReceiver(receivers, dmd.getType(), path + "delegate");
-                if (strategy == Closure.DELEGATE_FIRST) {
-                    if (dmd.getParent() == null) {
-                        receivers.addAll(owners);
-                    } else {
-                        //receivers.add(new Receiver<String>(CLOSURE_TYPE, path + "owner"));
-                        addReceivers(receivers, owners, dmd.getParent(), path + "owner.");
-                    }
-                }
-                break;
-            case Closure.OWNER_ONLY:
-            case Closure.OWNER_FIRST:
+          case Closure.DELEGATE_ONLY:
+          case Closure.DELEGATE_FIRST:
+            addDelegateReceiver(receivers, dmd.getType(), path + "delegate");
+            if (strategy == Closure.DELEGATE_FIRST) {
                 if (dmd.getParent() == null) {
                     receivers.addAll(owners);
                 } else {
                     //receivers.add(new Receiver<String>(CLOSURE_TYPE, path + "owner"));
                     addReceivers(receivers, owners, dmd.getParent(), path + "owner.");
                 }
-                if (strategy == Closure.OWNER_FIRST) {
-                    addDelegateReceiver(receivers, dmd.getType(), path + "delegate");
-                }
-                break;
+            }
+            break;
+          case Closure.OWNER_ONLY:
+          case Closure.OWNER_FIRST:
+            if (dmd.getParent() == null) {
+                receivers.addAll(owners);
+            } else {
+                //receivers.add(new Receiver<String>(CLOSURE_TYPE, path + "owner"));
+                addReceivers(receivers, owners, dmd.getParent(), path + "owner.");
+            }
+            if (strategy == Closure.OWNER_FIRST) {
+                addDelegateReceiver(receivers, dmd.getType(), path + "delegate");
+            }
+            break;
         }
     }
 
@@ -3359,21 +3359,21 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         boolean isCallOnClosure = false;
         FieldNode fieldNode = null;
         switch (name) {
-            case "call":
-            case "doCall":
-                if (!isThisObjectExpression) {
-                    isCallOnClosure = receiver.equals(CLOSURE_TYPE);
-                    break;
-                }
-            default:
-                if (isThisObjectExpression) {
-                    ClassNode enclosingType = typeCheckingContext.getEnclosingClassNode();
-                    fieldNode = enclosingType.getDeclaredField(name);
-                    if (fieldNode != null && getType(fieldNode).equals(CLOSURE_TYPE)
-                            && !enclosingType.hasPossibleMethod(name, callArguments)) {
-                        isCallOnClosure = true;
-                    }
+          case "call":
+          case "doCall":
+            if (!isThisObjectExpression) {
+                isCallOnClosure = receiver.equals(CLOSURE_TYPE);
+                break;
+            }
+          default:
+            if (isThisObjectExpression) {
+                ClassNode enclosingType = typeCheckingContext.getEnclosingClassNode();
+                fieldNode = enclosingType.getDeclaredField(name);
+                if (fieldNode != null && getType(fieldNode).equals(CLOSURE_TYPE)
+                        && !enclosingType.hasPossibleMethod(name, callArguments)) {
+                    isCallOnClosure = true;
                 }
+            }
         }
 
         try {
@@ -4920,7 +4920,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                     node.setDeclaringClass(property.getDeclaringClass());
                     return Collections.singletonList(node);
                 }
-            } else if (methods.isEmpty() && args != null && args.length == 1) {
+            } else if (methods.isEmpty() && args.length == 1) {
                 // maybe we are looking for a setter ?
                 String pname = extractPropertyNameFromMethodName("set", name);
                 if (pname != null) {
@@ -5951,10 +5951,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     public static class SignatureCodecFactory {
         public static SignatureCodec getCodec(final int version, final ClassLoader classLoader) {
             switch (version) {
-                case 1:
-                    return new SignatureCodecVersion1(classLoader);
-                default:
-                    return null;
+              case 1:
+                return new SignatureCodecVersion1(classLoader);
+              default:
+                return null;
             }
         }
     }


[groovy] 01/02: GROOVY-6022, GROOVY-10636: STC: closure(s) for variadic parameter

Posted by em...@apache.org.
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 496748a118a51b2dad33f9fd03a8039a1cf0127d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed May 25 13:02:58 2022 -0500

    GROOVY-6022, GROOVY-10636: STC: closure(s) for variadic parameter
---
 .../apache/groovy/parser/antlr4/AstBuilder.java    | 11 ++----
 .../groovy/ast/ClassCodeVisitorSupport.java        |  1 +
 .../transform/stc/StaticTypeCheckingVisitor.java   |  9 +++--
 .../stc/ClosureParamTypeInferenceSTCTest.groovy    | 14 +++++++
 .../groovy/transform/stc/ClosuresSTCTest.groovy    | 19 ++++++++-
 .../groovy/transform/stc/DelegatesToSTCTest.groovy | 45 ++++++++++++++++++++++
 6 files changed, 87 insertions(+), 12 deletions(-)

diff --git a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index 83644bfcf5..801d0dd1cb 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -747,14 +747,11 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
 
     @Override
     public Tuple2<Parameter, Expression> visitEnhancedForControl(final EnhancedForControlContext ctx) {
-        Parameter parameter = configureAST(
-                new Parameter(this.visitType(ctx.type()), this.visitVariableDeclaratorId(ctx.variableDeclaratorId()).getName()),
-                ctx.variableDeclaratorId());
+        Parameter parameter = new Parameter(this.visitType(ctx.type()), this.visitVariableDeclaratorId(ctx.variableDeclaratorId()).getName());
+        ModifierManager modifierManager = new ModifierManager(this, this.visitVariableModifiersOpt(ctx.variableModifiersOpt()));
+        modifierManager.processParameter(parameter);
 
-        // FIXME Groovy will ignore variableModifier of parameter in the for control
-        // In order to make the new parser behave same with the old one, we do not process variableModifier*
-
-        return tuple(parameter, (Expression) this.visit(ctx.expression()));
+        return tuple(configureAST(parameter, ctx.variableDeclaratorId()), (Expression) this.visit(ctx.expression()));
     }
 
     @Override
diff --git a/src/main/java/org/codehaus/groovy/ast/ClassCodeVisitorSupport.java b/src/main/java/org/codehaus/groovy/ast/ClassCodeVisitorSupport.java
index 24a998f300..8b09b01664 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassCodeVisitorSupport.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassCodeVisitorSupport.java
@@ -208,6 +208,7 @@ public abstract class ClassCodeVisitorSupport extends CodeVisitorSupport impleme
     public void visitForLoop(ForStatement statement) {
         visitStatement(statement);
         super.visitForLoop(statement);
+        visitAnnotations(statement.getVariable());
     }
 
     @Override
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 5c73dd6296..7afb96347f 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -2790,14 +2790,17 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         expressions.addAll(arguments.getExpressions());
 
         int nExpressions = expressions.size();
+        int nthParameter = parameters.length - 1;
         for (int i = 0; i < nExpressions; i += 1) {
             Expression expression = expressions.get(i);
             if (visitClosures && expression instanceof ClosureExpression
                     || !visitClosures && !(expression instanceof ClosureExpression)) {
-                if (i < parameters.length && visitClosures) {
-                    Parameter target = parameters[i];
-                    ClassNode targetType = target.getType();
+                if (visitClosures && nthParameter != -1) { // GROOVY-10636: vargs call
                     ClosureExpression source = (ClosureExpression) expression;
+                    Parameter target = parameters[Math.min(i, nthParameter)];
+                    ClassNode targetType = target.getType();
+                    if (targetType.isArray() && i >= nthParameter)
+                        targetType = targetType.getComponentType();
                     checkClosureWithDelegatesTo(receiver, selectedMethod, args(expressions), parameters, source, target);
                     if (selectedMethod instanceof ExtensionMethodNode) {
                         if (i > 0) {
diff --git a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
index 8d2039bd0d..112394283d 100644
--- a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
@@ -1222,6 +1222,20 @@ assert result == ['b', 'r', 'e', 'a', 'd', 'b', 'u', 't', 't', 'e', 'r']
         '''
     }
 
+    void testGroovy6022() {
+        assertScript '''import groovy.transform.stc.SimpleType
+            class Item {
+                int x
+            }
+
+            void m(Item item, @ClosureParams(value=SimpleType, options="Item") Closure... closures) {
+                closures*.call(item)
+            }
+
+            m(new Item(), { item -> item.x }, { it.x })
+        '''
+    }
+
     void testGroovy6602() {
         shouldFailWithMessages '''import groovy.transform.stc.SimpleType
             void foo(@ClosureParams(value=SimpleType, options="java.lang.Number") Closure c) {
diff --git a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
index b233142aa3..99138e8351 100644
--- a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
@@ -69,12 +69,28 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-10636
+    void testClosureWithoutArguments6() {
+        assertScript '''
+            def f(Closure<Number>... closures) {
+                closures*.call().sum()
+            }
+            Object result = f({->1},{->2})
+            assert result == 3
+        '''
+        shouldFailWithMessages '''
+            def f(Closure<Number>... closures) {
+            }
+            f({->1},{->'x'})
+        ''',
+        'Cannot return value of type java.lang.String for closure expecting java.lang.Number'
+    }
+
     void testClosureWithArguments1() {
         assertScript '''
             def c = { int a, int b -> a + b }
             assert c(5, 7) == 12
         '''
-
         shouldFailWithMessages '''
             def c = { int a, int b -> a + b }
             c('5', '7')
@@ -87,7 +103,6 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
             def result = { int a, int b -> a + b }(5, 7)
             assert result == 12
         '''
-
         shouldFailWithMessages '''
             { int a, int b -> a + b }('5', 7)
         ''',
diff --git a/src/test/groovy/transform/stc/DelegatesToSTCTest.groovy b/src/test/groovy/transform/stc/DelegatesToSTCTest.groovy
index 09284d971e..92f55fbf19 100644
--- a/src/test/groovy/transform/stc/DelegatesToSTCTest.groovy
+++ b/src/test/groovy/transform/stc/DelegatesToSTCTest.groovy
@@ -389,6 +389,51 @@ class DelegatesToSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-6022
+    void testDelegatesToVariadicParameter() {
+        assertScript '''
+            def m(@DelegatesTo.Target target, @DelegatesTo(strategy=Closure.DELEGATE_FIRST) Closure... a) {
+                for (Closure c : a) {
+                    c.resolveStrategy = Closure.DELEGATE_FIRST
+                    c.delegate = target
+                    c()
+                }
+            }
+
+            m([x:0], { get('x') }, { put('y',1) })
+        '''
+
+        assertScript '''
+            class Item {
+                int x
+            }
+
+            void m(@DelegatesTo.Target Item item, @DelegatesTo(strategy=Closure.DELEGATE_FIRST) Closure... closures) {
+                for (closure in closures) {
+                    closure.resolveStrategy = Closure.DELEGATE_FIRST
+                    closure.delegate = item
+                    closure.call()
+                }
+            }
+
+            m(new Item(), { x })
+        '''
+
+        assertScript '''
+            class Item {
+                int x
+            }
+
+            void m(@DelegatesTo.Target Item item, @DelegatesTo(strategy=Closure.DELEGATE_FIRST) Closure... closures) {
+                for (@DelegatesTo(strategy=Closure.DELEGATE_FIRST) Closure closure : closures) {
+                    item.with(closure)
+                }
+            }
+
+            m(new Item(), { x })
+        '''
+    }
+
     // GROOVY-6055
     void testDelegatesToInStaticContext() {
         assertScript '''