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 2016/07/29 00:02:30 UTC

[4/7] groovy git commit: GROOVY-7563: InvokerHelper: Safe format recursively and consistently (not just for lists)

GROOVY-7563: InvokerHelper: Safe format recursively and consistently (not just for lists)


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/e28f0014
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/e28f0014
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/e28f0014

Branch: refs/heads/master
Commit: e28f0014d17458a9f964c74c400a390100497966
Parents: ff4c62e
Author: Thibault Kruse <th...@gmx.de>
Authored: Wed Sep 2 19:38:55 2015 +0200
Committer: paulk <pa...@asert.com.au>
Committed: Fri Jul 29 08:36:43 2016 +1000

----------------------------------------------------------------------
 .../codehaus/groovy/runtime/InvokerHelper.java  | 75 +++++++++-----------
 .../runtime/InvokerHelperFormattingTest.groovy  | 20 ++++--
 2 files changed, 50 insertions(+), 45 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/e28f0014/src/main/org/codehaus/groovy/runtime/InvokerHelper.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/runtime/InvokerHelper.java b/src/main/org/codehaus/groovy/runtime/InvokerHelper.java
index 632b79b..53055f0 100644
--- a/src/main/org/codehaus/groovy/runtime/InvokerHelper.java
+++ b/src/main/org/codehaus/groovy/runtime/InvokerHelper.java
@@ -124,7 +124,7 @@ public class InvokerHelper {
     }
 
     public static String toString(Object arguments) {
-        return format(arguments, false);
+        return format(arguments, false, -1, false);
     }
 
     public static String inspect(Object self) {
@@ -573,19 +573,23 @@ public class InvokerHelper {
     }
 
     public static String format(Object arguments, boolean verbose, int maxSize) {
+        return format(arguments, verbose, maxSize, false);
+    }
+
+    public static String format(Object arguments, boolean verbose, 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, false);
+                return toArrayString((Object[]) arguments, verbose, maxSize, safe);
             }
             if (arguments instanceof char[]) {
                 return new String((char[]) arguments);
             }
             // other primitives
-            return formatCollection(DefaultTypeTransformation.arrayAsCollection(arguments), verbose, maxSize);
+            return formatCollection(DefaultTypeTransformation.arrayAsCollection(arguments), verbose, maxSize, safe);
         }
         if (arguments instanceof Range) {
             Range range = (Range) arguments;
@@ -596,10 +600,10 @@ public class InvokerHelper {
             }
         }
         if (arguments instanceof Collection) {
-            return formatCollection((Collection) arguments, verbose, maxSize);
+            return formatCollection((Collection) arguments, verbose, maxSize, safe);
         }
         if (arguments instanceof Map) {
-            return formatMap((Map) arguments, verbose, maxSize);
+            return formatMap((Map) arguments, verbose, maxSize, safe);
         }
         if (arguments instanceof Element) {
             try {
@@ -626,7 +630,15 @@ public class InvokerHelper {
         }
         // TODO: For GROOVY-2599 do we need something like below but it breaks other things
 //        return (String) invokeMethod(arguments, "toString", EMPTY_ARGS);
-        return arguments.toString();
+        try {
+            return arguments.toString();
+        } catch (RuntimeException ex) {
+            if (!safe) throw ex;
+            return handleFormattingException(arguments, ex);
+        } catch (Exception ex) {
+            if (!safe) throw new GroovyRuntimeException(ex);
+            return handleFormattingException(arguments, ex);
+        }
     }
 
     public static String escapeBackslashes(String orig) {
@@ -639,7 +651,18 @@ public class InvokerHelper {
                 .replaceAll("\\f", "\\\\f");     // form feed
     }
 
-    private static String formatMap(Map map, boolean verbose, int maxSize) {
+    private static String handleFormattingException(Object item, Exception ex) {
+
+        String hash;
+        try {
+            hash = Integer.toHexString(item.hashCode());
+        } catch (Exception ignored) {
+            hash = "????";
+        }
+        return "<" + item.getClass().getName() + "@" + hash + ">";
+    }
+
+    private static String formatMap(Map map, boolean verbose, int maxSize, boolean safe) {
         if (map.isEmpty()) {
             return "[:]";
         }
@@ -662,7 +685,7 @@ public class InvokerHelper {
             if (entry.getValue() == map) {
                 buffer.append("(this Map)");
             } else {
-                buffer.append(format(entry.getValue(), verbose, sizeLeft(maxSize, buffer)));
+                buffer.append(format(entry.getValue(), verbose, sizeLeft(maxSize, buffer), safe));
             }
         }
         buffer.append(']');
@@ -673,10 +696,6 @@ public class InvokerHelper {
         return maxSize == -1 ? maxSize : Math.max(0, maxSize - buffer.length());
     }
 
-    private static String formatCollection(Collection collection, boolean verbose, int maxSize) {
-        return formatCollection(collection, verbose, maxSize, false);
-    }
-
     private static String formatCollection(Collection collection, boolean verbose, int maxSize, boolean safe) {
         StringBuilder buffer = new StringBuilder(ITEM_ALLOCATE_SIZE * collection.size());
         buffer.append('[');
@@ -694,20 +713,7 @@ public class InvokerHelper {
             if (item == collection) {
                 buffer.append("(this Collection)");
             } else {
-                String str;
-                try {
-                    str = format(item, verbose, sizeLeft(maxSize, buffer));
-                } catch (Exception ex) {
-                    if (!safe) throw new GroovyRuntimeException(ex);
-                    String hash;
-                    try {
-                        hash = Integer.toHexString(item.hashCode());
-                    } catch (Exception ignored) {
-                        hash = "????";
-                    }
-                    str = "<" + item.getClass().getName() + "@" + hash + ">";
-                }
-                buffer.append(str);
+                buffer.append(format(item, verbose, sizeLeft(maxSize, buffer), safe));
             }
         }
         buffer.append(']');
@@ -752,7 +758,7 @@ public class InvokerHelper {
      * @return the string representation of the map
      */
     public static String toMapString(Map arg, int maxSize) {
-        return formatMap(arg, false, maxSize);
+        return formatMap(arg, false, maxSize, false);
     }
 
     /**
@@ -820,20 +826,7 @@ public class InvokerHelper {
             if (item == collection) {
                 argBuf.append("(this Collection)");
             } else {
-                String str;
-                try {
-                    str = format(item, verbose, sizeLeft(maxSize, argBuf));
-                } catch (Exception ex) {
-                    if (!safe) throw new GroovyRuntimeException(ex);
-                    String hash;
-                    try {
-                        hash = Integer.toHexString(item.hashCode());
-                    } catch (Exception ignored) {
-                        hash = "????";
-                    }
-                    str = "<" + item.getClass().getName() + "@" + hash + ">";
-                }
-                argBuf.append(str);
+                argBuf.append(format(item, verbose, sizeLeft(maxSize, argBuf), safe));
             }
         }
         argBuf.append(']');

http://git-wip-us.apache.org/repos/asf/groovy/blob/e28f0014/src/test/org/codehaus/groovy/runtime/InvokerHelperFormattingTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/runtime/InvokerHelperFormattingTest.groovy b/src/test/org/codehaus/groovy/runtime/InvokerHelperFormattingTest.groovy
index 7c70159..bed83fa 100644
--- a/src/test/org/codehaus/groovy/runtime/InvokerHelperFormattingTest.groovy
+++ b/src/test/org/codehaus/groovy/runtime/InvokerHelperFormattingTest.groovy
@@ -72,6 +72,7 @@ class InvokerHelperFormattingTest extends GroovyTestCase {
         shouldFail(UnsupportedOperationException) {
             InvokerHelper.format(eObject, false)
         }
+        assert InvokerHelper.format(new ExceptionOnToString(), false, -1, true) =~ (ExceptionOnToString.MATCHER)
     }
 
     public void testFormatRanges() {
@@ -79,6 +80,7 @@ class InvokerHelperFormattingTest extends GroovyTestCase {
         assert "a'b..a'd" == InvokerHelper.format('a\'b'..'a\'d', false)
         assert "[1..4]" == InvokerHelper.format([1..4], false)
         assert "[a'b..a'd]" == InvokerHelper.format(['a\'b'..'a\'d'], false)
+
         // verbose
         assert '1..4' == InvokerHelper.format(1..4, true)
         assert "'a\\'b'..'a\\'d'" == InvokerHelper.format('a\'b'..'a\'d', true)
@@ -104,16 +106,16 @@ class InvokerHelperFormattingTest extends GroovyTestCase {
         Object eObject = new ExceptionOnToString()
         assert InvokerHelper.toListString([eObject], -1, true) =~ "\\[${ExceptionOnToString.MATCHER}\\]"
         List list = [[z: eObject]]
-        assert InvokerHelper.toListString(list, -1, true) == '[<java.util.LinkedHashMap@' + Integer.toHexString(list[0].hashCode()) +'>]'
+        assert InvokerHelper.toListString(list, -1, true) =~ "\\[\\[z:${ExceptionOnToString.MATCHER}\\]\\]"
         // even when throwing object is deeply nested, exception handling only happens in Collection
         list = [[x: [y: [z: eObject, a: 2, b: 4]]]]
-        assert InvokerHelper.toListString(list, -1, true) == '[<java.util.LinkedHashMap@' + Integer.toHexString(list[0].hashCode()) + '>]'
+        assert InvokerHelper.toListString(list, -1, true) =~ "\\[\\[x:\\[y:\\[z:${ExceptionOnToString.MATCHER}, a:2, b:4\\]\\]\\]\\]"
 
         list = [[eObject, 1, 2]]
         // safe argument is not passed on recursively
-        assert InvokerHelper.toListString(list, -1, true) == '[<java.util.ArrayList@' + Integer.toHexString(list[0].hashCode()) + '>]'
+        assert InvokerHelper.toListString(list, -1, true) =~ "\\[\\[${ExceptionOnToString.MATCHER}, 1, 2\\]\\]"
         list = [[[[[eObject, 1, 2]]]]]
-        assert InvokerHelper.toListString(list, -1, true) == '[<java.util.ArrayList@' + Integer.toHexString(list[0].hashCode()) + '>]'
+        assert InvokerHelper.toListString(list, -1, true) =~ "\\[\\[\\[\\[\\[${ExceptionOnToString.MATCHER}, 1, 2\\]\\]\\]\\]\\]"
 
         shouldFail(UnsupportedOperationException) {
             InvokerHelper.toListString([eObject], -1, false)
@@ -147,6 +149,8 @@ class InvokerHelperFormattingTest extends GroovyTestCase {
         shouldFail(UnsupportedOperationException) {
             InvokerHelper.format([eObject] as ExceptionOnToString[], false)
         }
+
+        assert InvokerHelper.format([new ExceptionOnToString()] as Object[], false, -1, true) =~ "\\[${ExceptionOnToString.MATCHER}\\]"
     }
 
     public void testToStringMaps() {
@@ -157,12 +161,18 @@ class InvokerHelperFormattingTest extends GroovyTestCase {
     public void testFormatMaps() {
         assert '[:]' == InvokerHelper.format([:], false)
         assert "[a'b:1, 2:b'c]" == InvokerHelper.format(['a\'b':1, 2:'b\'c'], false)
+        assert "['a\\'b':1, 2:'b\\'c']" == InvokerHelper.format(['a\'b':1, 2:'b\'c'], true, -1, true)
 
         Object eObject = new ExceptionOnToString()
         shouldFail(UnsupportedOperationException) {
             InvokerHelper.format([foo: eObject], false)
         }
 
+        assert InvokerHelper.format([foo: eObject], false, -1, true) =~ "\\[foo:${ExceptionOnToString.MATCHER}\\]"
+        assert InvokerHelper.format([foo: eObject], true, -1, true) =~ "\\['foo':${ExceptionOnToString.MATCHER}\\]"
+        Map m = [:]
+        m.put(eObject, eObject)
+        assert InvokerHelper.format(m, false, -1, true) =~ "\\[${ExceptionOnToString.MATCHER}:${ExceptionOnToString.MATCHER}\\]"
     }
 
     public void testToMapString() {
@@ -188,6 +198,8 @@ class InvokerHelperFormattingTest extends GroovyTestCase {
         list.add(['h', 'i'] as String[])
         list.add([10, 11] as int[])
         assert "[key:[[a'b:c'd], [e, f, g], 5..9, fog..fop, [h, i], [10, 11]]]" == InvokerHelper.toString([key: list])
+
+        assert "['key':[['a\\'b':'c\\'d'], ['e', 'f', 'g'], 5..9, 'fog'..'fop', ['h', 'i'], [10, 11]]]" == InvokerHelper.format([key:list], true, -1, false)
     }
 
     public void testToStringSelfContained() {