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 494998222aaa94bc1ea8bb07b030b4d70808fa50 Author: Eric Milles <[email protected]> AuthorDate: Fri May 28 09:55:01 2021 -0500 GROOVY-5364: find static members from static script methods Conflicts: src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java --- .../groovy/classgen/VariableScopeVisitor.java | 15 +-- src/test/groovy/bugs/Groovy5364.groovy | 104 +++++++++++++++++++++ 2 files changed, 112 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java index cc6a324..07102bc 100644 --- a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java +++ b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java @@ -58,6 +58,7 @@ import java.util.function.BiConsumer; import static java.lang.reflect.Modifier.isFinal; import static java.lang.reflect.Modifier.isStatic; import static org.apache.groovy.ast.tools.MethodNodeUtils.getPropertyName; +import static org.codehaus.groovy.ast.tools.GeneralUtils.getAllProperties; /** * Initializes the variable scopes for an AST. @@ -170,10 +171,6 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport { final boolean abstractType = node.isAbstract(); for (ClassNode cn = node; cn != null && !cn.equals(ClassHelper.OBJECT_TYPE); cn = cn.getSuperClass()) { - if (cn.isScript()) { - return new DynamicVariable(name, false); - } - for (FieldNode fn : cn.getFields()) { if (name.equals(fn.getName())) return fn; } @@ -184,7 +181,11 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport { for (MethodNode mn : cn.getMethods()) { if ((abstractType || !mn.isAbstract()) && name.equals(getPropertyName(mn))) { - FieldNode fn = new FieldNode(name, mn.getModifiers() & 0xF, ClassHelper.OBJECT_TYPE, cn, null); + // check for override of super class property + for (PropertyNode pn : getAllProperties(cn.getSuperClass())) { + if (name.equals(pn.getName())) return pn; + } + FieldNode fn = new FieldNode(name, mn.getModifiers() & 0xF, ClassHelper.DYNAMIC_TYPE, cn, null); fn.setHasNoRealSourcePosition(true); fn.setDeclaringClass(cn); fn.setSynthetic(true); @@ -195,8 +196,8 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport { } } - for (ClassNode face : cn.getAllInterfaces()) { - FieldNode fn = face.getDeclaredField(name); + for (ClassNode in : cn.getAllInterfaces()) { + FieldNode fn = in.getDeclaredField(name); if (fn != null) return fn; } } diff --git a/src/test/groovy/bugs/Groovy5364.groovy b/src/test/groovy/bugs/Groovy5364.groovy new file mode 100644 index 0000000..5ab849e --- /dev/null +++ b/src/test/groovy/bugs/Groovy5364.groovy @@ -0,0 +1,104 @@ +/* + * 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.bugs + +import org.junit.Test + +import static groovy.test.GroovyAssert.assertScript +import static groovy.test.GroovyAssert.shouldFail + +final class Groovy5364 { + + @Test + void testStaticScriptMethodAsProperty1() { + assertScript ''' + static getStaticProperty() { + 'x' + } + + assert 'x' == getStaticProperty() + assert 'x' == staticProperty + ''' + } + + @Test + void testStaticScriptMethodAsProperty2() { + assertScript ''' + static getSomething() { 'x' } + something = 'y' // script var + + assert 'x' == getSomething() + assert 'y' == something + ''' + } + + @Test + void testStaticScriptMethodAsProperty3() { + new GroovyShell(new Binding(something: 'y')).evaluate ''' + static getSomething() { 'x' } + + assert 'x' == getSomething() + assert 'y' == something + ''' + } + + @Test + void testStaticScriptMethodAsProperty4() { + assertScript ''' + static getStaticProperty() { + 'x' + } + + void test() { + assert 'x' == getStaticProperty() + assert 'x' == staticProperty + } + test() + ''' + } + + @Test + void testStaticScriptMethodAsProperty5() { + assertScript ''' + static getStaticProperty() { + 'x' + } + + static void test() { + assert 'x' == getStaticProperty() + assert 'x' == staticProperty // Apparent variable 'staticProperty' was found in a static scope but doesn't refer to a local variable, static field or class + } + test() + ''' + } + + @Test + void testStaticScriptMethodAsProperty6() { + def err = shouldFail ''' + def getNonStaticProperty() { + 'x' + } + + static void test() { + nonStaticProperty + } + ''' + assert err =~ /Apparent variable 'nonStaticProperty' was found in a static scope but doesn't refer to a local variable, static field or class/ + } +}
