You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2019/12/17 03:57:47 UTC

[groovy] 03/05: normalize addPhaseOperations()

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

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

commit 0e7493353d1da16179020b1308822b6a8b32e530
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Dec 16 12:31:23 2019 -0600

    normalize addPhaseOperations()
    
    (cherry picked from commit 85c1891df466c10fe4aa450dfd90c45fcc6a3124)
---
 .../codehaus/groovy/control/CompilationUnit.java   | 235 +++++++++++----------
 .../groovy/control/DefaultTransformer.java         |  69 ------
 2 files changed, 125 insertions(+), 179 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
index 29ca6f3..210ec3f 100644
--- a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
+++ b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
@@ -21,12 +21,15 @@ package org.codehaus.groovy.control;
 import groovy.lang.GroovyClassLoader;
 import groovy.transform.CompilationUnitAware;
 import org.codehaus.groovy.GroovyBugError;
+import org.codehaus.groovy.ast.ClassCodeExpressionTransformer;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.CompileUnit;
 import org.codehaus.groovy.ast.GroovyClassVisitor;
 import org.codehaus.groovy.ast.InnerClassNode;
 import org.codehaus.groovy.ast.ModuleNode;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.classgen.AsmClassGenerator;
 import org.codehaus.groovy.classgen.ClassCompletionVerifier;
 import org.codehaus.groovy.classgen.EnumCompletionVisitor;
@@ -48,7 +51,6 @@ import org.codehaus.groovy.syntax.SyntaxException;
 import org.codehaus.groovy.tools.GroovyClass;
 import org.codehaus.groovy.transform.ASTTransformationVisitor;
 import org.codehaus.groovy.transform.AnnotationCollectorTransform;
-import org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys;
 import org.codehaus.groovy.transform.trait.TraitComposer;
 import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.ClassWriter;
@@ -72,6 +74,11 @@ import java.util.Queue;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
+import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.DYNAMIC_OUTER_NODE_CALLBACK;
+import static org.codehaus.groovy.transform.stc.StaticTypesMarker.SWITCH_CONDITION_EXPRESSION_TYPE;
+
 /**
  * The CompilationUnit collects all compilation data as it is generated by the compiler system.
  * You can use this object to add additional source units to the compilation, or force the
@@ -114,8 +121,6 @@ public class CompilationUnit extends ProcessingUnit {
     /** A callback for use during {@link #compile()} */
     protected ProgressCallback progressCallback;
 
-    protected StaticImportVisitor staticImportVisitor = new StaticImportVisitor();
-    protected DefaultTransformer defaultTransformer = new DefaultTransformer();
     protected ClassNodeResolver classNodeResolver = new ClassNodeResolver();
     protected ResolveVisitor resolveVisitor = new ResolveVisitor(this);
     protected OptimizerVisitor optimizer = new OptimizerVisitor(this);
@@ -182,97 +187,175 @@ public class CompilationUnit extends ProcessingUnit {
     private void addPhaseOperations() {
         addPhaseOperation(new SourceUnitOperation() {
             @Override
-            public void call(SourceUnit source) throws CompilationFailedException {
+            public void call(final SourceUnit source) throws CompilationFailedException {
                 source.parse();
             }
         }, Phases.PARSING);
-        addPhaseOperation(convert, Phases.CONVERSION);
+
+        addPhaseOperation(new SourceUnitOperation() {
+            @Override
+            public void call(final SourceUnit source) throws CompilationFailedException {
+                source.convert();
+                // add module to compile unit
+                getAST().addModule(source.getAST());
+
+                if (progressCallback != null) {
+                    progressCallback.call(source, phase);
+                }
+            }
+        }, Phases.CONVERSION);
         addPhaseOperation(new PrimaryClassNodeOperation() {
             @Override
-            public void call(SourceUnit source, GeneratorContext context,
-                             ClassNode classNode) throws CompilationFailedException {
-                EnumVisitor ev = new EnumVisitor(CompilationUnit.this, source);
-                ev.visitClass(classNode);
+            public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
+                GroovyClassVisitor visitor = new EnumVisitor(CompilationUnit.this, source);
+                visitor.visitClass(classNode);
             }
         }, Phases.CONVERSION);
+
         addPhaseOperation(resolve, Phases.SEMANTIC_ANALYSIS);
-        addPhaseOperation(staticImport, Phases.SEMANTIC_ANALYSIS);
         addPhaseOperation(new PrimaryClassNodeOperation() {
             @Override
-            public void call(SourceUnit source, GeneratorContext context,
-                             ClassNode classNode) throws CompilationFailedException {
-                InnerClassVisitor iv = new InnerClassVisitor(CompilationUnit.this, source);
-                iv.visitClass(classNode);
+            public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
+                StaticImportVisitor visitor = new StaticImportVisitor();
+                visitor.visitClass(classNode, source);
             }
         }, Phases.SEMANTIC_ANALYSIS);
         addPhaseOperation(new PrimaryClassNodeOperation() {
             @Override
-            public void call(SourceUnit source, GeneratorContext context,
-                             ClassNode classNode) throws CompilationFailedException {
+            public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
+                GroovyClassVisitor visitor = new InnerClassVisitor(CompilationUnit.this, source);
+                visitor.visitClass(classNode);
+            }
+        }, Phases.SEMANTIC_ANALYSIS);
+        addPhaseOperation(new PrimaryClassNodeOperation() {
+            @Override
+            public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
                 if (!classNode.isSynthetic()) {
-                    GenericsVisitor genericsVisitor = new GenericsVisitor(source);
-                    genericsVisitor.visitClass(classNode);
+                    GroovyClassVisitor visitor = new GenericsVisitor(source);
+                    visitor.visitClass(classNode);
                 }
             }
         }, Phases.SEMANTIC_ANALYSIS);
+
         addPhaseOperation(new PrimaryClassNodeOperation() {
             @Override
-            public void call(SourceUnit source, GeneratorContext context,
-                             ClassNode classNode) throws CompilationFailedException {
+            public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
                 TraitComposer.doExtendTraits(classNode, source, CompilationUnit.this);
             }
         }, Phases.CANONICALIZATION);
-        addPhaseOperation(compileCompleteCheck, Phases.CANONICALIZATION);
+        addPhaseOperation(new SourceUnitOperation() {
+            @Override
+            public void call(final SourceUnit source) throws CompilationFailedException {
+                List<ClassNode> classes = source.ast.getClasses();
+                for (ClassNode node : classes) {
+                    CompileUnit cu = node.getCompileUnit();
+                    for (Iterator<String> it = cu.iterateClassNodeToCompile(); it.hasNext(); ) {
+                        String name = it.next();
+                        StringBuilder message = new StringBuilder();
+                        message
+                                .append("Compilation incomplete: expected to find the class ")
+                                .append(name)
+                                .append(" in ")
+                                .append(source.getName());
+                        if (classes.isEmpty()) {
+                            message.append(", but the file seems not to contain any classes");
+                        } else {
+                            message.append(", but the file contains the classes: ");
+                            boolean first = true;
+                            for (ClassNode cn : classes) {
+                                if (!first) {
+                                    message.append(", ");
+                                } else {
+                                    first = false;
+                                }
+                                message.append(cn.getName());
+                            }
+                        }
+
+                        getErrorCollector().addErrorAndContinue(
+                                new SimpleMessage(message.toString(), CompilationUnit.this)
+                        );
+                        it.remove();
+                    }
+                }
+            }
+        }, Phases.CANONICALIZATION);
+
         addPhaseOperation(classgen, Phases.CLASS_GENERATION);
 
         addPhaseOperation(output);
 
         addPhaseOperation(new PrimaryClassNodeOperation() {
             @Override
-            public void call(SourceUnit source, GeneratorContext context,
-                             ClassNode classNode) throws CompilationFailedException {
-                AnnotationCollectorTransform.ClassChanger actt = new AnnotationCollectorTransform.ClassChanger();
-                actt.transformClass(classNode);
+            public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
+                AnnotationCollectorTransform.ClassChanger xformer = new AnnotationCollectorTransform.ClassChanger();
+                xformer.transformClass(classNode);
             }
         }, Phases.SEMANTIC_ANALYSIS);
         ASTTransformationVisitor.addPhaseOperations(this);
+
+        // post-transform operations:
+
         addPhaseOperation(new PrimaryClassNodeOperation() {
             @Override
-            public void call(SourceUnit source, GeneratorContext context,
-                             ClassNode classNode) throws CompilationFailedException {
-                StaticVerifier sv = new StaticVerifier();
-                sv.visitClass(classNode, source);
+            public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
+                StaticVerifier verifier = new StaticVerifier();
+                verifier.visitClass(classNode, source);
             }
         }, Phases.SEMANTIC_ANALYSIS);
+
         addPhaseOperation(new PrimaryClassNodeOperation() {
             @Override
-            public void call(SourceUnit source, GeneratorContext context,
-                             ClassNode classNode) throws CompilationFailedException {
-                InnerClassCompletionVisitor iv = new InnerClassCompletionVisitor(CompilationUnit.this, source);
-                iv.visitClass(classNode);
+            public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
+                GroovyClassVisitor visitor = new InnerClassCompletionVisitor(CompilationUnit.this, source);
+                visitor.visitClass(classNode);
             }
         }, Phases.CANONICALIZATION);
         addPhaseOperation(new PrimaryClassNodeOperation() {
             @Override
-            public void call(SourceUnit source, GeneratorContext context,
-                             ClassNode classNode) throws CompilationFailedException {
-                EnumCompletionVisitor ecv = new EnumCompletionVisitor(CompilationUnit.this, source);
-                ecv.visitClass(classNode);
+            public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
+                GroovyClassVisitor visitor = new EnumCompletionVisitor(CompilationUnit.this, source);
+                visitor.visitClass(classNode);
             }
         }, Phases.CANONICALIZATION);
+
         addPhaseOperation(new PrimaryClassNodeOperation() {
             @Override
-            public void call(SourceUnit source, GeneratorContext context,
-                             ClassNode classNode) throws CompilationFailedException {
-                Object callback = classNode.getNodeMetaData(StaticCompilationMetadataKeys.DYNAMIC_OUTER_NODE_CALLBACK);
+            public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
+                Object callback = classNode.getNodeMetaData(DYNAMIC_OUTER_NODE_CALLBACK);
                 if (callback instanceof PrimaryClassNodeOperation) {
                     ((PrimaryClassNodeOperation) callback).call(source, context, classNode);
-                    classNode.removeNodeMetaData(StaticCompilationMetadataKeys.DYNAMIC_OUTER_NODE_CALLBACK);
+                    classNode.removeNodeMetaData(DYNAMIC_OUTER_NODE_CALLBACK);
                 }
             }
         }, Phases.INSTRUCTION_SELECTION);
+        addPhaseOperation(new PrimaryClassNodeOperation() {
+            @Override
+            public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
+                // TODO: Could this be moved into org.codehaus.groovy.transform.sc.transformers.VariableExpressionTransformer?
+                new ClassCodeExpressionTransformer() {
+                    @Override
+                    protected SourceUnit getSourceUnit() {
+                        return source;
+                    }
 
-        addPhaseOperation(defaultTransform, Phases.INSTRUCTION_SELECTION);
+                    @Override
+                    public Expression transform(final Expression expression) {
+                        if (expression instanceof VariableExpression) {
+                            // check for "switch(enumType) { case CONST: ... }"
+                            ClassNode enumType = expression.getNodeMetaData(SWITCH_CONDITION_EXPRESSION_TYPE);
+                            if (enumType != null) {
+                                // replace "CONST" variable expression with "EnumType.CONST" property expression
+                                Expression propertyExpression = propX(classX(enumType), expression.getText());
+                                setSourcePosition(propertyExpression, expression);
+                                return propertyExpression;
+                            }
+                        }
+                        return expression;
+                    }
+                }.visitClass(classNode);
+            }
+        }, Phases.INSTRUCTION_SELECTION);
     }
 
     private void applyCompilationCustomizers() {
@@ -667,34 +750,6 @@ public class CompilationUnit extends ProcessingUnit {
         }
     };
 
-    private final PrimaryClassNodeOperation staticImport = new PrimaryClassNodeOperation() {
-        @Override
-        public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
-            staticImportVisitor.visitClass(classNode, source);
-        }
-    };
-
-    private PrimaryClassNodeOperation defaultTransform = new PrimaryClassNodeOperation() {
-        @Override
-        public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
-            defaultTransformer.visitClass(classNode, source);
-        }
-    };
-
-    /**
-     * Runs convert() on a single SourceUnit.
-     */
-    private final SourceUnitOperation convert = new SourceUnitOperation() {
-        @Override
-        public void call(final SourceUnit source) throws CompilationFailedException {
-            source.convert();
-            getAST().addModule(source.getAST());
-            if (progressCallback != null) {
-                progressCallback.call(source, phase);
-            }
-        }
-    };
-
     private final GroovyClassOperation output = new GroovyClassOperation() {
         @Override
         public void call(final GroovyClass groovyClass) throws CompilationFailedException {
@@ -718,46 +773,6 @@ public class CompilationUnit extends ProcessingUnit {
         }
     };
 
-    /* checks if all needed classes are compiled before generating the bytecode */
-    private final SourceUnitOperation compileCompleteCheck = new SourceUnitOperation() {
-        public void call(SourceUnit source) throws CompilationFailedException {
-            List<ClassNode> classes = source.ast.getClasses();
-            for (ClassNode node : classes) {
-                CompileUnit cu = node.getCompileUnit();
-                for (Iterator<String> iter = cu.iterateClassNodeToCompile(); iter.hasNext();) {
-                    String name = iter.next();
-                    SourceUnit su = ast.getScriptSourceLocation(name);
-                    List<ClassNode> classesInSourceUnit = su.ast.getClasses();
-                    StringBuilder message = new StringBuilder();
-                    message
-                            .append("Compilation incomplete: expected to find the class ")
-                            .append(name)
-                            .append(" in ")
-                            .append(su.getName());
-                    if (classesInSourceUnit.isEmpty()) {
-                        message.append(", but the file seems not to contain any classes");
-                    } else {
-                        message.append(", but the file contains the classes: ");
-                        boolean first = true;
-                        for (ClassNode cn : classesInSourceUnit) {
-                            if (!first) {
-                                message.append(", ");
-                            } else {
-                                first = false;
-                            }
-                            message.append(cn.getName());
-                        }
-                    }
-
-                    getErrorCollector().addErrorAndContinue(
-                            new SimpleMessage(message.toString(), CompilationUnit.this)
-                    );
-                    iter.remove();
-                }
-            }
-        }
-    };
-
     /**
      * Runs classgen() on a single ClassNode.
      */
diff --git a/src/main/java/org/codehaus/groovy/control/DefaultTransformer.java b/src/main/java/org/codehaus/groovy/control/DefaultTransformer.java
deleted file mode 100644
index 6daa511..0000000
--- a/src/main/java/org/codehaus/groovy/control/DefaultTransformer.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  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.control;
-
-import org.codehaus.groovy.ast.ClassCodeExpressionTransformer;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.PropertyExpression;
-import org.codehaus.groovy.ast.expr.VariableExpression;
-
-import static org.codehaus.groovy.transform.stc.StaticTypesMarker.SWITCH_CONDITION_EXPRESSION_TYPE;
-
-/**
- * The default transformer a.k.a. the last transformer to transform expressions, it can use type info if STC is enabled
- *
- * @since 3.0.0
- */
-public class DefaultTransformer extends ClassCodeExpressionTransformer {
-    private ClassNode currentClass;
-    private SourceUnit source;
-
-    public void visitClass(ClassNode node, SourceUnit source) {
-        this.currentClass = node;
-        this.source = source;
-        super.visitClass(node);
-    }
-
-    public Expression transform(Expression exp) {
-        if (null == exp) return null;
-
-        if (exp.getClass() == VariableExpression.class) {
-            return transformVariableExpression((VariableExpression) exp);
-        }
-        return exp;
-    }
-
-    private Expression transformVariableExpression(VariableExpression ve) {
-        ClassNode enumClassNode = ve.getNodeMetaData(SWITCH_CONDITION_EXPRESSION_TYPE);
-        if (null != enumClassNode) {
-            Expression result = new PropertyExpression(new ClassExpression(enumClassNode), ve.getName());
-            setSourcePosition(result, ve);
-
-            return result;
-        }
-        return ve;
-    }
-
-    @Override
-    protected SourceUnit getSourceUnit() {
-        return source;
-    }
-}