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 02a8b0edb60ce4843871f6db5936e604731988c1 Author: Eric Milles <[email protected]> AuthorDate: Sun Feb 1 09:53:17 2026 -0600 next step --- src/main/java/groovy/lang/MetaClassImpl.java | 54 +++++++++-------- .../groovy/classgen/EnumCompletionVisitor.java | 38 ------------ .../classgen/InnerClassCompletionVisitor.java | 10 ++-- src/test/groovy/bugs/Groovy7938Bug.groovy | 70 ---------------------- src/test/groovy/gls/enums/EnumTest.groovy | 17 ++++++ .../groovy/gls/innerClass/InnerClassTest.groovy | 53 ++++++++++++++++ 6 files changed, 104 insertions(+), 138 deletions(-) diff --git a/src/main/java/groovy/lang/MetaClassImpl.java b/src/main/java/groovy/lang/MetaClassImpl.java index bf6d78f4c7..6df885bcb3 100644 --- a/src/main/java/groovy/lang/MetaClassImpl.java +++ b/src/main/java/groovy/lang/MetaClassImpl.java @@ -380,7 +380,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass { inheritInterfaceNewMetaMethods(interfaces); - if (isGroovyObject) { + if (isGroovyObject()) { metaMethodIndex.copyMethodsToSuper(); // methods --> methodsForSuper connectMultimethods(superClasses, firstGroovySuper); removeMultimethodsOverloadedWithPrivateMethods(); @@ -662,7 +662,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass { } if (firstGroovy == null) { - return isGroovyObject ? theCachedClass.getCachedSuperClass() : theCachedClass; + return isGroovyObject() ? theCachedClass.getCachedSuperClass() : theCachedClass; } // Closure for closures and GroovyObjectSupport for extenders (including Closure) if (firstGroovy.getTheClass() == GroovyObjectSupport.class) { @@ -1490,13 +1490,15 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass { try { return invokeStaticMissingMethod(theClass, methodName, nonNullArguments); } catch (MissingMethodException missing) { - Class<?> outerClass = theClass.getEnclosingClass(); - if (outerClass != null) { - try { + if (isGroovyObject()) { // GROOVY-11823, et al. + var outerClass = theClass.getEnclosingClass(); + if (outerClass != null && object instanceof Class) { MetaClass omc = registry.getMetaClass(outerClass); - return omc.invokeStaticMethod(outerClass, methodName, arguments); - } catch (MissingMethodException mme) { - missing.addSuppressed(mme); + try { + return omc.invokeStaticMethod(outerClass, methodName, arguments); + } catch (MissingMethodException mme) { + missing.addSuppressed(mme); + } } } throw missing; @@ -1928,13 +1930,15 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass { // try $static_propertyMissing / throw MissingPropertyException return invokeStaticMissingProperty(receiver, name, null, true); } catch (MissingPropertyException missing) { - Class<?> outerClass = theClass.getEnclosingClass(); - if (outerClass != null && sender.isNestmateOf(outerClass)) { - try { - MetaClass omc = registry.getMetaClass(outerClass); - return omc.getProperty(sender, outerClass, name, false, false); - } catch (MissingPropertyException mpe) { - missing.addSuppressed(mpe); + if (isGroovyObject()) { // GROOVY-11823, et al. + var outerClass = theClass.getEnclosingClass(); + if (outerClass != null && sender.isNestmateOf(outerClass)) { + try { + MetaClass omc = registry.getMetaClass(outerClass); + return omc.getProperty(sender, outerClass, name, false, false); + } catch (MissingPropertyException mpe) { + missing.addSuppressed(mpe); + } } } throw missing; @@ -2082,7 +2086,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass { } catch (NoSuchFieldException e) { } } - return omc.getProperty(outerClass, outer, name, false, false); + return omc.getProperty(outerClass, outer, getName(), false, false); } catch (MissingPropertyException suppressed) { mpe.addSuppressed(suppressed); } catch (Throwable t) { @@ -2837,14 +2841,16 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass { try { invokeStaticMissingProperty(object, name, newValue, false); } catch (MissingPropertyException missing) { - Class<?> outerClass = theClass.getEnclosingClass(); - if (outerClass != null && sender.isNestmateOf(outerClass)) { - try { - MetaClass omc = registry.getMetaClass(outerClass); - omc.setProperty(sender, outerClass, name, newValue, false, false); - return; - } catch (MissingPropertyException mpe) { - missing.addSuppressed(mpe); + if (isGroovyObject()) { // GROOVY-11823, et al. + var outerClass = theClass.getEnclosingClass(); + if (outerClass != null && sender.isNestmateOf(outerClass)) { + try { + MetaClass omc = registry.getMetaClass(outerClass); + omc.setProperty(sender, outerClass, name, newValue, false, false); + return; + } catch (MissingPropertyException mpe) { + missing.addSuppressed(mpe); + } } } throw missing; diff --git a/src/main/java/org/codehaus/groovy/classgen/EnumCompletionVisitor.java b/src/main/java/org/codehaus/groovy/classgen/EnumCompletionVisitor.java index 87b8fa71d3..cd12c3b993 100644 --- a/src/main/java/org/codehaus/groovy/classgen/EnumCompletionVisitor.java +++ b/src/main/java/org/codehaus/groovy/classgen/EnumCompletionVisitor.java @@ -53,7 +53,6 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.params; import static org.codehaus.groovy.transform.sc.StaticCompilationVisitor.isStaticallyCompiled; import static org.objectweb.asm.Opcodes.ACC_PRIVATE; import static org.objectweb.asm.Opcodes.ACC_PUBLIC; -import static org.objectweb.asm.Opcodes.ACC_STATIC; import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC; /** @@ -222,19 +221,6 @@ public class EnumCompletionVisitor extends ClassCodeVisitorSupport { } ); - visitor.addMissingHandler( - innerClass, - "$static_methodMissing", - ACC_PUBLIC | ACC_STATIC, - OBJECT_TYPE, - params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, "args")), - (methodBody, parameters) -> { - InnerClassVisitorHelper.setMethodDispatcherCode(methodBody, classX(outerClass), parameters); - } - ); - - // - visitor.addMissingHandler( innerClass, "propertyMissing", @@ -246,19 +232,6 @@ public class EnumCompletionVisitor extends ClassCodeVisitorSupport { } ); - visitor.addMissingHandler( - innerClass, - "$static_propertyMissing", - ACC_PUBLIC | ACC_STATIC, - OBJECT_TYPE, - params(param(STRING_TYPE, "name")), - (methodBody, parameters) -> { - InnerClassVisitorHelper.setPropertyGetterDispatcher(methodBody, classX(outerClass), parameters); - } - ); - - // - visitor.addMissingHandler( innerClass, "propertyMissing", @@ -269,16 +242,5 @@ public class EnumCompletionVisitor extends ClassCodeVisitorSupport { InnerClassVisitorHelper.setPropertySetterDispatcher(methodBody, classX(outerClass), parameters); } ); - - visitor.addMissingHandler( - innerClass, - "$static_propertyMissing", - ACC_PUBLIC | ACC_STATIC, - VOID_TYPE, - params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, "value")), - (methodBody, parameters) -> { - InnerClassVisitorHelper.setPropertySetterDispatcher(methodBody, classX(outerClass), parameters); - } - ); } } diff --git a/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java b/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java index 0ea8845ba2..3217289209 100644 --- a/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java +++ b/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java @@ -54,6 +54,7 @@ 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; @@ -64,7 +65,6 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX; import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX; import static org.codehaus.groovy.ast.tools.GeneralUtils.param; import static org.codehaus.groovy.ast.tools.GeneralUtils.params; -import static org.codehaus.groovy.ast.tools.GeneralUtils.propX; import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt; import static org.codehaus.groovy.ast.tools.GeneralUtils.throwS; import static org.codehaus.groovy.ast.tools.GeneralUtils.tryCatchS; @@ -110,7 +110,7 @@ public class InnerClassCompletionVisitor extends InnerClassVisitorHelper { } if (node instanceof InnerClassNode innerClass) { - thisField = node.getField("this$0"); + thisField = node.getDeclaredField("this$0"); if (innerClass.getVariableScope() == null && node.getDeclaredConstructors().isEmpty()) { // add empty default constructor addGeneratedConstructor(innerClass, ACC_PUBLIC, Parameter.EMPTY_ARRAY, null, null); @@ -319,14 +319,12 @@ public class InnerClassCompletionVisitor extends InnerClassVisitorHelper { Parameter catchParam = param(OBJECT_TYPE, "notFound"); // dummy type ClassNode exceptionT; Expression newException; - Expression selfType = varX("this"); - if ((modifiers & ACC_STATIC) == 0) selfType = callX(selfType, "getClass"); if (methodName.endsWith("methodMissing")) { exceptionT = ClassHelper.make(groovy.lang.MissingMethodException.class); - newException = ctorX(exceptionT, args(propX(varX(catchParam),"method"), selfType, propX(varX(catchParam),"arguments"))); + 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(propX(varX(catchParam), "property"), selfType, propX(varX(catchParam), "cause"))); + newException = ctorX(exceptionT, args(callX(varX(catchParam),"getProperty"), callThisX("getClass"), callX(varX(catchParam),"getCause"))); } catchParam.setType(exceptionT); catchParam.setOriginType(exceptionT); diff --git a/src/test/groovy/bugs/Groovy7938Bug.groovy b/src/test/groovy/bugs/Groovy7938Bug.groovy deleted file mode 100644 index a7476f4f60..0000000000 --- a/src/test/groovy/bugs/Groovy7938Bug.groovy +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package bugs - -import groovy.test.GroovyTestCase - -class Groovy7938Bug extends GroovyTestCase { - void testClassUsageInInterfaceDef() { - assertScript """ - class Outer { - static Integer fooCount = 0 - Integer barCount = 0 - static void incFoo() { fooCount++ } - void incBar() { barCount++ } - static class Nested { - static void nestedIncFoo() { incFoo() } - static class NestedNested { - static void nestedNestedIncFoo() { incFoo() } - } - } - Inner innerFactory() { new Inner() } - class Inner { - InnerInner innerInnerFactory() { new InnerInner() } - void innerIncFoo() { incFoo() } - static void staticInnerIncFoo() { incFoo() } - class InnerInner { - void innerInnerIncFoo() { incFoo() } - static void staticInnerInnerIncFoo() { incFoo() } - } - } - } - Outer.incFoo() - Outer.Nested.nestedIncFoo() - Outer.Nested.NestedNested.nestedNestedIncFoo() - assert Outer.fooCount == 3 - new Outer().with { - incBar() - incFoo() - innerFactory().with { - incBar() - innerIncFoo() - staticInnerIncFoo() - innerInnerFactory().with { - incBar() - innerInnerIncFoo() - staticInnerInnerIncFoo() - } - } - assert barCount == 3 - assert fooCount == 8 - } - """ - } -} diff --git a/src/test/groovy/gls/enums/EnumTest.groovy b/src/test/groovy/gls/enums/EnumTest.groovy index d0e1255d3d..c490ea04d6 100644 --- a/src/test/groovy/gls/enums/EnumTest.groovy +++ b/src/test/groovy/gls/enums/EnumTest.groovy @@ -338,6 +338,23 @@ class EnumTest extends CompilableTestSupport { ''' } + void testInnerEnumInitWithUnqualifiedOuterClassValue() { + assertScript ''' + class C { + private static int ONE() { 1 } + enum E { + FOO(1 + ONE()) + final value + E(value) { + this.value = value + } + } + } + + assert C.E.FOO.value == 2 + ''' + } + // GROOVY-3693 void testStaticFieldInitValuesInAStaticBlock() { // trigger enum class load to test it - asserts are present in the enum diff --git a/src/test/groovy/gls/innerClass/InnerClassTest.groovy b/src/test/groovy/gls/innerClass/InnerClassTest.groovy index 2aac220e3f..a4fdb45a7d 100644 --- a/src/test/groovy/gls/innerClass/InnerClassTest.groovy +++ b/src/test/groovy/gls/innerClass/InnerClassTest.groovy @@ -1244,6 +1244,59 @@ final class InnerClassTest { ''' } + // GROOVY-7938 + @Test + void testUsageOfOuterMethod9() { + assertScript ''' + class Outer { + Integer barCount = 0 + static Integer fooCount = 0 + void incBar() { barCount++ } + static void incFoo() { fooCount++ } + Inner innerFactory() { new Inner() } + + static class Nested { + static void nestedIncFoo() { incFoo() } + static class NestedNested { + static void nestedNestedIncFoo() { incFoo() } + } + } + class Inner { + void innerIncFoo() { incFoo() } + static void staticInnerIncFoo() { incFoo() } + InnerInner innerInnerFactory() { new InnerInner() } + + class InnerInner { + void innerInnerIncFoo() { incFoo() } + static void staticInnerInnerIncFoo() { incFoo() } + } + } + } + + Outer.incFoo() + Outer.Nested.nestedIncFoo() + Outer.Nested.NestedNested.nestedNestedIncFoo() + assert Outer.fooCount == 3 + + new Outer().with { + incBar() + incFoo() + innerFactory().with { + incBar() + innerIncFoo() + staticInnerIncFoo() + innerInnerFactory().with { + incBar() + innerInnerIncFoo() + staticInnerInnerIncFoo() + } + } + assert barCount == 3 + assert fooCount == 8 + } + ''' + } + @Test void testUsageOfOuterMethodOverridden() { assertScript '''
