/*
 *  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 groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyRuntimeException;
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;
import org.codehaus.groovy.classgen.EnumVisitor;
import org.codehaus.groovy.classgen.ExtendedVerifier;
import org.codehaus.groovy.classgen.GeneratorContext;
import org.codehaus.groovy.classgen.InnerClassCompletionVisitor;
import org.codehaus.groovy.classgen.InnerClassVisitor;
import org.codehaus.groovy.classgen.VariableScopeVisitor;
import org.codehaus.groovy.classgen.Verifier;
import org.codehaus.groovy.control.customizers.CompilationCustomizer;
import org.codehaus.groovy.control.io.InputStreamReaderSource;
import org.codehaus.groovy.control.io.ReaderSource;
import org.codehaus.groovy.control.messages.ExceptionMessage;
import org.codehaus.groovy.control.messages.Message;
import org.codehaus.groovy.control.messages.SimpleMessage;
import org.codehaus.groovy.syntax.RuntimeParserException;
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.trait.TraitComposer;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.CodeSource;
import java.util.ArrayList;
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 static java.util.stream.Collectors.toList;
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
 * compilation to be run again (to affect only the deltas).
 * <p>
 * You can also add PhaseOperations to this compilation using the addPhaseOperation method.
 * This is commonly used when you want to wire a new AST Transformation into the compilation.
 */
public class CompilationUnit extends ProcessingUnit {

    /** The overall AST for this CompilationUnit. */
    protected CompileUnit ast; // TODO: Switch to private and access through getAST().

    /** The source units from which this unit is built. */
    protected Map<String, SourceUnit> sources = new LinkedHashMap<>();
    protected Queue<SourceUnit> queuedSources = new LinkedList<>();

    /** The classes generated during classgen. */
    private List<GroovyClass> generatedClasses = new ArrayList<>();

    private Deque<PhaseOperation>[] phaseOperations;
    private Deque<PhaseOperation>[] 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<>();
        }
    }

    /** Controls behavior of {@link #classgen} and other routines. */
    protected boolean debug;
    /** True after the first {@link #configure(CompilerConfiguration)} operation. */
    protected boolean configured;

    /** A callback for use during {@link #classgen} */
    protected ClassgenCallback classgenCallback;
    /** A callback for use during {@link #compile()} */
    protected ProgressCallback progressCallback;

    protected ClassNodeResolver classNodeResolver = new ClassNodeResolver();
    protected ResolveVisitor resolveVisitor = new ResolveVisitor(this);

    /** The AST transformations state data. */
    protected ASTTransformationsContext astTransformationsContext;

    private Set<javax.tools.JavaFileObject> javaCompilationUnitSet = new HashSet<>();

    /**
     * Initializes the CompilationUnit with defaults.
     */
    public CompilationUnit() {
        this(null, null, null);
    }

    /**
     * Initializes the CompilationUnit with defaults except for class loader.
     */
    public CompilationUnit(final GroovyClassLoader loader) {
        this(null, null, loader);
    }

    /**
     * Initializes the CompilationUnit with no security considerations.
     */
    public CompilationUnit(final CompilerConfiguration configuration) {
        this(configuration, null, null);
    }

    /**
     * Initializes the CompilationUnit with a CodeSource for controlling
     * security stuff and a class loader for loading classes.
     */
    public CompilationUnit(final CompilerConfiguration configuration, final CodeSource codeSource, final GroovyClassLoader loader) {
        this(configuration, codeSource, loader, null);
    }

    /**
     * Initializes the CompilationUnit with a CodeSource for controlling
     * security stuff, a class loader for loading classes, and a class
     * loader for loading AST transformations.
     * <p>
     * <b>Note</b>: The transform loader must be able to load compiler classes.
     * That means {@link #classLoader} must be at last a parent to {@code transformLoader}.
     * The other loader has no such constraint.
     *
     * @param transformLoader - the loader for transforms
     * @param loader          - loader used to resolve classes against during compilation
     * @param codeSource      - security setting for the compilation
     * @param configuration   - compilation configuration
     */
    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.ast = new CompileUnit(getClassLoader(), codeSource, getConfiguration());

        addPhaseOperations();
        applyCompilationCustomizers();
    }

    private void addPhaseOperations() {
        addPhaseOperation(SourceUnit::parse, Phases.PARSING);

        addPhaseOperation(source -> {
            source.convert();
            // add module to compile unit
            getAST().addModule(source.getAST());
            Optional.ofNullable(getProgressCallback())
                .ifPresent(callback -> callback.call(source, getPhase()));
        }, Phases.CONVERSION);

        addPhaseOperation((final SourceUnit source, final GeneratorContext context, final ClassNode classNode) -> {
            GroovyClassVisitor visitor = new EnumVisitor(this, source);
            visitor.visitClass(classNode);
        }, Phases.CONVERSION);

        addPhaseOperation(resolve, Phases.SEMANTIC_ANALYSIS);

        addPhaseOperation((final SourceUnit source, final GeneratorContext context, final ClassNode classNode) -> {
            GroovyClassVisitor visitor = new StaticImportVisitor(classNode, source);
            visitor.visitClass(classNode);
        }, Phases.SEMANTIC_ANALYSIS);

        addPhaseOperation((final SourceUnit source, final GeneratorContext context, final ClassNode classNode) -> {
            GroovyClassVisitor visitor = new InnerClassVisitor(this, source);
            visitor.visitClass(classNode);
        }, Phases.SEMANTIC_ANALYSIS);

        addPhaseOperation((final SourceUnit source, final GeneratorContext context, final ClassNode classNode) -> {
            if (!classNode.isSynthetic()) {
                GroovyClassVisitor visitor = new GenericsVisitor(source);
                visitor.visitClass(classNode);
            }
        }, Phases.SEMANTIC_ANALYSIS);

        addPhaseOperation((final SourceUnit source, final GeneratorContext context, final ClassNode classNode) -> {
            TraitComposer.doExtendTraits(classNode, source, this);
        }, Phases.CANONICALIZATION);

        addPhaseOperation(source -> {
            List<ClassNode> classes = source.getAST().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) {
                                first = false;
                            } else {
                                message.append(", ");
                            }
                            message.append(cn.getName());
                        }
                    }

                    getErrorCollector().addErrorAndContinue(
                            new SimpleMessage(message.toString(), this)
                    );
                    it.remove();
                }
            }
        }, Phases.CANONICALIZATION);

        addPhaseOperation(classgen, Phases.CLASS_GENERATION);

        addPhaseOperation(groovyClass -> {
            String name = groovyClass.getName().replace('.', File.separatorChar) + ".class";
            File path = new File(getConfiguration().getTargetDirectory(), name);

            // 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
            try (FileOutputStream stream = new FileOutputStream(path)) {
                byte[] bytes = groovyClass.getBytes();
                stream.write(bytes, 0, bytes.length);
            } catch (IOException e) {
                getErrorCollector().addError(Message.create(e.getMessage(), this));
            }
        });

        addPhaseOperation((final SourceUnit source, final GeneratorContext context, final ClassNode classNode) -> {
            AnnotationCollectorTransform.ClassChanger xformer = new AnnotationCollectorTransform.ClassChanger();
            xformer.transformClass(classNode);
        }, Phases.SEMANTIC_ANALYSIS);
        ASTTransformationVisitor.addPhaseOperations(this);

        // post-transform operations:

        addPhaseOperation((final SourceUnit source, final GeneratorContext context, final ClassNode classNode) -> {
            StaticVerifier verifier = new StaticVerifier();
            verifier.visitClass(classNode, source);
        }, Phases.SEMANTIC_ANALYSIS);

        addPhaseOperation((final SourceUnit source, final GeneratorContext context, final ClassNode classNode) -> {
            GroovyClassVisitor visitor = new InnerClassCompletionVisitor(this, source);
            visitor.visitClass(classNode);

            visitor = new EnumCompletionVisitor(this, source);
            visitor.visitClass(classNode);
        }, Phases.CANONICALIZATION);

        addPhaseOperation((final SourceUnit source, final GeneratorContext context, final ClassNode classNode) -> {
            Object callback = classNode.getNodeMetaData(DYNAMIC_OUTER_NODE_CALLBACK);
            if (callback instanceof IPrimaryClassNodeOperation) {
                ((IPrimaryClassNodeOperation) callback).call(source, context, classNode);
                classNode.removeNodeMetaData(DYNAMIC_OUTER_NODE_CALLBACK);
            }
        }, Phases.INSTRUCTION_SELECTION);

        addPhaseOperation((final SourceUnit source, final GeneratorContext context, final ClassNode classNode) -> {
            // TODO: Can this be moved into org.codehaus.groovy.transform.sc.transformers.VariableExpressionTransformer?
            GroovyClassVisitor visitor = new ClassCodeExpressionTransformer() {
                @Override
                protected SourceUnit getSourceUnit() {
                    return source;
                }

                @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;
                }
            };
            visitor.visitClass(classNode);
        }, Phases.INSTRUCTION_SELECTION);
    }

    private void applyCompilationCustomizers() {
        for (CompilationCustomizer customizer : getConfiguration().getCompilationCustomizers()) {
            if (customizer instanceof CompilationUnitAware) {
                ((CompilationUnitAware) customizer).setCompilationUnit(this);
            }
            addPhaseOperation(customizer, customizer.getPhase().getPhaseNumber());
        }
    }

    public void addPhaseOperation(final IGroovyClassOperation op) {
        phaseOperations[Phases.OUTPUT].addFirst(op);
    }

    public void addPhaseOperation(final ISourceUnitOperation op, final int phase) {
        validatePhase(phase);
        phaseOperations[phase].add(op);
    }

    public void addPhaseOperation(final IPrimaryClassNodeOperation op, final int phase) {
        validatePhase(phase);
        phaseOperations[phase].add(op);
    }

    public void addFirstPhaseOperation(final IPrimaryClassNodeOperation op, final int phase) {
        validatePhase(phase);
        phaseOperations[phase].addFirst(op);
    }

    public void addNewPhaseOperation(final ISourceUnitOperation 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(final CompilerConfiguration configuration) {
        super.configure(configuration);
        this.debug = getConfiguration().getDebug();
        this.configured = true;
    }

    /**
     * Returns the CompileUnit that roots our AST.
     */
    public CompileUnit getAST() {
        return this.ast;
    }

    /**
     * Get the GroovyClasses generated by compile().
     */
    public List<GroovyClass> getClasses() {
        return generatedClasses;
    }

    /**
     * Convenience routine to get the first ClassNode, for
     * when you are sure there is only one.
     */
    public ClassNode getFirstClassNode() {
        return getAST().getModules().get(0).getClasses().get(0);
    }

    /**
     * Convenience routine to get the named ClassNode.
     */
    public ClassNode getClassNode(final String name) {
        ClassNode[] result = new ClassNode[1];
        IPrimaryClassNodeOperation handler = (source, context, classNode) -> {
            if (classNode.getName().equals(name)) {
                result[0] = classNode;
            }
        };
        try {
            handler.doPhaseOperation(this);
        } catch (CompilationFailedException e) {
            if (debug) e.printStackTrace();
        }
        return result[0];
    }

    /**
     * @return the AST transformations current context
     */
    public ASTTransformationsContext getASTTransformationsContext() {
        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(final String[] paths) {
        for (String path : paths) {
            addSource(new File(path));
        }
    }

    /**
     * Adds a set of source files to the unit.
     */
    public void addSources(final File[] files) {
        for (File file : files) {
            addSource(file);
        }
    }

    /**
     * Adds a source file to the unit.
     */
    public SourceUnit addSource(final File file) {
        return addSource(new SourceUnit(file, getConfiguration(), getClassLoader(), getErrorCollector()));
    }

    /**
     * Adds a source file to the unit.
     */
    public SourceUnit addSource(final URL url) {
        return addSource(new SourceUnit(url, getConfiguration(), getClassLoader(), getErrorCollector()));
    }

    /**
     * Adds a InputStream source to the unit.
     */
    public SourceUnit addSource(final String name, final InputStream stream) {
        ReaderSource source = new InputStreamReaderSource(stream, getConfiguration());
        return addSource(new SourceUnit(name, source, getConfiguration(), getClassLoader(), getErrorCollector()));
    }

    public SourceUnit addSource(final String name, final String scriptText) {
        return addSource(new SourceUnit(name, scriptText, getConfiguration(), getClassLoader(), getErrorCollector()));
    }

    /**
     * Adds a SourceUnit to the unit.
     */
    public SourceUnit addSource(final SourceUnit source) {
        String name = source.getName();
        source.setClassLoader(getClassLoader());
        for (SourceUnit su : queuedSources) {
            if (name.equals(su.getName())) return su;
        }
        queuedSources.add(source);
        return source;
    }

    /**
     * Returns an iterator on the unit's SourceUnits.
     */
    public Iterator<SourceUnit> iterator() {
        return new Iterator<SourceUnit>() {
            private Iterator<String> nameIterator = sources.keySet().iterator();
            @Override
            public boolean hasNext() {
                return nameIterator.hasNext();
            }
            @Override
            public SourceUnit next() {
                String name = nameIterator.next();
                return sources.get(name);
            }
            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }

    /**
     * Adds a ClassNode directly to the unit (ie. without source).
     * WARNING: the source is needed for error reporting, using
     * this method without setting a SourceUnit will cause
     * NullPinterExceptions
     */
    public void addClassNode(final ClassNode node) {
        ModuleNode module = new ModuleNode(getAST());
        getAST().addModule(module);
        module.addClass(node);
    }

    //---------------------------------------------------------------------------
    // EXTERNAL CALLBACKS

    /**
     * A callback interface you can use to "accompany" the classgen()
     * code as it traverses the ClassNode tree.  You will be called-back
     * for each primary and inner class.  Use setClassgenCallback() before
     * running compile() to set your callback.
     */
    @FunctionalInterface
    public interface ClassgenCallback {
        void call(ClassVisitor writer, ClassNode node) throws CompilationFailedException;
    }

    public ClassgenCallback getClassgenCallback() {
        return classgenCallback;
    }

    /**
     * Sets a ClassgenCallback.  You can have only one, and setting
     * it to {@code null} removes any existing setting.
     */
    public void setClassgenCallback(final ClassgenCallback visitor) {
        this.classgenCallback = visitor;
    }

    /**
     * A callback interface you can use to get a callback after every
     * unit of the compile process.  You will be called-back with a
     * ProcessingUnit and a phase indicator.  Use setProgressCallback()
     * before running compile() to set your callback.
     */
    @FunctionalInterface
    public interface ProgressCallback {
        void call(ProcessingUnit context, int phase) throws CompilationFailedException;
    }

    public ProgressCallback getProgressCallback() {
        return progressCallback;
    }

    /**
     * Sets a ProgressCallback.  You can have only one, and setting
     * it to {@code null} removes any existing setting.
     */
    public void setProgressCallback(final ProgressCallback callback) {
        this.progressCallback = callback;
    }

    //---------------------------------------------------------------------------
    // ACTIONS

    /**
     * Synonym for {@code compile(Phases.ALL)}.
     */
    public void compile() throws CompilationFailedException {
        compile(Phases.ALL);
    }

    /**
     * Compiles the compilation unit from sources.
     */
    public void compile(int throughPhase) throws CompilationFailedException {
        //
        // To support delta compilations, we always restart
        // the compiler.  The individual passes are responsible
        // for not reprocessing old code.
        gotoPhase(Phases.INITIALIZATION);
        throughPhase = Math.min(throughPhase, Phases.ALL);

        while (throughPhase >= phase && phase <= Phases.ALL) {

            if (phase == Phases.SEMANTIC_ANALYSIS) {
                resolve.doPhaseOperation(this);
                if (dequeued()) continue;
            }

            processPhaseOperations(phase);
            // Grab processing may have brought in new AST transforms into various phases, process them as well
            processNewPhaseOperations(phase);

            Optional.ofNullable(getProgressCallback())
                .ifPresent(callback -> callback.call(this, phase));
            completePhase();
            mark();

            if (dequeued()) continue;

            gotoPhase(phase + 1);

            if (phase == Phases.CLASS_GENERATION) {
                sortClasses();
            }
        }

        getErrorCollector().failIfErrors();
    }

    private void processPhaseOperations(final int phase) {
        for (PhaseOperation op : phaseOperations[phase]) {
            op.doPhaseOperation(this);
        }
    }

    private void processNewPhaseOperations(final int phase) {
        recordPhaseOpsInAllOtherPhases(phase);
        Deque<PhaseOperation> currentPhaseNewOps = newPhaseOperations[phase];
        while (!currentPhaseNewOps.isEmpty()) {
            PhaseOperation operation = currentPhaseNewOps.removeFirst();
            // push this operation to master list and then process it
            phaseOperations[phase].add(operation);
            operation.doPhaseOperation(this);
            // 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(phase);
            currentPhaseNewOps = newPhaseOperations[phase];
        }
    }

    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 += 1) {
            if (ph != phase && !newPhaseOperations[ph].isEmpty()) {
                phaseOperations[ph].addAll(newPhaseOperations[ph]);
                newPhaseOperations[ph].clear();
            }
        }
    }

    private void sortClasses() {
        for (ModuleNode module : getAST().getModules()) {
            module.sortClasses();
        }
    }

    /**
     * Dequeues any source units add through addSource and resets the compiler phase
     * to initialization.
     * <p>
     * Note: this does not mean a file is recompiled. If a SourceUnit has already passed
     * a phase it is skipped until a higher phase is reached.
     *
     * @return true if there was a queued source
     * @throws CompilationFailedException
     */
    protected boolean dequeued() throws CompilationFailedException {
        boolean dequeue = !queuedSources.isEmpty();
        while (!queuedSources.isEmpty()) {
            SourceUnit unit = queuedSources.remove();
            String name = unit.getName();
            sources.put(name, unit);
        }
        if (dequeue) {
            gotoPhase(Phases.INITIALIZATION);
        }
        return dequeue;
    }

    /**
     * Resolves all types.
     */
    private final ISourceUnitOperation resolve = (final SourceUnit source) -> {
        for (ClassNode classNode : source.getAST().getClasses()) {
            GroovyClassVisitor visitor = new VariableScopeVisitor(source);
            visitor.visitClass(classNode);

            resolveVisitor.setClassNodeResolver(classNodeResolver);
            resolveVisitor.startResolving(classNode, source);
        }
    };

    /**
     * Runs class generation on a single {@code ClassNode}.
     */
    private final IPrimaryClassNodeOperation classgen = new IPrimaryClassNodeOperation() {
        @Override
        public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
            new OptimizerVisitor(CompilationUnit.this).visitClass(classNode, source); // GROOVY-4272: repositioned from static import visitor

            //
            // Run the Verifier on the outer class
            //
            GroovyClassVisitor visitor = new Verifier();
            try {
                visitor.visitClass(classNode);
            } catch (RuntimeParserException rpe) {
                getErrorCollector().addError(new SyntaxException(rpe.getMessage(), rpe.getNode()), source);
            }

            visitor = new LabelVerifier(source);
            visitor.visitClass(classNode);

            visitor = new InstanceOfVerifier() {
                @Override
                protected SourceUnit getSourceUnit() {
                    return source;
                }
            };
            visitor.visitClass(classNode);

            visitor = new ClassCompletionVerifier(source);
            visitor.visitClass(classNode);

            visitor = new ExtendedVerifier(source);
            visitor.visitClass(classNode);

            // because the class may be generated even if a error was found
            // and that class may have an invalid format we fail here if needed
            getErrorCollector().failIfErrors();

            //
            // Prep the generator machinery
            //
            ClassVisitor classVisitor = createClassVisitor();

            String sourceName = (source == null ? classNode.getModule().getDescription() : source.getName());
            // only show the file name and its extension like javac does in its stacktraces rather than the full path
            // also takes care of both \ and / depending on the host compiling environment
            if (sourceName != null) {
                sourceName = sourceName.substring(Math.max(sourceName.lastIndexOf('\\'), sourceName.lastIndexOf('/')) + 1);
            }

            //
            // Run the generation and create the class (if required)
            //
            visitor = new AsmClassGenerator(source, context, classVisitor, sourceName);
            visitor.visitClass(classNode);

            byte[] bytes = ((ClassWriter) classVisitor).toByteArray();
            getClasses().add(new GroovyClass(classNode.getName(), bytes));

            //
            // Handle any callback that's been set
            //
            Optional.ofNullable(getClassgenCallback())
                .ifPresent(callback -> callback.call(classVisitor, classNode));

            //
            // Recurse for inner classes
            //
            LinkedList<ClassNode> innerClasses = ((AsmClassGenerator) visitor).getInnerClasses();
            while (!innerClasses.isEmpty()) {
                classgen.call(source, context, innerClasses.removeFirst());
            }
        }

        @Override
        public boolean needSortedInput() {
            return true;
        }
    };

    protected ClassVisitor createClassVisitor() {
        CompilerConfiguration config = getConfiguration();
        int computeMaxStackAndFrames = ClassWriter.COMPUTE_MAXS;
        if (CompilerConfiguration.isPostJDK7(config.getTargetBytecode()) || config.isIndyEnabled()) {
            computeMaxStackAndFrames += ClassWriter.COMPUTE_FRAMES;
        }
        return new ClassWriter(computeMaxStackAndFrames) {
            private ClassNode getClassNode(String name) {
                // try classes under compilation
                CompileUnit cu = getAST();
                ClassNode cn = cu.getClass(name);
                if (cn != null) return cn;
                // try inner classes
                cn = cu.getGeneratedInnerClass(name);
                if (cn != null) return cn;
                ClassNodeResolver.LookupResult lookupResult = getClassNodeResolver().resolveName(name, CompilationUnit.this);
                return lookupResult == null ? null : lookupResult.getClassNode();
            }
            private ClassNode getCommonSuperClassNode(ClassNode c, ClassNode d) {
                // adapted from ClassWriter code
                if (c.isDerivedFrom(d)) return d;
                if (d.isDerivedFrom(c)) return c;
                if (c.isInterface() || d.isInterface()) return ClassHelper.OBJECT_TYPE;
                do {
                    c = c.getSuperClass();
                } while (c != null && !d.isDerivedFrom(c));
                if (c == null) return ClassHelper.OBJECT_TYPE;
                return c;
            }
            @Override
            protected String getCommonSuperClass(String arg1, String arg2) {
                ClassNode a = getClassNode(arg1.replace('/', '.'));
                ClassNode b = getClassNode(arg2.replace('/', '.'));
                return getCommonSuperClassNode(a,b).getName().replace('.','/');
            }
        };
    }

    //---------------------------------------------------------------------------
    // PHASE HANDLING

    /**
     * Updates the phase marker on all sources.
     */
    protected void mark() throws CompilationFailedException {
        ISourceUnitOperation mark = (final SourceUnit source) -> {
            if (source.phase < phase) {
                source.gotoPhase(phase);
            }
            if (source.phase == phase && phaseComplete && !source.phaseComplete) {
                source.completePhase();
            }
        };
        mark.doPhaseOperation(this);
    }

    //---------------------------------------------------------------------------
    // LOOP SIMPLIFICATION FOR SourceUnit OPERATIONS

    private interface PhaseOperation {
        void doPhaseOperation(CompilationUnit unit);
    }

    @FunctionalInterface
    public interface ISourceUnitOperation extends PhaseOperation {
        void call(SourceUnit source) throws CompilationFailedException;

        /**
         * A loop driver for applying operations to all SourceUnits.
         * Automatically skips units that have already been processed
         * through the current phase.
         */
        @Override
        default void doPhaseOperation(final CompilationUnit unit) throws CompilationFailedException {
            for (String name : unit.sources.keySet()) {
                SourceUnit source = unit.sources.get(name);
                if (source.phase < unit.phase || (source.phase == unit.phase && !source.phaseComplete)) {
                    try {
                        this.call(source);
                    } catch (CompilationFailedException e) {
                        throw e;
                    } catch (Exception e) {
                        GroovyBugError gbe = new GroovyBugError(e);
                        unit.changeBugText(gbe, source);
                        throw gbe;
                    } catch (GroovyBugError e) {
                        unit.changeBugText(e, source);
                        throw e;
                    }
                }
            }
            unit.getErrorCollector().failIfErrors();
        }
    }

    //---------------------------------------------------------------------------
    // LOOP SIMPLIFICATION FOR PRIMARY ClassNode OPERATIONS

    @FunctionalInterface
    public interface IPrimaryClassNodeOperation extends PhaseOperation {
        void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException;

        /**
         * A loop driver for applying operations to all primary ClassNodes in
         * our AST.  Automatically skips units that have already been processed
         * through the current phase.
         */
        @Override
        default void doPhaseOperation(final CompilationUnit unit) throws CompilationFailedException {
            for (ClassNode classNode : unit.getPrimaryClassNodes(this.needSortedInput())) {
                SourceUnit context = null;
                try {
                    context = classNode.getModule().getContext();
                    if (context == null || context.phase < unit.phase || (context.phase == unit.phase && !context.phaseComplete)) {
                        int offset = 1;
                        for (Iterator<InnerClassNode> it = classNode.getInnerClasses(); it.hasNext(); ) {
                            it.next();
                            offset += 1;
                        }
                        this.call(context, new GeneratorContext(unit.getAST(), offset), classNode);
                    }
                } catch (CompilationFailedException e) {
                    // fall through
                } catch (NullPointerException npe) {
                    GroovyBugError gbe = new GroovyBugError("unexpected NullPointerException", npe);
                    unit.changeBugText(gbe, context);
                    throw gbe;
                } catch (GroovyBugError e) {
                    unit.changeBugText(e, context);
                    throw e;
                } catch (Exception | LinkageError e) {
                    ErrorCollector errorCollector = null;
                    // check for a nested compilation exception
                    for (Throwable t = e.getCause(); t != e && t != null; t = t.getCause()) {
                        if (t instanceof MultipleCompilationErrorsException) {
                            errorCollector = ((MultipleCompilationErrorsException) t).getErrorCollector();
                            break;
                        }
                    }

                    if (errorCollector != null) {
                        unit.getErrorCollector().addCollectorContents(errorCollector);
                    } else {
                        if (e instanceof GroovyRuntimeException) {
                            GroovyRuntimeException gre = (GroovyRuntimeException) e;
                            context = Optional.ofNullable(gre.getModule()).map(ModuleNode::getContext).orElse(context);
                        }
                        if (context != null) {
                            if (e instanceof SyntaxException) {
                                unit.getErrorCollector().addError((SyntaxException) e, context);
                            } else if (e.getCause() instanceof SyntaxException) {
                                unit.getErrorCollector().addError((SyntaxException) e.getCause(), context);
                            } else {
                                unit.getErrorCollector().addException(e instanceof Exception ? (Exception) e : new RuntimeException(e), context);
                            }
                        } else {
                            unit.getErrorCollector().addError(new ExceptionMessage(e instanceof Exception ? (Exception) e : new RuntimeException(e), unit.debug, unit));
                        }
                    }
                }
            }
            unit.getErrorCollector().failIfErrors();
        }

        default boolean needSortedInput() {
            return false;
        }
    }

    @FunctionalInterface
    public interface IGroovyClassOperation extends PhaseOperation {
        void call(GroovyClass groovyClass) throws CompilationFailedException;

        @Override
        default void doPhaseOperation(final CompilationUnit unit) throws CompilationFailedException {
            if (unit.phase != Phases.OUTPUT && !(unit.phase == Phases.CLASS_GENERATION && unit.phaseComplete)) {
                throw new GroovyBugError("CompilationUnit not ready for output(). Current phase=" + unit.getPhaseDescription());
            }

            for (GroovyClass groovyClass : unit.getClasses()) {
                try {
                    this.call(groovyClass);
                } catch (CompilationFailedException e) {
                    // fall through
                } catch (NullPointerException npe) {
                    throw npe;
                } catch (GroovyBugError e) {
                    unit.changeBugText(e, null);
                    throw e;
                } catch (Exception e) {
                    throw new GroovyBugError(e);
                }
            }
            unit.getErrorCollector().failIfErrors();
        }
    }

    private static int getSuperClassCount(ClassNode classNode) {
        int count = 0;
        while (classNode != null) {
            count += 1;
            classNode = classNode.getSuperClass();
        }
        return count;
    }

    private static int getSuperInterfaceCount(final ClassNode classNode) {
        int count = 1;
        for (ClassNode face : classNode.getInterfaces()) {
            count = Math.max(count, getSuperInterfaceCount(face) + 1);
        }
        return count;
    }

    private List<ClassNode> getPrimaryClassNodes(final boolean sort) {
        List<ClassNode> unsorted = getAST().getModules().stream()
            .flatMap(module -> module.getClasses().stream()).collect(toList());

        if (!sort) return unsorted;

        int n = unsorted.size();
        int[] indexClass = new int[n];
        int[] indexInterface = new int[n];
        {
            int i = 0;
            for (ClassNode element : unsorted) {
                if (element.isInterface()) {
                    indexInterface[i] = getSuperInterfaceCount(element);
                    indexClass[i] = -1;
                } else {
                    indexClass[i] = getSuperClassCount(element);
                    indexInterface[i] = -1;
                }
                i += 1;
            }
        }

        List<ClassNode> sorted = getSorted(indexInterface, unsorted);
        sorted.addAll(getSorted(indexClass, unsorted));
        return sorted;
    }

    private static List<ClassNode> getSorted(final int[] index, final List<ClassNode> unsorted) {
        int unsortedSize = unsorted.size();
        List<ClassNode> sorted = new ArrayList<>(unsortedSize);
        for (int i = 0; i < unsortedSize; i += 1) {
            int min = -1;
            for (int j = 0; j < unsortedSize; j += 1) {
                if (index[j] == -1) continue;
                if (min == -1 || index[j] < index[min]) {
                    min = j;
                }
            }
            if (min == -1) break;
            sorted.add(unsorted.get(min));
            index[min] = -1;
        }
        return sorted;
    }

    private void changeBugText(final GroovyBugError e, final SourceUnit context) {
        e.setBugText("exception in phase '" + getPhaseDescription() + "' in source unit '" + (context != null ? context.getName() : "?") + "' " + e.getBugText());
    }

    //--------------------------------------------------------------------------

    @Deprecated
    public void addPhaseOperation(final GroovyClassOperation op) {
        addPhaseOperation((IGroovyClassOperation) op);
    }

    @Deprecated
    public void addPhaseOperation(final SourceUnitOperation op, final int phase) {
        addPhaseOperation((ISourceUnitOperation) op, phase);
    }

    @Deprecated
    public void addPhaseOperation(final PrimaryClassNodeOperation op, final int phase) {
        addPhaseOperation((IPrimaryClassNodeOperation) op, phase);
    }

    @Deprecated
    public void addFirstPhaseOperation(final PrimaryClassNodeOperation op, final int phase) {
        addFirstPhaseOperation((IPrimaryClassNodeOperation) op, phase);
    }

    @Deprecated
    public void addNewPhaseOperation(final SourceUnitOperation op, final int phase) {
        addNewPhaseOperation((ISourceUnitOperation) op, phase);
    }

    @Deprecated
    public void applyToSourceUnits(final SourceUnitOperation op) throws CompilationFailedException {
        op.doPhaseOperation(this);
    }

    @Deprecated
    public void applyToPrimaryClassNodes(final PrimaryClassNodeOperation op) throws CompilationFailedException {
        op.doPhaseOperation(this);
    }

    @Deprecated
    public abstract static class SourceUnitOperation implements ISourceUnitOperation {
    }

    @Deprecated
    public abstract static class GroovyClassOperation implements IGroovyClassOperation {
    }

    @Deprecated
    public abstract static class PrimaryClassNodeOperation implements IPrimaryClassNodeOperation {
    }
}
