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

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

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

    GROOVY-10602: fix dropped parameter detection
    
    3_0_X backport
---
 gradle/test.gradle                                 |  7 ++--
 .../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 +++++++++++--
 6 files changed, 68 insertions(+), 79 deletions(-)

diff --git a/gradle/test.gradle b/gradle/test.gradle
index f53a78c6f1..aadd19d077 100644
--- a/gradle/test.gradle
+++ b/gradle/test.gradle
@@ -19,12 +19,11 @@
 allprojects {
     tasks.withType(Test) {
         def jdk8 = ['-XX:+UseConcMarkSweepGC']
-        def jdk9 = ['-Djava.locale.providers=COMPAT,SPI']
-//        def jdk9 = ['-Djava.locale.providers=COMPAT,SPI', 
'--illegal-access=debug']
-        def common = ['-ea', "-Xms${groovyJUnit_ms}", "-Xmx${groovyJUnit_mx}", 
"-Duser.language=en" ]
+        def jdk9 = ['-Djava.locale.providers=COMPAT,SPI'/*, 
'--illegal-access=debug'*/]
+        def common = ['-ea', '-Duser.language=en', "-Xms${groovyJUnit_ms}", 
"-Xmx${groovyJUnit_mx}"]
         if (JavaVersion.current().isJava9Compatible()) {
             jvmArgs (*common, *jdk9)
-            systemProperty "groovy.force.illegal.access", 
findProperty("groovy.force.illegal.access")
+            systemProperty 'groovy.force.illegal.access', 
findProperty('groovy.force.illegal.access')
         } else {
             jvmArgs (*common, *jdk8)
         }
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java 
b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
index 7fd90f3829..5e8af6384c 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();
@@ -337,15 +339,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()));
     }
 
     
//--------------------------------------------------------------------------
@@ -476,20 +474,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.OBJECT_TYPE, "it");
-            var.setInStaticContext(currentScope.isInStaticContext());
-            currentScope.putDeclaredVariable(var);
+            Parameter implicit = new Parameter(ClassHelper.DYNAMIC_TYPE, "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 9b8d6e5153..c4ec0121d7 100644
--- a/src/main/java/org/codehaus/groovy/classgen/Verifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
@@ -779,16 +779,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 85b2fd814b..d03c255e00 100644
--- a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
@@ -182,15 +182,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() })
@@ -201,7 +202,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() 
} }
@@ -211,7 +212,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() 
} }
@@ -276,7 +277,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 {
@@ -290,6 +291,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-7141
     void testInferenceWithSAMTypeCoercion1() {
         String sam = '''
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 9de00b7e75..050a979165 100644
--- a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
@@ -42,7 +42,7 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
     void testCallClosure3() {
         shouldFail MissingMethodException, '''
             def c = { -> }
-            c('')
+            c("")
         '''
     }
 
@@ -424,14 +424,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) }
@@ -439,7 +439,7 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    void testFibClosureCallAsAMethodFromWithinClass() {
+    void testFibClosureCallAsMethodFromWithinClass() {
         assertScript '''
             class FibUtil {
                 private Closure<Integer> fibo
@@ -831,4 +831,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