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

[groovy] branch GROOVY_2_5_X updated (362ff57b86 -> d11dc4ad05)

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

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


    from 362ff57b86 GROOVY-8737: STC: no varargs distance for exact match of variadic method
     new 6fdc9f2096 sync with 3_0_X
     new d11dc4ad05 GROOVY-8762: within closure determined via `GeneratedClosure` interface

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


Summary of changes:
 build.bat                                          |   1 +
 .../org/codehaus/groovy/classgen/Verifier.java     |   2 +-
 .../groovy/classgen/asm/WriterController.java      | 301 ++++++++++-----------
 src/test/gls/innerClass/InnerClassTest.groovy      | 152 ++++++++++-
 4 files changed, 292 insertions(+), 164 deletions(-)
 create mode 100644 build.bat


[groovy] 01/02: sync with 3_0_X

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

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

commit 6fdc9f2096f4b52c45fefeaf4fa66f94a6ad0af3
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Aug 24 12:22:33 2022 -0500

    sync with 3_0_X
---
 .../org/codehaus/groovy/classgen/Verifier.java     |   2 +-
 .../groovy/classgen/asm/WriterController.java      | 301 ++++++++++-----------
 src/test/gls/innerClass/InnerClassTest.groovy      | 122 ++++++++-
 3 files changed, 261 insertions(+), 164 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/Verifier.java b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
index c8c89bad48..ed40d7731c 100644
--- a/src/main/java/org/codehaus/groovy/classgen/Verifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
@@ -408,7 +408,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
     }
 
     protected void addGroovyObjectInterfaceAndMethods(ClassNode node, final String classInternalName) {
-        if (!node.isDerivedFromGroovyObject()) node.addInterface(ClassHelper.make(GroovyObject.class));
+        if (!node.isDerivedFromGroovyObject()) node.addInterface(ClassHelper.GROOVY_OBJECT_TYPE);
         FieldNode metaClassField = getMetaClassField(node);
 
         boolean shouldAnnotate = classNode.getModule().getContext() != null;
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
index a89c9e1855..b70e923fe7 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
@@ -22,7 +22,6 @@ import org.codehaus.groovy.GroovyBugError;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.ConstructorNode;
-import org.codehaus.groovy.ast.InnerClassNode;
 import org.codehaus.groovy.ast.InterfaceHelperClassNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.classgen.AsmClassGenerator;
@@ -44,8 +43,9 @@ import java.util.Map;
 import static org.apache.groovy.util.SystemUtil.getBooleanSafe;
 
 public class WriterController {
-    private static final String GROOVY_LOG_CLASSGEN = "groovy.log.classgen";
-    private final boolean LOG_CLASSGEN = getBooleanSafe(GROOVY_LOG_CLASSGEN);
+
+    private static final boolean LOG_CLASSGEN = getBooleanSafe("groovy.log.classgen");
+
     private AsmClassGenerator acg;
     private MethodVisitor methodVisitor;
     private CompileStack compileStack;
@@ -62,39 +62,38 @@ public class WriterController {
     private String internalBaseClassName;
     private ClassNode outermostClass;
     private MethodNode methodNode;
-    private SourceUnit sourceUnit;
     private ConstructorNode constructorNode;
     private GeneratorContext context;
     private InterfaceHelperClassNode interfaceClassLoadingClass;
     public boolean optimizeForInt = true;
     private StatementWriter statementWriter;
-    private boolean fastPath = false;
+    private boolean fastPath;
     private TypeChooser typeChooser;
     private int bytecodeVersion = Opcodes.V1_5;
     private int lineNumber = -1;
     private int helperMethodIndex = 0;
     private List<String> superMethodNames = new ArrayList<String>();
 
-    public void init(AsmClassGenerator asmClassGenerator, GeneratorContext gcon, ClassVisitor cv, ClassNode cn) {
+    public void init(final AsmClassGenerator asmClassGenerator, final GeneratorContext gcon, final ClassVisitor cv, final ClassNode cn) {
         CompilerConfiguration config = cn.getCompileUnit().getConfig();
         Map<String,Boolean> optOptions = config.getOptimizationOptions();
-        boolean invokedynamic=false;
+        boolean invokedynamic = false;
         if (optOptions.isEmpty()) {
             // IGNORE
         } else if (Boolean.FALSE.equals(optOptions.get("all"))) {
-            optimizeForInt=false;
+            this.optimizeForInt = false;
             // set other optimizations options to false here
         } else {
-            if (Boolean.TRUE.equals(optOptions.get(CompilerConfiguration.INVOKEDYNAMIC))) invokedynamic=true;
-            if (Boolean.FALSE.equals(optOptions.get("int"))) optimizeForInt=false;
-            if (invokedynamic) optimizeForInt=false;
+            if (Boolean.TRUE.equals(optOptions.get(CompilerConfiguration.INVOKEDYNAMIC))) invokedynamic = true;
+            if (Boolean.FALSE.equals(optOptions.get("int"))) this.optimizeForInt = false;
+            if (invokedynamic) this.optimizeForInt = false;
             // set other optimizations options to false here
         }
         this.classNode = cn;
         this.outermostClass = null;
-        this.internalClassName = BytecodeHelper.getClassInternalName(classNode);
+        this.internalClassName = BytecodeHelper.getClassInternalName(cn);
 
-        bytecodeVersion = chooseBytecodeVersion(invokedynamic, config.isPreviewFeatures(), config.getTargetBytecode());
+        this.bytecodeVersion = chooseBytecodeVersion(invokedynamic, config.isPreviewFeatures(), config.getTargetBytecode());
 
         if (invokedynamic) {
             this.invocationWriter = new InvokeDynamicWriter(this);
@@ -107,9 +106,9 @@ public class WriterController {
         }
 
         this.unaryExpressionHelper = new UnaryExpressionHelper(this);
-        if (optimizeForInt) {
+        if (this.optimizeForInt) {
             this.fastPathBinaryExpHelper = new BinaryExpressionMultiTypeDispatcher(this);
-            // todo: replace with a real fast path unary expression helper when available
+            // TODO: replace with a real fast path unary expression helper when available
             this.fastPathUnaryExpressionHelper = new UnaryExpressionHelper(this);
         } else {
             this.fastPathBinaryExpHelper = this.binaryExpHelper;
@@ -119,13 +118,12 @@ public class WriterController {
         this.operandStack = new OperandStack(this);
         this.assertionWriter = new AssertionWriter(this);
         this.closureWriter = new ClosureWriter(this);
-        this.internalBaseClassName = BytecodeHelper.getClassInternalName(classNode.getSuperClass());
+        this.internalBaseClassName = BytecodeHelper.getClassInternalName(cn.getSuperClass());
         this.acg = asmClassGenerator;
-        this.sourceUnit = acg.getSourceUnit();
         this.context = gcon;
         this.compileStack = new CompileStack(this);
-        this.cv = this.createClassVisitor(cv);
-        if (optimizeForInt) {
+        this.cv = createClassVisitor(cv);
+        if (this.optimizeForInt) {
             this.statementWriter = new OptimizingStatementWriter(this);
         } else {
             this.statementWriter = new StatementWriter(this);
@@ -133,11 +131,8 @@ public class WriterController {
         this.typeChooser = new StatementMetaTypeChooser();
     }
 
-    private ClassVisitor createClassVisitor(ClassVisitor cv) {
-        if (!LOG_CLASSGEN) {
-            return cv;
-        }
-        if (cv instanceof LoggableClassVisitor) {
+    private static ClassVisitor createClassVisitor(final ClassVisitor cv) {
+        if (!LOG_CLASSGEN || cv instanceof LoggableClassVisitor) {
             return cv;
         }
         return new LoggableClassVisitor(cv);
@@ -145,64 +140,68 @@ public class WriterController {
 
     private static int chooseBytecodeVersion(final boolean invokedynamic, final boolean previewFeatures, final String targetBytecode) {
         Integer bytecodeVersion = CompilerConfiguration.JDK_TO_BYTECODE_VERSION_MAP.get(targetBytecode);
+        if (bytecodeVersion == null) {
+            throw new GroovyBugError("Bytecode version [" + targetBytecode + "] is not supported by the compiler");
+        }
 
-        if (invokedynamic && bytecodeVersion < Opcodes.V1_7) {
-            return Opcodes.V1_7;
+        if (invokedynamic && bytecodeVersion <= Opcodes.V1_7) {
+            return Opcodes.V1_7; // invokedynamic added here
+        } else if (previewFeatures) {
+            return bytecodeVersion | Opcodes.V_PREVIEW;
         } else {
-            if (null != bytecodeVersion) {
-                return previewFeatures ? bytecodeVersion | Opcodes.V_PREVIEW : bytecodeVersion;
-            }
+            return bytecodeVersion;
         }
-
-        throw new GroovyBugError("Bytecode version ["+targetBytecode+"] is not supported by the compiler");
     }
 
+    //--------------------------------------------------------------------------
+
     public AsmClassGenerator getAcg() {
         return acg;
     }
 
-    public void setMethodVisitor(MethodVisitor methodVisitor) {
-        this.methodVisitor = methodVisitor;
-    }
-
-    public MethodVisitor getMethodVisitor() {
-        return methodVisitor;
+    @Deprecated
+    public ClassVisitor getCv() {
+        return cv;
     }
 
-    public CompileStack getCompileStack() {
-        return compileStack;
+    public ClassVisitor getClassVisitor() {
+        return cv;
     }
 
-    public OperandStack getOperandStack() {
-        return operandStack;
+    public MethodVisitor getMethodVisitor() {
+        return methodVisitor;
     }
 
-    public ClassNode getClassNode() {
-        return classNode;
+    public void setMethodVisitor(final MethodVisitor methodVisitor) {
+        this.methodVisitor = methodVisitor;
     }
 
-    public CallSiteWriter getCallSiteWriter() {
-        return callSiteWriter;
+    public GeneratorContext getContext() {
+        return context;
     }
 
-    public ClassVisitor getClassVisitor() {
-        return cv;
+    public CompileStack getCompileStack() {
+        return compileStack;
     }
 
-    public ClosureWriter getClosureWriter() {
-        return closureWriter;
+    public OperandStack getOperandStack() {
+        return operandStack;
     }
 
-    public ClassVisitor getCv() {
-        return cv;
+    public SourceUnit getSourceUnit() {
+        return getAcg().getSourceUnit();
     }
 
-    public String getInternalClassName() {
-        return internalClassName;
+    public TypeChooser getTypeChooser() {
+        return typeChooser;
     }
 
-    public InvocationWriter getInvocationWriter() {
-        return invocationWriter;
+    public UnaryExpressionHelper getUnaryExpressionHelper() {
+        if (fastPath) {
+            return fastPathUnaryExpressionHelper;
+        } else {
+            return unaryExpressionHelper;
+        }
     }
 
     public BinaryExpressionHelper getBinaryExpressionHelper() {
@@ -213,89 +212,117 @@ public class WriterController {
         }
     }
 
-    public UnaryExpressionHelper getUnaryExpressionHelper() {
-        if (fastPath) {
-            return fastPathUnaryExpressionHelper;
-        } else {
-            return unaryExpressionHelper;
-        }
-    }
+    //--------------------------------------------------------------------------
 
     public AssertionWriter getAssertionWriter() {
         return assertionWriter;
     }
 
-    public TypeChooser getTypeChooser() {
-        return typeChooser;
+    public CallSiteWriter getCallSiteWriter() {
+        return callSiteWriter;
     }
 
-    public String getInternalBaseClassName() {
-        return internalBaseClassName;
+    public ClosureWriter getClosureWriter() {
+        return closureWriter;
+    }
+
+    public StatementWriter getStatementWriter() {
+        return statementWriter;
+    }
+
+    public InvocationWriter getInvocationWriter() {
+        return invocationWriter;
+    }
+
+    //--------------------------------------------------------------------------
+
+    public String getClassName() {
+        String className;
+        if (!classNode.isInterface() || interfaceClassLoadingClass == null) {
+            className = internalClassName;
+        } else {
+            className = BytecodeHelper.getClassInternalName(interfaceClassLoadingClass);
+        }
+        return className;
+    }
+
+    public ClassNode getClassNode() {
+        return classNode;
     }
 
     public MethodNode getMethodNode() {
         return methodNode;
     }
 
-    public void setMethodNode(MethodNode mn) {
-        methodNode = mn;
-        constructorNode = null;
+    public void setMethodNode(final MethodNode methodNode) {
+        this.methodNode = methodNode;
+        this.constructorNode = null;
     }
 
-    public ConstructorNode getConstructorNode(){
+    public ConstructorNode getConstructorNode() {
         return constructorNode;
     }
 
-    public void setConstructorNode(ConstructorNode cn) {
-        constructorNode = cn;
-        methodNode = null;
+    public void setConstructorNode(final ConstructorNode constructorNode) {
+        this.constructorNode = constructorNode;
+        this.methodNode = null;
     }
 
-    public boolean isNotClinit() {
-        return methodNode == null || !methodNode.getName().equals("<clinit>");
+    public ClassNode getReturnType() {
+        if (methodNode != null) {
+            return methodNode.getReturnType();
+        } else if (constructorNode != null) {
+            return constructorNode.getReturnType();
+        } else {
+            throw new GroovyBugError("I spotted a return that is neither in a method nor in a constructor... I can not handle that");
+        }
     }
 
-    public SourceUnit getSourceUnit() {
-        return sourceUnit;
+    public ClassNode getOutermostClass() {
+        if (outermostClass == null) {
+            List<ClassNode> outers = classNode.getOuterClasses();
+            outermostClass = !outers.isEmpty() ? outers.get(outers.size() - 1) : classNode;
+        }
+        return outermostClass;
     }
 
-    public boolean isStaticContext() {
-        if (compileStack!=null && compileStack.getScope()!=null) {
-            return compileStack.getScope().isInStaticContext();
-        }
-        if (!isInClosure()) return false;
-        if (constructorNode != null) return false;
-        return classNode.isStaticClass() || methodNode.isStatic();
+    public String getInternalClassName() {
+        return internalClassName;
     }
 
-    public boolean isInClosure() {
-        return classNode.getOuterClass() != null
-                && classNode.getSuperClass() == ClassHelper.CLOSURE_TYPE;
+    public String getInternalBaseClassName() {
+        return internalBaseClassName;
     }
 
-    public boolean isInClosureConstructor() {
-        return constructorNode != null
-                && classNode.getOuterClass() != null
-                && classNode.getSuperClass() == ClassHelper.CLOSURE_TYPE;
+    public List<String> getSuperMethodNames() {
+        return superMethodNames;
     }
 
-    public boolean isNotExplicitThisInClosure(boolean implicitThis) {
-        return implicitThis || !isInClosure();
+    public InterfaceHelperClassNode getInterfaceClassLoadingClass() {
+        return interfaceClassLoadingClass;
+    }
+
+    public void setInterfaceClassLoadingClass(final InterfaceHelperClassNode ihc) {
+        interfaceClassLoadingClass = ihc;
     }
 
+    //
+
+    public boolean isStaticContext() {
+        if (compileStack != null && compileStack.getScope() != null) {
+            return compileStack.getScope().isInStaticContext();
+        }
+        if (!isInClosure()) return false;
+        if (isConstructor()) return false;
+        return classNode.isStaticClass() || isStaticMethod();
+    }
 
     public boolean isStaticMethod() {
         return methodNode != null && methodNode.isStatic();
     }
 
-    public ClassNode getReturnType() {
-        if (methodNode != null) {
-            return methodNode.getReturnType();
-        } else if (constructorNode != null) {
-            return constructorNode.getReturnType();
-        } else {
-            throw new GroovyBugError("I spotted a return that is neither in a method nor in a constructor... I can not handle that");
-        }
+    public boolean isNotClinit() {
+        return methodNode == null || !methodNode.getName().equals("<clinit>");
     }
 
     public boolean isStaticConstructor() {
@@ -303,61 +330,35 @@ public class WriterController {
     }
 
     public boolean isConstructor() {
-        return constructorNode!=null;
+        return constructorNode != null;
     }
 
-    /**
-     * @return true if we are in a script body, where all variables declared are no longer
-     *         local variables but are properties
-     */
-    public boolean isInScriptBody() {
-        if (classNode.isScriptBody()) {
-            return true;
-        } else {
-            return classNode.isScript() && methodNode != null && methodNode.getName().equals("run");
-        }
-    }
-
-    public String getClassName() {
-        String className;
-        if (!classNode.isInterface() || interfaceClassLoadingClass == null) {
-            className = internalClassName;
-        } else {
-            className = BytecodeHelper.getClassInternalName(interfaceClassLoadingClass);
-        }
-        return className;
-    }
-
-    public ClassNode getOutermostClass() {
-        if (outermostClass == null) {
-            outermostClass = classNode;
-            while (outermostClass instanceof InnerClassNode) {
-                outermostClass = outermostClass.getOuterClass();
-            }
-        }
-        return outermostClass;
+    public boolean isInClosure() {
+        return classNode.getOuterClass() != null
+            && classNode.getSuperClass() == ClassHelper.CLOSURE_TYPE);
     }
 
-    public GeneratorContext getContext() {
-        return context;
+    public boolean isInClosureConstructor() {
+        return isConstructor() && isInClosure();
     }
 
-    public void setInterfaceClassLoadingClass(InterfaceHelperClassNode ihc) {
-        interfaceClassLoadingClass = ihc;
+    @Deprecated
+    public boolean isNotExplicitThisInClosure(final boolean implicitThis) {
+        return implicitThis || !isInClosure();
     }
 
-    public InterfaceHelperClassNode getInterfaceClassLoadingClass() {
-        return interfaceClassLoadingClass;
+    /**
+     * @return true if we are in a script body, where all variables declared are no longer
+     *         local variables but are properties
+     */
+    public boolean isInScriptBody() {
+        return classNode.isScriptBody() || (classNode.isScript() && methodNode != null && methodNode.getName().equals("run"));
     }
 
     public boolean shouldOptimizeForInt() {
         return optimizeForInt;
     }
 
-    public StatementWriter getStatementWriter() {
-        return statementWriter;
-    }
-
     public void switchToFastPath() {
         fastPath = true;
         resetLineNumber();
@@ -372,27 +373,23 @@ public class WriterController {
         return fastPath;
     }
 
-    public int getBytecodeVersion() {
-        return bytecodeVersion;
-    }
-
     public int getLineNumber() {
         return lineNumber;
     }
 
-    public void setLineNumber(int n) {
-        lineNumber = n;
+    public void setLineNumber(final int lineNumber) {
+        this.lineNumber = lineNumber;
     }
 
     public void resetLineNumber() {
         setLineNumber(-1);
     }
 
-    public int getNextHelperMethodIndex() {
-        return helperMethodIndex++;
+    public int getBytecodeVersion() {
+        return bytecodeVersion;
     }
 
-    public List<String> getSuperMethodNames() {
-        return superMethodNames;
+    public int getNextHelperMethodIndex() {
+        return helperMethodIndex += 1;
     }
 }
diff --git a/src/test/gls/innerClass/InnerClassTest.groovy b/src/test/gls/innerClass/InnerClassTest.groovy
index af8a5f96dc..0d9e17d846 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -203,6 +203,48 @@ final class InnerClassTest {
         '''
     }
 
+    @NotYetImplemented @Test // GROOVY-8423
+    void testPrivateInnerClassHasPrivateModifier() {
+        assertScript '''
+            import static java.lang.reflect.Modifier.*
+
+            class A {
+                private class B {}
+            }
+
+            int modifiers = A.B.modifiers
+            assert isPrivate(modifiers)
+        '''
+    }
+
+    @NotYetImplemented @Test // GROOVY-8423
+    void testProtectedInnerClassHasProtectedModifier() {
+        assertScript '''
+            import static java.lang.reflect.Modifier.*
+
+            class A {
+                protected class B {}
+            }
+
+            int modifiers = A.B.modifiers
+            assert isProtected(modifiers)
+        '''
+    }
+
+    @Test // GROOVY-8423
+    void testPackagePrivateInnerClassHasNoAccessModifier() {
+        assertScript '''
+            import static java.lang.reflect.Modifier.*
+
+            class A {
+                @groovy.transform.PackageScope class B {}
+            }
+
+            int modifiers = A.B.modifiers
+            assert !isPrivate(modifiers) && !isProtected(modifiers) && !isPublic(modifiers)
+        '''
+    }
+
     @Test
     void testStaticInnerClass() {
         assertScript '''
@@ -641,6 +683,19 @@ final class InnerClassTest {
         assert err =~ /Apparent variable 'count' was found in a static scope but doesn't refer to a local variable, static field or class./
     }
 
+    @Test // GROOVY-8050
+    void testUsageOfOuterField13() {
+        assertScript '''
+            class Outer {
+                class Inner {
+                }
+                def p = 1
+            }
+            def i = new Outer.Inner(new Outer())
+            assert i.p == 1
+        '''
+    }
+
     @Test
     void testUsageOfOuterSuperField() {
         assertScript '''
@@ -694,6 +749,29 @@ final class InnerClassTest {
         '''
     }
 
+    @Test // GROOVY-9905
+    void testUsageOfOuterSuperField3() {
+        assertScript '''
+            abstract class A {
+                protected final f = 'foo'
+                abstract static class B {}
+            }
+
+            class C extends A {
+                private class D extends A.B { // B is static inner
+                    String toString() {
+                        f + 'bar' // No such property: f for class: A
+                    }
+                }
+                def m() {
+                    new D().toString()
+                }
+            }
+
+            assert new C().m() == 'foobar'
+        '''
+    }
+
     @Test
     void testUsageOfOuterField_WrongCallToSuper() {
         shouldFail '''
@@ -1170,30 +1248,30 @@ final class InnerClassTest {
         '''
     }
 
-    @Test // GROOVY-5989
-    void testResolveInnerOfSuperType1() {
+    @Test // GROOVY-5754
+    void testResolveInnerOfSuperType() {
         assertScript '''
             interface I { class C { } }
 
             class Outer implements I {
-                static class Inner extends C { }
+                static class Inner extends C {}
             }
 
-            new Outer()
-            new Outer.Inner()
+            print I.C
         '''
     }
 
-    @Test // GROOVY-5754
+    @Test // GROOVY-5989
     void testResolveInnerOfSuperType2() {
         assertScript '''
             interface I { class C { } }
 
             class Outer implements I {
-                static class Inner extends C {}
+                static class Inner extends C { }
             }
 
-            print I.C
+            new Outer()
+            new Outer.Inner()
         '''
     }
 
@@ -1483,13 +1561,12 @@ final class InnerClassTest {
         '''
     }
 
-    @Test // GROOVY-9151
+    @Test // GROOVY-5681, GROOVY-9151
     void testEnclosingMethodIsSet2() {
         assertScript '''
             import groovy.transform.ASTTest
             import org.codehaus.groovy.ast.expr.*
             import static org.codehaus.groovy.classgen.Verifier.*
-            import static org.codehaus.groovy.control.CompilePhase.*
 
             @ASTTest(phase=CLASS_GENERATION, value={
                 def init = node.parameters[0].getNodeMetaData(INITIAL_EXPRESSION)
@@ -1516,7 +1593,6 @@ final class InnerClassTest {
             import org.codehaus.groovy.ast.expr.*
             import org.codehaus.groovy.ast.stmt.*
             import static org.codehaus.groovy.classgen.Verifier.*
-            import static org.codehaus.groovy.control.CompilePhase.*
 
             @ASTTest(phase=CLASS_GENERATION, value={
                 def init = node.parameters[0].getNodeMetaData(INITIAL_EXPRESSION)
@@ -1687,6 +1763,30 @@ final class InnerClassTest {
         '''
     }
 
+    @NotYetImplemented @Test // GROOVY-8274
+    void testMissingMethodHandling() {
+        assertScript '''
+            class A {
+                class B {
+                    def methodMissing(String name, args) {
+                        return name
+                    }
+                }
+
+                def test(Closure c) {
+                    c.resolveStrategy = Closure.DELEGATE_ONLY
+                    c.delegate = new B()
+                    c.call()
+                }
+            }
+
+            def x = new A().test { ->
+                hello() // missing
+            }
+            assert x == 'hello'
+        '''
+    }
+
     @Test // GROOVY-6831
     void testNestedPropertyHandling() {
         assertScript '''


[groovy] 02/02: GROOVY-8762: within closure determined via `GeneratedClosure` interface

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

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

commit d11dc4ad0516cfaa970d95596db523439ca3b07b
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Aug 24 12:24:52 2022 -0500

    GROOVY-8762: within closure determined via `GeneratedClosure` interface
---
 build.bat                                          |  1 +
 .../groovy/classgen/asm/WriterController.java      |  2 +-
 src/test/gls/innerClass/InnerClassTest.groovy      | 30 ++++++++++++++++++++++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/build.bat b/build.bat
new file mode 100644
index 0000000000..8dcd28a383
--- /dev/null
+++ b/build.bat
@@ -0,0 +1 @@
+.\gradlew --max-workers 1 --no-build-cache --no-daemon --no-scan %*
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
index b70e923fe7..2c61d3ad72 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
@@ -335,7 +335,7 @@ public class WriterController {
 
     public boolean isInClosure() {
         return classNode.getOuterClass() != null
-            && classNode.getSuperClass() == ClassHelper.CLOSURE_TYPE);
+            && classNode.implementsInterface(ClassHelper.GENERATED_CLOSURE_Type);
     }
 
     public boolean isInClosureConstructor() {
diff --git a/src/test/gls/innerClass/InnerClassTest.groovy b/src/test/gls/innerClass/InnerClassTest.groovy
index 0d9e17d846..9bff30aada 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -1851,6 +1851,36 @@ final class InnerClassTest {
         '''
     }
 
+    @Test // GROOVY-8762
+    void testReferenceToPrivateFieldInConstructor() {
+        assertScript '''
+            class Outer {
+                static class Inner extends Closure {
+                    private int x, y
+                    Inner(int i) {
+                        super(null, null)
+                        x = i
+                        this.y = i // NullPointerException
+                    }
+                    def doCall(... args) {
+                        return 42
+                    }
+                    int getMaximumNumberOfParameters() {
+                        throw new UnsupportedOperationException()
+                    }
+                    Class[] getParameterTypes() {
+                        throw new UnsupportedOperationException()
+                    }
+                }
+                def makeCallable() {
+                    new Inner(1)
+                }
+            }
+            Number result = new Outer().makeCallable().call()
+            assert result == 42
+        '''
+    }
+
     @Test // GROOVY-7609
     void testReferenceToInitializedThis1() {
         assertScript '''