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 22:35:48 UTC

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

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 37043f304c940a297efc9a36ce8de73d0224f574
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          |   50 +-
 .../ArraysAndCollectionsStaticCompileTest.groovy   |   27 +-
 .../groovy/text/MarkupTemplateEngineTest.groovy    |    7 +-
 10 files changed, 729 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..962272700a 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,35 @@ 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
+        '''
+    }
+
+    // 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
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() {