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

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


The following commit(s) were added to refs/heads/GROOVY_4_0_X by this push:
     new f8663922b6 GROOVY-10602: fix dropped parameter detection
f8663922b6 is described below

commit f8663922b64e544011bc5c7b8684c76618fcc68f
Author: Eric Milles <[email protected]>
AuthorDate: Tue Aug 8 11:12:41 2023 -0500

    GROOVY-10602: fix dropped parameter detection
    
    4_0_X backport
---
 .../groovy/classgen/VariableScopeVisitor.java      | 34 ++++++++---------
 .../org/codehaus/groovy/classgen/Verifier.java     |  6 +--
 .../stc/ClosureParamTypeInferenceSTCTest.groovy    | 32 +++++++++++++---
 .../stc/ClosureParamTypeResolverSTCTest.groovy     | 43 ----------------------
 .../groovy/transform/stc/ClosuresSTCTest.groovy    | 25 +++++++++++--
 5 files changed, 65 insertions(+), 75 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java 
b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
index 29d8517a07..53d3023378 100644
--- a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
@@ -130,15 +130,17 @@ public class VariableScopeVisitor extends 
ClassCodeVisitorSupport {
     }
 
     private void declare(final Variable variable, final ASTNode context) {
-        String scopeType = "scope";
+        String scopeType    = "scope";
         String variableType = "variable";
-
         if (context.getClass() == FieldNode.class) {
-            scopeType = "class";
+            scopeType    = "class";
             variableType = "field";
         } else if (context.getClass() == PropertyNode.class) {
-            scopeType = "class";
+            scopeType    = "class";
             variableType = "property";
+        } else if (context.getClass() == ClosureExpression.class) {
+            scopeType    = "parameter list";
+            variableType = "parameter";
         }
 
         StringBuilder msg = new StringBuilder();
@@ -339,15 +341,11 @@ public class VariableScopeVisitor extends 
ClassCodeVisitorSupport {
                     addError("Cannot refer to the static enum field '" + 
variable.getName() + "' within an initializer", expression);
                 }
             }
-            return;
+        } else if (currentScope.isInStaticContext()) {
+            // declare a static variable to be able to continue the check
+            currentScope.putDeclaredVariable(new 
DynamicVariable(variable.getName(), currentScope.isInStaticContext()));
+            addError(variable.getName() + " is declared in a dynamic context, 
but you tried to access it from a static context.", expression);
         }
-
-        if (!currentScope.isInStaticContext()) return;
-
-        addError(variable.getName() + " is declared in a dynamic context, but 
you tried to access it from a static context.", expression);
-
-        // declare a static variable to be able to continue the check
-        currentScope.putDeclaredVariable(new 
DynamicVariable(variable.getName(), currentScope.isInStaticContext()));
     }
 
     
//--------------------------------------------------------------------------
@@ -478,20 +476,18 @@ public class VariableScopeVisitor extends 
ClassCodeVisitorSupport {
         if (expression.isParameterSpecified()) {
             for (Parameter parameter : expression.getParameters()) {
                 parameter.setInStaticContext(currentScope.isInStaticContext());
-                if (parameter.hasInitialExpression()) {
-                    parameter.getInitialExpression().visit(this);
-                }
                 declare(parameter, expression);
+                if (parameter.hasInitialExpression())
+                    parameter.getInitialExpression().visit(this);
             }
         } else if (expression.getParameters() != null) {
-            Parameter var = new Parameter(ClassHelper.dynamicType(), "it");
-            var.setInStaticContext(currentScope.isInStaticContext());
-            currentScope.putDeclaredVariable(var);
+            Parameter implicit = new Parameter(ClassHelper.dynamicType(), 
"it");
+            implicit.setInStaticContext(currentScope.isInStaticContext());
+            currentScope.putDeclaredVariable(implicit);
         }
 
         super.visitClosureExpression(expression);
         markClosureSharedVariables();
-
         popState();
     }
 
diff --git a/src/main/java/org/codehaus/groovy/classgen/Verifier.java 
b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
index db78827edf..986f29744c 100644
--- a/src/main/java/org/codehaus/groovy/classgen/Verifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
@@ -908,16 +908,16 @@ public class Verifier implements GroovyClassVisitor, 
Opcodes {
 
                 @Override
                 public void visitClosureExpression(final ClosureExpression e) {
-                    boolean prev = inClosure; inClosure = true;
+                    boolean saved = inClosure; inClosure = true;
                     super.visitClosureExpression(e);
-                    inClosure = prev;
+                    inClosure = saved;
                 }
 
                 @Override
                 public void visitVariableExpression(final VariableExpression 
e) {
                     if (e.getAccessedVariable() instanceof Parameter) {
                         Parameter p = (Parameter) e.getAccessedVariable();
-                        if (p.hasInitialExpression() && 
!Arrays.asList(params).contains(p)) {
+                        if (!Arrays.asList(params).contains(p) && 
Arrays.asList(method.getParameters()).contains(p)) { // GROOVY-10602
                             VariableScope blockScope = 
block.getVariableScope();
                             VariableExpression localVariable = 
(VariableExpression) blockScope.getDeclaredVariable(p.getName());
                             if (localVariable == null) {
diff --git 
a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy 
b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
index 74f02ee953..6366dceb81 100644
--- a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
@@ -230,15 +230,16 @@ class ClosureParamTypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
     // GROOVY-7789
     void testFromStringWithTypeParameter4() {
         assertScript '''
-            class Monad<T> {  private final Closure c
-                Monad(@ClosureParams(value=FromString, options='T') Closure c) 
{
+            class Monad<T> {
+                private final Closure c
+                Monad(@ClosureParams(value=FromString, options="T") Closure c) 
{
                     this.c = c
                 }
                 def call(T t) {
                     c.call(t)
                 }
             }
-            def <U> Monad<U> wrap(@ClosureParams(value=FromString, 
options='U') Closure c) {
+            def <U> Monad<U> wrap(@ClosureParams(value=FromString, 
options="U") Closure c) {
                 new Monad<>(c)
             }
             def list_size = this.<List>wrap({ list -> list.size() })
@@ -249,7 +250,7 @@ class ClosureParamTypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
     void testFromStringWithTypeParameterFromClass() {
         assertScript '''
             class Foo<T> {
-                void 
foo(@ClosureParams(value=FromString,options="java.util.List<T>") Closure cl) { 
cl.call(['hey','ya']) }
+                void foo(@ClosureParams(value=FromString, 
options="java.util.List<T>") Closure cl) { cl.call(['hey','ya']) }
             }
             def foo = new Foo<String>()
             foo.foo { List<String> str -> str.each { println it.toUpperCase() 
} }
@@ -259,7 +260,7 @@ class ClosureParamTypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
     void testFromStringWithTypeParameterFromClassWithTwoGenerics() {
         assertScript '''
             class Foo<T,U> {
-                void 
foo(@ClosureParams(value=FromString,options="java.util.List<U>") Closure cl) { 
cl.call(['hey','ya']) }
+                void foo(@ClosureParams(value=FromString, 
options="java.util.List<U>") Closure cl) { cl.call(['hey','ya']) }
             }
             def foo = new Foo<Integer,String>()
             foo.foo { List<String> str -> str.each { println it.toUpperCase() 
} }
@@ -324,7 +325,7 @@ class ClosureParamTypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
                 }
             }
             class Tor<D,U> {
-                void foo(@ClosureParams(value=FromString, 
options=["D,List<U>", "D"]) Closure c) {
+                void foo(@ClosureParams(value=FromString, 
options=["D,List<U>","D"]) Closure c) {
                     if (c.maximumNumberOfParameters==2) {
                         c.call(3, [new Foo(), new Foo()])
                     } else {
@@ -338,6 +339,25 @@ class ClosureParamTypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
         '''
     }
 
+    void testFromStringWithConflictResolutionStrategy() {
+        assertScript '''
+            def transform(value, @ClosureParams(value=FromString, 
options=["Integer","String"], conflictResolutionStrategy=PickFirstResolver) 
Closure condition) {
+                if (condition.parameterTypes[0].simpleName == 'String') {
+                    condition(value.toString())
+                } else {
+                    condition(value instanceof Integer ? value : 
value.toString().size())
+                }
+            }
+
+            assert transform('dog') { String s -> s * 2 } == 'dogdog'
+            assert transform('dog') { Integer i -> i * 2 } == 6
+            assert transform('dog') { it.class.simpleName[0..it] } == 'Inte'
+            assert transform(35) { String s -> s * 2 } == '3535'
+            assert transform(35) { Integer i -> i * 2 } == 70
+            assert transform(35) { it * 2 } == 70
+        '''
+    }
+
     // GROOVY-6939
     @NotYetImplemented
     void testParamCountCheck1() {
diff --git 
a/src/test/groovy/transform/stc/ClosureParamTypeResolverSTCTest.groovy 
b/src/test/groovy/transform/stc/ClosureParamTypeResolverSTCTest.groovy
deleted file mode 100644
index 7cc2e3bfc1..0000000000
--- a/src/test/groovy/transform/stc/ClosureParamTypeResolverSTCTest.groovy
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package groovy.transform.stc
-/**
- * Unit tests for static type checking : closure parameter type resolution
- */
-class ClosureParamTypeResolverSTCTest extends StaticTypeCheckingTestCase {
-    void testInferenceForDGM_CollectUsingExplicitIt() {
-        assertScript '''
-            import groovy.transform.stc.*
-
-            def transform(item, @ClosureParams(value=FromString, 
conflictResolutionStrategy=PickFirstResolver, options=["Integer", "String"]) 
Closure condition) {
-              if (condition.parameterTypes[0].simpleName == 'String')
-                condition(item instanceof String ? item : item.toString())
-              else
-                condition(item instanceof Integer ? item : 
item.toString().size())
-            }
-
-            assert transform('dog') { String s -> s * 2 } == 'dogdog'
-            assert transform('dog') { Integer i -> i * 2 } == 6
-            assert transform('dog') { it.class.simpleName[0..it] } == 'Inte'
-            assert transform(35) { String s -> s * 2 } == '3535'
-            assert transform(35) { Integer i -> i * 2 } == 70
-            assert transform(35) { it * 2 } == 70
-        '''
-    }
-}
diff --git a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy 
b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
index 59dcc42570..19785b01a2 100644
--- a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
@@ -40,7 +40,7 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
     void testCallClosure3() {
         shouldFail MissingMethodException, '''
             def c = { -> }
-            c('')
+            c("")
         '''
     }
 
@@ -418,14 +418,14 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    void testRecurseClosureCallAsAMethod() {
+    void testRecurseClosureCallAsMethod() {
         assertScript '''
             Closure<Integer> cl
             cl = { int x -> x == 0 ? x : 1+cl(x-1) }
         '''
     }
 
-    void testFibClosureCallAsAMethod() {
+    void testFibClosureCallAsMethod() {
         assertScript '''
             Closure<Integer> fib
             fib = { int x-> x<1?x:fib(x-1)+fib(x-2) }
@@ -433,7 +433,7 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    void testFibClosureCallAsAMethodFromWithinClass() {
+    void testFibClosureCallAsMethodFromWithinClass() {
         assertScript '''
             class FibUtil {
                 private Closure<Integer> fibo
@@ -821,4 +821,21 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
         'Cannot assign value of type java.lang.Class<java.lang.Integer> to 
variable of type int',
         "named param 'bar' has type 'java.lang.Class<java.lang.Number>' but 
expected 'java.lang.Number'"
     }
+
+    // GROOVY-10602
+    void testMethodAndClosureParametersDefaultArguments() {
+        assertScript '''import java.util.function.*
+            String test(Closure one = { p ->
+                Closure two = { Supplier s = { -> p } ->
+                    s.get()
+                }
+                two()
+            }) {
+                one('foo')
+            }
+
+            String result = test()
+            assert result == 'foo'
+        '''
+    }
 }

Reply via email to