You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2022/07/22 06:53:36 UTC
[groovy] 02/02: GROOVY-10697: @ToString throws an NPE for POJO with null field
This is an automated email from the ASF dual-hosted git repository.
paulk pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 1602f63d11db8edb1f2848295fa9d9a305699567
Author: Paul King <pa...@asert.com.au>
AuthorDate: Thu Jul 21 16:42:59 2022 +1000
GROOVY-10697: @ToString throws an NPE for POJO with null field
---
.../java/org/apache/groovy/ast/tools/MethodCallUtils.java | 7 +++++++
.../groovy/transform/ToStringASTTransformation.java | 7 ++++---
.../groovy/transform/ToStringTransformTest.groovy | 15 +++++++++++++++
.../groovy/console/ui/AstNodeToScriptAdapterTest.groovy | 2 +-
4 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/src/main/java/org/apache/groovy/ast/tools/MethodCallUtils.java b/src/main/java/org/apache/groovy/ast/tools/MethodCallUtils.java
index 6b06eb1136..820cbc6a4e 100644
--- a/src/main/java/org/apache/groovy/ast/tools/MethodCallUtils.java
+++ b/src/main/java/org/apache/groovy/ast/tools/MethodCallUtils.java
@@ -23,7 +23,10 @@ import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.stmt.Statement;
import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.isNullX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ternaryX;
/**
* Utility class for commonly called methods
@@ -43,4 +46,8 @@ public class MethodCallUtils {
toString.setImplicitThis(false);
return toString;
}
+
+ public static Expression maybeNullToStringX(final Expression object) {
+ return ternaryX(isNullX(object), constX("null"), toStringX(object));
+ }
}
diff --git a/src/main/java/org/codehaus/groovy/transform/ToStringASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/ToStringASTTransformation.java
index 1924ea6864..759201e10d 100644
--- a/src/main/java/org/codehaus/groovy/transform/ToStringASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/ToStringASTTransformation.java
@@ -38,7 +38,7 @@ import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.FormatHelper;
import org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport;
import java.util.ArrayList;
@@ -49,6 +49,7 @@ import java.util.Set;
import static org.apache.groovy.ast.tools.ClassNodeUtils.addGeneratedMethod;
import static org.apache.groovy.ast.tools.MethodCallUtils.appendS;
+import static org.apache.groovy.ast.tools.MethodCallUtils.maybeNullToStringX;
import static org.apache.groovy.ast.tools.MethodCallUtils.toStringX;
import static org.codehaus.groovy.ast.ClassHelper.make;
import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS;
@@ -82,7 +83,7 @@ public class ToStringASTTransformation extends AbstractASTTransformation {
static final ClassNode MY_TYPE = make(MY_CLASS);
static final String MY_TYPE_NAME = "@" + MY_TYPE.getNameWithoutPackage();
private static final ClassNode STRINGBUILDER_TYPE = make(StringBuilder.class);
- private static final ClassNode INVOKER_TYPE = make(InvokerHelper.class);
+ private static final ClassNode FORMAT_TYPE = make(FormatHelper.class);
private static final ClassNode POJO_TYPE = make(POJO.class);
private static final String TO_STRING = "toString";
private static final String UNDER_TO_STRING = "_toString";
@@ -272,7 +273,7 @@ public class ToStringASTTransformation extends AbstractASTTransformation {
final Statement appendValue = ignoreNulls ? ifS(notNullX(value), thenBlock) : thenBlock;
appendCommaIfNotFirst(thenBlock, result, first, delims);
appendPrefix(thenBlock, result, name, includeNames, delims);
- Expression toString = pojo ? toStringX(value) : callX(INVOKER_TYPE, TO_STRING, value);
+ Expression toString = pojo ? maybeNullToStringX(value) : callX(FORMAT_TYPE, TO_STRING, value);
if (canBeSelf) {
thenBlock.addStatement(ifElseS(
sameX(value, varX("this")),
diff --git a/src/test/org/codehaus/groovy/transform/ToStringTransformTest.groovy b/src/test/org/codehaus/groovy/transform/ToStringTransformTest.groovy
index 12eb461640..9625ab5cdf 100644
--- a/src/test/org/codehaus/groovy/transform/ToStringTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/ToStringTransformTest.groovy
@@ -514,4 +514,19 @@ class ToStringTransformTest extends GroovyShellTestCase {
"""
}
+ // GROOVY-10697
+ void testToStringOnPojoWithNullField() {
+ assertScript '''
+ import groovy.transform.*
+
+ @ToString(pojo=true)
+ @CompileStatic
+ class Clazz {
+ String field = null
+ }
+
+ assert new Clazz().toString() == 'Clazz(null)'
+ '''
+ }
+
}
diff --git a/subprojects/groovy-console/src/test/groovy/groovy/console/ui/AstNodeToScriptAdapterTest.groovy b/subprojects/groovy-console/src/test/groovy/groovy/console/ui/AstNodeToScriptAdapterTest.groovy
index b8a9cec72b..136862307a 100644
--- a/subprojects/groovy-console/src/test/groovy/groovy/console/ui/AstNodeToScriptAdapterTest.groovy
+++ b/subprojects/groovy-console/src/test/groovy/groovy/console/ui/AstNodeToScriptAdapterTest.groovy
@@ -579,7 +579,7 @@ final class AstNodeToScriptAdapterTest extends GroovyTestCase {
String result = compileToScript(script, CompilePhase.CANONICALIZATION)
// we had problems with the ast transform passing a VariableExpression as StaticMethodCallExpression arguments
- assert result.contains("_result.append(org.codehaus.groovy.runtime.InvokerHelper.toString(this.getWhen())")
+ assert result.contains("_result.append(org.codehaus.groovy.runtime.FormatHelper.toString(this.getWhen())")
}
void testAtImmutableClassWithProperties() {