From commits-return-9530-archive-asf-public=cust-asf.ponee.io@groovy.apache.org Wed Oct 30 15:55:26 2019 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [207.244.88.153]) by mx-eu-01.ponee.io (Postfix) with SMTP id 1D724180654 for ; Wed, 30 Oct 2019 16:55:26 +0100 (CET) Received: (qmail 35414 invoked by uid 500); 30 Oct 2019 15:55:25 -0000 Mailing-List: contact commits-help@groovy.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@groovy.apache.org Delivered-To: mailing list commits@groovy.apache.org Received: (qmail 35308 invoked by uid 99); 30 Oct 2019 15:55:24 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 30 Oct 2019 15:55:24 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id B632B80626; Wed, 30 Oct 2019 15:55:24 +0000 (UTC) Date: Wed, 30 Oct 2019 15:55:27 +0000 To: "commits@groovy.apache.org" Subject: [groovy] 03/17: GROOVY-9292: Compilation error when accessing a protected super class field from a closure using owner, delegate or thisObject qualifier (different package) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit From: sunlan@apache.org In-Reply-To: <157245092409.924.15064251650937730612@gitbox.apache.org> References: <157245092409.924.15064251650937730612@gitbox.apache.org> X-Git-Host: gitbox.apache.org X-Git-Repo: groovy X-Git-Refname: refs/heads/GROOVY_3_0_X X-Git-Reftype: branch X-Git-Rev: 010e3759e527fcf7faedbcf101ea858df0c50b8a X-Git-NotificationType: diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated Message-Id: <20191030155524.B632B80626@gitbox.apache.org> This is an automated email from the ASF dual-hosted git repository. sunlan pushed a commit to branch GROOVY_3_0_X in repository https://gitbox.apache.org/repos/asf/groovy.git commit 010e3759e527fcf7faedbcf101ea858df0c50b8a Author: Daniel.Sun AuthorDate: Tue Oct 29 08:10:51 2019 +0800 GROOVY-9292: Compilation error when accessing a protected super class field from a closure using owner, delegate or thisObject qualifier (different package) (cherry picked from commit 3673e10c495f1e2618cf0679cc9887f8e8561e2f) --- .../transform/stc/StaticTypeCheckingVisitor.java | 18 + src/test/groovy/bugs/Groovy9288.groovy | 8 +- src/test/groovy/bugs/Groovy9292Bug.groovy | 1008 ++++++++++++++++++++ src/test/groovy/bugs/Groovy9293.groovy | 8 +- 4 files changed, 1034 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index bafe1cb..5161529 100644 --- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -222,6 +222,7 @@ import static org.codehaus.groovy.syntax.Types.MINUS_MINUS; import static org.codehaus.groovy.syntax.Types.MOD; import static org.codehaus.groovy.syntax.Types.MOD_EQUAL; import static org.codehaus.groovy.syntax.Types.PLUS_PLUS; +import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.RECEIVER_OF_DYNAMIC_PROPERTY; import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.ArrayList_TYPE; import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.Collection_TYPE; import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.Matcher_TYPE; @@ -1508,6 +1509,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { return existsProperty(pexp, checkForReadOnly, null); } + private static final Set CLOSURE_IMPLICIT_VARIABLE_SET = + Collections.unmodifiableSet(new HashSet<>(Arrays.asList("it", "this", "thisObject", "owner", "delegate"))); + /** * Checks whether a property exists on the receiver, or on any of the possible receiver classes (found in the * temporary type information table) @@ -1589,6 +1593,16 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { FieldNode field = current.getDeclaredField(propertyName); field = allowStaticAccessToMember(field, staticOnly); + + if (null != field) { + int fieldModifiers = field.getModifiers(); + if (Modifier.isProtected(fieldModifiers) || isPackagePrivate(fieldModifiers)) { + if (null != typeCheckingContext.getEnclosingClosure() && CLOSURE_IMPLICIT_VARIABLE_SET.contains(objectExpression.getText())) { + objectExpression.putNodeMetaData(RECEIVER_OF_DYNAMIC_PROPERTY, OBJECT_TYPE); + } + } + } + if (storeField(field, isAttributeExpression, pexp, current, visitor, receiver.getData(), !readMode)) { pexp.removeNodeMetaData(READONLY_PROPERTY); return true; @@ -1717,6 +1731,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { return foundGetterOrSetter; } + private static boolean isPackagePrivate(int modifiers) { + return !(Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers) || Modifier.isPrivate(modifiers)); + } + private static boolean hasAccessToField(FieldNode field, ClassNode objectExpressionType) { if (field != null) { if (field.isPublic() || field.isProtected()) { diff --git a/src/test/groovy/bugs/Groovy9288.groovy b/src/test/groovy/bugs/Groovy9288.groovy index f2b5bee..87f2ac8 100644 --- a/src/test/groovy/bugs/Groovy9288.groovy +++ b/src/test/groovy/bugs/Groovy9288.groovy @@ -100,7 +100,7 @@ final class Groovy9288 { ''' } - @Test @NotYetImplemented // GROOVY-9292 + @Test void 'test accessing a protected super class field inside a closure - diff package, it qualifier'() { shell.evaluate ''' package a @@ -204,7 +204,7 @@ final class Groovy9288 { ''' } - @Test @NotYetImplemented // GROOVY-9292 + @Test void 'test accessing a protected super class field inside a closure - diff package, owner qualifier'() { shell.evaluate ''' package a @@ -256,7 +256,7 @@ final class Groovy9288 { ''' } - @Test @NotYetImplemented // GROOVY-9292 + @Test void 'test accessing a protected super class field inside a closure - diff package, delegate qualifier'() { shell.evaluate ''' package a @@ -308,7 +308,7 @@ final class Groovy9288 { ''' } - @Test @NotYetImplemented // GROOVY-9292 + @Test void 'test accessing a protected super class field inside a closure - diff package, thisObject qualifier'() { shell.evaluate ''' package a diff --git a/src/test/groovy/bugs/Groovy9292Bug.groovy b/src/test/groovy/bugs/Groovy9292Bug.groovy new file mode 100644 index 0000000..6b11a4c --- /dev/null +++ b/src/test/groovy/bugs/Groovy9292Bug.groovy @@ -0,0 +1,1008 @@ +/* + * 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 groovy.test.NotYetImplemented +import org.junit.Test + +final class Groovy9292Bug { + + @Test + void "test accessing a protected super class field from inside a closure - different package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + protected String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + 'something'.with { + return superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a protected super class field from inside a closure - same package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + protected String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package a + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + 'something'.with { + return superField + } + } + } + assert true + ''') + + shell.evaluate("assert new a.ConcreteClass().doThing() == 'field'") + } + + + @Test + void "test accessing a protected super class field from inside a closure - using it - different package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + protected String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return it.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a protected super class field from inside a closure - using this - different package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + protected String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + 'something'.with { + return this.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + + @Test + void "test accessing a protected super class field from inside a closure - using thisObject - different package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + protected String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + 'something'.with { + return thisObject.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a protected super class field from inside a closure - using owner - different package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + protected String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + 'something'.with { + return owner.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a protected super class field from inside a closure - using delegate - different package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + protected String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return delegate.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a package-private super class field from inside a closure - same package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + @groovy.transform.PackageScope String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package a + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return delegate.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new a.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a package-private super class field from inside a closure - using delegate - same package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + @groovy.transform.PackageScope String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package a + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return delegate.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new a.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a package-private super class field from inside a closure - using it - same package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + @groovy.transform.PackageScope String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package a + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return it.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new a.ConcreteClass().doThing() == 'field'") + } + + @NotYetImplemented // java.lang.IllegalAccessError: class a.ConcreteClass$_doThing_closure1 tried to access field a.Abstract_Class.superField (a.ConcreteClass$_doThing_closure1 is in unnamed module of loader groovy.lang.GroovyClassLoader$InnerLoader @5fa47fea; a.Abstract_Class is in unnamed module of loader groovy.lang.GroovyClassLoader$InnerLoader @28cda624) + @Test + void "test accessing a package-private super class field from inside a closure - using this - same package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + @groovy.transform.PackageScope String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package a + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return this.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new a.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a package-private super class field from inside a closure - using thisObject - same package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + @groovy.transform.PackageScope String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package a + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return thisObject.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new a.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a package-private super class field from inside a closure - using owner - same package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + @groovy.transform.PackageScope String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package a + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return owner.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new a.ConcreteClass().doThing() == 'field'") + } + + + @Test + void "test accessing a public super class field from inside a closure - different package -- regression"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + public String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a public super class field from inside a closure - using delegate - different package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + public String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return delegate.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + + @Test + void "test accessing a public super class field from inside a closure - using it - different package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + public String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return it.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a public super class field from inside a closure - using this - different package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + public String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return this.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a public super class field from inside a closure - using thisObject - different package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + public String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return thisObject.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a public super class field from inside a closure - using owner - different package"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + public String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return owner.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + + @Test + void "test accessing a private super class field from inside a closure via getter - different package -- regression"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + + @Test + void "test accessing a private super class field from inside a closure via getter - using delegate - different package -- regression"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return delegate.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a private super class field from inside a closure via getter - using it - different package -- regression"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return it.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + + @Test + void "test accessing a private super class field from inside a closure via getter - using this - different package -- regression"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return this.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a private super class field from inside a closure via getter - using thisObject - different package -- regression"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return thisObject.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } + + @Test + void "test accessing a private super class field from inside a closure via getter - using owner - different package -- regression"() { + GroovyShell shell = new GroovyShell() + shell.evaluate(''' + package a + + import groovy.transform.CompileStatic + + @CompileStatic + abstract class Abstract_Class { + String superField = 'field' + + abstract String doThing() + } + assert true + ''') + + shell.evaluate(''' + package b + + import a.Abstract_Class + import groovy.transform.CompileStatic + + @CompileStatic + class ConcreteClass extends Abstract_Class { + + @Override + String doThing() { + this.with { + return owner.superField + } + } + } + assert true + ''') + + shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") + } +} diff --git a/src/test/groovy/bugs/Groovy9293.groovy b/src/test/groovy/bugs/Groovy9293.groovy index 268e5ea..c50276a 100644 --- a/src/test/groovy/bugs/Groovy9293.groovy +++ b/src/test/groovy/bugs/Groovy9293.groovy @@ -106,7 +106,7 @@ final class Groovy9293 { ''' } - @Test @NotYetImplemented // GROOVY-9293 + @Test void 'test accessing a package-private super class field inside a closure - diff package, it qualifier'() { shouldFail(MissingPropertyException) { shell.evaluate ''' @@ -216,7 +216,7 @@ final class Groovy9293 { ''' } - @Test @NotYetImplemented // GROOVY-9293 + @Test void 'test accessing a package-private super class field inside a closure - diff package, owner qualifier'() { shouldFail(MissingPropertyException) { shell.evaluate ''' @@ -271,7 +271,7 @@ final class Groovy9293 { ''' } - @Test @NotYetImplemented // GROOVY-9293 + @Test void 'test accessing a package-private super class field inside a closure - diff package, delegate qualifier'() { shouldFail(MissingPropertyException) { shell.evaluate ''' @@ -326,7 +326,7 @@ final class Groovy9293 { ''' } - @Test @NotYetImplemented // GROOVY-9293 + @Test void 'test accessing a package-private super class field inside a closure - diff package, thisObject qualifier'() { shouldFail(MissingPropertyException) { shell.evaluate '''