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

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


The following commit(s) were added to refs/heads/master by this push:
     new 7cc5f9a4e2 GROOVY-3803, GROOVY-4487, GROOVY-8875: `class` or 
`metaClass` for `null`
7cc5f9a4e2 is described below

commit 7cc5f9a4e2ea7e5a776f7665a38fb059ec645854
Author: Eric Milles <[email protected]>
AuthorDate: Tue Oct 17 17:06:53 2023 -0500

    GROOVY-3803, GROOVY-4487, GROOVY-8875: `class` or `metaClass` for `null`
---
 .../groovy/runtime/DefaultGroovyMethods.java       | 17 +++++-------
 .../org/codehaus/groovy/runtime/NullObject.java    | 11 ++++----
 .../codehaus/groovy/runtime/NullObjectTest.groovy  | 30 +++++++++++++++++++++-
 3 files changed, 41 insertions(+), 17 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java 
b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
index d30768d292..abe244f857 100644
--- a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+++ b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
@@ -11502,16 +11502,13 @@ public class DefaultGroovyMethods extends 
DefaultGroovyMethodsSupport {
      * @since 1.6.0
      */
     public static void setMetaClass(Class self, MetaClass metaClass) {
-        final MetaClassRegistry metaClassRegistry = 
GroovySystem.getMetaClassRegistry();
-        if (metaClass == null)
-            metaClassRegistry.removeMetaClass(self);
-        else {
-            if (metaClass instanceof HandleMetaClass) {
-                metaClassRegistry.setMetaClass(self, 
((HandleMetaClass)metaClass).getAdaptee());
-            } else {
-                metaClassRegistry.setMetaClass(self, metaClass);
-            }
-            if (NullObject.class.equals(self)) {
+        if (metaClass == null) {
+            GroovySystem.getMetaClassRegistry().removeMetaClass(self);
+        } else {
+            MetaClass mc = metaClass instanceof HandleMetaClass
+              ? ((HandleMetaClass)metaClass).getAdaptee() : metaClass;
+            GroovySystem.getMetaClassRegistry().setMetaClass(self,mc);
+            if (NullObject.class.equals(self)) { // GROOVY-3803
                 NullObject.getNullObject().setMetaClass(metaClass);
             }
         }
diff --git a/src/main/java/org/codehaus/groovy/runtime/NullObject.java 
b/src/main/java/org/codehaus/groovy/runtime/NullObject.java
index fd8e62adaa..0d24a258f0 100644
--- a/src/main/java/org/codehaus/groovy/runtime/NullObject.java
+++ b/src/main/java/org/codehaus/groovy/runtime/NullObject.java
@@ -29,7 +29,7 @@ public class NullObject extends GroovyObjectSupport {
     private static final NullObject INSTANCE = new NullObject();
 
     /**
-     * get the NullObject reference
+     * Returns the NullObject reference.
      *
      * @return the null object
      */
@@ -37,9 +37,6 @@ public class NullObject extends GroovyObjectSupport {
         return INSTANCE;
     }
 
-    /**
-     * private constructor
-     */
     private NullObject() {
         if (INSTANCE != null) {
             throw new RuntimeException("Can't instantiate NullObject. Use 
NullObject.getNullObject()");
@@ -85,18 +82,20 @@ public class NullObject extends GroovyObjectSupport {
     }
 
     /**
-     * Tries to get a property on null, which will always fail.
+     * Tries to get a property on null, which fails except for "class" and 
"metaClass".
      *
      * @return never
      * @throws NullPointerException
      */
     @Override
     public Object getProperty(final String name) {
+        if ("class".equals(name)) return getClass(); // GROOVY-4487
+        if ("metaClass".equals(name)) return 
DefaultGroovyMethods.getMetaClass(this);
         throw new NullPointerException("Cannot get property '" + name + "' on 
null object");
     }
 
     /**
-     * Tries to set a property on null, which will always fail
+     * Tries to set a property on null, which fails.
      *
      * @throws NullPointerException
      */
diff --git a/src/test/org/codehaus/groovy/runtime/NullObjectTest.groovy 
b/src/test/org/codehaus/groovy/runtime/NullObjectTest.groovy
index bb0bf6c560..26a25d3a9c 100644
--- a/src/test/org/codehaus/groovy/runtime/NullObjectTest.groovy
+++ b/src/test/org/codehaus/groovy/runtime/NullObjectTest.groovy
@@ -81,6 +81,15 @@ final class NullObjectTest {
         assert nil.toString() == 'null'
     }
 
+    // GROOVY-4487
+    @Test
+    void testGetClass() {
+        def nil = null
+        assert nil.class === nil.getClass()
+        assert nil.class.simpleName == 'NullObject'
+        assert nil.getClass().getSimpleName() == 'NullObject'
+    }
+
     @Test
     void testGetProperty() {
         def nil = null
@@ -245,8 +254,9 @@ final class NullObjectTest {
         }
     }
 
+    // GROOVY-3803
     @Test
-    void testMetaClass() {
+    void testMetaClass1() {
         def oldMC = NullObject.getMetaClass()
         try {
             NullObject.metaClass.hello = { -> 'Greeting from null' }
@@ -255,4 +265,22 @@ final class NullObjectTest {
             NullObject.setMetaClass(oldMC)
         }
     }
+
+    // GROOVY-8875
+    @Test
+    void testMetaClass2() {
+        def oldMC = NullObject.getMetaClass()
+        try {
+            NullObject.metaClass.toString = { -> 'bar' }
+            assert ('foo' + null) == 'foobar'
+        } finally {
+            NullObject.setMetaClass(oldMC)
+        }
+    }
+
+    @Test
+    void testMetaClass3() {
+        assert null.metaClass == null.getMetaClass()
+        assert null.metaClass.adaptee === null.getMetaClass().getAdaptee()
+    }
 }

Reply via email to