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

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


The following commit(s) were added to refs/heads/master by this push:
     new ed63edb33f GROOVY-11823: replace inner class propertyMissing with 
metaclass impl
ed63edb33f is described below

commit ed63edb33fa81b660493e8924487a05ce0735a65
Author: Eric Milles <[email protected]>
AuthorDate: Tue Feb 3 12:06:39 2026 -0600

    GROOVY-11823: replace inner class propertyMissing with metaclass impl
    
    GROOVY-4737, GROOVY-4862, GROOVY-5875, GROOVY-6580, GROOVY-6581,
    GROOVY-7024, GROOVY-8050, GROOVY-11198
---
 src/main/java/groovy/lang/MetaClassImpl.java       | 153 +++++++++-
 .../java/org/codehaus/groovy/ast/ModuleNode.java   |  12 +
 .../groovy/classgen/EnumCompletionVisitor.java     |  89 ------
 .../classgen/InnerClassCompletionVisitor.java      | 271 +----------------
 .../groovy/classgen/InnerClassVisitorHelper.java   |   2 +-
 .../stc/GroovyTypeCheckingExtensionSupport.java    |  31 +-
 src/test/groovy/bugs/Groovy7938Bug.groovy          |  70 -----
 src/test/groovy/gls/enums/EnumTest.groovy          |  17 ++
 .../groovy/gls/innerClass/InnerClassTest.groovy    | 325 ++++++++++++++++-----
 src/test/groovy/groovy/ClosureTest.groovy          | 285 +++++++-----------
 src/test/groovy/groovy/PropertyTest.groovy         |  18 --
 .../stc/AnonymousInnerClassSTCTest.groovy          |  19 +-
 .../packageScope/PackageScopeTransformTest.groovy  |   6 +-
 .../groovy/nio/extensions/NioExtensionsTest.groovy |  10 +-
 .../groovy/typecheckers/FormatStringChecker.groovy |  16 +-
 .../groovy/groovy/typecheckers/RegexChecker.groovy |  55 ++--
 .../groovy/typecheckers/CheckingVisitor.groovy     |  23 +-
 17 files changed, 622 insertions(+), 780 deletions(-)

diff --git a/src/main/java/groovy/lang/MetaClassImpl.java 
b/src/main/java/groovy/lang/MetaClassImpl.java
index 066ee504b6..ffeb8069c0 100644
--- a/src/main/java/groovy/lang/MetaClassImpl.java
+++ b/src/main/java/groovy/lang/MetaClassImpl.java
@@ -380,7 +380,7 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
 
         inheritInterfaceNewMetaMethods(interfaces);
 
-        if (isGroovyObject) {
+        if (isGroovyObject()) {
             metaMethodIndex.copyMethodsToSuper(); // methods --> 
methodsForSuper
             connectMultimethods(superClasses, firstGroovySuper);
             removeMultimethodsOverloadedWithPrivateMethods();
@@ -662,7 +662,7 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
         }
 
         if (firstGroovy == null) {
-            return isGroovyObject ? theCachedClass.getCachedSuperClass() : 
theCachedClass;
+            return isGroovyObject() ? theCachedClass.getCachedSuperClass() : 
theCachedClass;
         }
         // Closure for closures and GroovyObjectSupport for extenders 
(including Closure)
         if (firstGroovy.getTheClass() == GroovyObjectSupport.class) {
@@ -1217,7 +1217,59 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
             return transformedMetaMethod.doMethodInvoke(object, arguments);
         }
 
-        return invokePropertyOrMissing(sender, object, methodName, 
originalArguments, fromInsideClass, isCallToSuper);
+        try {
+            return invokePropertyOrMissing(sender, object, methodName, 
originalArguments, fromInsideClass, isCallToSuper);
+        } catch (MissingMethodException mme) {
+            if (!isCallToSuper) {
+                return invokeOuterMethod(sender, object, methodName, 
originalArguments, mme); // GROOVY-11823
+            }
+            throw mme;
+        }
+    }
+
+    private Object invokeOuterMethod(final Class<?> sender, final Object 
object, final String methodName, final Object[] arguments, final 
MissingMethodException mme) {
+        if (sender == theClass ? isGroovyObject() : 
GroovyObject.class.isAssignableFrom(sender)) {
+            var outerClass = getNonClosureOuter(sender); // check outer class 
nesting of call site
+            if (outerClass != null && (sender == theClass || 
sender.isAssignableFrom(theClass))) {
+                MetaClass omc = registry.getMetaClass(outerClass);
+                Object target = getOuterReference(sender, object);
+                try {
+                    return omc.invokeMethod(outerClass, target, methodName, 
arguments, false, false);
+                } catch (MissingMethodException e) {
+                    mme.addSuppressed(e);
+                }
+            }
+        }
+        throw mme;
+    }
+
+    private Object getOuterReference(final Class<?> innerClass, final Object 
object) {
+        Object outer = null;
+        // non-static inner class may have outer class reference available in 
this$0 field
+        if (!(object instanceof Class) && (innerClass.getModifiers() & 
Opcodes.ACC_STATIC) == 0) {
+            try {
+                innerClass.getDeclaredField("this$0");
+                outer = getAttribute(object,"this$0");
+                if (outer instanceof GeneratedClosure) {
+                    outer = ((Closure<?>) outer).getThisObject(); // skip 
closure(s)
+                }
+            } catch (NoSuchFieldException ignored) {
+                // an AIC is non-static but may not have this$0
+            } catch (Throwable t) {
+                throw new GroovyRuntimeException(t);
+            }
+        }
+        if (outer == null) {
+            outer = getNonClosureOuter(innerClass);
+        }
+        return outer;
+    }
+
+    private static Class<?> getNonClosureOuter(Class<?> c) {
+        do { c = c.getEnclosingClass();
+        } while (c != null && GeneratedClosure.class.isAssignableFrom(c));
+
+        return c;
     }
 
     private MetaMethod getMetaMethod(final Class<?> sender, final Object 
object, final String methodName, final boolean isCallToSuper, final Object[] 
arguments) {
@@ -1487,7 +1539,22 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
             }
         }
 
-        return invokeStaticMissingMethod(theClass, methodName, 
nonNullArguments);
+        try {
+            return invokeStaticMissingMethod(theClass, methodName, 
nonNullArguments);
+        } catch (MissingMethodException missing) {
+            if (isGroovyObject()) { // GROOVY-11823, et al.
+                var outerClass = getNonClosureOuter(theClass);
+                if (outerClass != null && object instanceof Class) {
+                    MetaClass omc = registry.getMetaClass(outerClass);
+                    try {
+                        return omc.invokeStaticMethod(outerClass, methodName, 
arguments);
+                    } catch (MissingMethodException mme) {
+                        missing.addSuppressed(mme);
+                    }
+                }
+            }
+            throw missing;
+        }
     }
 
     private Object invokeStaticMissingMethod(final Class<?> sender, final 
String methodName, final Object[] arguments) {
@@ -1495,7 +1562,7 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
         if (metaMethod != null) {
             return metaMethod.invoke(sender, new Object[]{methodName, 
arguments});
         }
-        throw new MissingMethodException(methodName, sender, arguments, true);
+        throw new MissingMethodExceptionNoStack(methodName, sender, arguments, 
true);
     }
 
     private MetaMethod pickStaticMethod(final String methodName, final 
Class<?>[] argumentTypes) throws MethodSelectionException {
@@ -1876,19 +1943,55 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
         
//----------------------------------------------------------------------
         // missing property protocol
         
//----------------------------------------------------------------------
-        return invokeMissingProperty(object, name, null, true);
+        try {
+            return invokeMissingProperty(object, name, null, true);
+        } catch (MissingPropertyException mpe) {
+            return getOuterProperty(sender, object, name, mpe);
+        }
     }
 
     private Object getClassProperty(final Class<?> sender, final Class<?> 
receiver, final String name) throws MissingPropertyException {
         try {
             MetaClass cmc = registry.getMetaClass(Class.class);
             return cmc.getProperty(Class.class, receiver, name, false, false);
-        } catch (MissingPropertyException ignore) {
+        } catch (MissingPropertyException ignored) {
+        }
+
+        try {
             // try $static_propertyMissing / throw MissingPropertyException
             return invokeStaticMissingProperty(receiver, name, null, true);
+        } catch (MissingPropertyException missing) {
+            if (isGroovyObject()) { // GROOVY-11823, et al.
+                var outerClass = getNonClosureOuter(theClass);
+                if (outerClass != null && sender.isNestmateOf(outerClass)) {
+                    try {
+                        MetaClass omc = registry.getMetaClass(outerClass);
+                        return omc.getProperty(sender, outerClass, name, 
false, false);
+                    } catch (MissingPropertyException mpe) {
+                        missing.addSuppressed(mpe);
+                    }
+                }
+            }
+            throw missing;
         }
     }
 
+    private Object getOuterProperty(final Class<?> sender, final Object 
object, final String name, final MissingPropertyException mpe) {
+        if (sender == theClass ? isGroovyObject() : 
GroovyObject.class.isAssignableFrom(sender)) {
+            var outerClass = getNonClosureOuter(sender); // check outer class 
nesting of call site
+            if (outerClass != null && (sender == theClass || 
sender.isAssignableFrom(theClass))) {
+                MetaClass omc = registry.getMetaClass(outerClass);
+                Object target = getOuterReference(sender, object);
+                try {
+                    return omc.getProperty(outerClass, target, name, false, 
false);
+                } catch (MissingPropertyException e) {
+                    mpe.addSuppressed(e);
+                }
+            }
+        }
+        throw mpe;
+    }
+
     public MetaProperty getEffectiveGetMetaProperty(final Class sender, final 
Object object, final String name, final boolean useSuper) {
 
         
//----------------------------------------------------------------------
@@ -2014,7 +2117,11 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
         return new ReadOnlyMetaProperty(name) {
             @Override
             public Object getProperty(final Object receiver) {
-                return invokeMissingProperty(receiver, getName(), null, true);
+                try {
+                    return invokeMissingProperty(receiver, getName(), null, 
true);
+                } catch (MissingPropertyException mpe) {
+                    return getOuterProperty(sender, receiver, getName(), mpe);
+                }
             }
         };
     }
@@ -2754,11 +2861,33 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
         if (mp != null) {
             throw new ReadOnlyPropertyException(name, theClass);
         }
-        if (!isStatic) {
-            invokeMissingProperty(object, name, newValue, false);
-        } else {
-            invokeStaticMissingProperty(object, name, newValue, false);
+        try {
+            if (!isStatic) {
+                invokeMissingProperty(object, name, newValue, false);
+            } else {
+                invokeStaticMissingProperty(object, name, newValue, false);
+            }
+        } catch (MissingPropertyException e) {
+            if (!useSuper) setOuterProperty(sender, object, name, newValue, 
e); else throw e; // GROOVY-11823
+        }
+    }
+
+    private void setOuterProperty(Class<?> sender, final Object object, final 
String name, final Object newValue, final MissingPropertyException mpe) {
+        if (sender == null) sender = theClass; // GROOVY-11745
+        if (sender == theClass ? isGroovyObject() : 
GroovyObject.class.isAssignableFrom(sender)) {
+            var outerClass = getNonClosureOuter(sender); // check outer class 
nesting of call site
+            if (outerClass != null && (sender == theClass || 
sender.isAssignableFrom(theClass))) {
+                MetaClass omc = registry.getMetaClass(outerClass);
+                Object target = getOuterReference(sender, object);
+                try {
+                    omc.setProperty(outerClass, target, name, newValue, false, 
false);
+                    return;
+                } catch (MissingPropertyException e) {
+                    mpe.addSuppressed(e);
+                }
+            }
         }
+        throw mpe;
     }
 
     private MetaProperty getMetaProperty(final Class<?> clazz, final String 
name, final boolean useSuper, final boolean useStatic) {
diff --git a/src/main/java/org/codehaus/groovy/ast/ModuleNode.java 
b/src/main/java/org/codehaus/groovy/ast/ModuleNode.java
index 9ba8598b6a..6c0760ba69 100644
--- a/src/main/java/org/codehaus/groovy/ast/ModuleNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/ModuleNode.java
@@ -19,6 +19,7 @@
 package org.codehaus.groovy.ast;
 
 import org.apache.groovy.ast.tools.ClassNodeUtils;
+import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
 import org.codehaus.groovy.ast.expr.DeclarationExpression;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.ListExpression;
@@ -452,6 +453,17 @@ public class ModuleNode extends ASTNode {
                 methodNode.addAnnotations(existingMain.getAnnotations());
             }
             ClassNodeUtils.addGeneratedMethod(classNode, methodNode, true);
+
+            new CodeVisitorSupport() {
+                @Override
+                public void visitConstructorCallExpression(final 
ConstructorCallExpression cce) {
+                    if (cce.isUsingAnonymousInnerClass()) { // GROOVY-11846
+                        cce.getType().setEnclosingMethod(methodNode);
+                    }
+                    super.visitConstructorCallExpression(cce);
+                }
+            }
+            .visit(statementBlock);
         } else {
             fields.forEach(classNode::addField);
             classNode.addAnnotations(existingRun.getAnnotations());
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/EnumCompletionVisitor.java 
b/src/main/java/org/codehaus/groovy/classgen/EnumCompletionVisitor.java
index 87b8fa71d3..1d0d9653ae 100644
--- a/src/main/java/org/codehaus/groovy/classgen/EnumCompletionVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/EnumCompletionVisitor.java
@@ -23,7 +23,6 @@ import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.CodeVisitorSupport;
 import org.codehaus.groovy.ast.ConstructorNode;
-import org.codehaus.groovy.ast.InnerClassNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.expr.ArgumentListExpression;
 import org.codehaus.groovy.ast.expr.CastExpression;
@@ -44,16 +43,7 @@ import java.util.List;
 
 import static java.util.stream.Collectors.toList;
 import static 
org.apache.groovy.ast.tools.ClassNodeUtils.addGeneratedConstructor;
-import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE;
-import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE;
-import static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
-import static 
org.codehaus.groovy.transform.sc.StaticCompilationVisitor.isStaticallyCompiled;
 import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
-import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
-import static org.objectweb.asm.Opcodes.ACC_STATIC;
 import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;
 
 /**
@@ -94,11 +84,6 @@ public class EnumCompletionVisitor extends 
ClassCodeVisitorSupport {
         for (ConstructorNode ctor : nonSyntheticConstructors(enumClass)) {
             transformConstructor(ctor);
         }
-
-        var outerClass = enumClass.getOuterClass(); // GROOVY-7024
-        if (outerClass != null && !isStaticallyCompiled(enumClass)) {
-            addOuterClassDispatch((InnerClassNode) enumClass, outerClass);
-        }
     }
 
     /**
@@ -207,78 +192,4 @@ public class EnumCompletionVisitor extends 
ClassCodeVisitorSupport {
     private static List<ConstructorNode> nonSyntheticConstructors(final 
ClassNode cn) {
         return cn.getDeclaredConstructors().stream().filter(c -> 
!c.isSynthetic()).collect(toList());
     }
-
-    private void addOuterClassDispatch(final InnerClassNode innerClass, final 
ClassNode outerClass) {
-        var visitor = new InnerClassCompletionVisitor(null, sourceUnit);
-
-        visitor.addMissingHandler(
-                innerClass,
-                "methodMissing",
-                ACC_PUBLIC,
-                OBJECT_TYPE,
-                params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, "args")),
-                (methodBody, parameters) -> {
-                    
InnerClassVisitorHelper.setMethodDispatcherCode(methodBody, classX(outerClass), 
parameters);
-                }
-        );
-
-        visitor.addMissingHandler(
-                innerClass,
-                "$static_methodMissing",
-                ACC_PUBLIC | ACC_STATIC,
-                OBJECT_TYPE,
-                params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, "args")),
-                (methodBody, parameters) -> {
-                    
InnerClassVisitorHelper.setMethodDispatcherCode(methodBody, classX(outerClass), 
parameters);
-                }
-        );
-
-        //
-
-        visitor.addMissingHandler(
-                innerClass,
-                "propertyMissing",
-                ACC_PUBLIC,
-                OBJECT_TYPE,
-                params(param(STRING_TYPE, "name")),
-                (methodBody, parameters) -> {
-                    
InnerClassVisitorHelper.setPropertyGetterDispatcher(methodBody, 
classX(outerClass), parameters);
-                }
-        );
-
-        visitor.addMissingHandler(
-                innerClass,
-                "$static_propertyMissing",
-                ACC_PUBLIC | ACC_STATIC,
-                OBJECT_TYPE,
-                params(param(STRING_TYPE, "name")),
-                (methodBody, parameters) -> {
-                    
InnerClassVisitorHelper.setPropertyGetterDispatcher(methodBody, 
classX(outerClass), parameters);
-                }
-        );
-
-        //
-
-        visitor.addMissingHandler(
-                innerClass,
-                "propertyMissing",
-                ACC_PUBLIC,
-                VOID_TYPE,
-                params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, 
"value")),
-                (methodBody, parameters) -> {
-                    
InnerClassVisitorHelper.setPropertySetterDispatcher(methodBody, 
classX(outerClass), parameters);
-                }
-        );
-
-        visitor.addMissingHandler(
-                innerClass,
-                "$static_propertyMissing",
-                ACC_PUBLIC | ACC_STATIC,
-                VOID_TYPE,
-                params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, 
"value")),
-                (methodBody, parameters) -> {
-                    
InnerClassVisitorHelper.setPropertySetterDispatcher(methodBody, 
classX(outerClass), parameters);
-                }
-        );
-    }
 }
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java 
b/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java
index fb70379836..399a82d438 100644
--- 
a/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java
+++ 
b/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java
@@ -18,56 +18,31 @@
  */
 package org.codehaus.groovy.classgen;
 
-import groovy.transform.CompileStatic;
-import groovy.transform.stc.POJO;
-import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.ConstructorNode;
 import org.codehaus.groovy.ast.FieldNode;
 import org.codehaus.groovy.ast.InnerClassNode;
-import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.TupleExpression;
 import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.ast.stmt.BlockStatement;
-import org.codehaus.groovy.ast.stmt.TryCatchStatement;
-import org.codehaus.groovy.classgen.asm.BytecodeHelper;
 import org.codehaus.groovy.control.CompilationUnit;
 import org.codehaus.groovy.control.SourceUnit;
-import org.objectweb.asm.MethodVisitor;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.StringJoiner;
-import java.util.function.BiConsumer;
 
-import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.hasAnnotation;
 import static 
org.apache.groovy.ast.tools.ClassNodeUtils.addGeneratedConstructor;
-import static org.apache.groovy.ast.tools.ClassNodeUtils.getMethod;
 import static 
org.apache.groovy.ast.tools.ConstructorNodeUtils.getFirstIfSpecialConstructorCall;
 import static org.apache.groovy.ast.tools.MethodNodeUtils.getCodeAsBlock;
-import static org.codehaus.groovy.ast.ClassHelper.CLOSURE_TYPE;
-import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE;
-import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE;
-import static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.castX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.catchS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorSuperX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorThisX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.throwS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.tryCatchS;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
 import static org.codehaus.groovy.transform.trait.Traits.isTrait;
 import static org.objectweb.asm.Opcodes.ACC_FINAL;
@@ -75,12 +50,6 @@ import static org.objectweb.asm.Opcodes.ACC_MANDATED;
 import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
 import static org.objectweb.asm.Opcodes.ACC_STATIC;
 import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;
-import static org.objectweb.asm.Opcodes.ACONST_NULL;
-import static org.objectweb.asm.Opcodes.ALOAD;
-import static org.objectweb.asm.Opcodes.ARETURN;
-import static org.objectweb.asm.Opcodes.CHECKCAST;
-import static org.objectweb.asm.Opcodes.GETFIELD;
-import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
 
 public class InnerClassCompletionVisitor extends InnerClassVisitorHelper {
 
@@ -104,25 +73,13 @@ public class InnerClassCompletionVisitor extends 
InnerClassVisitorHelper {
 
         if (node.isEnum() || node.isInterface() || 
isTrait(node.getOuterClass())) return;
 
-        // if the class has an inner class, add methods to support private 
member access
-        if (node.getInnerClasses().hasNext()) {
-            addDispatcherMethods(node);
-        }
-
         if (node instanceof InnerClassNode innerClass) {
-            thisField = node.getField("this$0");
+            thisField = node.getDeclaredField("this$0");
             if (innerClass.getVariableScope() == null && 
node.getDeclaredConstructors().isEmpty()) {
                 // add empty default constructor
                 addGeneratedConstructor(innerClass, ACC_PUBLIC, 
Parameter.EMPTY_ARRAY, null, null);
             }
-
             super.visitClass(node);
-
-            boolean innerPojo = hasAnnotation(node, new ClassNode(POJO.class))
-                    && hasAnnotation(node, new ClassNode(CompileStatic.class));
-            if (!innerPojo) {
-                addMopMethods(innerClass);
-            }
         }
     }
 
@@ -156,227 +113,7 @@ public class InnerClassCompletionVisitor extends 
InnerClassVisitorHelper {
         }
     }
 
-    private static String getTypeDescriptor(ClassNode node, boolean isStatic) {
-        return BytecodeHelper.getTypeDescription(getClassNode(node, isStatic));
-    }
-
-    private static String getInternalName(ClassNode node, boolean isStatic) {
-        return BytecodeHelper.getClassInternalName(getClassNode(node, 
isStatic));
-    }
-
-    private static void addDispatcherMethods(ClassNode classNode) {
-        final int objectDistance = getObjectDistance(classNode);
-
-        // since we added an anonymous inner class we should also
-        // add the dispatcher methods
-
-        // add method dispatcher
-        BlockStatement block = new BlockStatement();
-        MethodNode method = classNode.addSyntheticMethod(
-                "this$dist$invoke$" + objectDistance,
-                ACC_PUBLIC,
-                OBJECT_TYPE,
-                params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, "args")),
-                ClassNode.EMPTY_ARRAY,
-                block
-        );
-        setMethodDispatcherCode(block, VariableExpression.THIS_EXPRESSION, 
method.getParameters());
-
-        // add property setter
-        block = new BlockStatement();
-        method = classNode.addSyntheticMethod(
-                "this$dist$set$" + objectDistance,
-                ACC_PUBLIC,
-                VOID_TYPE,
-                params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, 
"value")),
-                ClassNode.EMPTY_ARRAY,
-                block
-        );
-        setPropertySetterDispatcher(block, VariableExpression.THIS_EXPRESSION, 
method.getParameters());
-
-        // add property getter
-        block = new BlockStatement();
-        method = classNode.addSyntheticMethod(
-                "this$dist$get$" + objectDistance,
-                ACC_PUBLIC,
-                OBJECT_TYPE,
-                params(param(STRING_TYPE, "name")),
-                ClassNode.EMPTY_ARRAY,
-                block
-        );
-        setPropertyGetterDispatcher(block, VariableExpression.THIS_EXPRESSION, 
method.getParameters());
-    }
-
-    private void getThis(final MethodVisitor mv, final String 
classInternalName, final String outerClassDescriptor, final String 
innerClassInternalName) {
-        mv.visitVarInsn(ALOAD, 0);
-        if (thisField != null && CLOSURE_TYPE.equals(thisField.getType())) {
-            mv.visitFieldInsn(GETFIELD, classInternalName, "this$0", 
BytecodeHelper.getTypeDescription(CLOSURE_TYPE));
-            mv.visitMethodInsn(INVOKEVIRTUAL, 
BytecodeHelper.getClassInternalName(CLOSURE_TYPE), "getThisObject", 
"()Ljava/lang/Object;", false);
-            mv.visitTypeInsn(CHECKCAST, innerClassInternalName);
-        } else {
-            mv.visitFieldInsn(GETFIELD, classInternalName, "this$0", 
outerClassDescriptor);
-        }
-    }
-
-    private void addMopMethods(final InnerClassNode node) {
-        final boolean isStatic = isStatic(node);
-        final ClassNode outerClass = node.getOuterClass();
-        final int outerClassDistance = getObjectDistance(outerClass);
-        final String classInternalName = 
BytecodeHelper.getClassInternalName(node);
-        final String outerClassInternalName = getInternalName(outerClass, 
isStatic);
-        final String outerClassDescriptor = getTypeDescriptor(outerClass, 
isStatic);
-
-        addMissingHandler(node,
-                "methodMissing",
-                ACC_PUBLIC,
-                OBJECT_TYPE,
-                params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, "args")),
-                (methodBody, parameters) -> {
-                    if (isStatic) {
-                        setMethodDispatcherCode(methodBody, 
classX(outerClass), parameters);
-                    } else {
-                        methodBody.addStatement(
-                                new BytecodeSequence(new BytecodeInstruction() 
{
-                                    @Override
-                                    public void visit(final MethodVisitor mv) {
-                                        getThis(mv, classInternalName, 
outerClassDescriptor, outerClassInternalName);
-                                        mv.visitVarInsn(ALOAD, 1);
-                                        mv.visitVarInsn(ALOAD, 2);
-                                        mv.visitMethodInsn(INVOKEVIRTUAL, 
outerClassInternalName, "this$dist$invoke$" + outerClassDistance, 
"(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", false);
-                                        mv.visitInsn(ARETURN);
-                                    }
-                                })
-                        );
-                    }
-                }
-        );
-
-        addMissingHandler(node,
-                "$static_methodMissing",
-                ACC_PUBLIC | ACC_STATIC,
-                OBJECT_TYPE,
-                params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, "args")),
-                (methodBody, parameters) -> {
-                    setMethodDispatcherCode(methodBody, classX(outerClass), 
parameters);
-                }
-        );
-
-        ClassNode[] nameValueTypes = {STRING_TYPE, OBJECT_TYPE};
-        MethodNode propertyMissing = getMethod(node, "propertyMissing", (m) -> 
!m.isStatic() && !m.isPrivate()
-                && 
Arrays.equals(Arrays.stream(m.getParameters()).map(Parameter::getType).toArray(),nameValueTypes));
-        ClassNode returnType = propertyMissing != null ? 
propertyMissing.getReturnType() : VOID_TYPE; // GROOVY-11822
-
-        addMissingHandler(node,
-                "propertyMissing",
-                ACC_PUBLIC,
-                returnType,
-                params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, 
"value")),
-                (methodBody, parameters) -> {
-                    if (isStatic) {
-                        setPropertySetterDispatcher(methodBody, 
classX(outerClass), parameters);
-                    } else {
-                        methodBody.addStatement(
-                                new BytecodeSequence(new BytecodeInstruction() 
{
-                                    @Override
-                                    public void visit(final MethodVisitor mv) {
-                                        getThis(mv, classInternalName, 
outerClassDescriptor, outerClassInternalName);
-                                        mv.visitVarInsn(ALOAD, 1);
-                                        mv.visitVarInsn(ALOAD, 2);
-                                        mv.visitMethodInsn(INVOKEVIRTUAL, 
outerClassInternalName, "this$dist$set$" + outerClassDistance, 
"(Ljava/lang/String;Ljava/lang/Object;)V", false);
-                                        if 
(!ClassHelper.isPrimitiveVoid(returnType)) mv.visitInsn(ACONST_NULL);
-                                        BytecodeHelper.doReturn(mv, 
returnType);
-                                    }
-                                })
-                        );
-                    }
-                }
-        );
-
-        addMissingHandler(node,
-                "$static_propertyMissing",
-                ACC_PUBLIC | ACC_STATIC,
-                VOID_TYPE,
-                params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, 
"value")),
-                (methodBody, parameters) -> {
-                    setPropertySetterDispatcher(methodBody, 
classX(outerClass), parameters);
-                }
-        );
-
-        addMissingHandler(node,
-                "propertyMissing",
-                ACC_PUBLIC,
-                OBJECT_TYPE,
-                params(param(STRING_TYPE, "name")),
-                (methodBody, parameters) -> {
-                    if (isStatic) {
-                        setPropertyGetterDispatcher(methodBody, 
classX(outerClass), parameters);
-                    } else {
-                        methodBody.addStatement(
-                                new BytecodeSequence(new BytecodeInstruction() 
{
-                                    @Override
-                                    public void visit(final MethodVisitor mv) {
-                                        getThis(mv, classInternalName, 
outerClassDescriptor, outerClassInternalName);
-                                        mv.visitVarInsn(ALOAD, 1);
-                                        mv.visitMethodInsn(INVOKEVIRTUAL, 
outerClassInternalName, "this$dist$get$" + outerClassDistance, 
"(Ljava/lang/String;)Ljava/lang/Object;", false);
-                                        mv.visitInsn(ARETURN);
-                                    }
-                                })
-                        );
-                    }
-                }
-        );
-
-        addMissingHandler(node,
-                "$static_propertyMissing",
-                ACC_PUBLIC | ACC_STATIC,
-                OBJECT_TYPE,
-                params(param(STRING_TYPE, "name")),
-                (methodBody, parameters) -> {
-                    setPropertyGetterDispatcher(methodBody, 
classX(outerClass), parameters);
-                }
-        );
-    }
-
-    /*   */ void addMissingHandler(final InnerClassNode innerClass, final 
String methodName, final int modifiers,
-            final ClassNode returnType, final Parameter[] parameters, final 
BiConsumer<BlockStatement, Parameter[]> consumer) {
-        MethodNode method = innerClass.getDeclaredMethod(methodName, 
parameters);
-        if (method == null) {
-            // try {
-            //   <consumer dispatch>
-            // } catch (MissingMethodException notFound) {
-            //   throw new MissingMethodException(notFound.method, this, 
notFound.arguments)
-            // }
-            Parameter catchParam = param(OBJECT_TYPE, "notFound"); // dummy 
type
-            ClassNode exceptionT;
-            Expression newException;
-            Expression selfType = varX("this");
-            if ((modifiers & ACC_STATIC) == 0) selfType = callX(selfType, 
"getClass");
-            if (methodName.endsWith("methodMissing")) {
-                exceptionT = 
ClassHelper.make(groovy.lang.MissingMethodException.class);
-                newException = ctorX(exceptionT, 
args(propX(varX(catchParam),"method"), selfType, 
propX(varX(catchParam),"arguments")));
-            } else {
-                exceptionT = 
ClassHelper.make(groovy.lang.MissingPropertyException.class);
-                newException = ctorX(exceptionT, args(propX(varX(catchParam), 
"property"), selfType, propX(varX(catchParam), "cause")));
-            }
-            catchParam.setType(exceptionT);
-            catchParam.setOriginType(exceptionT);
-            BlockStatement handleMissing = block();
-            consumer.accept(handleMissing, parameters);
-            TryCatchStatement tryCatch = tryCatchS(handleMissing);
-            tryCatch.addCatch(catchS(catchParam, throwS(newException)));
-
-            innerClass.addSyntheticMethod(methodName, modifiers, returnType, 
parameters, ClassNode.EMPTY_ARRAY, tryCatch);
-
-            // if there is a user-defined method, add compiler error and 
continue
-        } else if (isStatic(innerClass) && (method.getModifiers() & 
ACC_SYNTHETIC) == 0) {
-            addError("\"" + methodName + "\" implementations are not supported 
on static inner classes as " +
-                "a synthetic version of \"" + methodName + "\" is added during 
compilation for the purpose " +
-                "of outer class delegation.",
-                method);
-        }
-    }
-
-    private void addThisReference(ConstructorNode node) {
+    private void addThisReference(final ConstructorNode node) {
         if (!shouldHandleImplicitThisForInnerClass(classNode)) return;
 
         // add "this$0" field init
@@ -428,7 +165,7 @@ public class InnerClassCompletionVisitor extends 
InnerClassVisitorHelper {
         node.setCode(block);
     }
 
-    private boolean shouldImplicitlyPassThisZero(ConstructorCallExpression 
cce) {
+    private boolean shouldImplicitlyPassThisZero(final 
ConstructorCallExpression cce) {
         boolean pass = false;
         if (cce.isThisCall()) {
             pass = true;
@@ -447,7 +184,7 @@ public class InnerClassCompletionVisitor extends 
InnerClassVisitorHelper {
         return pass;
     }
 
-    private String getUniqueName(Parameter[] params, ConstructorNode node) {
+    private String getUniqueName(final Parameter[] params, final 
ConstructorNode node) {
         String namePrefix = "$p";
         outer:
         for (int i = 0; i < 100; i++) {
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitorHelper.java 
b/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitorHelper.java
index 32c5395164..e507af6416 100644
--- a/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitorHelper.java
+++ b/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitorHelper.java
@@ -97,7 +97,7 @@ public abstract class InnerClassVisitorHelper extends 
ClassCodeVisitorSupport {
 
     protected static boolean shouldHandleImplicitThisForInnerClass(final 
ClassNode cn) {
         final int explicitOrImplicitStatic = Opcodes.ACC_ENUM | 
Opcodes.ACC_INTERFACE | Opcodes.ACC_RECORD | Opcodes.ACC_STATIC;
-        return (cn.getModifiers() & explicitOrImplicitStatic) == 0 && (cn 
instanceof InnerClassNode && !((InnerClassNode) cn).isAnonymous())
+        return (cn.getModifiers() & explicitOrImplicitStatic) == 0 && (cn 
instanceof InnerClassNode inner && !inner.isAnonymous())
                 && cn.getAnnotations().stream().noneMatch(aNode -> 
"groovy.transform.RecordType".equals(aNode.getClassNode().getName())); // 
GROOVY-11600
     }
 }
diff --git 
a/src/main/java/org/codehaus/groovy/transform/stc/GroovyTypeCheckingExtensionSupport.java
 
b/src/main/java/org/codehaus/groovy/transform/stc/GroovyTypeCheckingExtensionSupport.java
index 90f204f79e..e837def17d 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/GroovyTypeCheckingExtensionSupport.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/GroovyTypeCheckingExtensionSupport.java
@@ -488,47 +488,46 @@ public class GroovyTypeCheckingExtensionSupport extends 
AbstractTypeCheckingExte
      * @see <a 
href="https://docs.groovy-lang.org/latest/html/documentation/#_a_dsl_for_type_checking";>Groovy
 Language Documentation</a>
      */
     public abstract static class TypeCheckingDSL extends Script {
+
         private GroovyTypeCheckingExtensionSupport extension;
 
         @Override
-        public Object getProperty(final String property) {
+        public Object getProperty(final String name) {
             try {
-                return InvokerHelper.getProperty(extension, property);
+                return InvokerHelper.getProperty(extension, name);
             } catch (Exception e) {
-                return super.getProperty(property);
+                return super.getProperty(name);
             }
         }
 
         @Override
-        public void setProperty(final String property, final Object newValue) {
+        public void setProperty(final String name, final Object value) {
             try {
-                InvokerHelper.setProperty(extension, property, newValue);
+                InvokerHelper.setProperty(extension, name, value);
             } catch (Exception e) {
-                super.setProperty(property, newValue);
+                super.setProperty(name, value);
             }
         }
 
-        @Override
-        public Object invokeMethod(final String name, final Object args) {
-            if (name.startsWith("is") && name.endsWith("Expression") && args 
instanceof Object[] && ((Object[]) args).length == 1) {
-                String type = name.substring(2);
-                Object target = ((Object[]) args)[0];
+        public Object methodMissing(final String name, final Object args) {
+            if (name.startsWith("is") && name.endsWith("Expression") && args 
instanceof Object[] array && array.length == 1) {
+                Object target = array[0];
                 if (target == null) return Boolean.FALSE;
                 try {
-                    Class<?> typeClass = 
Class.forName("org.codehaus.groovy.ast.expr." + type);
-                    return typeClass.isAssignableFrom(target.getClass());
+                    Class<?> type = 
Class.forName("org.codehaus.groovy.ast.expr." + name.substring(2));
+                    return type.isAssignableFrom(target.getClass());
                 } catch (ClassNotFoundException e) {
                     return Boolean.FALSE;
                 }
             }
 
-            if (args instanceof Object[] argsArray && ((Object[]) args).length 
== 1 && ((Object[]) args)[0] instanceof Closure) {
+            if (args instanceof Object[] array && array.length == 1 && 
array[0] instanceof Closure closure) {
                 String methodName = METHOD_ALIASES.get(name);
                 if (methodName == null) {
                     return InvokerHelper.invokeMethod(extension, name, args);
                 }
-                List<Closure> closures = 
extension.eventHandlers.computeIfAbsent(methodName, k -> new 
LinkedList<Closure>());
-                closures.add((Closure) argsArray[0]);
+                var closures = 
extension.eventHandlers.computeIfAbsent(methodName, k -> new LinkedList<>());
+                closures.add(closure);
                 return null;
             } else {
                 return InvokerHelper.invokeMethod(extension, name, args);
diff --git a/src/test/groovy/bugs/Groovy7938Bug.groovy 
b/src/test/groovy/bugs/Groovy7938Bug.groovy
deleted file mode 100644
index a7476f4f60..0000000000
--- a/src/test/groovy/bugs/Groovy7938Bug.groovy
+++ /dev/null
@@ -1,70 +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 bugs
-
-import groovy.test.GroovyTestCase
-
-class Groovy7938Bug extends GroovyTestCase {
-    void testClassUsageInInterfaceDef() {
-        assertScript """
-            class Outer {
-                static Integer fooCount = 0
-                Integer barCount = 0
-                static void incFoo() { fooCount++ }
-                void incBar() { barCount++ }
-                static class Nested {
-                    static void nestedIncFoo() { incFoo() }
-                    static class NestedNested {
-                        static void nestedNestedIncFoo() { incFoo() }
-                    }
-                }
-                Inner innerFactory() { new Inner() }
-                class Inner {
-                    InnerInner innerInnerFactory() { new InnerInner() }
-                    void innerIncFoo() { incFoo() }
-                    static void staticInnerIncFoo() { incFoo() }
-                    class InnerInner {
-                        void innerInnerIncFoo() { incFoo() }
-                        static void staticInnerInnerIncFoo() { incFoo() }
-                    }
-                }
-            }
-            Outer.incFoo()
-            Outer.Nested.nestedIncFoo()
-            Outer.Nested.NestedNested.nestedNestedIncFoo()
-            assert Outer.fooCount == 3
-            new Outer().with {
-                incBar()
-                incFoo()
-                innerFactory().with {
-                    incBar()
-                    innerIncFoo()
-                    staticInnerIncFoo()
-                    innerInnerFactory().with {
-                        incBar()
-                        innerInnerIncFoo()
-                        staticInnerInnerIncFoo()
-                    }
-                }
-                assert barCount == 3
-                assert fooCount == 8
-            }
-        """
-    }
-}
diff --git a/src/test/groovy/gls/enums/EnumTest.groovy 
b/src/test/groovy/gls/enums/EnumTest.groovy
index d0e1255d3d..c490ea04d6 100644
--- a/src/test/groovy/gls/enums/EnumTest.groovy
+++ b/src/test/groovy/gls/enums/EnumTest.groovy
@@ -338,6 +338,23 @@ class EnumTest extends CompilableTestSupport {
         '''
     }
 
+    void testInnerEnumInitWithUnqualifiedOuterClassValue() {
+        assertScript '''
+            class C {
+                private static int ONE() { 1 }
+                enum E {
+                    FOO(1 + ONE())
+                    final value
+                    E(value) {
+                        this.value = value
+                    }
+                }
+            }
+
+            assert C.E.FOO.value == 2
+        '''
+    }
+
     // GROOVY-3693
     void testStaticFieldInitValuesInAStaticBlock() {
         // trigger enum class load to test it - asserts are present in the enum
diff --git a/src/test/groovy/gls/innerClass/InnerClassTest.groovy 
b/src/test/groovy/gls/innerClass/InnerClassTest.groovy
index ed46f15eda..f8b44e9c89 100644
--- a/src/test/groovy/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/groovy/gls/innerClass/InnerClassTest.groovy
@@ -413,7 +413,8 @@ final class InnerClassTest {
     void testStaticInnerClass2() {
         assertScript '''
             class A {
-                static class B {}
+                static class B {
+                }
             }
 
             assert A.declaredClasses.length == 1
@@ -427,11 +428,12 @@ final class InnerClassTest {
             class A {
                 static class B {
                     String p
+                    String getQ() { WHY }
                 }
                 B m() {
                     return [p:'x'] // calls 
ScriptBytecodeAdapter.castToType([p:'x'], A$B.class)
                 }
-                static final String q = 'y'
+                private static final String WHY = 'y'
             }
 
             o = new A().m()
@@ -601,14 +603,14 @@ final class InnerClassTest {
     @Test
     void testUsageOfOuterField() {
         assertScript '''
-            interface Run {
+            interface A {
                 def run()
             }
-            class Foo {
+            class C {
                 private x = 1
 
                 def foo() {
-                    def runner = new Run() {
+                    def runner = new A() {
                         def run() { return x }
                     }
                     runner.run()
@@ -616,24 +618,25 @@ final class InnerClassTest {
 
                 void x(y) { x = y }
             }
-            def foo = new Foo()
-            assert foo.foo() == 1
-            foo.x(2)
-            assert foo.foo() == 2
+
+            def c = new C()
+            assert c.foo() == 1
+            c.x(2)
+            assert c.foo() == 2
         '''
     }
 
     @Test
     void testUsageOfOuterField2() {
         assertScript '''
-            interface Run {
+            interface A {
                 def run()
             }
-            class Foo {
+            class C {
                 private static x = 1
 
                 static foo() {
-                    def runner = new Run() {
+                    def runner = new A() {
                         def run() { return x }
                     }
                     runner.run()
@@ -641,39 +644,16 @@ final class InnerClassTest {
 
                 static x(y) { x = y }
             }
-            assert Foo.foo() == 1
-            Foo.x(2)
-            assert Foo.foo() == 2
-        '''
-    }
 
-    @Test
-    void testUsageOfOuterField3() {
-        assertScript '''
-            interface X {
-                def m()
-            }
-
-            class A {
-                def pm = "pm"
-
-                def bar(x) {x().m()}
-                def foo() {
-                    bar { ->
-                        return new X() {
-                            def m() { pm }
-                        }
-                    }
-                }
-            }
-            def a = new A()
-            assert "pm" == a.foo()
+            assert C.foo() == 1
+            C.x(2)
+            assert C.foo() == 2
         '''
     }
 
     // GROOVY-6141
     @Test
-    void testUsageOfOuterField4() {
+    void testUsageOfOuterField3() {
         assertScript '''
             class A {
                 def x = 1
@@ -704,7 +684,7 @@ final class InnerClassTest {
 
     // GROOVY-9189
     @Test
-    void testUsageOfOuterField5() {
+    void testUsageOfOuterField4() {
         assertScript '''
             interface Run {
                 def run()
@@ -720,6 +700,7 @@ final class InnerClassTest {
 
                 static x(y) { x = y }
             }
+
             assert Foo.foo() == 1
             Foo.x(2)
             assert Foo.foo() == 2
@@ -728,7 +709,7 @@ final class InnerClassTest {
 
     // GROOVY-9168
     @Test
-    void testUsageOfOuterField6() {
+    void testUsageOfOuterField5() {
         assertScript '''
             class A {
                 //                  AIC in this position can use static 
properties:
@@ -747,7 +728,7 @@ final class InnerClassTest {
 
     // GROOVY-9501
     @Test
-    void testUsageOfOuterField7() {
+    void testUsageOfOuterField6() {
         assertScript '''
             class Main extends Outer {
                 static main(args) {
@@ -783,7 +764,7 @@ final class InnerClassTest {
     }
 
     @Test // inner class is static instead of final
-    void testUsageOfOuterField8() {
+    void testUsageOfOuterField7() {
         assertScript '''
             class Main extends Outer {
                 static main(args) {
@@ -820,7 +801,7 @@ final class InnerClassTest {
 
     // GROOVY-9569
     @Test
-    void testUsageOfOuterField9() {
+    void testUsageOfOuterField8() {
         assertScript '''
             class Main extends Outer {
                 static main(args) {
@@ -857,7 +838,7 @@ final class InnerClassTest {
     }
 
     @Test
-    void testUsageOfOuterField10() {
+    void testUsageOfOuterField9() {
         assertScript '''
             class Outer {
                 static final String OUTER_CONSTANT = 'Constant Value'
@@ -881,7 +862,7 @@ final class InnerClassTest {
 
     // GROOVY-5259
     @Test
-    void testUsageOfOuterField11() {
+    void testUsageOfOuterField10() {
         assertScript '''
             class Base {
                 Base(String string) {
@@ -913,7 +894,7 @@ final class InnerClassTest {
     }
 
     @Test
-    void testUsageOfOuterField12() {
+    void testUsageOfOuterField11() {
         def err = shouldFail '''
             class C {
                 int count
@@ -934,15 +915,32 @@ final class InnerClassTest {
 
     // GROOVY-8050
     @Test
-    void testUsageOfOuterField13() {
-        assertScript '''
+    void testUsageOfOuterField12() {
+        def err = shouldFail '''
             class Outer {
                 class Inner {
                 }
                 def p = 1
             }
-            def i = new Outer.Inner(new Outer())
-            assert i.p == 1
+
+            new Outer.Inner(new Outer()).p
+        '''
+        assert err =~ /MissingPropertyException: No such property: p for 
class: Outer.Inner/
+    }
+
+    @NotYetImplemented @Test
+    void testUsageOfOuterField13() {
+        assertScript '''
+            class Outer {
+                interface Inner {
+                    default i() {
+                        'i' + o
+                    }
+                }
+                private static o = 'o'
+            }
+
+            assert (new Outer.Inner() {}).i() == 'io'
         '''
     }
 
@@ -1054,28 +1052,27 @@ final class InnerClassTest {
     @Test
     void testUsageOfOuterFieldOverridden() {
         assertScript '''
-            interface Run {
+            interface A {
                 def run()
             }
-            class Foo {
-                private x = 1
-
-                def foo() {
-                    def runner = new Run() {
+            class B {
+                def test() {
+                    def runner = new A() {
                         def run() { return x } // <-- dynamic variable
                     }
                     runner.run()
                 }
-
+                private x = 1
                 void setX(val) { x = val }
             }
-            class Bar extends Foo {
-                def x = 'string' // hides 'foo.@x' and overrides 
'foo.setX(val)'
+            class C extends B {
+                def x = 'string' // hides 'B.@x' and overrides 'B.setX(val)'
             }
-            def bar = new Bar()
-            assert bar.foo() == 'string'
-            bar.x = 'new string'
-            assert bar.foo() == 'new string'
+
+            def c = new C()
+            assert c.test() == 1
+            c.x = 'new string'
+            assert c.test() == 1
         '''
     }
 
@@ -1095,6 +1092,7 @@ final class InnerClassTest {
                     runner.run()
                 }
             }
+
             def foo = new Foo()
             assert foo.foo() == 1
         '''
@@ -1116,6 +1114,7 @@ final class InnerClassTest {
                     runner.run()
                 }
             }
+
             def foo = new Foo()
             assert foo.foo() == 1
         '''
@@ -1136,6 +1135,7 @@ final class InnerClassTest {
                     runner.run()
                 }
             }
+
             def foo = new Foo()
             assert foo.foo() == 1
         '''
@@ -1157,6 +1157,7 @@ final class InnerClassTest {
                     runner.run()
                 }
             }
+
             def foo = new Foo()
             assert foo.foo() == 1
         '''
@@ -1254,6 +1255,75 @@ final class InnerClassTest {
         '''
     }
 
+    // GROOVY-7938
+    @Test
+    void testUsageOfOuterMethod9() {
+        assertScript '''
+            class Outer {
+                Integer barCount = 0
+                static Integer fooCount = 0
+                void incBar() { barCount++ }
+                static void incFoo() { fooCount++ }
+                Inner innerFactory() { new Inner() }
+
+                static class Nested {
+                    static void nestedIncFoo() { incFoo() }
+                    static class NestedNested {
+                        static void nestedNestedIncFoo() { incFoo() }
+                    }
+                }
+                class Inner {
+                    void innerIncFoo() { incFoo() }
+                    static void staticInnerIncFoo() { incFoo() }
+                    InnerInner innerInnerFactory() { new InnerInner() }
+
+                    class InnerInner {
+                        void innerInnerIncFoo() { incFoo() }
+                        static void staticInnerInnerIncFoo() { incFoo() }
+                    }
+                }
+            }
+
+            Outer.incFoo()
+            Outer.Nested.nestedIncFoo()
+            Outer.Nested.NestedNested.nestedNestedIncFoo()
+            assert Outer.fooCount == 3
+
+            new Outer().with {
+                incBar()
+                incFoo()
+                innerFactory().with {
+                    incBar()
+                    innerIncFoo()
+                    staticInnerIncFoo()
+                    innerInnerFactory().with {
+                        incBar()
+                        innerInnerIncFoo()
+                        staticInnerInnerIncFoo()
+                    }
+                }
+                assert barCount == 3
+                assert fooCount == 8
+            }
+        '''
+    }
+
+    @NotYetImplemented @Test
+    void testUsageOfOuterMethod10() {
+        assertScript '''
+            class Outer {
+                interface Inner {
+                    default i() {
+                        'i' + o()
+                    }
+                }
+                private static o() { 'o' }
+            }
+
+            assert (new Outer.Inner() {}).i() == 'io'
+        '''
+    }
+
     @Test
     void testUsageOfOuterMethodOverridden() {
         assertScript '''
@@ -1965,10 +2035,12 @@ final class InnerClassTest {
     @Test
     void testEnclosingMethodIsSet2() {
         assertScript '''
-            import groovy.transform.ASTTest
+            import groovy.transform.*
             import org.codehaus.groovy.ast.expr.*
             import static org.codehaus.groovy.classgen.Verifier.*
 
+            @Field Object result
+
             @ASTTest(phase=CLASS_GENERATION, value={
                 def init = 
node.parameters[0].getNodeMetaData(INITIAL_EXPRESSION)
                 assert init instanceof MapExpression
@@ -2144,6 +2216,7 @@ final class InnerClassTest {
                     inner.inner()
                 }
             }
+
             assert new Outer().test() == 1
         '''
     }
@@ -2165,17 +2238,18 @@ final class InnerClassTest {
                     }
                 }
             }
+
             new Outer().obj.toString()
         '''
     }
 
     // GROOVY-8274
     @Test
-    void testMissingMethodHandling() {
+    void testMethodMissing1() {
         assertScript '''
             class Outer {
                 class Inner {
-                    def methodMissing(String name, args) {
+                    def methodMissing(String name, Object args) {
                         return name
                     }
                 }
@@ -2194,6 +2268,68 @@ final class InnerClassTest {
         '''
     }
 
+    @Test
+    void testMethodMissing2() {
+        assertScript '''
+            class Outer {
+                class Inner {
+                    def methodMissing(String name, Object args) {
+                        return 42
+                    }
+                    def propertyMissing(String name) {
+                        return 42
+                    }
+                }
+            }
+
+            def i = new Outer.Inner(new Outer())
+            assert i.foo()  == 42
+            assert i.foobar == 42
+        '''
+    }
+
+    @Test
+    void testMethodMissing3() {
+        assertScript '''
+            class Outer {
+                static class Inner {
+                    def methodMissing(String name, Object args) {
+                        return 42
+                    }
+                    def propertyMissing(String name) {
+                        return 42
+                    }
+                }
+            }
+
+            def i = new Outer.Inner()
+            assert i.foo()  == 42
+            assert i.foobar == 42
+        '''
+    }
+
+    @Test
+    void testMethodMissing4() {
+        assertScript '''
+            class Outer {
+                static class Inner {
+                    def methodMissing(String name, Object args) {
+                        return 42
+                    }
+                    def propertyMissing(String name) {
+                        return 42
+                    }
+                }
+                static class Other extends Inner {
+                }
+            }
+
+            def o = new Outer.Other()
+            assert o.foo()  == 42
+            assert o.foobar == 42
+        '''
+    }
+
     // GROOVY-6831
     @Test
     void testNestedPropertyHandling() {
@@ -2255,6 +2391,7 @@ final class InnerClassTest {
         def err = shouldFail """
             class Upper {
                 $returnType propertyMissing(String name, Object value) {
+                    throw new MissingPropertyException(name, getClass())
                 }
             }
             class Outer {
@@ -2266,6 +2403,60 @@ final class InnerClassTest {
         assert err =~ /No such property: missing for class: Outer.Inner/
     }
 
+    // GROOVY-11823
+    @Test
+    void testNestedPropertyHandling5() {
+        assertScript '''
+            class Upper {
+                Object propertyMissing(String name) {
+                    if (name == 'fizz') return 'buzz'
+                    throw new MissingPropertyException(name, getClass())
+                }
+            }
+            class Outer {
+                static class Inner extends Upper {
+                }
+            }
+            def inner = new Outer.Inner()
+            assert inner.fizz == 'buzz'
+        '''
+    }
+
+    // GROOVY-9618
+    @Test
+    void testNestedPropertyHandling6() {
+        assertScript '''
+            class Super {
+                public static X = 1
+                static getX() { 2 }
+            }
+            class Outer extends Super {
+                static class Inner {
+                    def m() { X }
+                }
+            }
+
+            assert new Outer.Inner().m() == 2
+        '''
+
+        def err = shouldFail '''
+            class Outer {
+                public static X = 1
+                static getX() { 2 }
+                static class Inner {
+                }
+            }
+            class Other extends Outer.Inner {
+                def m() {
+                    X // can't read super outer this way
+                }
+            }
+
+            new Other().m()
+        '''
+        assert err =~ /MissingPropertyException: No such property: X for 
class: Other/
+    }
+
     // GROOVY-7312
     @Test
     void testInnerClassOfInterfaceIsStatic() {
diff --git a/src/test/groovy/groovy/ClosureTest.groovy 
b/src/test/groovy/groovy/ClosureTest.groovy
index 829645151d..7797016645 100644
--- a/src/test/groovy/groovy/ClosureTest.groovy
+++ b/src/test/groovy/groovy/ClosureTest.groovy
@@ -18,8 +18,9 @@
  */
 package groovy
 
-import org.codehaus.groovy.control.MultipleCompilationErrorsException
-import org.junit.Test
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.ValueSource
 
 import static groovy.test.GroovyAssert.assertScript
 import static groovy.test.GroovyAssert.shouldFail
@@ -484,72 +485,6 @@ final class ClosureTest {
         '''
     }
 
-    @Test
-    void testStaticInnerClassOwnerWithPropertyMissingImplementation() {
-        def err = shouldFail MultipleCompilationErrorsException, '''
-            class ClosureTestA {
-                static class ClosureTestB {
-                    def propertyMissing(String myName, Object myValue) {
-                        return myValue
-                    }
-
-                    def propertyMissing(String myName) {
-                        return 42
-                    }
-
-                    def methodMissing(String myName, Object myArgs) {
-                        return 42
-                    }
-                }
-            }
-        '''
-
-        assert err.message.contains('"methodMissing" implementations are not 
supported on static inner classes as a synthetic version of "methodMissing" is 
added during compilation for the purpose of outer class delegation.')
-        assert err.message.contains('"propertyMissing" implementations are not 
supported on static inner classes as a synthetic version of "propertyMissing" 
is added during compilation for the purpose of outer class delegation.')
-    }
-
-    @Test
-    void testInnerClassOwnerWithPropertyMissingImplementation() {
-        assertScript '''
-            class ClosureTestA {
-                class ClosureTestB {
-                    def propertyMissing(String myName, Object myValue) {
-                        return myValue
-                    }
-
-                    def propertyMissing(String myName) {
-                        return 42
-                    }
-
-                    def methodMissing(String myName, Object myArgs) {
-                        return 42
-                    }
-                }
-            }
-
-            def a = new ClosureTestA()
-            def b = new ClosureTestA.ClosureTestB(a)
-        '''
-    }
-
-    @Test
-    void testStaticInnerClassHierarchyWithMethodMissing() {
-        def err = shouldFail MultipleCompilationErrorsException, '''
-            class ClosureTestA {
-                static class ClosureTestB {
-                    def methodMissing(String myName, Object myArgs) {
-                        return 42
-                    }
-                }
-
-                static class ClosureTestB1 extends ClosureTestB {
-                }
-            }
-        '''
-
-        assert err.message.contains('"methodMissing" implementations are not 
supported on static inner classes as a synthetic version of "methodMissing" is 
added during compilation for the purpose of outer class delegation.')
-    }
-
     // GROOVY-10943
     @Test
     void testClosureUnderscorePlaceholder() {
@@ -564,150 +499,148 @@ final class ClosureTest {
     }
 
     // GROOVY-2433, GROOVY-3073, GROOVY-9987, GROOVY-11128
-    @Test
-    void testClosureAccessToEnclosingClassPrivateMethod() {
-        for (who in ['this.', 'owner.', 'thisObject.', '']) {
-            assertScript """
-                class C {
-                    def getIds() {
-                        populateIds()
-                    }
-                    def populateIds = { ->
-                        ${who}sort([ 1, 5, 3, 4, 2 ])
-                    }
-                    private sort(list) {
-                        list.sort{ one, two -> one <=> two }
-                    }
+    @ParameterizedTest
+    @ValueSource(strings=['this.', 'owner.', 'thisObject.', ''])
+    void testClosureAccessToEnclosingClassPrivateMethod(String who) {
+        assertScript """
+            class C {
+                def getIds() {
+                    populateIds()
                 }
+                def populateIds = { ->
+                    ${who}sort([ 1, 5, 3, 4, 2 ])
+                }
+                private sort(list) {
+                    list.sort{ one, two -> one <=> two }
+                }
+            }
 
-                class D extends C {
-                    void test() {
-                        assert ids == [1,2,3,4,5]
-                    }
+            class D extends C {
+                void test() {
+                    assert ids == [1,2,3,4,5]
                 }
+            }
 
-                new D().test()
-            """
+            new D().test()
+        """
 
-            assertScript """
-                class C {
-                    protected String protectedMethod() {
-                        def closure = { ->
-                            ${who}privateMethod()
-                        }
-                        closure()
-                    }
-                    private String privateMethod() {
-                        'hello world'
+        assertScript """
+            class C {
+                protected String protectedMethod() {
+                    def closure = { ->
+                        ${who}privateMethod()
                     }
+                    closure()
+                }
+                private String privateMethod() {
+                    'hello world'
                 }
+            }
 
-                class D extends C {
-                    void test() {
-                        def result = protectedMethod()
-                        assert result == 'hello world'
-                    }
+            class D extends C {
+                void test() {
+                    def result = protectedMethod()
+                    assert result == 'hello world'
                 }
+            }
 
-                new D().test()
-            """
+            new D().test()
+        """
 
-            assertScript """
-                class C {
-                    def publicMethod() {
-                        [1].each {
-                            ${who}privateStaticMethod()
-                        }
-                    }
-                    private static privateStaticMethod() {
-                        'hello world'
+        assertScript """
+            class C {
+                def publicMethod() {
+                    [1].each {
+                        ${who}privateStaticMethod()
                     }
                 }
+                private static privateStaticMethod() {
+                    'hello world'
+                }
+            }
 
-                class D extends C {
-                    void test() {
-                        publicMethod()
-                    }
+            class D extends C {
+                void test() {
+                    publicMethod()
                 }
+            }
 
-                new D().test()
-            """
-        }
+            new D().test()
+        """
     }
 
     // GROOVY-3142, GROOVY-5438, GROOVY-6335, GROOVY-11128
-    @Test
-    void testClosureAccessToEnclosingClassPrivateField() {
-        for (who in ['this.@', 'this.', 'owner.', 'thisObject.', '']) {
-            assertScript """
-                class C {
-                    String data
-                    C(arg) {
-                        arg.each() { ${who}data = it } // MissingFieldException
-                    }
+    @ParameterizedTest
+    @ValueSource(strings=['this.@', 'this.', 'owner.', 'thisObject.', ''])
+    void testClosureAccessToEnclosingClassPrivateField(String who) {
+        assertScript """
+            class C {
+                String data
+                C(arg) {
+                    arg.each() { ${who}data = it } // MissingFieldException
                 }
+            }
 
-                class D extends C {
-                    D(arg) {
-                        super(arg)
-                    }
+            class D extends C {
+                D(arg) {
+                    super(arg)
                 }
+            }
 
-                new D(["test"])
-            """
+            new D(["test"])
+        """
 
-            assertScript """
-                class C {
-                    private String data
-                    C(arg) {
-                        arg.each() { ${who}data = it } // 
ReadOnlyPropertyException
-                    }
-                    String getData() { this.@data }
-                    private void setData(String value) { this.@data = value }
+        assertScript """
+            class C {
+                private String data
+                C(arg) {
+                    arg.each() { ${who}data = it } // ReadOnlyPropertyException
                 }
+                String getData() { this.@data }
+                private void setData(String value) { this.@data = value }
+            }
 
-                class D extends C {
-                    D(arg) {
-                        super(arg)
-                    }
+            class D extends C {
+                D(arg) {
+                    super(arg)
                 }
+            }
 
-                new D(["test"])
-            """
+            new D(["test"])
+        """
 
-            assertScript """
-                class C {
-                    private String string = 'foo'
-                    def test(List<String> strings) {
-                        strings.collect { ${who}string + it }
-                    }
+        assertScript """
+            class C {
+                private String string = 'foo'
+                def test(List<String> strings) {
+                    strings.collect { ${who}string + it }
                 }
+            }
 
-                def result = new C().test(['bar','baz'])
-                assert result == ['foobar','foobaz']
+            def result = new C().test(['bar','baz'])
+            assert result == ['foobar','foobaz']
 
-                class D extends C {
-                }
+            class D extends C {
+            }
+
+            result = new D().test(['bar','baz'])
+            assert result == ['foobar','foobaz']
+        """
 
-                result = new D().test(['bar','baz'])
-                assert result == ['foobar','foobaz']
-            """
-
-            assertScript """
-                @groovy.util.logging.Log
-                class C {
-                    void test() {
-                        1.times {
-                            ${who}log.info('sth')
-                        }
+        assertScript """
+            @groovy.util.logging.Log
+            class C {
+                void test() {
+                    1.times {
+                        ${who}log.info('sth')
                     }
                 }
+            }
 
-                class D extends C {
-                }
+            class D extends C {
+            }
 
-                new D().test()
-            """
-        }
+            new D().test()
+        """
     }
 }
diff --git a/src/test/groovy/groovy/PropertyTest.groovy 
b/src/test/groovy/groovy/PropertyTest.groovy
index 761fcde041..2b2547912e 100644
--- a/src/test/groovy/groovy/PropertyTest.groovy
+++ b/src/test/groovy/groovy/PropertyTest.groovy
@@ -831,24 +831,6 @@ final class PropertyTest {
         '''
     }
 
-    // GROOVY-9618
-    @Test
-    void testPropertyAndStaticUppercaseFieldPriority() {
-        assertScript '''
-            class A {
-                public static X = 1
-                static getX() { 2 }
-                static class B { }
-            }
-            class C extends A.B {
-                def test() {
-                    X
-                }
-            }
-            assert new C().test() == 2
-        '''
-    }
-
     
//--------------------------------------------------------------------------
 
     static class Base {
diff --git 
a/src/test/groovy/groovy/transform/stc/AnonymousInnerClassSTCTest.groovy 
b/src/test/groovy/groovy/transform/stc/AnonymousInnerClassSTCTest.groovy
index 8ae6966ba1..653aebf263 100644
--- a/src/test/groovy/groovy/transform/stc/AnonymousInnerClassSTCTest.groovy
+++ b/src/test/groovy/groovy/transform/stc/AnonymousInnerClassSTCTest.groovy
@@ -176,23 +176,24 @@ class AnonymousInnerClassSTCTest extends 
StaticTypeCheckingTestCase {
     // GROOVY-6904
     void testAICInClosure() {
         assertScript '''
-            interface X {
+            interface A {
                 def m()
             }
-
-            class A {
-                Object pm = "pm"
-                def bar(Closure<? extends X> x) {x().m()}
+            class C {
+                def bar(Closure<? extends A> closure) {
+                    closure().m()
+                }
                 def foo() {
                     bar { ->
-                        return new X() {
-                            def m() { pm }
+                        return new A() {
+                            def m() { p }
                         }
                     }
                 }
+                final String p = 'p'
             }
-            def a = new A()
-            assert a.foo() == "pm"
+
+            assert new C().foo() == 'p'
         '''
     }
 
diff --git 
a/src/test/groovy/org/codehaus/groovy/transform/packageScope/PackageScopeTransformTest.groovy
 
b/src/test/groovy/org/codehaus/groovy/transform/packageScope/PackageScopeTransformTest.groovy
index 12f3a5e6e6..7add367f14 100644
--- 
a/src/test/groovy/org/codehaus/groovy/transform/packageScope/PackageScopeTransformTest.groovy
+++ 
b/src/test/groovy/org/codehaus/groovy/transform/packageScope/PackageScopeTransformTest.groovy
@@ -19,7 +19,7 @@
 package org.codehaus.groovy.transform.packageScope
 
 import groovy.transform.CompileStatic
-import org.junit.Test
+import org.junit.jupiter.api.Test
 
 import static groovy.test.GroovyAssert.assertScript
 
@@ -191,7 +191,7 @@ final class PackageScopeTransformTest {
             import groovy.transform.PackageScope
 
             @CompileStatic
-            class Test {
+            class Outer {
                 @PackageScope static final String S = 'S'
                 protected static final String T = 'T'
                 private static final String U = 'U'
@@ -202,7 +202,7 @@ final class PackageScopeTransformTest {
                 }
             }
 
-            assert new Test.Inner().method() == 'STU'
+            assert new Outer.Inner().method() == 'STU'
         '''
     }
 }
diff --git 
a/subprojects/groovy-nio/src/test/groovy/org/apache/groovy/nio/extensions/NioExtensionsTest.groovy
 
b/subprojects/groovy-nio/src/test/groovy/org/apache/groovy/nio/extensions/NioExtensionsTest.groovy
index e6b30f3c48..ed7b2cadeb 100644
--- 
a/subprojects/groovy-nio/src/test/groovy/org/apache/groovy/nio/extensions/NioExtensionsTest.groovy
+++ 
b/subprojects/groovy-nio/src/test/groovy/org/apache/groovy/nio/extensions/NioExtensionsTest.groovy
@@ -659,13 +659,9 @@ class NioExtensionsTest extends Specification {
         def writable = path.filterLine { it.startsWith('a') || 
it.startsWith('g') || it.startsWith('d') }
         def sw = new StringWriter()
         writable.writeTo(sw)
-        def result = sw.toString()
 
         then:
-        result.contains('alpha')
-        result.contains('gamma')
-        result.contains('delta')
-        !result.contains('beta')
+        sw.toString() == 
['alpha','gamma','delta',''].join(System.lineSeparator())
     }
 
     def testFilterLineWithCharset() {
@@ -679,7 +675,7 @@ class NioExtensionsTest extends Specification {
         writable.writeTo(sw)
 
         then:
-        sw.toString().trim() == 'alpha\ngamma'
+        sw.toString() == ['alpha','gamma',''].join(System.lineSeparator())
     }
 
     def testFilterLineToWriter() {
@@ -692,7 +688,7 @@ class NioExtensionsTest extends Specification {
         path.filterLine(sw) { it.contains('2') || it.contains('4') }
 
         then:
-        sw.toString().trim() == 'line2\nline4'
+        sw.toString() == ['line2','line4',''].join(System.lineSeparator())
     }
 
     def testCreateParentDirectories() {
diff --git 
a/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/FormatStringChecker.groovy
 
b/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/FormatStringChecker.groovy
index 893cab1ae0..a93af52c30 100644
--- 
a/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/FormatStringChecker.groovy
+++ 
b/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/FormatStringChecker.groovy
@@ -68,8 +68,10 @@ import static org.codehaus.groovy.ast.ClassHelper.makeCached
  */
 @Incubating
 class FormatStringChecker extends 
GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
+
     private static final ClassNode LOCALE_TYPE = makeCached(Locale)
     private static final ClassNode FORMATTER_TYPE = makeCached(Formatter)
+
     private String formatSpecifier = /%(\d+\$)?([-#+ 
0,(\<]*)?(\d+)?(\.\d+)?([tT])?([a-zA-Z%])/
     private List<ASTNode> formatMethods = [
         macro(CompilePhase.SEMANTIC_ANALYSIS) { String.format(a) 
}.withConstraints { varargPlaceholder a },
@@ -95,13 +97,13 @@ class FormatStringChecker extends 
GroovyTypeCheckingExtensionSupport.TypeCheckin
                 makeVisitor().checkFormatterMethod(call)
             }
         }
+
         afterVisitMethod { MethodNode method ->
-            def visitor = makeVisitor()
-            method.code.visit(visitor)
+            method.code.visit(makeVisitor())
         }
     }
 
-    private makeVisitor() {
+    private CheckingVisitor makeVisitor() {
         new CheckingVisitor() {
             @Override
             void visitMethodCallExpression(MethodCallExpression call) {
@@ -145,7 +147,7 @@ class FormatStringChecker extends 
GroovyTypeCheckingExtensionSupport.TypeCheckin
                 }
             }
 
-            void checkFormatStringTypes(Expression expression, 
List<Expression> args, Expression target) {
+            private void checkFormatStringTypes(Expression expression, 
List<Expression> args, Expression target) {
                 int next = 0
                 int prevIndex = -1
                 expression.value.eachMatch(formatSpecifier) { spec ->
@@ -254,14 +256,14 @@ class FormatStringChecker extends 
GroovyTypeCheckingExtensionSupport.TypeCheckin
                 }
             }
 
-            void checkBadFlags(flagList, conversion, Expression target, String 
badFlags) {
+            private void checkBadFlags(flagList, conversion, Expression 
target, String badFlags) {
                 def mismatched = flagList?.findAll { badFlags.contains(it) 
}?.join()
                 if (mismatched) {
                     addStaticTypeError("FormatFlagsConversionMismatch: 
Conversion = $conversion, Flags = '$mismatched'", target)
                 }
             }
 
-            void checkFormatStringConstantArgs(ConstantExpression 
formatString, args, Expression target) {
+            private void checkFormatStringConstantArgs(ConstantExpression 
formatString, args, Expression target) {
                 try {
                     new Formatter().format(formatString.value, *args)
                 } catch (IllegalFormatException ex) {
@@ -275,7 +277,7 @@ class FormatStringChecker extends 
GroovyTypeCheckingExtensionSupport.TypeCheckin
             void visitDeclarationExpression(DeclarationExpression decl) {
                 super.visitDeclarationExpression(decl)
                 if (decl.variableExpression != null) {
-                    if (isConstantExpression(decl.rightExpression)) {
+                    if (decl.rightExpression instanceof ConstantExpression) {
                         localConstVars.put(decl.variableExpression, 
decl.rightExpression)
                     }
                 }
diff --git 
a/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/RegexChecker.groovy
 
b/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/RegexChecker.groovy
index 09e6e6a16d..f53ef4f3ed 100644
--- 
a/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/RegexChecker.groovy
+++ 
b/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/RegexChecker.groovy
@@ -25,12 +25,14 @@ import org.codehaus.groovy.ast.ClassNode
 import org.codehaus.groovy.ast.MethodNode
 import org.codehaus.groovy.ast.expr.BinaryExpression
 import org.codehaus.groovy.ast.expr.BitwiseNegationExpression
+import org.codehaus.groovy.ast.expr.ClassExpression
 import org.codehaus.groovy.ast.expr.ConstantExpression
 import org.codehaus.groovy.ast.expr.DeclarationExpression
 import org.codehaus.groovy.ast.expr.Expression
 import org.codehaus.groovy.ast.expr.MethodCall
 import org.codehaus.groovy.ast.expr.MethodCallExpression
 import org.codehaus.groovy.ast.expr.StaticMethodCallExpression
+import org.codehaus.groovy.ast.expr.VariableExpression
 import org.codehaus.groovy.syntax.Types
 import org.codehaus.groovy.transform.stc.GroovyTypeCheckingExtensionSupport
 import org.codehaus.groovy.transform.stc.StaticTypesMarker
@@ -100,14 +102,15 @@ import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.checkC
  */
 @Incubating
 class RegexChecker extends GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
-    private static final String REGEX_GROUP_COUNT = RegexChecker.simpleName + 
'_INFERRED_GROUP_COUNT'
-    private static final String REGEX_MATCHER_RESULT_TYPE = 
RegexChecker.simpleName + '_MATCHER_RESULT_INFERRED_TYPE'
+
     private static final ClassNode MATCHER_TYPE = ClassHelper.make(Matcher)
+    private static final String REGEX_GROUP_COUNT = 
RegexChecker.getSimpleName() + '_INFERRED_GROUP_COUNT'
+    private static final String REGEX_MATCHER_RESULT_TYPE = 
RegexChecker.getSimpleName() + '_MATCHER_RESULT_INFERRED_TYPE'
 
     @Override
     Object run() {
         beforeVisitMethod { MethodNode method ->
-            def visitor = new CheckingVisitor() {
+            method.code.visit(new CheckingVisitor() {
                 @Override
                 void visitBitwiseNegationExpression(BitwiseNegationExpression 
expression) {
                     super.visitBitwiseNegationExpression(expression)
@@ -122,7 +125,7 @@ class RegexChecker extends 
GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
                         def exp = findConstExp(expression.rightExpression, 
String)
                         checkRegex(exp, expression)
                     } else if (expression.operation.type == 
Types.LEFT_SQUARE_BRACKET) {
-                        if (isVariableExpression(expression.leftExpression)) {
+                        if (expression.leftExpression instanceof 
VariableExpression) {
                             def var = 
findTargetVariable(expression.leftExpression)
                             def groupCount = 
var?.getNodeMetaData(REGEX_GROUP_COUNT)
                             if (groupCount != null) {
@@ -140,7 +143,7 @@ class RegexChecker extends 
GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
                 @Override
                 void visitMethodCallExpression(MethodCallExpression call) {
                     super.visitMethodCallExpression(call)
-                    if (isClassExpression(call.objectExpression)) {
+                    if (call.objectExpression instanceof ClassExpression) {
                         checkPatternMethod(call, call.objectExpression.type)
                     } else if (isPattern(call.receiver) && call.methodAsString 
== 'matcher') {
                         def var = findTargetVariable(call.receiver)
@@ -169,7 +172,7 @@ class RegexChecker extends 
GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
                 void visitDeclarationExpression(DeclarationExpression decl) {
                     super.visitDeclarationExpression(decl)
                     if (decl.variableExpression != null) {
-                        if (isConstantExpression(decl.rightExpression)) {
+                        if (decl.rightExpression instanceof 
ConstantExpression) {
                             localConstVars.put(decl.variableExpression, 
decl.rightExpression)
                         }
                         def groupCount = 
decl.rightExpression.getNodeMetaData(REGEX_GROUP_COUNT)
@@ -178,15 +181,13 @@ class RegexChecker extends 
GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
                         }
                     }
                 }
-
-            }
-            method.code.visit(visitor)
+            })
         }
 
         incompatibleAssignment { lhsType, rhsType, expr ->
-            if (isBinaryExpression(expr) && isAssignment(expr.operation.type)) 
{
+            if (expr instanceof BinaryExpression && 
isAssignment(expr.operation.type)) {
                 def from = expr.rightExpression
-                if (isBinaryExpression(from) && from.operation.type == 
Types.LEFT_SQUARE_BRACKET && getType(from.leftExpression) == MATCHER_TYPE) {
+                if (from instanceof BinaryExpression && from.operation.type == 
Types.LEFT_SQUARE_BRACKET && getType(from.leftExpression) == MATCHER_TYPE) {
                     ClassNode inferred = 
from.getNodeMetaData(REGEX_MATCHER_RESULT_TYPE)
                     if (inferred) {
                         handled = true
@@ -200,9 +201,9 @@ class RegexChecker extends 
GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
             }
         }
 
-        methodNotFound { receiverType, name, argList, argTypes, call ->
+        methodNotFound { receiverType, name, argList, argTypes, MethodCall 
call ->
             def receiver = call.receiver
-            if (isBinaryExpression(receiver) && receiver.operation.type == 
Types.LEFT_SQUARE_BRACKET && getType(receiver.leftExpression) == MATCHER_TYPE) {
+            if (receiver instanceof BinaryExpression && 
receiver.operation.type == Types.LEFT_SQUARE_BRACKET && 
getType(receiver.leftExpression) == MATCHER_TYPE) {
                 ClassNode inferred = 
receiver.getNodeMetaData(REGEX_MATCHER_RESULT_TYPE)
                 if (inferred) {
                     makeDynamic(call, inferred)
@@ -211,12 +212,12 @@ class RegexChecker extends 
GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
         }
 
         afterVisitMethod { MethodNode method ->
-            def visitor = new CheckingVisitor() {
+            method.code.visit(new CheckingVisitor() {
                 @Override
                 void visitDeclarationExpression(DeclarationExpression decl) {
                     super.visitDeclarationExpression(decl)
                     if (decl.variableExpression != null) {
-                        if (isConstantExpression(decl.rightExpression)) {
+                        if (decl.rightExpression instanceof 
ConstantExpression) {
                             localConstVars.put(decl.variableExpression, 
decl.rightExpression)
                         }
                         def groupCount = 
decl.rightExpression.getNodeMetaData(REGEX_GROUP_COUNT)
@@ -236,7 +237,7 @@ class RegexChecker extends 
GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
                         }
                     }
                     super.visitMethodCallExpression(call)
-                    if (isVariableExpression(call.objectExpression) && 
call.methodAsString == 'group' && isMatcher(call.receiver) && 
call.arguments.expressions) {
+                    if (call.objectExpression instanceof VariableExpression && 
call.methodAsString == 'group' && isMatcher(call.receiver) && 
call.arguments.expressions) {
                         def var = findTargetVariable(call.receiver)
                         def maxCnt = var?.getNodeMetaData(REGEX_GROUP_COUNT)
                         if (maxCnt != null) {
@@ -261,21 +262,22 @@ class RegexChecker extends 
GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
                         }
                     }
                 }
-            }
-            method.code.visit(visitor)
+            })
         }
     }
 
-    private boolean isMatcher(Expression obj) {
-        obj.type == MATCHER_TYPE ||
-                obj.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE) == 
MATCHER_TYPE ||
-                obj.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE) == 
MATCHER_TYPE
+    
//--------------------------------------------------------------------------
+
+    private boolean isMatcher(Expression exp) {
+        exp.type == MATCHER_TYPE
+            || exp.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE) == 
MATCHER_TYPE
+            || exp.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE) == 
MATCHER_TYPE
     }
 
-    private boolean isPattern(Expression obj) {
-        obj.type == PATTERN_TYPE ||
-                obj.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE) == 
PATTERN_TYPE ||
-                obj.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE) == 
PATTERN_TYPE
+    private boolean isPattern(Expression exp) {
+        exp.type == PATTERN_TYPE
+            || exp.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE) == 
PATTERN_TYPE
+            || exp.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE) == 
PATTERN_TYPE
     }
 
     private void checkRegex(ConstantExpression regex, Expression target) {
@@ -290,5 +292,4 @@ class RegexChecker extends 
GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
             addStaticTypeError('Bad regex' + additional + ex.message, target)
         }
     }
-
 }
diff --git 
a/subprojects/groovy-typecheckers/src/main/groovy/org/apache/groovy/typecheckers/CheckingVisitor.groovy
 
b/subprojects/groovy-typecheckers/src/main/groovy/org/apache/groovy/typecheckers/CheckingVisitor.groovy
index 1bd63804b5..f7b285fc1d 100644
--- 
a/subprojects/groovy-typecheckers/src/main/groovy/org/apache/groovy/typecheckers/CheckingVisitor.groovy
+++ 
b/subprojects/groovy-typecheckers/src/main/groovy/org/apache/groovy/typecheckers/CheckingVisitor.groovy
@@ -18,6 +18,7 @@
  */
 package org.apache.groovy.typecheckers
 
+import groovy.transform.AutoFinal
 import groovy.transform.CompileStatic
 import org.codehaus.groovy.ast.ClassCodeVisitorSupport
 import org.codehaus.groovy.ast.FieldNode
@@ -27,10 +28,15 @@ import org.codehaus.groovy.ast.expr.Expression
 import org.codehaus.groovy.ast.expr.VariableExpression
 import org.codehaus.groovy.control.SourceUnit
 
-@CompileStatic
-@SuppressWarnings('Instanceof')
+@AutoFinal @CompileStatic
 class CheckingVisitor extends ClassCodeVisitorSupport {
-    protected final Map<Expression, Expression> localConstVars = new 
HashMap<>()
+
+    @Override
+    protected SourceUnit getSourceUnit() {
+        null
+    }
+
+    protected final Map<Expression,Expression> localConstVars = [:]
 
     protected Expression findConstExp(Expression exp, Class type) {
         if (exp instanceof ConstantExpression && 
type.isAssignableFrom(exp.value.getClass())) {
@@ -48,16 +54,11 @@ class CheckingVisitor extends ClassCodeVisitorSupport {
         null
     }
 
-    @Override
-    protected SourceUnit getSourceUnit() {
-        null
-    }
-
-    static Variable findTargetVariable(final VariableExpression ve) {
-        Variable accessedVariable = ve.accessedVariable
+    protected Variable findTargetVariable(VariableExpression ve) {
+        def accessedVariable = ve.accessedVariable
         if (accessedVariable != null && accessedVariable != ve) {
             if (accessedVariable instanceof VariableExpression) {
-                return findTargetVariable((VariableExpression) 
accessedVariable)
+                return findTargetVariable(accessedVariable)
             }
             return accessedVariable
         }


Reply via email to