groovy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sun...@apache.org
Subject [02/21] groovy git commit: GROOVY-8011: @ToString if used with includes='prop1, prop2' could allow the pseudo prop name 'super' as an alternative to using the includeSuper flag (closes #467)
Date Wed, 21 Dec 2016 12:00:44 GMT
GROOVY-8011: @ToString if used with includes='prop1,prop2' could allow the pseudo prop name
'super' as an alternative to using the includeSuper flag (closes #467)


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

Branch: refs/heads/parrot
Commit: 9d2b7fd219ff4ce11a6e75a2c530923f8293844b
Parents: e9e7724
Author: paulk <paulk@asert.com.au>
Authored: Thu Dec 1 14:55:20 2016 +1000
Committer: paulk <paulk@asert.com.au>
Committed: Fri Dec 2 04:34:09 2016 +1000

----------------------------------------------------------------------
 src/main/groovy/transform/ToString.java         | 15 +++----
 .../transform/ToStringASTTransformation.java    | 42 +++++++++++++++-----
 .../transform/ToStringTransformTest.groovy      | 21 ++++++++++
 3 files changed, 61 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/9d2b7fd2/src/main/groovy/transform/ToString.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/ToString.java b/src/main/groovy/transform/ToString.java
index c1e2145..9fc4627 100644
--- a/src/main/groovy/transform/ToString.java
+++ b/src/main/groovy/transform/ToString.java
@@ -273,6 +273,7 @@ public @interface ToString {
      * can be used in addition to an array (using Groovy's literal list notation) of String
values.
      * The default value is a special marker value indicating that no includes are defined;
all fields and/or properties
      * are included if 'includes' remains undefined and 'excludes' is explicitly or implicitly
an empty list.
+     * The special name 'super' can be used instead of using the 'includeSuper' flag.
      */
     String[] includes() default {Undefined.STRING};
 
@@ -328,11 +329,11 @@ public @interface ToString {
      */
     boolean cache() default false;
 
-    /**
-     * Whether to include all fields and/or properties in the generated toString, including
those with names that
-     * are considered internal.
-     *
-     * @since 2.5.0
-     */
-    boolean allNames() default false;
+    /**
+     * Whether to include all fields and/or properties in the generated toString, including
those with names that
+     * are considered internal.
+     *
+     * @since 2.5.0
+     */
+    boolean allNames() default false;
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/9d2b7fd2/src/main/org/codehaus/groovy/transform/ToStringASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/ToStringASTTransformation.java b/src/main/org/codehaus/groovy/transform/ToStringASTTransformation.java
index 5040414..3cba4a5 100644
--- a/src/main/org/codehaus/groovy/transform/ToStringASTTransformation.java
+++ b/src/main/org/codehaus/groovy/transform/ToStringASTTransformation.java
@@ -37,6 +37,7 @@ import org.codehaus.groovy.ast.stmt.Statement;
 import org.codehaus.groovy.ast.tools.BeanUtils;
 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.transform.stc.StaticTypeCheckingSupport;
 
@@ -70,20 +71,23 @@ public class ToStringASTTransformation extends AbstractASTTransformation
{
             boolean includeSuper = memberHasValue(anno, "includeSuper", true);
             boolean includeSuperProperties = memberHasValue(anno, "includeSuperProperties",
true);
             boolean cacheToString = memberHasValue(anno, "cache", true);
+            List<String> excludes = getMemberStringList(anno, "excludes");
+            List<String> includes = getMemberStringList(anno, "includes");
+            if (includes != null && includes.contains("super")) {
+                includeSuper = true;
+            }
             if (includeSuper && cNode.getSuperClass().getName().equals("java.lang.Object"))
{
                 addError("Error during " + MY_TYPE_NAME + " processing: includeSuper=true
but '" + cNode.getName() + "' has no super class.", anno);
             }
             boolean includeNames = memberHasValue(anno, "includeNames", true);
             boolean includeFields = memberHasValue(anno, "includeFields", true);
-            List<String> excludes = getMemberStringList(anno, "excludes");
-            List<String> includes = getMemberStringList(anno, "includes");
             boolean ignoreNulls = memberHasValue(anno, "ignoreNulls", true);
             boolean includePackage = !memberHasValue(anno, "includePackage", false);
             boolean allProperties = !memberHasValue(anno, "allProperties", false);
             boolean allNames = memberHasValue(anno, "allNames", true);
 
             if (!checkIncludeExcludeUndefinedAware(anno, excludes, includes, MY_TYPE_NAME))
return;
-            if (!checkPropertyList(cNode, includes, "includes", anno, MY_TYPE_NAME, includeFields))
return;
+            if (!checkPropertyList(cNode, includes != null ? DefaultGroovyMethods.minus(includes,
"super") : null, "includes", anno, MY_TYPE_NAME, includeFields)) return;
             if (!checkPropertyList(cNode, excludes, "excludes", anno, MY_TYPE_NAME, includeFields))
return;
             createToString(cNode, includeSuper, includeFields, excludes, includes, includeNames,
ignoreNulls, includePackage, cacheToString, includeSuperProperties, allProperties, allNames);
         }
@@ -137,10 +141,23 @@ public class ToStringASTTransformation extends AbstractASTTransformation
{
                 ClassHelper.STRING_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body));
     }
 
+    private static class ToStringElement {
+        ToStringElement(Expression value, String name, boolean canBeSelf) {
+            this.value = value;
+            this.name = name;
+            this.canBeSelf = canBeSelf;
+        }
+
+        Expression value;
+        String name;
+        boolean canBeSelf;
+    }
+
     private static Expression calculateToStringStatements(ClassNode cNode, boolean includeSuper,
boolean includeFields, List<String> excludes, List<String> includes, boolean includeNames,
boolean ignoreNulls, boolean includePackage, boolean includeSuperProperties, boolean allProperties,
BlockStatement body, boolean allNames) {
         // def _result = new StringBuilder()
         final Expression result = varX("_result");
         body.addStatement(declS(result, ctorX(STRINGBUILDER_TYPE)));
+        List<ToStringElement> elements = new ArrayList<ToStringElement>();
 
         // def $toStringFirst = true
         final VariableExpression first = varX("$toStringFirst");
@@ -155,7 +172,7 @@ public class ToStringASTTransformation extends AbstractASTTransformation
{
         for (PropertyNode pNode : pList) {
             if (shouldSkip(pNode.getName(), excludes, includes, allNames)) continue;
             Expression getter = getterThisX(cNode, pNode);
-            appendValue(cNode, body, result, first, getter, pNode.getOriginType(), pNode.getName(),
includeNames, ignoreNulls);
+            elements.add(new ToStringElement(getter, pNode.getName(), canBeSelf(cNode, pNode.getOriginType())));
         }
 
         // append fields if needed
@@ -164,16 +181,18 @@ public class ToStringASTTransformation extends AbstractASTTransformation
{
             fList.addAll(getInstanceNonPropertyFields(cNode));
             for (FieldNode fNode : fList) {
                 if (shouldSkip(fNode.getName(), excludes, includes, allNames)) continue;
-                appendValue(cNode, body, result, first, varX(fNode), fNode.getType(), fNode.getName(),
includeNames, ignoreNulls);
+                elements.add(new ToStringElement(varX(fNode), fNode.getName(), canBeSelf(cNode,
fNode.getType())));
             }
         }
 
         // append super if needed
         if (includeSuper) {
-            appendCommaIfNotFirst(body, result, first);
-            appendPrefix(body, result, "super", includeNames);
             // not through MOP to avoid infinite recursion
-            body.addStatement(appendS(result, callSuperX("toString")));
+            elements.add(new ToStringElement(callSuperX("toString"), "super", false));
+        }
+
+        for (ToStringElement el : elements) {
+            appendValue(body, result, first, el.value, el.name, includeNames, ignoreNulls,
el.canBeSelf);
         }
 
         // wrap up
@@ -183,12 +202,11 @@ public class ToStringASTTransformation extends AbstractASTTransformation
{
         return toString;
     }
 
-    private static void appendValue(ClassNode cNode, BlockStatement body, Expression result,
VariableExpression first, Expression value, ClassNode valueType, String name, boolean includeNames,
boolean ignoreNulls) {
+    private static void appendValue(BlockStatement body, Expression result, VariableExpression
first, Expression value, String name, boolean includeNames, boolean ignoreNulls, boolean canBeSelf)
{
         final BlockStatement thenBlock = new BlockStatement();
         final Statement appendValue = ignoreNulls ? ifS(notNullX(value), thenBlock) : thenBlock;
         appendCommaIfNotFirst(thenBlock, result, first);
         appendPrefix(thenBlock, result, name, includeNames);
-        boolean canBeSelf = StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(valueType,
cNode);
         if (canBeSelf) {
             thenBlock.addStatement(ifElseS(
                     sameX(value, new VariableExpression("this")),
@@ -201,6 +219,10 @@ public class ToStringASTTransformation extends AbstractASTTransformation
{
         body.addStatement(appendValue);
     }
 
+    private static boolean canBeSelf(ClassNode cNode, ClassNode valueType) {
+        return StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(valueType, cNode);
+    }
+
     private static void appendCommaIfNotFirst(BlockStatement body, Expression result, VariableExpression
first) {
         // if ($toStringFirst) $toStringFirst = false else result.append(", ")
         body.addStatement(ifElseS(

http://git-wip-us.apache.org/repos/asf/groovy/blob/9d2b7fd2/src/test/org/codehaus/groovy/transform/ToStringTransformTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/transform/ToStringTransformTest.groovy b/src/test/org/codehaus/groovy/transform/ToStringTransformTest.groovy
index 7f28237..18f5d10 100644
--- a/src/test/org/codehaus/groovy/transform/ToStringTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/ToStringTransformTest.groovy
@@ -448,4 +448,25 @@ class ToStringTransformTest extends GroovyShellTestCase {
         '''
     }
 
+    void testIncludesWithSuper_Groovy8011() {
+        def toString = evaluate("""
+            import groovy.transform.*
+
+            @ToString
+            class Foo {
+                String baz = 'baz'
+            }
+
+            @ToString(includes='super,num,blah', includeNames=true)
+            class Bar extends Foo {
+                String blah = 'blah'
+                int num = 42
+            }
+
+            new Bar().toString()
+        """)
+
+        assert toString.contains('super:Foo(baz)')
+    }
+
 }


Mime
View raw message