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 2021/12/20 22:36:58 UTC
[groovy] branch master updated: GROOVY-10428: Refactor: split formatting methods out of InvokerHelper (allow separate control of escapeBackslashes)
This is an automated email from the ASF dual-hosted git repository.
paulk 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 5ac18b7 GROOVY-10428: Refactor: split formatting methods out of InvokerHelper (allow separate control of escapeBackslashes)
5ac18b7 is described below
commit 5ac18b7539766b513e6a642413ed3937e4e21d19
Author: Paul King <pa...@asert.com.au>
AuthorDate: Mon Dec 20 16:10:24 2021 +1000
GROOVY-10428: Refactor: split formatting methods out of InvokerHelper (allow separate control of escapeBackslashes)
---
.../org/codehaus/groovy/runtime/FormatHelper.java | 100 +++++++++++++++------
1 file changed, 74 insertions(+), 26 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/runtime/FormatHelper.java b/src/main/java/org/codehaus/groovy/runtime/FormatHelper.java
index 7283509..6612732 100644
--- a/src/main/java/org/codehaus/groovy/runtime/FormatHelper.java
+++ b/src/main/java/org/codehaus/groovy/runtime/FormatHelper.java
@@ -48,11 +48,15 @@ import static java.lang.Math.max;
* Formatting methods
*/
public class FormatHelper {
+
+ private static final String SQ = "'";
+ private static final String DQ = "\"";
+
private FormatHelper() {}
private static final Object[] EMPTY_ARGS = {};
- // heuristic size to pre-alocate stringbuffers for collections of items
+ // heuristic size to pre-allocate stringbuffers for collections of items
private static final int ITEM_ALLOCATE_SIZE = 5;
public static final MetaClassRegistry metaRegistry = GroovySystem.getMetaClassRegistry();
@@ -82,43 +86,83 @@ public class FormatHelper {
return format(arguments, verbose, -1);
}
+ public static String format(Object arguments, boolean inspect, boolean escapeBackslashes) {
+ return format(arguments, inspect, -1);
+ }
+
public static String format(Object arguments, boolean verbose, int maxSize) {
return format(arguments, verbose, maxSize, false);
}
+ public static String format(Object arguments, boolean inspect, boolean escapeBackslashes, int maxSize) {
+ return format(arguments, inspect, escapeBackslashes, maxSize, false);
+ }
+
+ /**
+ * Output the {@code toString} for the argument(s) with various options to configure.
+ * Configuration options:
+ * <pre>
+ * <dl>
+ * <dt>safe</dt><dd>provides protection if the {@code toString} throws an exception, in which case the exception is swallowed and a dumber default {@code toString} is used</dd>
+ * <dt>maxSize</dt><dd>will attempt to truncate the output to fit approx the maxSize number of characters, -1 means don't truncate</dd>
+ * <dt>inspect</dt><dd>if false, render a value by its {@code toString}, otherwise use its {@code inspect} value</dd>
+ * <dt>escapeBackSlashes</dt><dd>whether characters like tab, newline, etc. are converted to their escaped rendering ('\t', '\n', etc.)</dd>
+ * <dt>verbose</dt><dd>shorthand to turn on both {@code inspect} and {@code escapeBackslashes}</dd>
+ * </dl>
+ * </pre>
+ *
+ * @param options a map of configuration options
+ * @param arguments the argument(s) to calulate the {@code toString} for
+ * @return the string rendering of the argument(s)
+ * @see DefaultGroovyMethods#inspect(Object)
+ */
public static String toString(@NamedParams({
@NamedParam(value = "safe", type = Boolean.class),
@NamedParam(value = "maxSize", type = Integer.class),
- @NamedParam(value = "verbose", type = Boolean.class)
+ @NamedParam(value = "verbose", type = Boolean.class),
+ @NamedParam(value = "escapeBackslashes", type = Boolean.class),
+ @NamedParam(value = "inspect", type = Boolean.class)
}) Map<String, Object> options, Object arguments) {
Object safe = options.get("safe");
if (!(safe instanceof Boolean)) safe = false;
Object maxSize = options.get("maxSize");
if (!(maxSize instanceof Integer)) maxSize = -1;
Object verbose = options.get("verbose");
+ Object inspect = options.get("inspect");
+ Object escapeBackslashes = options.get("escapeBackslashes");
+ if (!(inspect instanceof Boolean)) inspect = false;
+ if (!(escapeBackslashes instanceof Boolean)) escapeBackslashes = false;
if (!(verbose instanceof Boolean)) verbose = false;
- return format(arguments, (boolean) verbose, (int) maxSize, (boolean) safe);
+ if (Boolean.TRUE.equals(verbose)) {
+ inspect = true;
+ escapeBackslashes = true;
+ }
+ return format(arguments, (boolean) inspect, (boolean) escapeBackslashes, (int) maxSize, (boolean) safe);
}
public static String format(Object arguments, boolean verbose, int maxSize, boolean safe) {
+ return format(arguments, verbose, verbose, maxSize, safe);
+ }
+
+ public static String format(Object arguments, boolean inspect, boolean escapeBackslashes, int maxSize, boolean safe) {
if (arguments == null) {
final NullObject nullObject = NullObject.getNullObject();
return (String) nullObject.getMetaClass().invokeMethod(nullObject, "toString", EMPTY_ARGS);
}
if (arguments.getClass().isArray()) {
if (arguments instanceof Object[]) {
- return toArrayString((Object[]) arguments, verbose, maxSize, safe);
+ return toArrayString((Object[]) arguments, inspect, escapeBackslashes, maxSize, safe);
}
if (arguments instanceof char[]) {
return new String((char[]) arguments);
}
// other primitives
- return formatCollection(DefaultTypeTransformation.arrayAsCollection(arguments), verbose, maxSize, safe);
+ return formatCollection(DefaultTypeTransformation.arrayAsCollection(arguments), inspect, escapeBackslashes, maxSize, safe);
}
if (arguments instanceof Range) {
Range range = (Range) arguments;
try {
- if (verbose) {
+ if (inspect) {
return range.inspect();
} else {
return range.toString();
@@ -132,10 +176,10 @@ public class FormatHelper {
}
}
if (arguments instanceof Collection) {
- return formatCollection((Collection) arguments, verbose, maxSize, safe);
+ return formatCollection((Collection) arguments, inspect, escapeBackslashes, maxSize, safe);
}
if (arguments instanceof Map) {
- return formatMap((Map) arguments, verbose, maxSize, safe);
+ return formatMap((Map) arguments, inspect, escapeBackslashes, maxSize, safe);
}
if (arguments instanceof Element) {
try {
@@ -145,14 +189,14 @@ public class FormatHelper {
throw new RuntimeException(e);
}
}
- if (arguments instanceof String) {
- if (verbose) {
- String arg = escapeBackslashes((String) arguments)
- .replace("'", "\\'"); // single quotation mark
- return "'" + arg + "'";
- } else {
- return (String) arguments;
+ if (arguments instanceof CharSequence) {
+ String arg = escapeBackslashes ? escapeBackslashes(arguments.toString()) : arguments.toString();
+ if (arguments instanceof String) {
+ if (!inspect) return arg;
+ return !escapeBackslashes && multiline(arg) ? "'''" + arg + "'''" : SQ + arg.replace(SQ, "\\'") + SQ;
}
+ if (!inspect) return arg;
+ return !escapeBackslashes && multiline(arg) ? "\"\"\"" + arg + "\"\"\"" : DQ + arg.replace(DQ, "\\\"") + DQ;
}
try {
// TODO: For GROOVY-2599 do we need something like below but it breaks other things
@@ -167,6 +211,10 @@ public class FormatHelper {
}
}
+ private static boolean multiline(String s) {
+ return s.contains("\n") || s.contains("\r");
+ }
+
public static String escapeBackslashes(String orig) {
// must replace backslashes first, as the other replacements add backslashes not to be escaped
return orig
@@ -188,7 +236,7 @@ public class FormatHelper {
return "<" + typeName(item) + "@" + hash + ">";
}
- private static String formatMap(Map map, boolean verbose, int maxSize, boolean safe) {
+ private static String formatMap(Map map, boolean inspect, boolean escapeBackslashes, int maxSize, boolean safe) {
if (map.isEmpty()) {
return "[:]";
}
@@ -209,13 +257,13 @@ public class FormatHelper {
if (entry.getKey() == map) {
buffer.append("(this Map)");
} else {
- buffer.append(format(entry.getKey(), verbose, sizeLeft(maxSize, buffer), safe));
+ buffer.append(format(entry.getKey(), inspect, escapeBackslashes, sizeLeft(maxSize, buffer), safe));
}
buffer.append(":");
if (entry.getValue() == map) {
buffer.append("(this Map)");
} else {
- buffer.append(format(entry.getValue(), verbose, sizeLeft(maxSize, buffer), safe));
+ buffer.append(format(entry.getValue(), inspect, escapeBackslashes, sizeLeft(maxSize, buffer), safe));
}
}
buffer.append(']');
@@ -226,7 +274,7 @@ public class FormatHelper {
return maxSize == -1 ? maxSize : max(0, maxSize - buffer.length());
}
- private static String formatCollection(Collection collection, boolean verbose, int maxSize, boolean safe) {
+ private static String formatCollection(Collection collection, boolean inspect, boolean escapeBackslashes, int maxSize, boolean safe) {
StringBuilder buffer = new StringBuilder(ITEM_ALLOCATE_SIZE * collection.size());
buffer.append('[');
boolean first = true;
@@ -243,7 +291,7 @@ public class FormatHelper {
if (item == collection) {
buffer.append("(this Collection)");
} else {
- buffer.append(format(item, verbose, sizeLeft(maxSize, buffer), safe));
+ buffer.append(format(item, inspect, escapeBackslashes, sizeLeft(maxSize, buffer), safe));
}
}
buffer.append(']');
@@ -317,7 +365,7 @@ public class FormatHelper {
* @return the string representation of the map
*/
public static String toMapString(Map arg, int maxSize) {
- return formatMap(arg, false, maxSize, false);
+ return formatMap(arg, false, false, maxSize, false);
}
/**
@@ -350,7 +398,7 @@ public class FormatHelper {
* @return the string representation of the collection
*/
public static String toListString(Collection arg, int maxSize, boolean safe) {
- return formatCollection(arg, false, maxSize, safe);
+ return formatCollection(arg, false, false, maxSize, safe);
}
/**
@@ -361,10 +409,10 @@ public class FormatHelper {
* @return the string representation of the array
*/
public static String toArrayString(Object[] arguments) {
- return toArrayString(arguments, false, -1, false);
+ return toArrayString(arguments, false, false, -1, false);
}
- private static String toArrayString(Object[] array, boolean verbose, int maxSize, boolean safe) {
+ private static String toArrayString(Object[] array, boolean inspect, boolean escapeBackslashes, int maxSize, boolean safe) {
if (array == null) {
return "null";
}
@@ -385,7 +433,7 @@ public class FormatHelper {
if (item == array) {
argBuf.append("(this array)");
} else {
- argBuf.append(format(item, verbose, sizeLeft(maxSize, argBuf), safe));
+ argBuf.append(format(item, inspect, escapeBackslashes, sizeLeft(maxSize, argBuf), safe));
}
}
argBuf.append(']');
@@ -402,7 +450,7 @@ public class FormatHelper {
* @return the string representation of the array
*/
public static String toArrayString(Object[] arguments, int maxSize, boolean safe) {
- return toArrayString(arguments, false, maxSize, safe);
+ return toArrayString(arguments, false, false, maxSize, safe);
}
/**