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' + ''' + } }
