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 <[email protected]>
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 '''

Reply via email to