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 2019/07/07 09:00:52 UTC

[groovy] 01/02: Override getText() in DeclarationExpression to provide type info

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

commit d3177e870f774a4cc82032eb214218fa063892f5
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Jul 6 19:13:57 2019 -0500

    Override getText() in DeclarationExpression to provide type info
---
 .../groovy/ast/expr/DeclarationExpression.java     | 92 +++++++++++++++-------
 .../ast/expr/DeclarationExpressionTest.groovy      | 69 ++++++++++++++++
 2 files changed, 134 insertions(+), 27 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/expr/DeclarationExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/DeclarationExpression.java
index e5aebda..074a0b4 100644
--- a/src/main/java/org/codehaus/groovy/ast/expr/DeclarationExpression.java
+++ b/src/main/java/org/codehaus/groovy/ast/expr/DeclarationExpression.java
@@ -22,9 +22,11 @@ import org.codehaus.groovy.GroovyBugError;
 import org.codehaus.groovy.ast.GroovyCodeVisitor;
 import org.codehaus.groovy.syntax.Token;
 
+import static org.apache.groovy.ast.tools.ClassNodeUtils.formatTypeName;
+
 /**
  * Represents one or more local variables. Typically it is a single local variable
- * declared by name with an expression like "def foo" or with type "String foo". However, 
+ * declared by name with an expression like "def foo" or with type "String foo". However,
  * the multiple assignment feature allows you to create two or more variables using
  * an expression like: <code>def (x, y) = [1, 2]</code>.
  * <p>
@@ -42,35 +44,35 @@ import org.codehaus.groovy.syntax.Token;
  * is not appropriate is unsafe and will result in a <code>ClassCastException</code>.
  */
 public class DeclarationExpression extends BinaryExpression {
-    
+
     /**
-     * Creates a DeclarationExpression for VariableExpressions like "def x" or "String y = 'foo'". 
+     * Creates a DeclarationExpression for VariableExpressions like "def x" or "String y = 'foo'".
      * @param left
      *      the left hand side of a variable declaration
      * @param operation
      *      the operation, typically an assignment operator
      * @param right
      *      the right hand side of a declaration
-     */ 
+     */
     public DeclarationExpression(VariableExpression left, Token operation, Expression right) {
         super(left,operation,right);
     }
-    
+
     /**
      * Creates a DeclarationExpression for Expressions like "def (x, y) = [1, 2]"
      * @param left
-     *      the left hand side of a declaration. Must be either a VariableExpression or 
-     *      a TupleExpression with at least one element.  
+     *      the left hand side of a declaration. Must be either a VariableExpression or
+     *      a TupleExpression with at least one element.
      * @param operation
      *       the operation, typically an assignment operator
      * @param right
      *       the right hand side of a declaration
-     */ 
+     */
     public DeclarationExpression(Expression left, Token operation, Expression right) {
         super(left,operation,right);
         check(left);
     }
-    
+
     private static void check(Expression left) {
         if (left instanceof VariableExpression) {
             //nothing
@@ -82,6 +84,7 @@ public class DeclarationExpression extends BinaryExpression {
         }
     }
 
+    @Override
     public void visit(GroovyCodeVisitor visitor) {
         visitor.visitDeclarationExpression(this);
     }
@@ -90,7 +93,7 @@ public class DeclarationExpression extends BinaryExpression {
      * This method returns the left hand side of the declaration cast to the VariableExpression type.
      * This is an unsafe method to call. In a multiple assignment statement, the left hand side will
      * be a TupleExpression and a ClassCastException will occur. If you invoke this method then
-     * be sure to invoke isMultipleAssignmentDeclaration() first to check that it is safe to do so. 
+     * be sure to invoke isMultipleAssignmentDeclaration() first to check that it is safe to do so.
      * If that method returns true then this method is safe to call.
      *
      * @return left hand side of normal variable declarations
@@ -103,16 +106,16 @@ public class DeclarationExpression extends BinaryExpression {
                     ? (VariableExpression) leftExpression
                     : null;
     }
-    
+
     /**
      * This method returns the left hand side of the declaration cast to the TupleExpression type.
      * This is an unsafe method to call. In a single assignment statement, the left hand side will
      * be a VariableExpression and a ClassCastException will occur. If you invoke this method then
-     * be sure to invoke isMultipleAssignmentDeclaration() first to check that it is safe to do so. 
-     * If that method returns true then this method is safe to call. 
+     * be sure to invoke isMultipleAssignmentDeclaration() first to check that it is safe to do so.
+     * If that method returns true then this method is safe to call.
      * @return
      *      left hand side of multiple assignment declarations
-     * @throws ClassCastException 
+     * @throws ClassCastException
      *      if the left hand side is not a TupleExpression (and is probably a VariableExpression).
      *
      */
@@ -123,22 +126,58 @@ public class DeclarationExpression extends BinaryExpression {
                     ? (TupleExpression) leftExpression
                     : null;
     }
-    
+
+    @Override
+    public String getText() {
+        StringBuilder text = new StringBuilder();
+
+        if (!isMultipleAssignmentDeclaration()) {
+            VariableExpression v = getVariableExpression();
+            if (v.isDynamicTyped()) {
+                text.append("def");
+            } else {
+                text.append(formatTypeName(v.getType()));
+            }
+            text.append(' ').append(v.getText());
+        } else {
+            TupleExpression t = getTupleExpression();
+            text.append("def (");
+            for (Expression e : t.getExpressions()) {
+                if (e instanceof VariableExpression) {
+                    VariableExpression v = (VariableExpression) e;
+                    if (!v.isDynamicTyped()) {
+                        text.append(formatTypeName(v.getType())).append(' ');
+                    }
+                }
+                text.append(e.getText()).append(", ");
+            }
+            text.setLength(text.length() - 2);
+            text.append(')');
+        }
+        text.append(' ').append(getOperation().getText());
+        text.append(' ').append(getRightExpression().getText());
+
+        return text.toString();
+    }
+
     /**
      * This method sets the leftExpression for this BinaryExpression. The parameter must be
-     * either a VariableExpression or a TupleExpression with one or more elements. 
+     * either a VariableExpression or a TupleExpression with one or more elements.
      * @param leftExpression
-     *      either a VariableExpression or a TupleExpression with one or more elements. 
-     */ 
+     *      either a VariableExpression or a TupleExpression with one or more elements.
+     */
+    @Override
     public void setLeftExpression(Expression leftExpression) {
         check(leftExpression);
         super.setLeftExpression(leftExpression);
     }
-    
+
+    @Override
     public void setRightExpression(Expression rightExpression) {
         super.setRightExpression(rightExpression);
     }
-    
+
+    @Override
     public Expression transformExpression(ExpressionTransformer transformer) {
         Expression ret = new DeclarationExpression(transformer.transform(getLeftExpression()),
                 getOperation(), transformer.transform(getRightExpression()));
@@ -148,18 +187,17 @@ public class DeclarationExpression extends BinaryExpression {
         ret.copyNodeMetaData(this);
         return ret;
     }
-    
+
     /**
-     * This method tells you if this declaration is a multiple assignment declaration, which 
+     * This method tells you if this declaration is a multiple assignment declaration, which
      * has the form "def (x, y) = ..." in Groovy. If this method returns true, then the left
-     * hand side is an ArgumentListExpression. Do not call "getVariableExpression()" on this 
-     * object if this method returns true, instead use "getLeftExpression()". 
+     * hand side is an ArgumentListExpression. Do not call "getVariableExpression()" on this
+     * object if this method returns true, instead use "getLeftExpression()".
      * @return
      *      true if this declaration is a multiple assignment declaration, which means the
-     *      left hand side is an ArgumentListExpression. 
-     */ 
+     *      left hand side is an ArgumentListExpression.
+     */
     public boolean isMultipleAssignmentDeclaration() {
         return getLeftExpression() instanceof TupleExpression;
     }
 }
-
diff --git a/src/test/org/codehaus/groovy/ast/expr/DeclarationExpressionTest.groovy b/src/test/org/codehaus/groovy/ast/expr/DeclarationExpressionTest.groovy
new file mode 100644
index 0000000..caa8961
--- /dev/null
+++ b/src/test/org/codehaus/groovy/ast/expr/DeclarationExpressionTest.groovy
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.codehaus.groovy.ast.expr
+
+import org.junit.Test
+
+final class DeclarationExpressionTest {
+
+    @Test
+    void getTextForBasicDeclaration() {
+        def ast = macro {
+            String greeting = 'hello'
+        }
+
+        assert ast.text == 'String greeting = hello'
+    }
+
+    @Test
+    void getTextForDynamicDeclaration() {
+        def ast = macro {
+            def greeting = 'hello'
+        }
+
+        assert ast.text == 'def greeting = hello'
+    }
+
+    @Test
+    void getTextForMultipleDeclaration() {
+        def ast = macro {
+            def (one, two) = ['1', '2']
+        }
+
+        assert ast.text == 'def (one, two) = [1, 2]'
+    }
+
+    @Test
+    void getTextForMultipleMixedDeclaration() {
+        def ast = macro {
+            def (String one, two) = ['1', '2']
+        }
+
+        assert ast.text == 'def (String one, two) = [1, 2]'
+    }
+
+    @Test
+    void getTextForMultipleTypedDeclaration() {
+        def ast = macro {
+            def (String one, CharSequence two) = ['1', '2']
+        }
+
+        assert ast.text == 'def (String one, CharSequence two) = [1, 2]'
+    }
+}