compilationunit.java

来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· Java 代码 · 共 1,012 行 · 第 1/3 页

JAVA
1,012
字号
/*
 $Id: CompilationUnit.java 4661 2007-01-02 16:52:26Z blackdrag $


 Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.


 Redistribution and use of this software and associated documentation
 ("Software"), with or without modification, are permitted provided
 that the following conditions are met:

 1. Redistributions of source code must retain copyright
    statements and notices.  Redistributions must also contain a
    copy of this document.


 2. Redistributions in binary form must reproduce the
    above copyright notice, this list of conditions and the
    following disclaimer in the documentation and/or other
    materials provided with the distribution.


 3. The name "groovy" must not be used to endorse or promote
    products derived from this Software without prior written
    permission of The Codehaus.  For written permission,
    please contact info@codehaus.org.


 4. Products derived from this Software may not be called "groovy"
    nor may "groovy" appear in their names without prior written
    permission of The Codehaus. "groovy" is a registered
    trademark of The Codehaus.


 5. Due credit should be given to The Codehaus -
    http://groovy.codehaus.org/


 THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
 ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 OF THE POSSIBILITY OF SUCH DAMAGE.
 */


package org.codehaus.groovy.control;

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

import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.CompileUnit;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.classgen.AsmClassGenerator;
import org.codehaus.groovy.classgen.ClassCompletionVerifier;
import org.codehaus.groovy.classgen.ClassGenerator;
import org.codehaus.groovy.classgen.GeneratorContext;
import org.codehaus.groovy.classgen.VariableScopeVisitor;
import org.codehaus.groovy.classgen.Verifier;
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.SyntaxException;
import org.codehaus.groovy.syntax.ClassSource;
import org.codehaus.groovy.syntax.SourceSummary;
import org.codehaus.groovy.tools.GroovyClass;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyRuntimeException;

/**
 * Collects all compilation data as it is generated by the compiler system.
 * Allows additional source units to be added and compilation run again (to
 * affect only the deltas).
 *
 * @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
 * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
 * @version $Id: CompilationUnit.java 4661 2007-01-02 16:52:26Z blackdrag $
 */

public class CompilationUnit extends ProcessingUnit {


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


    protected HashMap 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 ArrayList names;      // Names for each SourceUnit in sources.
    protected LinkedList queuedSources;
    
    
    protected CompileUnit ast;        // The overall AST for this CompilationUnit.
    protected ArrayList generatedClasses;    // The classes generated during classgen.


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

    
    protected boolean debug;      // Controls behaviour 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;

    LinkedList[] phaseOperations;
    

    /**
     * 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) {
        super(configuration, loader, null);
        this.names = new ArrayList();
        this.queuedSources = new LinkedList();
        this.sources = new HashMap();
        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);
        
        phaseOperations = new LinkedList[Phases.ALL+1];
        for (int i=0; i<phaseOperations.length; i++) {
            phaseOperations[i] = new LinkedList();
        }
        addPhaseOperation(new SourceUnitOperation() {
            public void call(SourceUnit source) throws CompilationFailedException {
                source.parse();
            }
        }, Phases.PARSING);
        addPhaseOperation(summarize, Phases.PARSING);
        addPhaseOperation(convert,   Phases.CONVERSION);
        addPhaseOperation(resolve,   Phases.SEMANTIC_ANALYSIS);
        addPhaseOperation(compileCompleteCheck, Phases.CANONICALIZATION);
        addPhaseOperation(classgen,  Phases.CLASS_GENERATION);
        addPhaseOperation(output);
        
        this.classgenCallback = null;
    }
    
    
    
    
    
    public void addPhaseOperation(SourceUnitOperation op, int phase) {
        if (phase<0 || phase>Phases.ALL) throw new IllegalArgumentException("phase "+phase+" is unknown");
        phaseOperations[phase].add(op);
    }
    
    public void addPhaseOperation(PrimaryClassNodeOperation op, int phase) {
        if (phase<0 || phase>Phases.ALL) throw new IllegalArgumentException("phase "+phase+" is unknown");
        phaseOperations[phase].add(op);        
    }
    
    public void addPhaseOperation(GroovyClassOperation op) {
        phaseOperations[Phases.OUTPUT].addFirst(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}.
     */
    public void configure(CompilerConfiguration configuration) {
        super.configure(configuration);
        this.debug = configuration.getDebug();

        if (!this.configured && this.classLoader instanceof GroovyClassLoader) {
            appendCompilerConfigurationClasspathToClassLoader(configuration, (GroovyClassLoader) this.classLoader);
        }

        this.configured = true;
    }

    private void appendCompilerConfigurationClasspathToClassLoader(CompilerConfiguration configuration, GroovyClassLoader classLoader) {
        /*for (Iterator iterator = configuration.getClasspath().iterator(); iterator.hasNext(); ) {
            classLoader.addClasspath((String) iterator.next());
        }*/
    }

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


    /**
     * Convenience routine to get the first ClassNode, for
     * when you are sure there is only one.
     */
    public ClassNode getFirstClassNode() {
        return (ClassNode) ((ModuleNode) 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[]{null};
        PrimaryClassNodeOperation handler = new PrimaryClassNodeOperation() {
            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];
    }





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


    /**
     * Adds a set of file paths to the unit.
     */
    public void addSources(String[] paths) {
        for (int i = 0; i < paths.length; i++) {
            File file = new File(paths[i]);
            addSource(file);
        }
    }


    /**
     * Adds a set of source files to the unit.
     */
    public void addSources(File[] files) {
        for (int i = 0; i < files.length; i++) {
            addSource(files[i]);
        }
    }


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

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?