/*
 *  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.transform.CompilationUnitAware;
import org.codehaus.groovy.GroovyBugError;
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.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.sc.StaticCompilationMetadataKeys;
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;
import java.io.InputStream;
import java.net.URL;
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.HashMap;
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.Set;

/**
 * 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 {

    //---------------------------------------------------------------------------
    // CONSTRUCTION AND SUCH

    protected ASTTransformationsContext astTransformationsContext; // AST transformations state data

    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;

    protected CompileUnit ast;        // The overall AST for this CompilationUnit.
    protected List<GroovyClass> generatedClasses;  // The classes generated during classgen.

    protected Verifier verifier;   // For use by verify().

    protected boolean debug;      // Controls behavior of classgen() and other routines.
    protected boolean configured; // Set true after the first configure() operation

    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 OptimizerVisitor optimizer;
    protected ClassNodeResolver classNodeResolver;

    LinkedList[] phaseOperations;
    LinkedList[] newPhaseOperations;

    private Set<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(GroovyClassLoader loader) {
        this(null, null, loader);
    }

    /**
     * Initializes the CompilationUnit with no security considerations.
     */
    public CompilationUnit(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(CompilerConfiguration configuration, CodeSource security, GroovyClassLoader loader) {
        this(configuration, security, 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.
     * <b>Note</b> The transform loader must be
     * able to load compiler classes. That means CompilationUnit.class.classLoader
     * must be at last a parent to 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 security        - security setting for the compilation
     * @param configuration   - compilation configuration
     */
    public CompilationUnit(CompilerConfiguration configuration, CodeSource security,
                           GroovyClassLoader loader, 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.optimizer = new OptimizerVisitor(this);

        initPhaseOperations();
        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() {
        addPhaseOperation(new SourceUnitOperation() {
            @Override
            public void call(SourceUnit source) throws CompilationFailedException {
                source.parse();
            }
        }, Phases.PARSING);
        addPhaseOperation(convert, 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);
            }
        }, 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);
            }
        }, Phases.SEMANTIC_ANALYSIS);
        addPhaseOperation(new PrimaryClassNodeOperation() {
            @Override
            public void call(SourceUnit source, GeneratorContext context,
                             ClassNode classNode) throws CompilationFailedException {
                if (!classNode.isSynthetic()) {
                    GenericsVisitor genericsVisitor = new GenericsVisitor(source);
                    genericsVisitor.visitClass(classNode);
                }
            }
        }, Phases.SEMANTIC_ANALYSIS);
        addPhaseOperation(new PrimaryClassNodeOperation() {
            @Override
            public void call(SourceUnit source, GeneratorContext context,
                             ClassNode classNode) throws CompilationFailedException {
                TraitComposer.doExtendTraits(classNode, source, CompilationUnit.this);
            }
        }, Phases.CANONICALIZATION);
        addPhaseOperation(compileCompleteCheck, 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);
            }
        }, Phases.SEMANTIC_ANALYSIS);
        ASTTransformationVisitor.addPhaseOperations(this);
        addPhaseOperation(new PrimaryClassNodeOperation() {
            @Override
            public void call(SourceUnit source, GeneratorContext context,
                             ClassNode classNode) throws CompilationFailedException {
                StaticVerifier sv = new StaticVerifier();
                sv.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);
            }
        }, 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);
            }
        }, 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);
                if (callback instanceof PrimaryClassNodeOperation) {
                    ((PrimaryClassNodeOperation) callback).call(source, context, classNode);
                    classNode.removeNodeMetaData(StaticCompilationMetadataKeys.DYNAMIC_OUTER_NODE_CALLBACK);
                }
            }
        }, Phases.INSTRUCTION_SELECTION);
    }

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

    /**
     * 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(SourceUnitOperation op, int phase) {
        validatePhase(phase);
        phaseOperations[phase].add(op);
    }

    public void addPhaseOperation(PrimaryClassNodeOperation op, 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) {
        validatePhase(phase);
        phaseOperations[phase].add(0, op);
    }

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

    public void addNewPhaseOperation(SourceUnitOperation op, int phase) {
        validatePhase(phase);
        newPhaseOperations[phase].add(op);
    }

    /**
     * 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) {
        super.configure(configuration);
        this.debug = this.configuration.getDebug();
        this.configured = true;
    }

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

    /**
     * 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() {
        return generatedClasses;
    }

    /**
     * Convenience routine to get the first ClassNode, for
     * when you are sure there is only one.
     */
    public ClassNode getFirstClassNode() {
        return this.ast.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];
        PrimaryClassNodeOperation handler = new PrimaryClassNodeOperation() {
            @Override
            public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) {
                if (classNode.getName().equals(name)) {
                    result[0] = classNode;
                }
            }
        };

        try {
            applyToPrimaryClassNodes(handler);
        } catch (CompilationFailedException e) {
            if (debug) e.printStackTrace();
        }
        return result[0];
    }

    /**
     * @return the AST transformations current context
     */
    public ASTTransformationsContext getASTTransformationsContext() {
        return astTransformationsContext;
    }

    //---------------------------------------------------------------------------
    // SOURCE CREATION

    /**
     * Adds a set of file paths to the unit.
     */
    public void addSources(String[] paths) {
        for (String path : paths) {
            addSource(new File(path));
        }
    }

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

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

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

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

    public SourceUnit addSource(String name, String scriptText) {
        return addSource(new SourceUnit(name, scriptText, configuration, classLoader, getErrorCollector()));
    }

    /**
     * Adds a SourceUnit to the unit.
     */
    public SourceUnit addSource(SourceUnit source) {
        String name = source.getName();
        source.setClassLoader(this.classLoader);
        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>() {
            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(ClassNode node) {
        ModuleNode module = new ModuleNode(this.ast);
        this.ast.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;
    }

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

    public ClassgenCallback getClassgenCallback() {
        return classgenCallback;
    }

    /**
     * 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;
    }

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

    public ProgressCallback getProgressCallback() {
        return progressCallback;
    }

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

    /**
     * Synonym for 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) {
                doPhaseOperation(resolve);
                if (dequeued()) continue;
            }

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

            if (progressCallback != null) progressCallback.call(this, phase);
            completePhase();
            applyToSourceUnits(mark);

            if (dequeued()) continue;

            gotoPhase(phase + 1);

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

        errorCollector.failIfErrors();
    }

    private void processPhaseOperations(int ph) {
        LinkedList ops = phaseOperations[ph];
        for (Object next : ops) {
            doPhaseOperation(next);
        }
    }

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

    private void doPhaseOperation(Object operation) {
        if (operation instanceof PrimaryClassNodeOperation) {
            applyToPrimaryClassNodes((PrimaryClassNodeOperation) operation);
        } else if (operation instanceof SourceUnitOperation) {
            applyToSourceUnits((SourceUnitOperation) operation);
        } else {
            applyToGeneratedGroovyClasses((GroovyClassOperation) operation);
        }
    }

    private void recordPhaseOpsInAllOtherPhases(int currPhase) {
        // 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()) {
                phaseOperations[ph].addAll(newPhaseOperations[ph]);
                newPhaseOperations[ph].clear();
            }
        }
    }

    private void sortClasses() throws CompilationFailedException {
        for (ModuleNode module : this.ast.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 su = queuedSources.removeFirst();
            String name = su.getName();
            sources.put(name, su);
        }
        if (dequeue) {
            gotoPhase(Phases.INITIALIZATION);
        }
        return dequeue;
    }

    /**
     * Resolves all types
     */
    private final SourceUnitOperation resolve = new SourceUnitOperation() {
        public void call(SourceUnit source) throws CompilationFailedException {
            List<ClassNode> classes = source.ast.getClasses();
            for (ClassNode node : classes) {
                VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(source);
                scopeVisitor.visitClass(node);

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

        }
    };

    private final PrimaryClassNodeOperation staticImport = new PrimaryClassNodeOperation() {
        public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
            staticImportVisitor.visitClass(classNode, source);
        }
    };

    /**
     * Runs convert() on a single SourceUnit.
     */
    private final SourceUnitOperation convert = new SourceUnitOperation() {
        public void call(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);
            }
        }
    };

    private final GroovyClassOperation output = new GroovyClassOperation() {
        public void call(GroovyClass gclass) throws CompilationFailedException {
            String name = gclass.getName().replace('.', File.separatorChar) + ".class";
            File path = new File(configuration.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
            //
            byte[] bytes = gclass.getBytes();

            try (FileOutputStream stream = new FileOutputStream(path)) {
                stream.write(bytes, 0, bytes.length);
            } catch (IOException e) {
                getErrorCollector().addError(Message.create(e.getMessage(), CompilationUnit.this));
            }
        }
    };

    /* 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.
     */
    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

            //
            // Run the Verifier on the outer class
            //
            GroovyClassVisitor visitor = 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);

            visitor = null;

            // 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);
            AsmClassGenerator generator = new AsmClassGenerator(source, context, classVisitor, sourceName);

            //
            // Run the generation and create the class (if required)
            //
            generator.visitClass(classNode);

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

            //
            // Handle any callback that's been set
            //
            if (CompilationUnit.this.classgenCallback != null) {
                classgenCallback.call(classVisitor, classNode);
            }

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

    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 {
        applyToSourceUnits(mark);
    }

    /**
     * Marks a single SourceUnit with the current phase,
     * if it isn't already there yet.
     */
    private final SourceUnitOperation mark = new SourceUnitOperation() {
        public void call(SourceUnit source) throws CompilationFailedException {
            if (source.phase < phase) {
                source.gotoPhase(phase);
            }

            if (source.phase == phase && phaseComplete && !source.phaseComplete) {
                source.completePhase();
            }
        }
    };

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

    /**
     * An callback interface for use in the applyToSourceUnits loop driver.
     */
    public abstract static class SourceUnitOperation {
        public abstract 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.
     */
    public void applyToSourceUnits(SourceUnitOperation body) throws CompilationFailedException {
        for (String name : sources.keySet()) {
            SourceUnit source = sources.get(name);
            if ((source.phase < phase) || (source.phase == phase && !source.phaseComplete)) {
                try {
                    body.call(source);
                } catch (CompilationFailedException e) {
                    throw e;
                } catch (Exception e) {
                    GroovyBugError gbe = new GroovyBugError(e);
                    changeBugText(gbe, source);
                    throw gbe;
                } catch (GroovyBugError e) {
                    changeBugText(e, source);
                    throw e;
                }
            }
        }

        getErrorCollector().failIfErrors();
    }

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

    /**
     * An callback interface for use in the applyToPrimaryClassNodes loop driver.
     */
    public abstract static class PrimaryClassNodeOperation {
        public abstract void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException;

        public boolean needSortedInput() {
            return false;
        }
    }

    public abstract static class GroovyClassOperation {
        public abstract void call(GroovyClass gclass) throws CompilationFailedException;
    }

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

    private int getSuperInterfaceCount(ClassNode element) {
        int count = 1;
        ClassNode[] interfaces = element.getInterfaces();
        for (ClassNode anInterface : interfaces) {
            count = Math.max(count, getSuperInterfaceCount(anInterface) + 1);
        }
        return count;
    }

    private List<ClassNode> getPrimaryClassNodes(boolean sort) {
        List<ClassNode> unsorted = new ArrayList<ClassNode>();
        for (ModuleNode module : this.ast.getModules()) {
            unsorted.addAll(module.getClasses());
        }

        if (!sort) return unsorted;

        int unsortedSize = unsorted.size();
        int[] indexClass = new int[unsortedSize];
        int[] indexInterface = new int[unsortedSize];
        {
            int i = 0;
            for (Iterator<ClassNode> iter = unsorted.iterator(); iter.hasNext(); i++) {
                ClassNode element = iter.next();
                if (element.isInterface()) {
                    indexInterface[i] = getSuperInterfaceCount(element);
                    indexClass[i] = -1;
                } else {
                    indexClass[i] = getSuperClassCount(element);
                    indexInterface[i] = -1;
                }
            }
        }

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

    private static List<ClassNode> getSorted(int[] index, List<ClassNode> unsorted) {
        int unsortedSize = unsorted.size();
        List<ClassNode> sorted = new ArrayList<ClassNode>(unsortedSize);
        for (int i = 0; i < unsortedSize; i++) {
            int min = -1;
            for (int j = 0; j < unsortedSize; j++) {
                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;
    }

    /**
     * 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.
     */
    public void applyToPrimaryClassNodes(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++;
                    }
                    body.call(context, new GeneratorContext(this.ast, offset), classNode);
                }
            } catch (CompilationFailedException e) {
                // fall through, getErrorReporter().failIfErrors() will trigger
            } catch (NullPointerException npe) {
                GroovyBugError gbe = new GroovyBugError("unexpected NullPointerException", npe);
                changeBugText(gbe, context);
                throw gbe;
            } catch (GroovyBugError e) {
                changeBugText(e, context);
                throw e;
            } catch (NoClassDefFoundError | Exception e) {
                // effort to get more logging in case a dependency of a class is loaded
                // although it shouldn't have
                convertUncaughtExceptionToCompilationError(e);
            }
        }

        getErrorCollector().failIfErrors();
    }

    private void convertUncaughtExceptionToCompilationError(final Throwable e) {
        // check the exception for a nested compilation exception
        ErrorCollector nestedCollector = null;
        for (Throwable next = e.getCause(); next != e && next != null; next = next.getCause()) {
            if (!(next instanceof MultipleCompilationErrorsException)) continue;
            MultipleCompilationErrorsException mcee = (MultipleCompilationErrorsException) next;
            nestedCollector = mcee.collector;
            break;
        }

        if (nestedCollector != null) {
            getErrorCollector().addCollectorContents(nestedCollector);
        } else {
            Exception err = e instanceof Exception?((Exception)e):new RuntimeException(e);
            getErrorCollector().addError(new ExceptionMessage(err, configuration.getDebug(), this));
        }
    }

    public void applyToGeneratedGroovyClasses(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());
        }

        for (GroovyClass gclass : this.generatedClasses) {
            //
            // Get the class and calculate its filesystem name
            //
            try {
                body.call(gclass);
            } catch (CompilationFailedException e) {
                // fall through, getErrorReporter().failIfErrors() will trigger
            } catch (NullPointerException npe) {
                throw npe;
            } catch (GroovyBugError e) {
                changeBugText(e, null);
                throw e;
            } catch (Exception e) {
                throw new GroovyBugError(e);
            }
        }

        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);
    }
}
