You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2019/12/16 18:31:40 UTC

[groovy] 01/03: minor edits

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

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

commit d3a67f009dc24fc884a410c79fa9819a343141da
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Dec 16 10:55:47 2019 -0600

    minor edits
---
 .../codehaus/groovy/control/CompilationUnit.java   | 379 ++++++++++-----------
 .../java/org/codehaus/groovy/control/Phases.java   |  57 ++--
 .../codehaus/groovy/control/ResolveVisitor.java    |   1 +
 .../asm/sc/StaticCompilationTestSupport.groovy     |   4 +-
 4 files changed, 207 insertions(+), 234 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
index 51763cf..193a13d 100644
--- a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
+++ b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
@@ -53,7 +53,6 @@ import org.codehaus.groovy.transform.trait.TraitComposer;
 import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.ClassWriter;
 
-import javax.tools.JavaFileObject;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -61,14 +60,17 @@ import java.io.InputStream;
 import java.net.URL;
 import java.security.CodeSource;
 import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Deque;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
+import java.util.Queue;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * The CompilationUnit collects all compilation data as it is generated by the compiler system.
@@ -80,37 +82,49 @@ import java.util.Set;
  */
 public class CompilationUnit extends ProcessingUnit {
 
-    //---------------------------------------------------------------------------
-    // CONSTRUCTION AND SUCH
+    /** The overall AST for this CompilationUnit. */
+    protected CompileUnit ast; // TODO: Switch to private and access through getAST().
 
-    protected ASTTransformationsContext astTransformationsContext; // AST transformations state data
+    /** The source units from which this unit is built. */
+    protected Map<String, SourceUnit> sources = new LinkedHashMap<>();
+    protected Queue<SourceUnit> queuedSources = new LinkedList<>();
 
-    protected Map<String, SourceUnit> sources;    // The SourceUnits from which this unit is built
-    protected Map summariesBySourceName;      // Summary of each SourceUnit
-    protected Map summariesByPublicClassName;       // Summary of each SourceUnit
-    protected Map classSourcesByPublicClassName;    // Summary of each Class
-    protected LinkedList<SourceUnit> queuedSources;
+    /** The classes generated during classgen. */
+    private List<GroovyClass> generatedClasses = new ArrayList<>();
 
-    protected CompileUnit ast;        // The overall AST for this CompilationUnit.
-    protected List<GroovyClass> generatedClasses;  // The classes generated during classgen.
+    private Deque[] phaseOperations;
+    private Deque[] newPhaseOperations;
+    {
+        final int n = Phases.ALL + 1;
+        phaseOperations = new Deque[n];
+        newPhaseOperations = new Deque[n];
+        for (int i = 0; i < n; i += 1) {
+            phaseOperations[i] = new LinkedList<>();
+            newPhaseOperations[i] = new LinkedList<>();
+        }
+    }
 
-    protected Verifier verifier;   // For use by verify().
+    /** Controls behavior of {@link #classgen()} and other routines. */
+    protected boolean debug;
+    /** True after the first {@link #configure()} operation. */
+    protected boolean configured;
 
-    protected boolean debug;      // Controls behavior of classgen() and other routines.
-    protected boolean configured; // Set true after the first configure() operation
+    /** A callback for use during {@link #classgen()} */
+    protected ClassgenCallback classgenCallback;
+    /** A callback for use during {@link #compile()} */
+    protected ProgressCallback progressCallback;
 
-    protected ClassgenCallback classgenCallback;  // A callback for use during classgen()
-    protected ProgressCallback progressCallback;  // A callback for use during compile()
-    protected ResolveVisitor resolveVisitor;
-    protected StaticImportVisitor staticImportVisitor;
-    protected DefaultTransformer defaultTransformer;
-    protected OptimizerVisitor optimizer;
-    protected ClassNodeResolver classNodeResolver;
+    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);
+    protected Verifier verifier = new Verifier();
 
-    LinkedList[] phaseOperations;
-    LinkedList[] newPhaseOperations;
+    /** The AST transformations state data. */
+    protected ASTTransformationsContext astTransformationsContext;
 
-    private Set<JavaFileObject> javaCompilationUnitSet = new HashSet<>();
+    private Set<javax.tools.JavaFileObject> javaCompilationUnitSet = new HashSet<>();
 
     /**
      * Initializes the CompilationUnit with defaults.
@@ -122,14 +136,14 @@ public class CompilationUnit extends ProcessingUnit {
     /**
      * Initializes the CompilationUnit with defaults except for class loader.
      */
-    public CompilationUnit(GroovyClassLoader loader) {
+    public CompilationUnit(final GroovyClassLoader loader) {
         this(null, null, loader);
     }
 
     /**
      * Initializes the CompilationUnit with no security considerations.
      */
-    public CompilationUnit(CompilerConfiguration configuration) {
+    public CompilationUnit(final CompilerConfiguration configuration) {
         this(configuration, null, null);
     }
 
@@ -137,8 +151,8 @@ public class CompilationUnit extends ProcessingUnit {
      * Initializes the CompilationUnit with a CodeSource for controlling
      * security stuff and a class loader for loading classes.
      */
-    public CompilationUnit(CompilerConfiguration configuration, CodeSource security, GroovyClassLoader loader) {
-        this(configuration, security, loader, null);
+    public CompilationUnit(final CompilerConfiguration configuration, final CodeSource codeSource, final GroovyClassLoader loader) {
+        this(configuration, codeSource, loader, null);
     }
 
     /**
@@ -151,46 +165,18 @@ public class CompilationUnit extends ProcessingUnit {
      *
      * @param transformLoader - the loader for transforms
      * @param loader          - loader used to resolve classes against during compilation
-     * @param security        - security setting for the compilation
+     * @param codeSource      - security setting for the compilation
      * @param configuration   - compilation configuration
      */
-    public CompilationUnit(CompilerConfiguration configuration, CodeSource security,
-                           GroovyClassLoader loader, GroovyClassLoader transformLoader) {
+    public CompilationUnit(final CompilerConfiguration configuration, final CodeSource codeSource,
+                           final GroovyClassLoader loader, final GroovyClassLoader transformLoader) {
         super(configuration, loader, null);
 
         this.astTransformationsContext = new ASTTransformationsContext(this, transformLoader);
-        this.queuedSources = new LinkedList<>();
-        this.sources = new LinkedHashMap<>();
-        this.summariesBySourceName = new HashMap<>();
-        this.summariesByPublicClassName = new HashMap<>();
-        this.classSourcesByPublicClassName = new HashMap<>();
-
-        this.ast = new CompileUnit(this.classLoader, security, this.configuration);
-        this.generatedClasses = new ArrayList<>();
-
-        this.verifier = new Verifier();
-        this.resolveVisitor = new ResolveVisitor(this);
-        this.staticImportVisitor = new StaticImportVisitor();
-        this.defaultTransformer = new DefaultTransformer();
-        this.optimizer = new OptimizerVisitor(this);
-
-        initPhaseOperations();
-        addPhaseOperations();
+        this.ast = new CompileUnit(this.classLoader, codeSource, this.configuration);
 
+        addPhaseOperations();
         applyCompilationCustomizers();
-
-        this.classgenCallback = null;
-        this.classNodeResolver = new ClassNodeResolver();
-    }
-
-    private void initPhaseOperations() {
-        int cnt = Phases.ALL + 1;
-        phaseOperations = new LinkedList[cnt];
-        newPhaseOperations = new LinkedList[cnt];
-        for (int i = 0; i < phaseOperations.length; i++) {
-            phaseOperations[i] = new LinkedList<>();
-            newPhaseOperations[i] = new LinkedList<>();
-        }
     }
 
     private void addPhaseOperations() {
@@ -298,48 +284,42 @@ public class CompilationUnit extends ProcessingUnit {
         }
     }
 
-    /**
-     * Returns the class loader for loading AST transformations.
-     * @return - the transform class loader
-     */
-    public GroovyClassLoader getTransformLoader() {
-        return astTransformationsContext.getTransformLoader() == null ? getClassLoader() : astTransformationsContext.getTransformLoader();
+    public void addPhaseOperation(final GroovyClassOperation op) {
+        phaseOperations[Phases.OUTPUT].addFirst(op);
     }
 
-    public void addPhaseOperation(SourceUnitOperation op, int phase) {
+    public void addPhaseOperation(final SourceUnitOperation op, final int phase) {
         validatePhase(phase);
         phaseOperations[phase].add(op);
     }
 
-    public void addPhaseOperation(PrimaryClassNodeOperation op, int phase) {
+    public void addPhaseOperation(final PrimaryClassNodeOperation op, final int phase) {
         validatePhase(phase);
         phaseOperations[phase].add(op);
     }
 
-    private static void validatePhase(int phase) {
-        if (phase < 0 || phase > Phases.ALL) throw new IllegalArgumentException("phase " + phase + " is unknown");
-    }
-
-    public void addFirstPhaseOperation(PrimaryClassNodeOperation op, int phase) {
+    public void addFirstPhaseOperation(final PrimaryClassNodeOperation op, final int phase) {
         validatePhase(phase);
-        phaseOperations[phase].add(0, op);
-    }
-
-    public void addPhaseOperation(GroovyClassOperation op) {
-        phaseOperations[Phases.OUTPUT].addFirst(op);
+        phaseOperations[phase].addFirst(op);
     }
 
-    public void addNewPhaseOperation(SourceUnitOperation op, int phase) {
+    public void addNewPhaseOperation(final SourceUnitOperation op, final int phase) {
         validatePhase(phase);
         newPhaseOperations[phase].add(op);
     }
 
+    private static void validatePhase(final int phase) {
+        if (phase < 1 || phase > Phases.ALL) {
+            throw new IllegalArgumentException("phase " + phase + " is unknown");
+        }
+    }
+
     /**
      * Configures its debugging mode and classloader classpath from a given compiler configuration.
      * This cannot be done more than once due to limitations in {@link java.net.URLClassLoader URLClassLoader}.
      */
     @Override
-    public void configure(CompilerConfiguration configuration) {
+    public void configure(final CompilerConfiguration configuration) {
         super.configure(configuration);
         this.debug = this.configuration.getDebug();
         this.configured = true;
@@ -353,25 +333,6 @@ public class CompilationUnit extends ProcessingUnit {
     }
 
     /**
-     * Get the source summaries
-     */
-    public Map getSummariesBySourceName() {
-        return summariesBySourceName;
-    }
-
-    public Map getSummariesByPublicClassName() {
-        return summariesByPublicClassName;
-    }
-
-    public Map getClassSourcesByPublicClassName() {
-        return classSourcesByPublicClassName;
-    }
-
-    public boolean isPublicClass(String className) {
-        return summariesByPublicClassName.containsKey(className);
-    }
-
-    /**
      * Get the GroovyClasses generated by compile().
      */
     public List<GroovyClass> getClasses() {
@@ -383,14 +344,14 @@ public class CompilationUnit extends ProcessingUnit {
      * when you are sure there is only one.
      */
     public ClassNode getFirstClassNode() {
-        return this.ast.getModules().get(0).getClasses().get(0);
+        return getAST().getModules().get(0).getClasses().get(0);
     }
 
     /**
      * Convenience routine to get the named ClassNode.
      */
     public ClassNode getClassNode(final String name) {
-        final ClassNode[] result = new ClassNode[1];
+        ClassNode[] result = new ClassNode[1];
         PrimaryClassNodeOperation handler = new PrimaryClassNodeOperation() {
             @Override
             public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) {
@@ -399,7 +360,6 @@ public class CompilationUnit extends ProcessingUnit {
                 }
             }
         };
-
         try {
             applyToPrimaryClassNodes(handler);
         } catch (CompilationFailedException e) {
@@ -415,13 +375,36 @@ public class CompilationUnit extends ProcessingUnit {
         return astTransformationsContext;
     }
 
+    public ClassNodeResolver getClassNodeResolver() {
+        return classNodeResolver;
+    }
+
+    public void setClassNodeResolver(final ClassNodeResolver classNodeResolver) {
+        this.classNodeResolver = classNodeResolver;
+    }
+
+    public Set<javax.tools.JavaFileObject> getJavaCompilationUnitSet() {
+        return javaCompilationUnitSet;
+    }
+
+    public void addJavaCompilationUnits(final Set<javax.tools.JavaFileObject> javaCompilationUnitSet) {
+        this.javaCompilationUnitSet.addAll(javaCompilationUnitSet);
+    }
+
+    /**
+     * @return the class loader for loading AST transformations
+     */
+    public GroovyClassLoader getTransformLoader() {
+        return Optional.ofNullable(getASTTransformationsContext().getTransformLoader()).orElseGet(this::getClassLoader);
+    }
+
     //---------------------------------------------------------------------------
     // SOURCE CREATION
 
     /**
      * Adds a set of file paths to the unit.
      */
-    public void addSources(String[] paths) {
+    public void addSources(final String[] paths) {
         for (String path : paths) {
             addSource(new File(path));
         }
@@ -430,7 +413,7 @@ public class CompilationUnit extends ProcessingUnit {
     /**
      * Adds a set of source files to the unit.
      */
-    public void addSources(File[] files) {
+    public void addSources(final File[] files) {
         for (File file : files) {
             addSource(file);
         }
@@ -439,33 +422,33 @@ public class CompilationUnit extends ProcessingUnit {
     /**
      * Adds a source file to the unit.
      */
-    public SourceUnit addSource(File file) {
+    public SourceUnit addSource(final File file) {
         return addSource(new SourceUnit(file, configuration, classLoader, getErrorCollector()));
     }
 
     /**
      * Adds a source file to the unit.
      */
-    public SourceUnit addSource(URL url) {
+    public SourceUnit addSource(final URL url) {
         return addSource(new SourceUnit(url, configuration, classLoader, getErrorCollector()));
     }
 
     /**
      * Adds a InputStream source to the unit.
      */
-    public SourceUnit addSource(String name, InputStream stream) {
+    public SourceUnit addSource(final String name, final InputStream stream) {
         ReaderSource source = new InputStreamReaderSource(stream, configuration);
         return addSource(new SourceUnit(name, source, configuration, classLoader, getErrorCollector()));
     }
 
-    public SourceUnit addSource(String name, String scriptText) {
+    public SourceUnit addSource(final String name, final String scriptText) {
         return addSource(new SourceUnit(name, scriptText, configuration, classLoader, getErrorCollector()));
     }
 
     /**
      * Adds a SourceUnit to the unit.
      */
-    public SourceUnit addSource(SourceUnit source) {
+    public SourceUnit addSource(final SourceUnit source) {
         String name = source.getName();
         source.setClassLoader(this.classLoader);
         for (SourceUnit su : queuedSources) {
@@ -480,7 +463,7 @@ public class CompilationUnit extends ProcessingUnit {
      */
     public Iterator<SourceUnit> iterator() {
         return new Iterator<SourceUnit>() {
-            Iterator<String> nameIterator = sources.keySet().iterator();
+            private Iterator<String> nameIterator = sources.keySet().iterator();
             @Override
             public boolean hasNext() {
                 return nameIterator.hasNext();
@@ -503,9 +486,9 @@ public class CompilationUnit extends ProcessingUnit {
      * this method without setting a SourceUnit will cause
      * NullPinterExceptions
      */
-    public void addClassNode(ClassNode node) {
-        ModuleNode module = new ModuleNode(this.ast);
-        this.ast.addModule(module);
+    public void addClassNode(final ClassNode node) {
+        ModuleNode module = new ModuleNode(getAST());
+        getAST().addModule(module);
         module.addClass(node);
     }
 
@@ -527,7 +510,7 @@ public class CompilationUnit extends ProcessingUnit {
      * Sets a ClassgenCallback.  You can have only one, and setting
      * it to {@code null} removes any existing setting.
      */
-    public void setClassgenCallback(ClassgenCallback visitor) {
+    public void setClassgenCallback(final ClassgenCallback visitor) {
         this.classgenCallback = visitor;
     }
 
@@ -550,7 +533,7 @@ public class CompilationUnit extends ProcessingUnit {
      * Sets a ProgressCallback.  You can have only one, and setting
      * it to {@code null} removes any existing setting.
      */
-    public void setProgressCallback(ProgressCallback callback) {
+    public void setProgressCallback(final ProgressCallback callback) {
         this.progressCallback = callback;
     }
 
@@ -606,29 +589,28 @@ public class CompilationUnit extends ProcessingUnit {
         errorCollector.failIfErrors();
     }
 
-    private void processPhaseOperations(int ph) {
-        LinkedList ops = phaseOperations[ph];
-        for (Object next : ops) {
-            doPhaseOperation(next);
+    private void processPhaseOperations(final int phase) {
+        for (Object op : phaseOperations[phase]) {
+            doPhaseOperation(op);
         }
     }
 
-    private void processNewPhaseOperations(int currPhase) {
-        recordPhaseOpsInAllOtherPhases(currPhase);
-        LinkedList currentPhaseNewOps = newPhaseOperations[currPhase];
+    private void processNewPhaseOperations(final int phase) {
+        recordPhaseOpsInAllOtherPhases(phase);
+        LinkedList currentPhaseNewOps = newPhaseOperations[phase];
         while (!currentPhaseNewOps.isEmpty()) {
             Object operation = currentPhaseNewOps.removeFirst();
             // push this operation to master list and then process it.
-            phaseOperations[currPhase].add(operation);
+            phaseOperations[phase].add(operation);
             doPhaseOperation(operation);
             // if this operation has brought in more phase ops for ast transforms, keep recording them
-            // in master list of other phases and keep processing them for this phase.
-            recordPhaseOpsInAllOtherPhases(currPhase);
-            currentPhaseNewOps = newPhaseOperations[currPhase];
+            // in master list of other phases and keep processing them for this phase
+            recordPhaseOpsInAllOtherPhases(phase);
+            currentPhaseNewOps = newPhaseOperations[phase];
         }
     }
 
-    private void doPhaseOperation(Object operation) {
+    private void doPhaseOperation(final Object operation) {
         if (operation instanceof PrimaryClassNodeOperation) {
             applyToPrimaryClassNodes((PrimaryClassNodeOperation) operation);
         } else if (operation instanceof SourceUnitOperation) {
@@ -638,10 +620,10 @@ public class CompilationUnit extends ProcessingUnit {
         }
     }
 
-    private void recordPhaseOpsInAllOtherPhases(int currPhase) {
+    private void recordPhaseOpsInAllOtherPhases(final int phase) {
         // apart from current phase, push new operations for every other phase in the master phase ops list
-        for (int ph = Phases.INITIALIZATION; ph <= Phases.ALL; ph++) {
-            if (ph != currPhase && !newPhaseOperations[ph].isEmpty()) {
+        for (int ph = Phases.INITIALIZATION; ph <= Phases.ALL; ph += 1) {
+            if (ph != phase && !newPhaseOperations[ph].isEmpty()) {
                 phaseOperations[ph].addAll(newPhaseOperations[ph]);
                 newPhaseOperations[ph].clear();
             }
@@ -649,7 +631,7 @@ public class CompilationUnit extends ProcessingUnit {
     }
 
     private void sortClasses() throws CompilationFailedException {
-        for (ModuleNode module : this.ast.getModules()) {
+        for (ModuleNode module : getAST().getModules()) {
             module.sortClasses();
         }
     }
@@ -667,9 +649,9 @@ public class CompilationUnit extends ProcessingUnit {
     protected boolean dequeued() throws CompilationFailedException {
         boolean dequeue = !queuedSources.isEmpty();
         while (!queuedSources.isEmpty()) {
-            SourceUnit su = queuedSources.removeFirst();
-            String name = su.getName();
-            sources.put(name, su);
+            SourceUnit unit = queuedSources.remove();
+            String name = unit.getName();
+            sources.put(name, unit);
         }
         if (dequeue) {
             gotoPhase(Phases.INITIALIZATION);
@@ -678,10 +660,11 @@ public class CompilationUnit extends ProcessingUnit {
     }
 
     /**
-     * Resolves all types
+     * Resolves all types.
      */
     private final SourceUnitOperation resolve = new SourceUnitOperation() {
-        public void call(SourceUnit source) throws CompilationFailedException {
+        @Override
+        public void call(final SourceUnit source) throws CompilationFailedException {
             List<ClassNode> classes = source.ast.getClasses();
             for (ClassNode node : classes) {
                 VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(source);
@@ -695,13 +678,15 @@ public class CompilationUnit extends ProcessingUnit {
     };
 
     private final PrimaryClassNodeOperation staticImport = new PrimaryClassNodeOperation() {
-        public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
+        @Override
+        public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
             staticImportVisitor.visitClass(classNode, source);
         }
     };
 
     private PrimaryClassNodeOperation defaultTransform = new PrimaryClassNodeOperation() {
-        public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
+        @Override
+        public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
             defaultTransformer.visitClass(classNode, source);
         }
     };
@@ -710,34 +695,30 @@ public class CompilationUnit extends ProcessingUnit {
      * Runs convert() on a single SourceUnit.
      */
     private final SourceUnitOperation convert = new SourceUnitOperation() {
-        public void call(SourceUnit source) throws CompilationFailedException {
+        @Override
+        public void call(final SourceUnit source) throws CompilationFailedException {
             source.convert();
-            CompilationUnit.this.ast.addModule(source.getAST());
-
-
-            if (CompilationUnit.this.progressCallback != null) {
-                CompilationUnit.this.progressCallback.call(source, CompilationUnit.this.phase);
+            getAST().addModule(source.getAST());
+            if (progressCallback != null) {
+                progressCallback.call(source, phase);
             }
         }
     };
 
     private final GroovyClassOperation output = new GroovyClassOperation() {
-        public void call(GroovyClass gclass) throws CompilationFailedException {
-            String name = gclass.getName().replace('.', File.separatorChar) + ".class";
+        @Override
+        public void call(final GroovyClass groovyClass) throws CompilationFailedException {
+            String name = groovyClass.getName().replace('.', File.separatorChar) + ".class";
             File path = new File(configuration.getTargetDirectory(), name);
 
-            //
-            // Ensure the path is ready for the file
-            //
+            // ensure the path is ready for the file
             File directory = path.getParentFile();
             if (directory != null && !directory.exists()) {
                 directory.mkdirs();
             }
 
-            //
-            // Create the file and write out the data
-            //
-            byte[] bytes = gclass.getBytes();
+            // create the file and write out the data
+            byte[] bytes = groovyClass.getBytes();
 
             try (FileOutputStream stream = new FileOutputStream(path)) {
                 stream.write(bytes, 0, bytes.length);
@@ -792,12 +773,8 @@ public class CompilationUnit extends ProcessingUnit {
      */
     private final PrimaryClassNodeOperation classgen = new PrimaryClassNodeOperation() {
         @Override
-        public boolean needSortedInput() {
-            return true;
-        }
-        @Override
-        public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
-            optimizer.visitClass(classNode, source); // GROOVY-4272: repositioned it here from staticImport
+        public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
+            optimizer.visitClass(classNode, source); // GROOVY-4272: repositioned it here from static import visitor
 
             //
             // Run the Verifier on the outer class
@@ -867,6 +844,10 @@ public class CompilationUnit extends ProcessingUnit {
                 classgen.call(source, context, innerClasses.removeFirst());
             }
         }
+        @Override
+        public boolean needSortedInput() {
+            return true;
+        }
     };
 
     protected ClassVisitor createClassVisitor() {
@@ -922,11 +903,11 @@ public class CompilationUnit extends ProcessingUnit {
      * if it isn't already there yet.
      */
     private final SourceUnitOperation mark = new SourceUnitOperation() {
-        public void call(SourceUnit source) throws CompilationFailedException {
+        @Override
+        public void call(final SourceUnit source) throws CompilationFailedException {
             if (source.phase < phase) {
                 source.gotoPhase(phase);
             }
-
             if (source.phase == phase && phaseComplete && !source.phaseComplete) {
                 source.completePhase();
             }
@@ -937,8 +918,9 @@ public class CompilationUnit extends ProcessingUnit {
     // LOOP SIMPLIFICATION FOR SourceUnit OPERATIONS
 
     /**
-     * An callback interface for use in the applyToSourceUnits loop driver.
+     * A callback interface for use in the applyToSourceUnits loop driver.
      */
+    // TODO: convert to functional interface
     public abstract static class SourceUnitOperation {
         public abstract void call(SourceUnit source) throws CompilationFailedException;
     }
@@ -948,7 +930,7 @@ public class CompilationUnit extends ProcessingUnit {
      * Automatically skips units that have already been processed
      * through the current phase.
      */
-    public void applyToSourceUnits(SourceUnitOperation body) throws CompilationFailedException {
+    public void applyToSourceUnits(final SourceUnitOperation body) throws CompilationFailedException {
         for (String name : sources.keySet()) {
             SourceUnit source = sources.get(name);
             if ((source.phase < phase) || (source.phase == phase && !source.phaseComplete)) {
@@ -966,7 +948,6 @@ public class CompilationUnit extends ProcessingUnit {
                 }
             }
         }
-
         getErrorCollector().failIfErrors();
     }
 
@@ -976,6 +957,7 @@ public class CompilationUnit extends ProcessingUnit {
     /**
      * An callback interface for use in the applyToPrimaryClassNodes loop driver.
      */
+    // TODO: convert to functional interface
     public abstract static class PrimaryClassNodeOperation {
         public abstract void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException;
 
@@ -984,20 +966,21 @@ public class CompilationUnit extends ProcessingUnit {
         }
     }
 
+    // TODO: convert to functional interface
     public abstract static class GroovyClassOperation {
-        public abstract void call(GroovyClass gclass) throws CompilationFailedException;
+        public abstract void call(GroovyClass groovyClass) throws CompilationFailedException;
     }
 
     private static int getSuperClassCount(ClassNode element) {
         int count = 0;
         while (element != null) {
-            count++;
+            count += 1;
             element = element.getSuperClass();
         }
         return count;
     }
 
-    private int getSuperInterfaceCount(ClassNode element) {
+    private int getSuperInterfaceCount(final ClassNode element) {
         int count = 1;
         ClassNode[] interfaces = element.getInterfaces();
         for (ClassNode anInterface : interfaces) {
@@ -1006,21 +989,18 @@ public class CompilationUnit extends ProcessingUnit {
         return count;
     }
 
-    private List<ClassNode> getPrimaryClassNodes(boolean sort) {
-        List<ClassNode> unsorted = new ArrayList<ClassNode>();
-        for (ModuleNode module : this.ast.getModules()) {
-            unsorted.addAll(module.getClasses());
-        }
+    private List<ClassNode> getPrimaryClassNodes(final boolean sort) {
+        List<ClassNode> unsorted = getAST().getModules().stream()
+            .flatMap(module -> module.getClasses().stream()).collect(Collectors.toList());
 
         if (!sort) return unsorted;
 
-        int unsortedSize = unsorted.size();
-        int[] indexClass = new int[unsortedSize];
-        int[] indexInterface = new int[unsortedSize];
+        int n = unsorted.size();
+        int[] indexClass = new int[n];
+        int[] indexInterface = new int[n];
         {
             int i = 0;
-            for (Iterator<ClassNode> iter = unsorted.iterator(); iter.hasNext(); i++) {
-                ClassNode element = iter.next();
+            for (ClassNode element : unsorted) {
                 if (element.isInterface()) {
                     indexInterface[i] = getSuperInterfaceCount(element);
                     indexClass[i] = -1;
@@ -1028,6 +1008,7 @@ public class CompilationUnit extends ProcessingUnit {
                     indexClass[i] = getSuperClassCount(element);
                     indexInterface[i] = -1;
                 }
+                i += 1;
             }
         }
 
@@ -1036,12 +1017,12 @@ public class CompilationUnit extends ProcessingUnit {
         return sorted;
     }
 
-    private static List<ClassNode> getSorted(int[] index, List<ClassNode> unsorted) {
+    private static List<ClassNode> getSorted(final int[] index, final List<ClassNode> unsorted) {
         int unsortedSize = unsorted.size();
-        List<ClassNode> sorted = new ArrayList<ClassNode>(unsortedSize);
-        for (int i = 0; i < unsortedSize; i++) {
+        List<ClassNode> sorted = new ArrayList<>(unsortedSize);
+        for (int i = 0; i < unsortedSize; i += 1) {
             int min = -1;
-            for (int j = 0; j < unsortedSize; j++) {
+            for (int j = 0; j < unsortedSize; j += 1) {
                 if (index[j] == -1) continue;
                 if (min == -1 || index[j] < index[min]) {
                     min = j;
@@ -1059,18 +1040,18 @@ public class CompilationUnit extends ProcessingUnit {
      * our AST.  Automatically skips units that have already been processed
      * through the current phase.
      */
-    public void applyToPrimaryClassNodes(PrimaryClassNodeOperation body) throws CompilationFailedException {
+    public void applyToPrimaryClassNodes(final PrimaryClassNodeOperation body) throws CompilationFailedException {
         for (ClassNode classNode : getPrimaryClassNodes(body.needSortedInput())) {
             SourceUnit context = null;
             try {
                 context = classNode.getModule().getContext();
                 if (context == null || context.phase < phase || (context.phase == phase && !context.phaseComplete)) {
                     int offset = 1;
-                    for (Iterator<InnerClassNode> iterator = classNode.getInnerClasses(); iterator.hasNext(); ) {
-                        iterator.next();
-                        offset++;
+                    for (Iterator<InnerClassNode> it = classNode.getInnerClasses(); it.hasNext(); ) {
+                        it.next();
+                        offset += 1;
                     }
-                    body.call(context, new GeneratorContext(this.ast, offset), classNode);
+                    body.call(context, new GeneratorContext(getAST(), offset), classNode);
                 }
             } catch (CompilationFailedException e) {
                 // fall through, getErrorReporter().failIfErrors() will trigger
@@ -1109,7 +1090,7 @@ public class CompilationUnit extends ProcessingUnit {
         }
     }
 
-    public void applyToGeneratedGroovyClasses(GroovyClassOperation body) throws CompilationFailedException {
+    public void applyToGeneratedGroovyClasses(final GroovyClassOperation body) throws CompilationFailedException {
         if (this.phase != Phases.OUTPUT && !(this.phase == Phases.CLASS_GENERATION && this.phaseComplete)) {
             throw new GroovyBugError("CompilationUnit not ready for output(). Current phase=" + getPhaseDescription());
         }
@@ -1135,23 +1116,7 @@ public class CompilationUnit extends ProcessingUnit {
         getErrorCollector().failIfErrors();
     }
 
-    private void changeBugText(GroovyBugError e, SourceUnit context) {
-        e.setBugText("exception in phase '" + getPhaseDescription() + "' in source unit '" + ((context != null) ? context.getName() : "?") + "' " + e.getBugText());
-    }
-
-    public ClassNodeResolver getClassNodeResolver() {
-        return classNodeResolver;
-    }
-
-    public void setClassNodeResolver(ClassNodeResolver classNodeResolver) {
-        this.classNodeResolver = classNodeResolver;
-    }
-
-    public Set<JavaFileObject> getJavaCompilationUnitSet() {
-        return javaCompilationUnitSet;
-    }
-
-    public void addJavaCompilationUnits(Set<JavaFileObject> javaCompilationUnitSet) {
-        this.javaCompilationUnitSet.addAll(javaCompilationUnitSet);
+    private void changeBugText(final GroovyBugError e, final SourceUnit context) {
+        e.setBugText("exception in phase '" + getPhaseDescription() + "' in source unit '" + (context != null ? context.getName() : "?") + "' " + e.getBugText());
     }
 }
diff --git a/src/main/java/org/codehaus/groovy/control/Phases.java b/src/main/java/org/codehaus/groovy/control/Phases.java
index eecba8d..2d962ae 100644
--- a/src/main/java/org/codehaus/groovy/control/Phases.java
+++ b/src/main/java/org/codehaus/groovy/control/Phases.java
@@ -22,37 +22,46 @@ package org.codehaus.groovy.control;
  * Compilation phase identifiers.
  */
 public class Phases {
-    public static final int INITIALIZATION = 1;   // Opening of files and such
-    public static final int PARSING = 2;   // Lexing, parsing, and AST building
-    public static final int CONVERSION = 3;   // CST to AST conversion
-    public static final int SEMANTIC_ANALYSIS = 4;   // AST semantic analysis and elucidation
-    public static final int CANONICALIZATION = 5;   // AST completion
-    public static final int INSTRUCTION_SELECTION = 6;   // Class generation, phase 1
-    public static final int CLASS_GENERATION = 7;   // Class generation, phase 2
-    public static final int OUTPUT = 8;   // Output of class to disk
-    public static final int FINALIZATION = 9;   // Cleanup
-    public static final int ALL = 9;   // Synonym for full compilation
+    /** Opening of files and such */
+    public static final int INITIALIZATION = 1;
+    /** Lexing, parsing, and AST building */
+    public static final int PARSING = 2;
+    /** CST to AST conversion */
+    public static final int CONVERSION = 3;
+    /** AST semantic analysis and elucidation */
+    public static final int SEMANTIC_ANALYSIS = 4;
+    /** AST completion */
+    public static final int CANONICALIZATION = 5;
+    /** Class generation (pt.1) */
+    public static final int INSTRUCTION_SELECTION = 6;
+    /** Class generation (pt.2) */
+    public static final int CLASS_GENERATION = 7;   //
+    /** Output of class to disk */
+    public static final int OUTPUT = 8;
+    /** Cleanup */
+    public static final int FINALIZATION = 9;
 
+    /** Synonym for full compilation */
+    public static final int ALL = FINALIZATION;
+
+    // TODO: If no reference is made to array, convert to switch in getDescription(int).
     public static final String[] descriptions = {
-            "startup"
-            , "initialization"
-            , "parsing"
-            , "conversion"
-            , "semantic analysis"
-            , "canonicalization"
-            , "instruction selection"
-            , "class generation"
-            , "output"
-            , "cleanup"
+        "startup",
+        "initialization",
+        "parsing",
+        "conversion",
+        "semantic analysis",
+        "canonicalization",
+        "instruction selection",
+        "class generation",
+        "output",
+        "cleanup",
     };
 
-
     /**
      * Returns a description of the specified phase.
      */
-
-    public static String getDescription(int phase) {
+    public static String getDescription(final int phase) {
         return descriptions[phase];
     }
-
 }
diff --git a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
index 06e9df1..30b3476 100644
--- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
@@ -248,6 +248,7 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
 
     public ResolveVisitor(final CompilationUnit compilationUnit) {
         this.compilationUnit = compilationUnit;
+        // TODO: CompilationUnit.ClassNodeResolver?
         setClassNodeResolver(new ClassNodeResolver());
     }
 
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompilationTestSupport.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompilationTestSupport.groovy
index bcfc58f..9e9c67b 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompilationTestSupport.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompilationTestSupport.groovy
@@ -121,8 +121,7 @@ trait StaticCompilationTestSupport {
         void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) {
             def unit = testCase.compilationUnit
             if (!unit) return
-            List<GroovyClass> classes = unit.generatedClasses
-            classes.each { GroovyClass groovyClass ->
+            unit.classes.each { GroovyClass groovyClass ->
                 StringWriter stringWriter = new StringWriter()
                 try {
                     ClassReader cr = new ClassReader(groovyClass.bytes)
@@ -135,5 +134,4 @@ trait StaticCompilationTestSupport {
             }
         }
     }
-
 }