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

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

commit 62858b5f98525e4b32b4cf08c50acd691db22c6d
Author: Eric Milles <[email protected]>
AuthorDate: Mon Feb 2 13:52:24 2026 -0600

    next step
    
    7024 8050
---
 src/main/java/groovy/lang/MetaClassImpl.java       |  35 ++-
 .../classgen/InnerClassCompletionVisitor.java      | 237 +--------------------
 .../groovy/classgen/InnerClassVisitorHelper.java   |  57 +----
 .../stc/GroovyTypeCheckingExtensionSupport.java    |  31 ++-
 .../groovy/gls/innerClass/InnerClassTest.groovy    | 106 +++++----
 .../groovy/typecheckers/FormatStringChecker.groovy |  16 +-
 .../groovy/groovy/typecheckers/RegexChecker.groovy |  55 ++---
 .../groovy/typecheckers/CheckingVisitor.groovy     |  23 +-
 8 files changed, 165 insertions(+), 395 deletions(-)

diff --git a/src/main/java/groovy/lang/MetaClassImpl.java 
b/src/main/java/groovy/lang/MetaClassImpl.java
index 7f88b8314d..23e49d0a34 100644
--- a/src/main/java/groovy/lang/MetaClassImpl.java
+++ b/src/main/java/groovy/lang/MetaClassImpl.java
@@ -1232,8 +1232,9 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
             var outerClass = sender.getEnclosingClass(); // 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, outerClass, 
methodName, arguments, false, false);
+                    return omc.invokeMethod(outerClass, target, methodName, 
arguments, false, false);
                 } catch (MissingMethodException e) {
                     mme.addSuppressed(e);
                 }
@@ -1242,6 +1243,32 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
         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) {
+            Class<?> outerClass = innerClass.getEnclosingClass();
+            while (GeneratedClosure.class.isAssignableFrom(outerClass)) {
+                outerClass = outerClass.getEnclosingClass(); // skip closure(s)
+            }
+            outer = outerClass;
+        }
+        return outer;
+    }
+
     private MetaMethod getMetaMethod(final Class<?> sender, final Object 
object, final String methodName, final boolean isCallToSuper, final Object[] 
arguments) {
         MetaMethod method = null;
         if (CALL_METHOD.equals(methodName) && object instanceof 
GeneratedClosure) {
@@ -1951,8 +1978,9 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
             var outerClass = sender.getEnclosingClass(); // 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, outerClass, name, 
false, false);
+                    return omc.getProperty(outerClass, target, name, false, 
false);
                 } catch (MissingPropertyException e) {
                     mpe.addSuppressed(e);
                 }
@@ -2847,8 +2875,9 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
             var outerClass = sender.getEnclosingClass(); // 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, outerClass, name, newValue, 
false, false);
+                    omc.setProperty(outerClass, target, name, newValue, false, 
false);
                     return;
                 } catch (MissingPropertyException e) {
                     mpe.addSuppressed(e);
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java 
b/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java
index 8706be493b..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.callThisX;
-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.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.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 && !isStatic(innerClass)) {
-                addMopMethods(innerClass);
-            }
         }
     }
 
@@ -156,195 +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);
-                                    }
-                                })
-                        );
-                    }
-                }
-        );
-
-        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,
-                "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);
-                                    }
-                                })
-                        );
-                    }
-                }
-        );
-    }
-
-    private 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;
-            if (methodName.endsWith("methodMissing")) {
-                exceptionT = 
ClassHelper.make(groovy.lang.MissingMethodException.class);
-                newException = ctorX(exceptionT, 
args(callX(varX(catchParam),"getMethod"), callThisX("getClass"), 
callX(varX(catchParam),"getArguments")));
-            } else {
-                exceptionT = 
ClassHelper.make(groovy.lang.MissingPropertyException.class);
-                newException = ctorX(exceptionT, 
args(callX(varX(catchParam),"getProperty"), callThisX("getClass"), 
callX(varX(catchParam),"getCause")));
-            }
-            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
@@ -396,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;
@@ -415,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..ff1a9202da 100644
--- a/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitorHelper.java
+++ b/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitorHelper.java
@@ -19,85 +19,30 @@
 package org.codehaus.groovy.classgen;
 
 import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
-import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.FieldNode;
 import org.codehaus.groovy.ast.InnerClassNode;
 import org.codehaus.groovy.ast.Parameter;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.SpreadExpression;
 import org.codehaus.groovy.ast.stmt.BlockStatement;
 import org.objectweb.asm.Opcodes;
 
 import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
-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.constX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.eqX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.indexX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.isInstanceOfX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.notX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
 
 public abstract class InnerClassVisitorHelper extends ClassCodeVisitorSupport {
 
-    private static final ClassNode OBJECT_ARRAY = 
ClassHelper.OBJECT_TYPE.makeArray();
-
     protected static void addFieldInit(final Parameter p, final FieldNode fn, 
final BlockStatement block) {
         block.addStatement(assignS(fieldX(fn), varX(p)));
     }
 
-    protected static void setPropertyGetterDispatcher(final BlockStatement 
block, final Expression target, final Parameter[] parameters) {
-        block.addStatement(returnS(propX(target, varX(parameters[0]))));
-    }
-
-    protected static void setPropertySetterDispatcher(final BlockStatement 
block, final Expression target, final Parameter[] parameters) {
-        block.addStatement(stmt(assignX(propX(target, varX(parameters[0])), 
varX(parameters[1]))));
-    }
-
-    protected static void setMethodDispatcherCode    (final BlockStatement 
block, final Expression target, final Parameter[] parameters) {
-        // if (!(args instanceof Object[])) return target.(name)(args)
-        block.addStatement(ifS(
-            notX(isInstanceOfX(varX(parameters[1]), OBJECT_ARRAY)),
-            returnS(callX(target, varX(parameters[0]), varX(parameters[1])))));
-
-        // if (((Object[])args).length == 1) return target.(name)(args[0])
-        block.addStatement(ifS(
-            eqX(propX(castX(OBJECT_ARRAY, varX(parameters[1])), "length"), 
constX(1, true)),
-            returnS(callX(target, varX(parameters[0]), 
indexX(castX(OBJECT_ARRAY, varX(parameters[1])), constX(0, true))))));
-
-        // return target.(name)(*args)
-        block.addStatement(returnS(callX(target, varX(parameters[0]), new 
SpreadExpression(varX(parameters[1])))));
-    }
-
-    
//--------------------------------------------------------------------------
-
-    protected static ClassNode getClassNode(final ClassNode cn, final boolean 
isStatic) {
-        return isStatic ? ClassHelper.CLASS_Type : cn; // TODO: Set class type 
parameter?
-    }
-
-    protected static int getObjectDistance(ClassNode cn) {
-        int count = 0;
-        while (cn != null && !ClassHelper.isObjectType(cn)) {
-            cn = cn.getSuperClass();
-            count += 1;
-        }
-        return count;
-    }
-
     protected static boolean isStatic(final InnerClassNode cn) {
         return cn.getDeclaredField("this$0") == null;
     }
 
     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/gls/innerClass/InnerClassTest.groovy 
b/src/test/groovy/gls/innerClass/InnerClassTest.groovy
index 90f7f7a1ae..58fa45ab1b 100644
--- a/src/test/groovy/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/groovy/gls/innerClass/InnerClassTest.groovy
@@ -594,14 +594,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()
@@ -609,24 +609,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()
@@ -634,33 +635,34 @@ final class InnerClassTest {
 
                 static x(y) { x = y }
             }
-            assert Foo.foo() == 1
-            Foo.x(2)
-            assert Foo.foo() == 2
+
+            assert C.foo() == 1
+            C.x(2)
+            assert C.foo() == 2
         '''
     }
 
     @Test
     void testUsageOfOuterField3() {
         assertScript '''
-            interface X {
+            interface A {
                 def m()
             }
-
-            class A {
-                def pm = "pm"
-
-                def bar(x) {x().m()}
+            class C {
+                def bar(x) {
+                    x().m()
+                }
                 def foo() {
                     bar { ->
-                        return new X() {
-                            def m() { pm }
+                        return new A() {
+                            def m() { p }
                         }
                     }
                 }
+                final p = 'p'
             }
-            def a = new A()
-            assert "pm" == a.foo()
+
+            assert new C().foo() == 'p'
         '''
     }
 
@@ -713,6 +715,7 @@ final class InnerClassTest {
 
                 static x(y) { x = y }
             }
+
             assert Foo.foo() == 1
             Foo.x(2)
             assert Foo.foo() == 2
@@ -928,15 +931,16 @@ final class InnerClassTest {
     // GROOVY-8050
     @Test
     void testUsageOfOuterField13() {
-        assertScript '''
+        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
@@ -1063,28 +1067,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
         '''
     }
 
@@ -2044,10 +2047,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
@@ -2410,9 +2415,28 @@ final class InnerClassTest {
         assert err =~ /No such property: missing for class: Outer.Inner/
     }
 
-    // GROOVY-9618
+    // 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
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