You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2022/08/25 23:04:10 UTC

[groovy] branch GROOVY_2_5_X updated (37043f304c -> 1428950822)

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a change to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git


 discard 37043f304c GROOVY-9127, GROOVY-9195, GROOVY-9293: STC: super field access checks
     new 1428950822 GROOVY-9127, GROOVY-9195, GROOVY-9293: STC: super field access checks

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (37043f304c)
            \
             N -- N -- N   refs/heads/GROOVY_2_5_X (1428950822)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy     | 10 ++++++++++
 1 file changed, 10 insertions(+)


[groovy] 01/01: GROOVY-9127, GROOVY-9195, GROOVY-9293: STC: super field access checks

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 142895082234dcc17d7779553735f25c88b8aea1
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Aug 25 16:04:53 2022 -0500

    GROOVY-9127, GROOVY-9195, GROOVY-9293: STC: super field access checks
---
 .../groovy/classgen/AsmClassGenerator.java         |   32 +-
 .../transform/stc/StaticTypeCheckingVisitor.java   |   55 +-
 src/test/groovy/bugs/Groovy9127.groovy             |  164 ++++
 src/test/groovy/bugs/Groovy9136.groovy             |   61 +-
 src/test/groovy/bugs/Groovy9288.groovy             |  109 ++-
 src/test/groovy/bugs/Groovy9292.groovy             |  382 ++++++++
 src/test/groovy/bugs/Groovy9292Bug.groovy          | 1008 --------------------
 .../stc/FieldsAndPropertiesSTCTest.groovy          |   60 +-
 .../ArraysAndCollectionsStaticCompileTest.groovy   |   27 +-
 .../groovy/text/MarkupTemplateEngineTest.groovy    |    7 +-
 10 files changed, 739 insertions(+), 1166 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index a9e12910e7..9d3ced436b 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -91,6 +91,7 @@ import org.codehaus.groovy.ast.stmt.SynchronizedStatement;
 import org.codehaus.groovy.ast.stmt.ThrowStatement;
 import org.codehaus.groovy.ast.stmt.TryCatchStatement;
 import org.codehaus.groovy.ast.stmt.WhileStatement;
+import org.codehaus.groovy.ast.tools.GeneralUtils;
 import org.codehaus.groovy.ast.tools.WideningCategories;
 import org.codehaus.groovy.classgen.asm.BytecodeHelper;
 import org.codehaus.groovy.classgen.asm.BytecodeVariable;
@@ -1180,8 +1181,7 @@ public class AsmClassGenerator extends ClassGenerator {
     }
 
     private boolean isThisOrSuperInStaticContext(Expression objectExpression) {
-        if (controller.isInClosure()) return false;
-        return controller.isStaticContext() && isThisOrSuper(objectExpression);
+        return isThisOrSuper(objectExpression) && controller.isStaticContext() && !controller.isInClosure();
     }
 
     public void visitPropertyExpression(PropertyExpression expression) {
@@ -1233,11 +1233,11 @@ public class AsmClassGenerator extends ClassGenerator {
             if (controller.getCompileStack().isLHS()) {
                 adapter = setField;
                 if (isGroovyObject(objectExpression)) adapter = setGroovyObjectField;
-                if (usesSuper(expression)) adapter = setFieldOnSuper;
+                if (isSuperExpression(objectExpression)) adapter = setFieldOnSuper;
             } else {
                 adapter = getField;
                 if (isGroovyObject(objectExpression)) adapter = getGroovyObjectField;
-                if (usesSuper(expression)) adapter = getFieldOnSuper;
+                if (isSuperExpression(objectExpression)) adapter = getFieldOnSuper;
             }
             visitAttributeOrProperty(expression, adapter);
         }
@@ -1249,18 +1249,18 @@ public class AsmClassGenerator extends ClassGenerator {
         }
     }
 
-    private static boolean usesSuper(PropertyExpression pe) {
-        Expression expression = pe.getObjectExpression();
-        if (expression instanceof VariableExpression) {
-            VariableExpression varExp = (VariableExpression) expression;
-            String variable = varExp.getName();
-            return variable.equals("super");
-        }
-        return false;
+    private boolean isGroovyObject(Expression objectExpression) {
+        if (ExpressionUtils.isThisExpression(objectExpression)) return true;
+        if (objectExpression instanceof ClassExpression) return false;
+
+        ClassNode objectExpressionType = controller.getTypeChooser().resolveType(objectExpression, controller.getClassNode());
+        if (objectExpressionType.equals(ClassHelper.OBJECT_TYPE)) objectExpressionType = objectExpression.getType();
+        if (GeneralUtils.isOrImplements(objectExpressionType, ClassHelper.MAP_TYPE)) return false; // GROOVY-8074
+        return implementsGroovyObject(objectExpressionType); // GROOVY-9195, GROOVY-9288, et al.
     }
 
-    private static boolean isGroovyObject(Expression objectExpression) {
-        return ExpressionUtils.isThisExpression(objectExpression) || objectExpression.getType().isDerivedFromGroovyObject() && !(objectExpression instanceof ClassExpression);
+    private static boolean implementsGroovyObject(ClassNode cn) {
+        return cn.isDerivedFromGroovyObject() || (!cn.isInterface() && cn.getCompileUnit() != null);
     }
 
     public void visitFieldExpression(FieldExpression expression) {
@@ -1691,8 +1691,8 @@ public class AsmClassGenerator extends ClassGenerator {
     public void loadWrapper(Expression argument) {
         MethodVisitor mv = controller.getMethodVisitor();
         ClassNode goalClass = argument.getType();
-        visitClassExpression(new ClassExpression(goalClass));
-        if (goalClass.isDerivedFromGroovyObject()) {
+        visitClassExpression(classX(goalClass));
+        if (implementsGroovyObject(goalClass)) {
             createGroovyObjectWrapperMethod.call(mv);
         } else {
             createPojoWrapperMethod.call(mv);
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 954d8c06ba..9212345315 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1450,9 +1450,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return existsProperty(pexp, checkForReadOnly, null);
     }
 
-    private static final Set<String> 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)
@@ -1476,9 +1473,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             // Outer.this for any level of nesting
             ClassNode outerNode = objectExpressionType.getGenericsTypes()[0].getType();
             ClassNode found = null;
-            for (ClassNode current : enclosingTypes) {
-                if (!current.isStaticClass() && current instanceof InnerClassNode && outerNode.equals(current.getOuterClass())) {
-                    found = current;
+            for (ClassNode enclosingType : enclosingTypes) {
+                if (!enclosingType.isStaticClass() && outerNode.equals(enclosingType.getOuterClass())) {
+                    found = enclosingType;
                     break;
                 }
             }
@@ -1492,9 +1489,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         List<Receiver<String>> receivers = new ArrayList<>();
         addReceivers(receivers, makeOwnerList(objectExpression), pexp.isImplicitThis());
 
-        String capName = MetaClassHelper.capitalize(propertyName);
+        String capName = MetaClassHelper.capitalize(propertyName), isserName = "is" + capName, getterName = "get" + capName, setterName = "set" + capName;
         boolean isAttributeExpression = pexp instanceof AttributeExpression;
-        HashSet<ClassNode> handledNodes = new HashSet<ClassNode>();
+        Set<ClassNode> handledNodes = new HashSet<>();
         for (Receiver<String> receiver : receivers) {
             ClassNode receiverType = receiver.getType();
 
@@ -1538,16 +1535,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 }
                 field = allowStaticAccessToMember(field, staticOnly);
 
-                // GROOVY-9288, GROOVY-9292, GROOVY-9293
-                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(StaticCompilationMetadataKeys.RECEIVER_OF_DYNAMIC_PROPERTY, OBJECT_TYPE);
-                        }
-                    }
-                }
-
                 // skip property/accessor checks for "x.@field"
                 if (storeField(field, isAttributeExpression, pexp, receiverType, visitor, receiver.getData(), !readMode)) {
                     pexp.removeNodeMetaData(StaticTypesMarker.READONLY_PROPERTY);
@@ -1562,13 +1549,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                     return true;
                 }
 
-                boolean isThisExpression = enclosingTypes.contains(receiverType);
-
-                MethodNode getter = findGetter(current, "get" + capName, pexp.isImplicitThis());
+                MethodNode getter = findGetter(current, getterName, pexp.isImplicitThis());
                 getter = allowStaticAccessToMember(getter, staticOnly);
-                if (getter == null) getter = findGetter(current, "is" + capName, pexp.isImplicitThis());
+                if (getter == null) getter = findGetter(current, isserName, pexp.isImplicitThis());
                 getter = allowStaticAccessToMember(getter, staticOnly);
-                final String setterName = "set" + capName;
                 List<MethodNode> setters = findSetters(current, setterName, false);
                 setters = allowStaticAccessToMember(setters, staticOnly);
 
@@ -1578,7 +1562,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 PropertyNode propertyNode = current.getProperty(propertyName);
                 propertyNode = allowStaticAccessToMember(propertyNode, staticOnly);
                 // prefer explicit getter or setter over property if receiver is not 'this'
-                boolean checkGetterOrSetter = !isThisExpression || propertyNode == null;
+                boolean checkGetterOrSetter = propertyNode == null || !enclosingTypes.contains(receiverType);
 
                 if (readMode && checkGetterOrSetter) {
                     if (getter != null) {
@@ -1587,8 +1571,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                         storeTargetMethod(pexp, getter);
                         pexp.removeNodeMetaData(StaticTypesMarker.READONLY_PROPERTY);
                         String delegationData = receiver.getData();
-                        if (delegationData != null)
+                        if (delegationData != null) {
                             pexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, delegationData);
+                        }
                         return true;
                     }
                 } else if (!readMode && checkGetterOrSetter) {
@@ -1610,6 +1595,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                         if (enclosingBinaryExpression != null) {
                             putSetterInfo(enclosingBinaryExpression.getLeftExpression(), info);
                         }
+                        pexp.removeNodeMetaData(StaticTypesMarker.READONLY_PROPERTY);
                         String delegationData = receiver.getData();
                         if (delegationData != null) {
                             pexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, delegationData);
@@ -1632,8 +1618,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
             // GROOVY-5568: the property may be defined by DGM
             for (ClassNode dgmReceiver : isPrimitiveType(receiverType) ? new ClassNode[]{receiverType, getWrapper(receiverType)} : new ClassNode[]{receiverType}) {
-                List<MethodNode> methods = findDGMMethodsByNameAndArguments(getSourceUnit().getClassLoader(), dgmReceiver, "get" + capName, ClassNode.EMPTY_ARRAY);
-                for (MethodNode m : findDGMMethodsByNameAndArguments(getSourceUnit().getClassLoader(), dgmReceiver, "is" + capName, ClassNode.EMPTY_ARRAY)) {
+                List<MethodNode> methods = findDGMMethodsByNameAndArguments(getSourceUnit().getClassLoader(), dgmReceiver, getterName, ClassNode.EMPTY_ARRAY);
+                for (MethodNode m : findDGMMethodsByNameAndArguments(getSourceUnit().getClassLoader(), dgmReceiver, isserName, ClassNode.EMPTY_ARRAY)) {
                     if (Boolean_TYPE.equals(getWrapper(m.getReturnType()))) methods.add(m);
                 }
                 if (isUsingGenericsOrIsArrayUsingGenerics(dgmReceiver)) { // GROOVY-10075: "List<Integer>" vs "List<String>"
@@ -1697,18 +1683,15 @@ 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.isPublic() || field.isProtected()) {
+    private static boolean hasAccessToField(final FieldNode field, final ClassNode accessor) {
+        if (field.isPublic() || accessor.equals(field.getDeclaringClass())) {
             return true;
         }
-        if (!field.isPrivate() && Objects.equals(objectExpressionType.getPackageName(), field.getDeclaringClass().getPackageName())) {
-            return true;
+        if (field.isProtected()) {
+            return accessor.isDerivedFrom(field.getDeclaringClass());
+        } else {
+            return !field.isPrivate() && Objects.equals(accessor.getPackageName(), field.getDeclaringClass().getPackageName());
         }
-        return false;
     }
 
     private MethodNode findGetter(ClassNode current, String name, boolean searchOuterClasses) {
diff --git a/src/test/groovy/bugs/Groovy9127.groovy b/src/test/groovy/bugs/Groovy9127.groovy
new file mode 100644
index 0000000000..60c957a00a
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9127.groovy
@@ -0,0 +1,164 @@
+/*
+ *  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.transform.CompileStatic
+import org.codehaus.groovy.control.CompilationFailedException
+import org.codehaus.groovy.control.CompilationUnit
+
+import static org.codehaus.groovy.control.Phases.CLASS_GENERATION
+
+@CompileStatic
+final class Groovy9127 extends GroovyTestCase {
+
+    void testReadOnlyPropertyAssignment1() {
+        assertScript '''
+            @groovy.transform.CompileStatic
+            class Foo {
+                protected String field = 'foo'
+                String getField() { return field }
+            }
+            @groovy.transform.CompileStatic
+            class Bar extends Foo {
+                void changeField() {
+                    field = 'bar' // GROOVY-9127: [Static type checking] - Cannot set read-only property: field
+                }
+                @Override
+                String getField() { return 'value' }
+            }
+            def bar = new Bar()
+            bar.changeField()
+            assert bar.field == 'value'
+        '''
+    }
+
+    void testReadOnlyPropertyAssignment2() {
+        assertScript '''
+            @groovy.transform.CompileStatic
+            class Foo {
+                public String field = 'foo'
+                String getField() { return field }
+            }
+            @groovy.transform.CompileStatic
+            class Bar extends Foo {
+                void changeField() {
+                    field = 'bar'
+                }
+                @Override
+                String getField() { return 'value' }
+            }
+            def bar = new Bar()
+            bar.changeField()
+            assert bar.field == 'value'
+        '''
+    }
+
+    void testReadOnlyPropertyAssignment3() {
+        assertScript '''
+            @groovy.transform.CompileStatic
+            class Foo {
+                @groovy.transform.PackageScope String field = 'foo'
+                String getField() { return field }
+            }
+            @groovy.transform.CompileStatic
+            class Bar extends Foo {
+                void changeField() {
+                    field = 'bar'
+                }
+                @Override
+                String getField() { return 'value' }
+            }
+            def bar = new Bar()
+            bar.changeField()
+            assert bar.field == 'value'
+        '''
+    }
+
+    void testReadOnlyPropertyAssignment4() {
+        new CompilationUnit().with {
+            addSource 'Foo.groovy', '''
+                package foo
+
+                @groovy.transform.CompileStatic
+                class Foo {
+                    @groovy.transform.PackageScope String field = 'foo'
+                    String getField() { return field }
+                }
+            '''
+
+            addSource 'Bar.groovy', '''
+                package bar
+
+                @groovy.transform.CompileStatic
+                class Bar extends foo.Foo {
+                    void changeField() {
+                        field = 'bar'
+                    }
+                    @Override
+                    String getField() { return 'value' }
+                }
+            '''
+
+            def err = shouldFail CompilationFailedException, {
+                compile CLASS_GENERATION
+            }
+            assert err =~ /\[Static type checking\] - Cannot set read-only property: field/
+        }
+    }
+
+    void testReadOnlyPropertyAssignment5() {
+        def err = shouldFail CompilationFailedException, '''
+            @groovy.transform.CompileStatic
+            class Foo {
+                private String field = 'foo'
+                String getField() { return field }
+            }
+            @groovy.transform.CompileStatic
+            class Bar extends Foo {
+                void changeField() {
+                    field = 'bar'
+                }
+                @Override
+                String getField() { return 'value' }
+            }
+        '''
+        assert err =~ /\[Static type checking\] - Cannot set read-only property: field/
+    }
+
+    void testAttributeAssignmentVariation() {
+        assertScript '''
+            @groovy.transform.CompileStatic
+            class Foo {
+                protected String field = 'foo'
+                String getField() { return field }
+            }
+            @groovy.transform.CompileStatic
+            class Bar extends Foo {
+                void changeField() {
+                    this.@field = 'bar'
+                }
+                @Override
+                String getField() { return 'value' }
+            }
+            def bar = new Bar()
+            bar.changeField()
+            assert bar.field == 'value'
+        '''
+    }
+}
diff --git a/src/test/groovy/bugs/Groovy9136.groovy b/src/test/groovy/bugs/Groovy9136.groovy
index f85aff276e..eac12742c8 100644
--- a/src/test/groovy/bugs/Groovy9136.groovy
+++ b/src/test/groovy/bugs/Groovy9136.groovy
@@ -18,28 +18,71 @@
  */
 package groovy.bugs
 
-import groovy.transform.CompileStatic
+import org.junit.Test
 
-@CompileStatic
-final class Groovy9136 extends GroovyTestCase {
+import static groovy.test.GroovyAssert.assertScript
 
-    void testMethodParameterAccessFromClosure() {
+final class Groovy9136 {
+
+    @Test
+    void testMethodParameterFieldAccessFromClosure1() {
         assertScript '''
-            @groovy.transform.CompileStatic
             class Foo {
                 public String field = 'foo'
             }
-            @groovy.transform.CompileStatic
             class Bar {
-                def doIt(Foo foo) {
+                @groovy.transform.CompileStatic
+                def test(Foo foo) {
                     'baz'.with {
-                        foo.field // GROOVY-9136: Access to Foo#foo is forbidden at line: -1, column: -1
+                        foo.field // Access to Foo#foo is forbidden at line: -1, column: -1
+                    }
+                }
+            }
+
+            def bar = new Bar()
+            def out = bar.test(new Foo())
+            assert out == 'foo'
+        '''
+    }
+
+    @Test // GROOVY-9195
+    void testMethodParameterFieldAccessFromClosure2() {
+        assertScript '''
+            class Foo {
+                private String field = 'foo'
+            }
+            class Bar {
+                @groovy.transform.CompileStatic
+                def test(Foo foo) {
+                    'baz'.with {
+                        foo.field
+                    }
+                }
+            }
+
+            def bar = new Bar()
+            def out = bar.test(new Foo())
+            assert out == 'foo'
+        '''
+    }
+
+    @Test
+    void testMethodParameterFieldAccessFromClosure3() {
+        assertScript '''
+            class Foo {
+                private String field = 'foo'
+            }
+            @groovy.transform.CompileStatic
+            class Bar {
+                def test(Foo foo) {
+                    foo.with {
+                        field
                     }
                 }
             }
 
             def bar = new Bar()
-            def out = bar.doIt(new Foo())
+            def out = bar.test(new Foo())
             assert out == 'foo'
         '''
     }
diff --git a/src/test/groovy/bugs/Groovy9288.groovy b/src/test/groovy/bugs/Groovy9288.groovy
index d8650eecb3..d1b67e3b6c 100644
--- a/src/test/groovy/bugs/Groovy9288.groovy
+++ b/src/test/groovy/bugs/Groovy9288.groovy
@@ -19,18 +19,31 @@
 package groovy.bugs
 
 import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.junit.runners.Parameterized.Parameter
+import org.junit.runners.Parameterized.Parameters
 
+@RunWith(Parameterized)
 final class Groovy9288 {
 
+    @Parameters
+    static modifiers() {
+        ['public', 'protected']
+    }
+
+    @Parameter
+    public String modifier
+
     private final GroovyShell shell = new GroovyShell()
 
     @Test
-    void 'test accessing a protected super class field inside a closure - same package'() {
-        shell.evaluate '''
+    void 'test accessing a super class field inside a closure - same package'() {
+        shell.evaluate """
             package a
 
             class A {
-                protected String superField = 'works'
+                $modifier String superField = 'works'
             }
 
             class B extends A {
@@ -44,20 +57,20 @@ final class Groovy9288 {
 
             def obj = new B()
             assert obj.test() == "works"
-        '''
+        """
     }
 
     @Test
-    void 'test accessing a protected super class field inside a closure - diff package'() {
-        shell.evaluate '''
+    void 'test accessing a super class field inside a closure - diff package'() {
+        shell.evaluate """
             package a
 
             class A {
-                protected String superField = 'works'
+                $modifier String superField = 'works'
             }
 
             assert true
-        '''
+        """
 
         shell.evaluate '''
             package b
@@ -77,12 +90,12 @@ final class Groovy9288 {
     }
 
     @Test
-    void 'test accessing a protected super class field inside a closure - same package, it qualifier'() {
-        shell.evaluate '''
+    void 'test accessing a super class field inside a closure - same package, it qualifier'() {
+        shell.evaluate """
             package a
 
             class A {
-                protected String superField = 'works'
+                $modifier String superField = 'works'
             }
 
             class B extends A {
@@ -96,20 +109,20 @@ final class Groovy9288 {
 
             def obj = new B()
             assert obj.test() == "works"
-        '''
+        """
     }
 
     @Test
-    void 'test accessing a protected super class field inside a closure - diff package, it qualifier'() {
-        shell.evaluate '''
+    void 'test accessing a super class field inside a closure - diff package, it qualifier'() {
+        shell.evaluate """
             package a
 
             class A {
-                protected String superField = 'works'
+                $modifier String superField = 'works'
             }
 
             assert true
-        '''
+        """
 
         shell.evaluate '''
             package b
@@ -129,12 +142,12 @@ final class Groovy9288 {
     }
 
     @Test
-    void 'test accessing a protected super class field inside a closure - same package, this qualifier'() {
-        shell.evaluate '''
+    void 'test accessing a super class field inside a closure - same package, this qualifier'() {
+        shell.evaluate """
             package a
 
             class A {
-                protected String superField = 'works'
+                $modifier String superField = 'works'
             }
 
             class B extends A {
@@ -148,20 +161,20 @@ final class Groovy9288 {
 
             def obj = new B()
             assert obj.test() == "works"
-        '''
+        """
     }
 
     @Test
-    void 'test accessing a protected super class field inside a closure - diff package, this qualifier'() {
-        shell.evaluate '''
+    void 'test accessing a super class field inside a closure - diff package, this qualifier'() {
+        shell.evaluate """
             package a
 
             class A {
-                protected String superField = 'works'
+                $modifier String superField = 'works'
             }
 
             assert true
-        '''
+        """
 
         shell.evaluate '''
             package b
@@ -181,12 +194,12 @@ final class Groovy9288 {
     }
 
     @Test
-    void 'test accessing a protected super class field inside a closure - same package, owner qualifier'() {
-        shell.evaluate '''
+    void 'test accessing a super class field inside a closure - same package, owner qualifier'() {
+        shell.evaluate """
             package a
 
             class A {
-                protected String superField = 'works'
+                $modifier String superField = 'works'
             }
 
             class B extends A {
@@ -200,20 +213,20 @@ final class Groovy9288 {
 
             def obj = new B()
             assert obj.test() == "works"
-        '''
+        """
     }
 
     @Test
-    void 'test accessing a protected super class field inside a closure - diff package, owner qualifier'() {
-        shell.evaluate '''
+    void 'test accessing a super class field inside a closure - diff package, owner qualifier'() {
+        shell.evaluate """
             package a
 
             class A {
-                protected String superField = 'works'
+                $modifier String superField = 'works'
             }
 
             assert true
-        '''
+        """
 
         shell.evaluate '''
             package b
@@ -233,12 +246,12 @@ final class Groovy9288 {
     }
 
     @Test
-    void 'test accessing a protected super class field inside a closure - same package, delegate qualifier'() {
-        shell.evaluate '''
+    void 'test accessing a super class field inside a closure - same package, delegate qualifier'() {
+        shell.evaluate """
             package a
 
             class A {
-                protected String superField = 'works'
+                $modifier String superField = 'works'
             }
 
             class B extends A {
@@ -252,20 +265,20 @@ final class Groovy9288 {
 
             def obj = new B()
             assert obj.test() == "works"
-        '''
+        """
     }
 
     @Test
-    void 'test accessing a protected super class field inside a closure - diff package, delegate qualifier'() {
-        shell.evaluate '''
+    void 'test accessing a super class field inside a closure - diff package, delegate qualifier'() {
+        shell.evaluate """
             package a
 
             class A {
-                protected String superField = 'works'
+                $modifier String superField = 'works'
             }
 
             assert true
-        '''
+        """
 
         shell.evaluate '''
             package b
@@ -285,12 +298,12 @@ final class Groovy9288 {
     }
 
     @Test
-    void 'test accessing a protected super class field inside a closure - same package, thisObject qualifier'() {
-        shell.evaluate '''
+    void 'test accessing a super class field inside a closure - same package, thisObject qualifier'() {
+        shell.evaluate """
             package a
 
             class A {
-                protected String superField = 'works'
+                $modifier String superField = 'works'
             }
 
             class B extends A {
@@ -304,20 +317,20 @@ final class Groovy9288 {
 
             def obj = new B()
             assert obj.test() == "works"
-        '''
+        """
     }
 
     @Test
-    void 'test accessing a protected super class field inside a closure - diff package, thisObject qualifier'() {
-        shell.evaluate '''
+    void 'test accessing a super class field inside a closure - diff package, thisObject qualifier'() {
+        shell.evaluate """
             package a
 
             class A {
-                protected String superField = 'works'
+                $modifier String superField = 'works'
             }
 
             assert true
-        '''
+        """
 
         shell.evaluate '''
             package b
diff --git a/src/test/groovy/bugs/Groovy9292.groovy b/src/test/groovy/bugs/Groovy9292.groovy
new file mode 100644
index 0000000000..3ffe823f8e
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9292.groovy
@@ -0,0 +1,382 @@
+/*
+ *  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.shouldFail
+
+final class Groovy9292 {
+
+    private final GroovyShell shell = new GroovyShell()
+
+    @Test
+    void 'test accessing a private super class field inside a closure - same module'() {
+        shouldFail(MissingPropertyException) {
+            shell.evaluate '''
+                package a
+
+                class A {
+                    private String superField
+                }
+
+                class B extends A {
+                    @groovy.transform.CompileStatic
+                    def test() {
+                        'something'.with {
+                            return superField
+                        }
+                    }
+                }
+
+                new B().test()
+            '''
+        }
+    }
+
+    @Test
+    void 'test accessing a private super class field inside a closure - same package'() {
+        shouldFail(MissingPropertyException) {
+            shell.evaluate '''
+                package a
+
+                class A {
+                    private String superField
+                }
+
+                assert true
+            '''
+
+            shell.evaluate '''
+                package a
+
+                class B extends A {
+                    @groovy.transform.CompileStatic
+                    def test() {
+                        'something'.with {
+                            return superField
+                        }
+                    }
+                }
+
+                new B().test()
+            '''
+        }
+    }
+
+    @Test
+    void 'test accessing a private super class field inside a closure - diff package'() {
+        shouldFail(MissingPropertyException) {
+            shell.evaluate '''
+                package a
+
+                class A {
+                    private String superField
+                }
+
+                assert true
+            '''
+
+            shell.evaluate '''
+                package b
+
+                class B extends a.A {
+                    @groovy.transform.CompileStatic
+                    def test() {
+                        'something'.with {
+                            return superField
+                        }
+                    }
+                }
+
+                new B().test()
+            '''
+        }
+    }
+
+    @Test
+    void 'test accessing a private super class field inside a closure - same package, it qualifier'() {
+        shouldFail(MissingPropertyException) {
+            shell.evaluate '''
+                package a
+
+                class A {
+                    private String superField
+                }
+
+                class B extends A {
+                    @groovy.transform.CompileStatic
+                    def test() {
+                        with {
+                            return it.superField
+                        }
+                    }
+                }
+
+                new B().test()
+            '''
+        }
+    }
+
+    @Test
+    void 'test accessing a private super class field inside a closure - diff package, it qualifier'() {
+        shouldFail(MissingPropertyException) {
+            shell.evaluate '''
+                package a
+
+                class A {
+                    private String superField
+                }
+
+                assert true
+            '''
+
+            shell.evaluate '''
+                package b
+
+                class B extends a.A {
+                    @groovy.transform.CompileStatic
+                    def test() {
+                        with {
+                            return it.superField
+                        }
+                    }
+                }
+
+                new B().test()
+            '''
+        }
+    }
+
+    @Test
+    void 'test accessing a private super class field inside a closure - same package, this qualifier'() {
+        shouldFail(MissingPropertyException) {
+            shell.evaluate '''
+                package a
+
+                class A {
+                    private String superField
+                }
+
+                class B extends A {
+                    @groovy.transform.CompileStatic
+                    def test() {
+                        'something'.with {
+                            return this.superField
+                        }
+                    }
+                }
+
+                new B().test()
+            '''
+        }
+    }
+
+    @Test
+    void 'test accessing a private super class field inside a closure - diff package, this qualifier'() {
+        shouldFail(MissingPropertyException) {
+            shell.evaluate '''
+                package a
+
+                class A {
+                    private String superField
+                }
+
+                assert true
+            '''
+
+            shell.evaluate '''
+                package b
+
+                class B extends a.A {
+                    @groovy.transform.CompileStatic
+                    def test() {
+                        'something'.with {
+                            return this.superField
+                        }
+                    }
+                }
+
+                new B().test()
+            '''
+        }
+    }
+
+    @Test
+    void 'test accessing a private super class field inside a closure - same package, owner qualifier'() {
+        shouldFail(MissingPropertyException) {
+            shell.evaluate '''
+                package a
+
+                class A {
+                    private String superField
+                }
+
+                class B extends A {
+                    @groovy.transform.CompileStatic
+                    def test() {
+                        'something'.with {
+                            return owner.superField
+                        }
+                    }
+                }
+
+                new B().test()
+            '''
+        }
+    }
+
+    @Test
+    void 'test accessing a private super class field inside a closure - diff package, owner qualifier'() {
+        shouldFail(MissingPropertyException) {
+            shell.evaluate '''
+                package a
+
+                class A {
+                    private String superField
+                }
+
+                assert true
+            '''
+
+            shell.evaluate '''
+                package b
+
+                class B extends a.A {
+                    @groovy.transform.CompileStatic
+                    def test() {
+                        'something'.with {
+                            return owner.superField
+                        }
+                    }
+                }
+
+                new B().test()
+            '''
+        }
+    }
+
+    @Test
+    void 'test accessing a private super class field inside a closure - same package, delegate qualifier'() {
+        shouldFail(MissingPropertyException) {
+            shell.evaluate '''
+                package a
+
+                class A {
+                    private String superField
+                }
+
+                class B extends A {
+                    @groovy.transform.CompileStatic
+                    def test() {
+                        with {
+                            return delegate.superField
+                        }
+                    }
+                }
+
+                new B().test()
+            '''
+        }
+    }
+
+    @Test
+    void 'test accessing a private super class field inside a closure - diff package, delegate qualifier'() {
+        shouldFail(MissingPropertyException) {
+            shell.evaluate '''
+                package a
+
+                class A {
+                    private String superField
+                }
+
+                assert true
+            '''
+
+            shell.evaluate '''
+                package b
+
+                class B extends a.A {
+                    @groovy.transform.CompileStatic
+                    def test() {
+                        with {
+                            return delegate.superField
+                        }
+                    }
+                }
+
+                new B().test()
+            '''
+        }
+    }
+
+    @Test
+    void 'test accessing a private super class field inside a closure - same package, thisObject qualifier'() {
+        shouldFail(MissingPropertyException) {
+            shell.evaluate '''
+                package a
+
+                class A {
+                    private String superField
+                }
+
+                class B extends A {
+                    @groovy.transform.CompileStatic
+                    def test() {
+                        'something'.with {
+                            return thisObject.superField
+                        }
+                    }
+                }
+
+                new B().test()
+            '''
+        }
+    }
+
+    @Test
+    void 'test accessing a private super class field inside a closure - diff package, thisObject qualifier'() {
+        shouldFail(MissingPropertyException) {
+            shell.evaluate '''
+                package a
+
+                class A {
+                    private String superField
+                }
+
+                assert true
+            '''
+
+            shell.evaluate '''
+                package b
+
+                class B extends a.A {
+                    @groovy.transform.CompileStatic
+                    def test() {
+                        'something'.with {
+                            return thisObject.superField
+                        }
+                    }
+                }
+
+                new B().test()
+            '''
+        }
+    }
+}
diff --git a/src/test/groovy/bugs/Groovy9292Bug.groovy b/src/test/groovy/bugs/Groovy9292Bug.groovy
deleted file mode 100644
index 06cadbca21..0000000000
--- a/src/test/groovy/bugs/Groovy9292Bug.groovy
+++ /dev/null
@@ -1,1008 +0,0 @@
-/*
- *  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.transform.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/transform/stc/FieldsAndPropertiesSTCTest.groovy b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
index f0688df44e..fa6a866e5e 100644
--- a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
+++ b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
@@ -383,23 +383,6 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    // GROOVY-5517
-    void testShouldFindStaticPropertyEvenIfObjectImplementsMap() {
-        assertScript '''
-            class C extends HashMap {
-                public static int version = 666
-            }
-            def map = new C()
-            map['foo'] = 123
-            def value = map.foo
-            assert value == 123
-            map['foo'] = 4.5
-            value = map['foo']
-            assert value == 4.5
-            assert C.version == 666
-        '''
-    }
-
     void testClassPropertyOnInterface() {
         assertScript '''
             Class test(Serializable arg) {
@@ -476,7 +459,7 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
     }
 
     // GROOVY-5700
-    void testInferenceOfMapDotProperty() {
+    void testMapPropertyAccess1() {
         assertScript '''
             def map = [key: 123]
             @ASTTest(phase=INSTRUCTION_SELECTION, value={
@@ -488,7 +471,7 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
     }
 
     // GROOVY-5700, GROOVY-8788
-    void testInferenceOfMapSubProperty() {
+    void testMapPropertyAccess2() {
         assertScript '''
             def map = [key: 123]
             @ASTTest(phase=INSTRUCTION_SELECTION, value={
@@ -499,6 +482,41 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-8074
+    void testMapPropertyAccess3() {
+        assertScript '''
+            class C extends HashMap {
+                def foo = 1
+            }
+            def map = new C()
+            map.put('foo', 42)
+            assert map.foo == 42
+        '''
+
+        assertScript """
+            def map = new ${MapType.name}()
+            map.put('foo', 42)
+            assert map.foo == 42
+        """
+    }
+
+    // GROOVY-5517
+    void testMapPropertyAccess4() {
+        assertScript '''
+            class C extends HashMap {
+                public static int version = 666
+            }
+            def map = new C()
+            map['foo'] = 123
+            def value = map.foo
+            assert value == 123
+            map['foo'] = 4.5
+            value = map['foo']
+            assert value == 4.5
+            assert C.version == 666
+        '''
+    }
+
     void testTypeCheckerDoesNotThinkPropertyIsReadOnly() {
         assertScript '''
             // a base class defining a read-only property
@@ -1270,6 +1288,10 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
         String boo = "I don't fancy fields in interfaces"
     }
 
+    static class MapType extends HashMap<String,Object> {
+        def foo = 1
+    }
+
     static class BaseClass {
         int x
     }
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/ArraysAndCollectionsStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/ArraysAndCollectionsStaticCompileTest.groovy
index b61bffb579..8e68703f7a 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/ArraysAndCollectionsStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/ArraysAndCollectionsStaticCompileTest.groovy
@@ -97,7 +97,7 @@ class ArraysAndCollectionsStaticCompileTest extends ArraysAndCollectionsSTCTest
         }
     }
 
-    //GROOVY-7442
+    // GROOVY-7442
     void testSpreadDotOperatorWithinAssert() {
         assertScript '''
             def myMethod(String a, String b) {
@@ -108,7 +108,7 @@ class ArraysAndCollectionsStaticCompileTest extends ArraysAndCollectionsSTCTest
         '''
     }
 
-    //GROOVY-7688
+    // GROOVY-7688
     void testSpreadSafeMethodCallReceiversWithSideEffectsShouldNotBeVisitedTwice() {
         try {
             assertScript '''
@@ -125,27 +125,4 @@ class ArraysAndCollectionsStaticCompileTest extends ArraysAndCollectionsSTCTest
             assert astTrees['Foo'][1].count('DefaultGroovyMethods.toList') == 1
         }
     }
-
-    //GROOVY-8074
-    void testMapSubclassPropertyStyleAccess() {
-        assertScript '''
-            class MyMap extends LinkedHashMap {
-                def foo = 1
-            }
-        
-            def map = new MyMap()
-            map.put('foo', 42)
-            assert map.foo == 42               
-        '''
-    }
-
-    @Override
-    void testForInLoop() {
-        try {
-            super.testForInLoop()
-        } finally {
-            println astTrees
-        }
-    }
 }
-
diff --git a/subprojects/groovy-templates/src/test/groovy/groovy/text/MarkupTemplateEngineTest.groovy b/subprojects/groovy-templates/src/test/groovy/groovy/text/MarkupTemplateEngineTest.groovy
index 162edc1665..091913ce4d 100644
--- a/subprojects/groovy-templates/src/test/groovy/groovy/text/MarkupTemplateEngineTest.groovy
+++ b/subprojects/groovy-templates/src/test/groovy/groovy/text/MarkupTemplateEngineTest.groovy
@@ -736,10 +736,9 @@ html {
 }
 '''
         StringWriter rendered = new StringWriter()
-        def model = [persons: [[name: 'Cedric'], [name: 'Jochen']]]
+        def model = [persons: [Person[name: 'Cedric'], Person[name: 'Jochen']]]
         template.make(model).writeTo(rendered)
         assert rendered.toString() == '<html><body><ul><li>Cedric</li><li>Jochen</li></ul></body></html>'
-
     }
 
     void testInlinedModelTypeDeclarationShouldFailBecauseIncorrectType() {
@@ -761,11 +760,9 @@ html {
 }
 '''
             StringWriter rendered = new StringWriter()
-            def model = [persons: [[name: 'Cedric'], [name: 'Jochen']]]
+            def model = [persons: [Person[name: 'Cedric'], Person[name: 'Jochen']]]
             template.make(model).writeTo(rendered)
-            assert rendered.toString() == '<html><body><ul><li>Cedric</li><li>Jochen</li></ul></body></html>'
         } =~ 'No such property: name for class: java.lang.String'
-
     }
 
     void testFragment() {