📄 compilationunit.java
字号:
} } /** * 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())); } /** * Adds a SourceUnit to the unit. */ public SourceUnit addSource(SourceUnit source) { String name = source.getName(); source.setClassLoader(this.classLoader); for (Iterator iter = queuedSources.iterator(); iter.hasNext();) { SourceUnit su = (SourceUnit) iter.next(); if (name.equals(su.getName())) return su; } queuedSources.add(source); return source; } /** * Returns an iterator on the unit's SourceUnits. */ public Iterator iterator() { return new Iterator() { Iterator nameIterator = names.iterator(); public boolean hasNext() { return nameIterator.hasNext(); } public Object next() { String name = (String) nameIterator.next(); return sources.get(name); } 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. */ public static abstract class ClassgenCallback { public abstract void call(ClassVisitor writer, ClassNode node) throws CompilationFailedException; } /** * Sets a ClassgenCallback. You can have only one, and setting * it to null removes any existing setting. */ public void setClassgenCallback(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. */ public static abstract class ProgressCallback { public abstract void call(ProcessingUnit context, int phase) throws CompilationFailedException; } /** * Sets a ProgressCallback. You can have only one, and setting * it to null removes any existing setting. */ public void setProgressCallback(ProgressCallback callback) { this.progressCallback = callback; } //--------------------------------------------------------------------------- // 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) { for (Iterator it = phaseOperations[phase].iterator(); it.hasNext();) { Object operation = it.next(); if (operation instanceof PrimaryClassNodeOperation) { applyToPrimaryClassNodes((PrimaryClassNodeOperation) operation); } else if (operation instanceof SourceUnitOperation) { applyToSourceUnits((SourceUnitOperation)operation); } else { applyToGeneratedGroovyClasses((GroovyClassOperation)operation); } } if (dequeued()) continue; if ( phase==Phases.CLASS_GENERATION && ast.hasClassNodeToCompile()) { break; } if (progressCallback != null) progressCallback.call(this, phase); completePhase(); applyToSourceUnits(mark); gotoPhase(phase+1); if (phase==Phases.CLASS_GENERATION) { sortClasses(); } } for (Iterator iter = ast.iterateClassNodeToCompile(); iter.hasNext();) { String name = (String) iter.next(); String location = ast.getScriptSourceLocation(name); getErrorCollector().addErrorAndContinue( new SimpleMessage("Compilation incomplete: expected to find the class "+name+" in "+location,this) ); } errorCollector.failIfErrors(); } private void sortClasses() throws CompilationFailedException { Iterator modules = this.ast.getModules().iterator(); while (modules.hasNext()) { ModuleNode module = (ModuleNode) modules.next(); // before we actually do the sorting we should check // for cyclic references List classes = module.getClasses(); for (Iterator iter = classes.iterator(); iter.hasNext();) { ClassNode start = (ClassNode) iter.next(); ClassNode cn = start; HashSet parents = new HashSet(); do { if (parents.contains(cn.getName())) { getErrorCollector().addErrorAndContinue( new SimpleMessage("cyclic inheritance involving "+cn.getName()+" in class "+start.getName(),this) ); cn=null; } else { parents.add(cn.getName()); cn = cn.getSuperClass(); } } while (cn!=null); } errorCollector.failIfErrors(); module.sortClasses(); } } /** * Dequeues any source units add through addSource and resets the compiler phase * to initialization. * * Note: this does not mean a file is recompiled. If a SoucreUnit has already passed * a phase it is skipped until a higher phase is reached. * @return TODO * * @throws CompilationFailedException */ protected boolean dequeued() throws CompilationFailedException { boolean dequeue = !queuedSources.isEmpty(); while (!queuedSources.isEmpty()) { SourceUnit su = (SourceUnit) queuedSources.removeFirst(); String name = su.getName(); names.add(name); sources.put(name,su); } if (dequeue) { gotoPhase(Phases.INITIALIZATION); } return dequeue; } /** * Adds summary of each class to maps */ private SourceUnitOperation summarize = new SourceUnitOperation() { public void call(SourceUnit source) throws CompilationFailedException { SourceSummary sourceSummary = source.getSourceSummary(); if (sourceSummary != null) { summariesBySourceName.put(source.getName(),sourceSummary); List publicClassSources = sourceSummary.getPublicClassSources(); if (publicClassSources == null || publicClassSources.size() == 0) { //todo - is this the best way to handle scripts? summariesByPublicClassName.put("*NoName*",sourceSummary); // nothing to put into classSourcesByClassName as no ClassSource } else { Iterator itr = publicClassSources.iterator(); while (itr.hasNext()) { ClassSource classSource = (ClassSource)itr.next(); summariesByPublicClassName.put(classSource.getName(),sourceSummary); classSourcesByPublicClassName.put(classSource.getName(),classSource); } } } } }; /** * Resolves all types */ private SourceUnitOperation resolve = new SourceUnitOperation() { public void call(SourceUnit source) throws CompilationFailedException { List classes = source.ast.getClasses(); for (Iterator it = classes.iterator(); it.hasNext();) { ClassNode node = (ClassNode) it.next(); VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(source); scopeVisitor.visitClass(node); resolveVisitor.startResolving(node,source); } } }; /** * Runs convert() on a single SourceUnit. */ private 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 GroovyClassOperation output = new GroovyClassOperation() { public void call(GroovyClass gclass) throws CompilationFailedException { boolean failures = false; 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(); FileOutputStream stream = null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -