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


The following commit(s) were added to refs/heads/GROOVY-4737 by this push:
     new 32328595d6 next step
32328595d6 is described below

commit 32328595d65602be84a990c847681e33dac536ba
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       |  37 +++-
 .../classgen/InnerClassCompletionVisitor.java      | 237 +--------------------
 .../groovy/classgen/InnerClassVisitorHelper.java   |  57 +----
 .../groovy/gls/innerClass/InnerClassTest.groovy    | 102 +++++----
 4 files changed, 100 insertions(+), 333 deletions(-)

diff --git a/src/main/java/groovy/lang/MetaClassImpl.java 
b/src/main/java/groovy/lang/MetaClassImpl.java
index 7f88b8314d..bbcc25b319 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,10 @@ 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 /*target instanceof GroovyObject go ? 
go.getProperty(name)
+                         : */omc.getProperty(outerClass, target, name, false, 
false);
                 } catch (MissingPropertyException e) {
                     mpe.addSuppressed(e);
                 }
@@ -2847,8 +2876,10 @@ 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);
+                    if (target instanceof GroovyObject go) 
go.setProperty(name, newValue);
+                    else 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/test/groovy/gls/innerClass/InnerClassTest.groovy 
b/src/test/groovy/gls/innerClass/InnerClassTest.groovy
index 90f7f7a1ae..a5a79381f3 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
         '''
     }
 
@@ -2410,9 +2413,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

Reply via email to