From 8324f8b8f81fe5fd4162f1ceb6b4000b5ed6c840 Mon Sep 17 00:00:00 2001 From: Eric Milles Date: Sat, 27 Apr 2024 15:00:26 -0500 Subject: [PATCH] GROOVY-8283: field hides setter of super class (not interface) --- src/main/java/groovy/lang/MetaClassImpl.java | 8 +-- src/test/groovy/bugs/Groovy8283.groovy | 72 ++++++++++++++++++++ 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/main/java/groovy/lang/MetaClassImpl.java b/src/main/java/groovy/lang/MetaClassImpl.java index 0ff27734a10..f21bb1a0884 100644 --- a/src/main/java/groovy/lang/MetaClassImpl.java +++ b/src/main/java/groovy/lang/MetaClassImpl.java @@ -2747,7 +2747,7 @@ public void setProperty(final Class sender, final Object object, final String na Object proxy = Proxy.newProxyInstance( theClass.getClassLoader(), new Class[]{method.getParameterTypes()[0].getTheClass()}, - new ConvertedClosure((Closure) newValue, name)); + new ConvertedClosure((Closure) newValue, name)); arguments = new Object[]{proxy}; newValue = proxy; } else { @@ -2758,7 +2758,7 @@ public void setProperty(final Class sender, final Object object, final String na //---------------------------------------------------------------------- // field //---------------------------------------------------------------------- - if (method == null && field != null) { + if (field != null && (method == null || isVisibleProperty(field, method, sender))) { boolean mapInstance = (isMap && !isStatic); if (field.isFinal()) { if (mapInstance) { // GROOVY-8065 @@ -2806,9 +2806,9 @@ public void setProperty(final Class sender, final Object object, final String na return; } - //------------------------------------------------------------------ + //---------------------------------------------------------------------- // java.util.Map put method - //------------------------------------------------------------------ + //---------------------------------------------------------------------- if (isMap && !isStatic) { ((Map) object).put(name, newValue); return; diff --git a/src/test/groovy/bugs/Groovy8283.groovy b/src/test/groovy/bugs/Groovy8283.groovy index 96956770ad2..ec99829e2dd 100644 --- a/src/test/groovy/bugs/Groovy8283.groovy +++ b/src/test/groovy/bugs/Groovy8283.groovy @@ -57,4 +57,76 @@ final class Groovy8283 { assert new E().foo.class == A // not the field from this perspective ''' } + + @Test + void testWriteFieldPropertyShadowing() { + def shell = new GroovyShell() + shell.parse '''package p + class A {} + class B {} + class C { + boolean setter + protected A foo = new A() + A getFooA() { return this.@foo } + void setFoo(A a) { setter = true; this.@foo = a } + } + class D extends C { + protected B foo = new B() // hides A#foo; should hide A#setFoo in subclasses + B getFooB() { return this.@foo } + } + ''' + assertScript shell, '''import p.* + class E extends D { + void test1() { + foo = null + assert !setter + assert fooA != null + assert fooB == null + } + void test2() { + this.foo = null + assert !setter + assert fooA != null + assert fooB == null + } + void test3() { + this.@foo = null + assert !setter + assert fooA != null + assert fooB == null + } + void test4() { + this.setFoo(null) + assert setter + assert fooA == null + assert fooB != null + } + void test5() { + def that = new E() + that.foo = null + assert !that.setter + assert that.fooA != null + assert that.fooB == null + + that = new E() + that.@foo = null + assert !that.setter + assert that.fooA != null + assert that.fooB == null + + that = new E() + that.setFoo(null) + assert that.setter + assert that.fooA == null + assert that.fooB != null + } + } + + new E().test1() + new E().test2() + new E().test3() + new E().test4() + new E().test5() + ''' + } }