This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch GROOVY_5_0_X in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 12bb310243672c29305a4470063658baa8ecb455 Author: Eric Milles <[email protected]> AuthorDate: Tue Sep 16 10:12:56 2025 -0500 new property access method when super's is private or package-private --- .../org/codehaus/groovy/classgen/Verifier.java | 24 +++++++------ src/test/groovy/groovy/PropertyTest.groovy | 42 ++++++++++++++++++---- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/codehaus/groovy/classgen/Verifier.java b/src/main/java/org/codehaus/groovy/classgen/Verifier.java index a7b08f0310..beac6f0125 100644 --- a/src/main/java/org/codehaus/groovy/classgen/Verifier.java +++ b/src/main/java/org/codehaus/groovy/classgen/Verifier.java @@ -114,6 +114,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX; import static org.codehaus.groovy.ast.tools.GeneralUtils.declS; import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX; import static org.codehaus.groovy.ast.tools.GeneralUtils.getInterfacesAndSuperInterfaces; +import static org.codehaus.groovy.ast.tools.GeneralUtils.inSamePackage; import static org.codehaus.groovy.ast.tools.GeneralUtils.localVarX; import static org.codehaus.groovy.ast.tools.GeneralUtils.param; import static org.codehaus.groovy.ast.tools.GeneralUtils.params; @@ -809,16 +810,6 @@ public class Verifier implements GroovyClassVisitor, Opcodes { public void visitField(final FieldNode node) { } - private boolean methodNeedsReplacement(final MethodNode m) { - // no method found, we need to replace - if (m == null) return true; - // method is in current class, nothing to be done - if (m.getDeclaringClass() == getClassNode()) return false; - // do not overwrite final - if (isFinal(m.getModifiers())) return false; - return true; - } - @Override public void visitProperty(final PropertyNode node) { String name = node.getName(); @@ -868,6 +859,19 @@ public class Verifier implements GroovyClassVisitor, Opcodes { } } + private boolean methodNeedsReplacement(final MethodNode mn) { + if (mn != null) { + ClassNode declaringClass = mn.getDeclaringClass(); + // nothing to be done for method of current class + if (declaringClass == classNode) return false; + // cannot overwrite a non-private final method + if (mn.isFinal() && !mn.isPrivate() && (!mn.isPackageScope() || inSamePackage(declaringClass, classNode))) { + return false; + } + } + return true; + } + private void visitGetter(final PropertyNode node, final FieldNode field, final Statement getterBlock, final int getterModifiers, final String getterName) { MethodNode getter = new MethodNode(getterName, getterModifiers, node.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getterBlock); getter.setSynthetic(true); diff --git a/src/test/groovy/groovy/PropertyTest.groovy b/src/test/groovy/groovy/PropertyTest.groovy index 30f6653370..88c3493600 100644 --- a/src/test/groovy/groovy/PropertyTest.groovy +++ b/src/test/groovy/groovy/PropertyTest.groovy @@ -325,15 +325,42 @@ final class PropertyTest { ''' } + @Test + void testPropertyOverridesGetterAndSetter2() { + assertScript ''' + abstract class A { + private final String getFoo() { 'A' } + } + class C extends A { + final String foo = 'C' + } + + assert new C().getFoo() == 'C' + assert C.getMethod('getFoo').declaringClass.name == 'C' + ''' + + assertScript ''' + abstract class A { + private final void setFoo(String foo) { } + } + class C extends A { + String foo + } + + assert new C(foo: 'C').getFoo() == 'C' + assert C.getMethod('setFoo', String).declaringClass.name == 'C' + ''' + } + @Test void testPropertyWithOverrideGetterAndSetter() { assertScript ''' - abstract class Base { + abstract class A { abstract String getName() abstract void setName(String name) } - class A extends Base { - private String name = 'AA' + class C extends A { + private String name = 'C' @Override String getName() { @@ -344,10 +371,11 @@ final class PropertyTest { this.name = name } } - Base a = new A() - assert 'AA' == a.name - a.name = 'BB' - assert 'BB' == a.name + + A a = new C() + assert a.name == 'C' + a.name = 'X' + assert a.name == 'X' ''' }
