This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch GROOVY-8283 in repository https://gitbox.apache.org/repos/asf/groovy.git
commit a2efe422c2b1b34e7644b28857bb313323d0a3d0 Author: Eric Milles <[email protected]> AuthorDate: Fri Nov 22 12:02:46 2024 -0600 GROOVY-8283: SC: field hides getter of super class --- .../classgen/asm/sc/StaticTypesCallSiteWriter.java | 7 +++ src/test/groovy/bugs/Groovy8283.groovy | 54 +++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java index a1c344030e..6664621b67 100644 --- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java +++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java @@ -55,6 +55,7 @@ import java.util.function.Predicate; import static org.apache.groovy.ast.tools.ClassNodeUtils.getField; import static org.apache.groovy.ast.tools.ClassNodeUtils.getMethod; +import static org.apache.groovy.ast.tools.ClassNodeUtils.isSubtype; import static org.apache.groovy.ast.tools.ExpressionUtils.isThisExpression; import static org.apache.groovy.util.BeanUtils.capitalize; import static org.codehaus.groovy.ast.ClassHelper.CLASS_Type; @@ -454,6 +455,12 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter { if (!AsmClassGenerator.isMemberDirectlyAccessible(getterNode.getModifiers(), getterNode.getDeclaringClass(), controller.getClassNode())) { return false; // GROOVY-6277 } + FieldNode fieldNode = getField(receiverType, propertyName); + if (fieldNode != null && !getterNode.getDeclaringClass().equals(fieldNode.getDeclaringClass()) + && isSubtype(getterNode.getDeclaringClass(), fieldNode.getDeclaringClass()) // field found before getter (starting from receiver type) + && AsmClassGenerator.isMemberDirectlyAccessible(fieldNode.getModifiers(), fieldNode.getDeclaringClass(), controller.getClassNode())) { + return false; // GROOVY-8283 + } MethodCallExpression call = callX(receiver, getterName); call.setImplicitThis(implicitThis); call.setMethodTarget(getterNode); diff --git a/src/test/groovy/bugs/Groovy8283.groovy b/src/test/groovy/bugs/Groovy8283.groovy index 9e75a720b2..fc34722f4a 100644 --- a/src/test/groovy/bugs/Groovy8283.groovy +++ b/src/test/groovy/bugs/Groovy8283.groovy @@ -35,7 +35,7 @@ final class Groovy8283 { A getFoo() { return foo } } class D extends C { - protected B foo = new B() // hides A#foo; should hide A#getFoo in subclasses + protected B foo = new B() } ''' assertScript shell, '''import p.* @@ -56,6 +56,22 @@ final class Groovy8283 { new E().test() assert new E().foo.class == A // not the field from this perspective ''' + } + + @Test + void testReadFieldPropertyShadowing2() { + def shell = new GroovyShell() + shell.parse '''package p + class A {} + class B {} + class C { + protected A foo = new A() + A getFoo() { return foo } + } + class D extends C { + protected B foo = new B() + } + ''' assertScript shell, '''import p.* class E extends D { @groovy.transform.ASTTest(phase=org.codehaus.groovy.control.CompilePhase.INSTRUCTION_SELECTION, value={ @@ -102,6 +118,42 @@ final class Groovy8283 { ''' } + @Test + void testReadFieldPropertyShadowing3() { + def shell = GroovyShell.withConfig { + ast(groovy.transform.CompileStatic) + } + shell.parse '''package p + class A {} + class B {} + class C { + protected A foo = new A() + A getFoo() { return foo } + } + class D extends C { + protected B foo = new B() + } + ''' + assertScript shell, '''import p.* + class E extends D { + void test() { + assert foo.class == B + assert this.foo.class == B + assert [email protected] == B + assert this.getFoo().getClass() == A + + def that = new E() + assert that.foo.class == B + assert [email protected] == B + assert that.getFoo().getClass() == A + } + } + + new E().test() + assert new E().foo.class == A // not the field from this perspective + ''' + } + @Test void testWriteFieldPropertyShadowing() { def shell = new GroovyShell()
