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()
+ }
}