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 6b8ced28ed3fb8b1956a725994ba1e311103cbe3 Author: Eric Milles <[email protected]> AuthorDate: Sat Jan 24 11:08:04 2026 -0600 4737, 4862, 5875, 6580, 6581 --- src/main/java/groovy/lang/MetaClassImpl.java | 103 +++++++++++++++++++-- .../classgen/InnerClassCompletionVisitor.java | 30 ------ 2 files changed, 97 insertions(+), 36 deletions(-) diff --git a/src/main/java/groovy/lang/MetaClassImpl.java b/src/main/java/groovy/lang/MetaClassImpl.java index 066ee504b6..bf6d78f4c7 100644 --- a/src/main/java/groovy/lang/MetaClassImpl.java +++ b/src/main/java/groovy/lang/MetaClassImpl.java @@ -1487,7 +1487,20 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass { } } - return invokeStaticMissingMethod(theClass, methodName, nonNullArguments); + try { + return invokeStaticMissingMethod(theClass, methodName, nonNullArguments); + } catch (MissingMethodException missing) { + Class<?> outerClass = theClass.getEnclosingClass(); + if (outerClass != null) { + try { + MetaClass omc = registry.getMetaClass(outerClass); + return omc.invokeStaticMethod(outerClass, methodName, arguments); + } catch (MissingMethodException mme) { + missing.addSuppressed(mme); + } + } + throw missing; + } } private Object invokeStaticMissingMethod(final Class<?> sender, final String methodName, final Object[] arguments) { @@ -1495,7 +1508,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass { if (metaMethod != null) { return metaMethod.invoke(sender, new Object[]{methodName, arguments}); } - throw new MissingMethodException(methodName, sender, arguments, true); + throw new MissingMethodExceptionNoStack(methodName, sender, arguments, true); } private MetaMethod pickStaticMethod(final String methodName, final Class<?>[] argumentTypes) throws MethodSelectionException { @@ -1876,16 +1889,55 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass { //---------------------------------------------------------------------- // missing property protocol //---------------------------------------------------------------------- - return invokeMissingProperty(object, name, null, true); + try { + return invokeMissingProperty(object, name, null, true); + } catch (MissingPropertyException mpe) { + if (false && sender == theClass) { + Class<?> outerClass = theClass.getEnclosingClass(); + if (outerClass != null) { + MetaClass omc = registry.getMetaClass(outerClass); + try { + Object outer = outerClass; + if ((theClass.getModifiers() & Opcodes.ACC_STATIC) == 0) { + try { + theClass.getDeclaredField("this$0"); + outer = getAttribute(object, "this$0"); + } catch (NoSuchFieldException e) { + } + } + return omc.getProperty(outerClass, outer, name, false, false); + } catch (MissingPropertyException suppressed) { + mpe.addSuppressed(suppressed); + } catch (Throwable t) { + t.printStackTrace(); + } + } + } + throw mpe; + } } private Object getClassProperty(final Class<?> sender, final Class<?> receiver, final String name) throws MissingPropertyException { try { MetaClass cmc = registry.getMetaClass(Class.class); return cmc.getProperty(Class.class, receiver, name, false, false); - } catch (MissingPropertyException ignore) { + } catch (MissingPropertyException ignored) { + } + + try { // 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); + } + } + throw missing; } } @@ -2014,7 +2066,32 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass { return new ReadOnlyMetaProperty(name) { @Override public Object getProperty(final Object receiver) { - return invokeMissingProperty(receiver, getName(), null, true); + try { + return invokeMissingProperty(receiver, getName(), null, true); + } catch (MissingPropertyException mpe) { + if (false && sender == theClass) { + Class<?> outerClass = theClass.getEnclosingClass(); + if (outerClass != null) { + MetaClass omc = registry.getMetaClass(outerClass); + try { + Object outer = outerClass; + if ((theClass.getModifiers() & Opcodes.ACC_STATIC) == 0) { + try { + theClass.getDeclaredField("this$0"); + outer = getAttribute(receiver, "this$0"); + } catch (NoSuchFieldException e) { + } + } + return omc.getProperty(outerClass, outer, name, false, false); + } catch (MissingPropertyException suppressed) { + mpe.addSuppressed(suppressed); + } catch (Throwable t) { + t.printStackTrace(); + } + } + } + throw mpe; + } } }; } @@ -2757,7 +2834,21 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass { if (!isStatic) { invokeMissingProperty(object, name, newValue, false); } else { - invokeStaticMissingProperty(object, name, newValue, false); + 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); + } + } + throw missing; + } } } diff --git a/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java b/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java index fb70379836..0ea8845ba2 100644 --- a/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java +++ b/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java @@ -251,16 +251,6 @@ public class InnerClassCompletionVisitor extends InnerClassVisitorHelper { } ); - addMissingHandler(node, - "$static_methodMissing", - ACC_PUBLIC | ACC_STATIC, - OBJECT_TYPE, - params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, "args")), - (methodBody, parameters) -> { - setMethodDispatcherCode(methodBody, classX(outerClass), parameters); - } - ); - 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)); @@ -292,16 +282,6 @@ public class InnerClassCompletionVisitor extends InnerClassVisitorHelper { } ); - addMissingHandler(node, - "$static_propertyMissing", - ACC_PUBLIC | ACC_STATIC, - VOID_TYPE, - params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, "value")), - (methodBody, parameters) -> { - setPropertySetterDispatcher(methodBody, classX(outerClass), parameters); - } - ); - addMissingHandler(node, "propertyMissing", ACC_PUBLIC, @@ -325,16 +305,6 @@ public class InnerClassCompletionVisitor extends InnerClassVisitorHelper { } } ); - - addMissingHandler(node, - "$static_propertyMissing", - ACC_PUBLIC | ACC_STATIC, - OBJECT_TYPE, - params(param(STRING_TYPE, "name")), - (methodBody, parameters) -> { - setPropertyGetterDispatcher(methodBody, classX(outerClass), parameters); - } - ); } /* */ void addMissingHandler(final InnerClassNode innerClass, final String methodName, final int modifiers,
