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 2020/02/21 05:05:57 UTC

[groovy] 02/03: minor refactor: remove duplicate code

This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit ebdd0fce904c430f94d62b40592dbafd46d7cfbf
Author: Paul King <pa...@asert.com.au>
AuthorDate: Wed Feb 19 10:44:31 2020 +1000

    minor refactor: remove duplicate code
---
 .../groovy/ast/tools/ConstructorNodeUtils.java     | 60 ++++++++++++++++++++++
 .../apache/groovy/ast/tools/MethodNodeUtils.java   | 26 ++++++++++
 .../java/org/codehaus/groovy/ast/ClassNode.java    | 12 +----
 .../codehaus/groovy/ast/tools/GeneralUtils.java    | 24 +++++++--
 .../classgen/InnerClassCompletionVisitor.java      | 42 ++++-----------
 .../org/codehaus/groovy/classgen/Verifier.java     | 21 ++------
 .../tools/javac/JavaAwareResolveVisitor.java       | 25 ++-------
 .../groovy/tools/javac/JavaStubGenerator.java      | 26 ++--------
 .../transform/trait/TraitASTTransformation.java    | 12 +----
 9 files changed, 131 insertions(+), 117 deletions(-)

diff --git a/src/main/java/org/apache/groovy/ast/tools/ConstructorNodeUtils.java b/src/main/java/org/apache/groovy/ast/tools/ConstructorNodeUtils.java
new file mode 100644
index 0000000..87851f4
--- /dev/null
+++ b/src/main/java/org/apache/groovy/ast/tools/ConstructorNodeUtils.java
@@ -0,0 +1,60 @@
+/*
+ *  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.apache.groovy.ast.tools;
+
+import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.ast.stmt.ExpressionStatement;
+import org.codehaus.groovy.ast.stmt.Statement;
+
+import java.util.List;
+
+/**
+ * Utility class for working with ConstructorNodes
+ */
+public class ConstructorNodeUtils {
+    private ConstructorNodeUtils() { }
+
+    /**
+     * Return the first statement from the constructor code if it is a call to super or this, otherwise null.
+     *
+     * @param code
+     * @return the first statement if a special call or null
+     */
+    public static ConstructorCallExpression getFirstIfSpecialConstructorCall(Statement code) {
+        if (code == null) return null;
+
+        if (code instanceof BlockStatement) {
+            final BlockStatement block = (BlockStatement) code;
+            final List<Statement> statementList = block.getStatements();
+            if (statementList.isEmpty()) return null;
+            // handle blocks of blocks
+            return getFirstIfSpecialConstructorCall(statementList.get(0));
+        }
+
+        if (!(code instanceof ExpressionStatement)) return null;
+
+        Expression expression = ((ExpressionStatement) code).getExpression();
+        if (!(expression instanceof ConstructorCallExpression)) return null;
+        ConstructorCallExpression cce = (ConstructorCallExpression) expression;
+        if (cce.isSpecialCall()) return cce;
+        return null;
+    }
+}
diff --git a/src/main/java/org/apache/groovy/ast/tools/MethodNodeUtils.java b/src/main/java/org/apache/groovy/ast/tools/MethodNodeUtils.java
index 1dc0d33..aa7cd3d 100644
--- a/src/main/java/org/apache/groovy/ast/tools/MethodNodeUtils.java
+++ b/src/main/java/org/apache/groovy/ast/tools/MethodNodeUtils.java
@@ -21,6 +21,8 @@ package org.apache.groovy.ast.tools;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.ast.stmt.Statement;
 
 import static org.apache.groovy.util.BeanUtils.decapitalize;
 
@@ -94,4 +96,28 @@ public class MethodNodeUtils {
     }
 
     private MethodNodeUtils() { }
+
+    /**
+     * Gets the code for a method (or constructor) as a block.
+     * If no code is found, an empty block will be returned.
+     * If a single non-block statement is found, a block containing that statement will be returned.
+     * Otherwise the existing block statement will be returned.
+     * The original {@code node} is not modified.
+     *
+     * @param node the method (or constructor) node
+     * @return the found or created block statement
+     */
+    public static BlockStatement getCodeAsBlock(MethodNode node) {
+        Statement code = node.getCode();
+        BlockStatement block;
+        if (code == null) {
+            block = new BlockStatement();
+        } else if (!(code instanceof BlockStatement)) {
+            block = new BlockStatement();
+            block.addStatement(code);
+        } else {
+            block = (BlockStatement) code;
+        }
+        return block;
+    }
 }
diff --git a/src/main/java/org/codehaus/groovy/ast/ClassNode.java b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
index 15f6eb0..4d0e12f 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
@@ -51,6 +51,7 @@ import java.util.stream.Collectors;
 
 import static java.util.Arrays.stream;
 import static java.util.stream.Collectors.joining;
+import static org.apache.groovy.ast.tools.MethodNodeUtils.getCodeAsBlock;
 
 /**
  * Represents a class in the AST.
@@ -796,16 +797,7 @@ public class ClassNode extends AnnotatedNode implements Opcodes {
 
     public void addStaticInitializerStatements(List<Statement> staticStatements, boolean fieldInit) {
         MethodNode method = getOrAddStaticConstructorNode();
-        BlockStatement block = null;
-        Statement statement = method.getCode();
-        if (statement == null) {
-            block = new BlockStatement();
-        } else if (statement instanceof BlockStatement) {
-            block = (BlockStatement) statement;
-        } else {
-            block = new BlockStatement();
-            block.addStatement(statement);
-        }
+        BlockStatement block = getCodeAsBlock(method);
 
         // while anything inside a static initializer block is appended
         // we don't want to append in the case we have a initialization
diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java b/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java
index 0d850ce..38062a4 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java
@@ -271,19 +271,35 @@ public class GeneralUtils {
     }
 
     public static Statement ctorSuperS(final Expression args) {
-        return stmt(ctorX(ClassNode.SUPER, args));
+        return stmt(ctorSuperX(args));
+    }
+
+    public static ConstructorCallExpression ctorSuperX(Expression args) {
+        return ctorX(ClassNode.SUPER, args);
     }
 
     public static Statement ctorThisS(final Expression args) {
-        return stmt(ctorX(ClassNode.THIS, args));
+        return stmt(ctorThisX(args));
+    }
+
+    public static ConstructorCallExpression ctorThisX(Expression args) {
+        return ctorX(ClassNode.THIS, args);
     }
 
     public static Statement ctorSuperS() {
-        return stmt(ctorX(ClassNode.SUPER));
+        return stmt(ctorSuperX());
+    }
+
+    public static ConstructorCallExpression ctorSuperX() {
+        return ctorX(ClassNode.SUPER);
     }
 
     public static Statement ctorThisS() {
-        return stmt(ctorX(ClassNode.THIS));
+        return stmt(ctorThisX());
+    }
+
+    public static ConstructorCallExpression ctorThisX() {
+        return ctorX(ClassNode.THIS);
     }
 
     public static Statement declS(final Expression target, final Expression init) {
diff --git a/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java b/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java
index 4b8a1a2..077d84a 100644
--- a/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java
@@ -31,8 +31,6 @@ import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.TupleExpression;
 import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.ast.stmt.BlockStatement;
-import org.codehaus.groovy.ast.stmt.ExpressionStatement;
-import org.codehaus.groovy.ast.stmt.Statement;
 import org.codehaus.groovy.classgen.asm.BytecodeHelper;
 import org.codehaus.groovy.control.CompilationUnit;
 import org.codehaus.groovy.control.SourceUnit;
@@ -42,7 +40,13 @@ import org.objectweb.asm.Opcodes;
 import java.util.List;
 
 import static org.apache.groovy.ast.tools.ClassNodeUtils.addGeneratedConstructor;
+import static org.apache.groovy.ast.tools.MethodNodeUtils.getCodeAsBlock;
+import static org.apache.groovy.ast.tools.ConstructorNodeUtils.getFirstIfSpecialConstructorCall;
 import static org.codehaus.groovy.ast.ClassHelper.CLOSURE_TYPE;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorSuperX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
 
 public class InnerClassCompletionVisitor extends InnerClassVisitorHelper implements Opcodes {
 
@@ -368,7 +372,6 @@ public class InnerClassCompletionVisitor extends InnerClassVisitorHelper impleme
 
     private void addThisReference(ConstructorNode node) {
         if (!shouldHandleImplicitThisForInnerClass(classNode)) return;
-        Statement code = node.getCode();
 
         // add "this$0" field init
 
@@ -382,27 +385,19 @@ public class InnerClassCompletionVisitor extends InnerClassVisitorHelper impleme
         newParams[0] = thisPara;
         node.setParameters(newParams);
 
-        BlockStatement block = null;
-        if (code == null) {
-            block = new BlockStatement();
-        } else if (!(code instanceof BlockStatement)) {
-            block = new BlockStatement();
-            block.addStatement(code);
-        } else {
-            block = (BlockStatement) code;
-        }
-        BlockStatement newCode = new BlockStatement();
+        BlockStatement block = getCodeAsBlock(node);
+        BlockStatement newCode = block();
         addFieldInit(thisPara, thisField, newCode);
         ConstructorCallExpression cce = getFirstIfSpecialConstructorCall(block);
         if (cce == null) {
-            cce = new ConstructorCallExpression(ClassNode.SUPER, new TupleExpression());
-            block.getStatements().add(0, new ExpressionStatement(cce));
+            cce = ctorSuperX(new TupleExpression());
+            block.getStatements().add(0, stmt(cce));
         }
         if (shouldImplicitlyPassThisPara(cce)) {
             // add thisPara to this(...)
             TupleExpression args = (TupleExpression) cce.getArguments();
             List<Expression> expressions = args.getExpressions();
-            VariableExpression ve = new VariableExpression(thisPara.getName());
+            VariableExpression ve = varX(thisPara.getName());
             ve.setAccessedVariable(thisPara);
             expressions.add(0, ve);
         }
@@ -446,19 +441,4 @@ public class InnerClassCompletionVisitor extends InnerClassVisitorHelper impleme
         return namePrefix;
     }
 
-    private static ConstructorCallExpression getFirstIfSpecialConstructorCall(BlockStatement code) {
-        if (code == null) return null;
-
-        final List<Statement> statementList = code.getStatements();
-        if (statementList.isEmpty()) return null;
-
-        final Statement statement = statementList.get(0);
-        if (!(statement instanceof ExpressionStatement)) return null;
-
-        Expression expression = ((ExpressionStatement) statement).getExpression();
-        if (!(expression instanceof ConstructorCallExpression)) return null;
-        ConstructorCallExpression cce = (ConstructorCallExpression) expression;
-        if (cce.isSpecialCall()) return cce;
-        return null;
-    }
 }
diff --git a/src/main/java/org/codehaus/groovy/classgen/Verifier.java b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
index 4310bfb..394ddfa 100644
--- a/src/main/java/org/codehaus/groovy/classgen/Verifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
@@ -90,6 +90,8 @@ import static java.lang.reflect.Modifier.isPublic;
 import static java.lang.reflect.Modifier.isStatic;
 import static java.util.stream.Collectors.joining;
 import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated;
+import static org.apache.groovy.ast.tools.MethodNodeUtils.getCodeAsBlock;
+import static org.apache.groovy.ast.tools.ConstructorNodeUtils.getFirstIfSpecialConstructorCall;
 import static org.apache.groovy.ast.tools.ExpressionUtils.transformInlineConstants;
 import static org.apache.groovy.ast.tools.MethodNodeUtils.getPropertyName;
 import static org.apache.groovy.ast.tools.MethodNodeUtils.methodDescriptorWithoutReturnType;
@@ -1041,15 +1043,8 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
 
         statements.addAll(node.getObjectInitializerStatements());
 
-        Statement code = constructorNode.getCode();
-        BlockStatement block = new BlockStatement();
+        BlockStatement block = getCodeAsBlock(constructorNode);
         List<Statement> otherStatements = block.getStatements();
-        if (code instanceof BlockStatement) {
-            block = (BlockStatement) code;
-            otherStatements = block.getStatements();
-        } else if (code != null) {
-            otherStatements.add(code);
-        }
         if (!otherStatements.isEmpty()) {
             if (first != null) {
                 // it is super(..) since this(..) is already covered
@@ -1121,16 +1116,6 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
         return false;
     }
 
-    private static ConstructorCallExpression getFirstIfSpecialConstructorCall(Statement code) {
-        if (!(code instanceof ExpressionStatement)) return null;
-
-        Expression expression = ((ExpressionStatement) code).getExpression();
-        if (!(expression instanceof ConstructorCallExpression)) return null;
-        ConstructorCallExpression cce = (ConstructorCallExpression) expression;
-        if (cce.isSpecialCall()) return cce;
-        return null;
-    }
-
     protected void addFieldInitialization(List list, List staticList, FieldNode fieldNode,
                                           boolean isEnumClassNode, List initStmtsAfterEnumValuesInit, Set explicitStaticPropsInEnum) {
         Expression expression = fieldNode.getInitialExpression();
diff --git a/src/main/java/org/codehaus/groovy/tools/javac/JavaAwareResolveVisitor.java b/src/main/java/org/codehaus/groovy/tools/javac/JavaAwareResolveVisitor.java
index 4291ac4..c885885 100644
--- a/src/main/java/org/codehaus/groovy/tools/javac/JavaAwareResolveVisitor.java
+++ b/src/main/java/org/codehaus/groovy/tools/javac/JavaAwareResolveVisitor.java
@@ -20,42 +20,25 @@ package org.codehaus.groovy.tools.javac;
 
 import org.codehaus.groovy.ast.ASTNode;
 import org.codehaus.groovy.ast.ConstructorNode;
-import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
 import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.stmt.BlockStatement;
-import org.codehaus.groovy.ast.stmt.ExpressionStatement;
 import org.codehaus.groovy.ast.stmt.Statement;
 import org.codehaus.groovy.control.CompilationUnit;
 import org.codehaus.groovy.control.ResolveVisitor;
 
+import static org.apache.groovy.ast.tools.ConstructorNodeUtils.getFirstIfSpecialConstructorCall;
+
 public class JavaAwareResolveVisitor extends ResolveVisitor {
 
     public JavaAwareResolveVisitor(CompilationUnit cu) {
         super(cu);
     }
 
-    private static Expression getConstructorCall(Statement code) {
-        if (code==null) return null;
-        if (code instanceof BlockStatement) {
-            BlockStatement bs = (BlockStatement) code;
-            if (bs.isEmpty()) return null;
-            return getConstructorCall(bs.getStatements().get(0));
-        }
-        if (!(code instanceof ExpressionStatement)) return null;
-        ExpressionStatement es = (ExpressionStatement) code;
-        Expression exp = es.getExpression();
-        if (!(exp instanceof ConstructorCallExpression)) return null;
-        ConstructorCallExpression cce = (ConstructorCallExpression) exp;
-        if (!cce.isSpecialCall()) return null;
-        return cce;
-    }
-
     @Override
     public void visitConstructor(ConstructorNode node) {
         super.visitConstructor(node);
         Statement code = node.getCode();
-        Expression cce = getConstructorCall(code);
-        if (cce==null) return;
+        Expression cce = getFirstIfSpecialConstructorCall(code);
+        if (cce == null) return;
         cce.visit(this);
     }
 
diff --git a/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java b/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
index 871fe37..7e73515 100644
--- a/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
+++ b/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
@@ -76,6 +76,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import static org.apache.groovy.ast.tools.ConstructorNodeUtils.getFirstIfSpecialConstructorCall;
 import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpec;
 import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec;
 
@@ -531,27 +532,6 @@ public class JavaStubGenerator {
         return "\"" + escapeSpecialChars(s) + "\"";
     }
 
-    private static ConstructorCallExpression getConstructorCallExpression(ConstructorNode constructorNode) {
-        Statement code = constructorNode.getCode();
-        if (!(code instanceof BlockStatement))
-            return null;
-
-        BlockStatement block = (BlockStatement) code;
-        List stats = block.getStatements();
-        if (stats == null || stats.isEmpty())
-            return null;
-
-        Statement stat = (Statement) stats.get(0);
-        if (!(stat instanceof ExpressionStatement))
-            return null;
-
-        Expression expr = ((ExpressionStatement) stat).getExpression();
-        if (!(expr instanceof ConstructorCallExpression))
-            return null;
-
-        return (ConstructorCallExpression) expr;
-    }
-
     private void printConstructor(PrintWriter out, ClassNode clazz, ConstructorNode constructorNode) {
         printAnnotations(out, constructorNode);
         // printModifiers(out, constructorNode.getModifiers());
@@ -564,8 +544,8 @@ public class JavaStubGenerator {
 
         printParams(out, constructorNode);
 
-        ConstructorCallExpression constrCall = getConstructorCallExpression(constructorNode);
-        if (constrCall == null || !constrCall.isSpecialCall()) {
+        ConstructorCallExpression constrCall = getFirstIfSpecialConstructorCall(constructorNode.getCode());
+        if (constrCall == null) {
             out.println(" {}");
         } else {
             out.println(" {");
diff --git a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
index 70952bf..2daeae2 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
@@ -69,6 +69,7 @@ import java.util.List;
 import java.util.Set;
 
 import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated;
+import static org.apache.groovy.ast.tools.MethodNodeUtils.getCodeAsBlock;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
 import static org.codehaus.groovy.transform.trait.SuperCallTraitTransformer.UNRESOLVED_HELPER_CLASS;
 
@@ -227,7 +228,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
                 if (!methodNode.isAbstract()) {
                     MethodNode newMethod = processMethod(cNode, helper, methodNode, fieldHelper, fieldNames);
                     if (methodNode.getName().equals("<clinit>")) {
-                        staticInitStatements = getStatements(newMethod.getCode());
+                        staticInitStatements = getCodeAsBlock(newMethod).getStatements();
                     } else {
                         // add non-abstract methods; abstract methods covered from trait interface
                         helper.addMethod(newMethod);
@@ -311,15 +312,6 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         return toBlock;
     }
 
-    private List<Statement> getStatements(Statement stmt) {
-        if (stmt instanceof BlockStatement) {
-            return ((BlockStatement) stmt).getStatements();
-        }
-        List<Statement> result = new ArrayList<Statement>();
-        result.add(stmt);
-        return result;
-    }
-
     private static MethodNode createInitMethod(final boolean isStatic, final ClassNode cNode, final ClassNode helper) {
         MethodNode initializer = new MethodNode(
                 isStatic?Traits.STATIC_INIT_METHOD:Traits.INIT_METHOD,