📄 compilationunit.java
字号:
try { stream = new FileOutputStream(path); stream.write(bytes, 0, bytes.length); } catch (IOException e) { getErrorCollector().addError(Message.create(e.getMessage(),CompilationUnit.this)); failures = true; } finally { if (stream != null) { try { stream.close(); } catch (Exception e) { } } } } }; /** * Runs classgen() on a single ClassNode. */ private PrimaryClassNodeOperation classgen = new PrimaryClassNodeOperation() { public boolean needSortedInput() { return true; } public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { // // Run the Verifier on the outer class // try { verifier.visitClass(classNode); } catch (GroovyRuntimeException rpe) { ASTNode node = rpe.getNode(); getErrorCollector().addError( new SyntaxException(rpe.getMessage(),null,node.getLineNumber(),node.getColumnNumber()), source ); } LabelVerifier lv = new LabelVerifier(source); lv.visitClass(classNode); ClassCompletionVerifier completionVerifier = new ClassCompletionVerifier(source); completionVerifier.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 visitor = 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); ClassGenerator generator = new AsmClassGenerator(context, visitor, classLoader, sourceName); // // Run the generation and create the class (if required) // generator.visitClass(classNode); byte[] bytes = ((ClassWriter) visitor).toByteArray(); generatedClasses.add(new GroovyClass(classNode.getName(), bytes)); // // Handle any callback that's been set // if (CompilationUnit.this.classgenCallback != null) { classgenCallback.call(visitor, classNode); } // // Recurse for inner classes // LinkedList innerClasses = generator.getInnerClasses(); while (!innerClasses.isEmpty()) { classgen.call(source, context, (ClassNode) innerClasses.removeFirst()); } } }; protected ClassVisitor createClassVisitor() { return new ClassWriter(true); } //--------------------------------------------------------------------------- // 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 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 static abstract 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 { Iterator keys = names.iterator(); while (keys.hasNext()) { String name = (String) keys.next(); SourceUnit source = (SourceUnit) 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 applyToSourceUnits loop driver. */ public static abstract class PrimaryClassNodeOperation { public abstract void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException; public boolean needSortedInput(){ return false; } } public static abstract class GroovyClassOperation { public abstract void call(GroovyClass gclass) throws CompilationFailedException; } private List getPrimaryClassNodes(boolean sort) { ArrayList unsorted = new ArrayList(); Iterator modules = this.ast.getModules().iterator(); while (modules.hasNext()) { ModuleNode module = (ModuleNode) modules.next(); Iterator classNodes = module.getClasses().iterator(); while (classNodes.hasNext()) { ClassNode classNode = (ClassNode) classNodes.next(); unsorted.add(classNode); } } if(sort==false) return unsorted; int[] index = new int[unsorted.size()]; { int i = 0; for (Iterator iter = unsorted.iterator(); iter.hasNext(); i++) { ClassNode element = (ClassNode) iter.next(); int count = 0; while (element!=null){ count++; element = element.getSuperClass(); } index[i] = count; } } ArrayList sorted = new ArrayList(unsorted.size()); int start = 0; for (int i=0; i<index.length; i++) { int min = -1; for (int j=0; j<index.length; j++) { if (index[j]==-1) continue; if (min==-1) { min = j; } else if (index[j]<index[min]) { min = j; } } 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 { Iterator classNodes = getPrimaryClassNodes(body.needSortedInput()).iterator(); while (classNodes.hasNext()) { SourceUnit context=null; try { ClassNode classNode = (ClassNode) classNodes.next(); context = classNode.getModule().getContext(); if (context == null || context.phase <= phase) { body.call(context, new GeneratorContext(this.ast), classNode); } } catch (CompilationFailedException e) { // fall thorugh, getErrorREporter().failIfErrors() will triger } catch (NullPointerException npe){ throw npe; } catch (GroovyBugError e) { changeBugText(e,context); throw e; } catch (Exception 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 { getErrorCollector().addError(new ExceptionMessage(e,configuration.getDebug(),this)); } } } getErrorCollector().failIfErrors(); } 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()); } boolean failures = false; Iterator iterator = this.generatedClasses.iterator(); while (iterator.hasNext()) { // // Get the class and calculate its filesystem name // GroovyClass gclass = (GroovyClass) iterator.next(); try { body.call(gclass); } catch (CompilationFailedException e) { // fall thorugh, getErrorREporter().failIfErrors() will triger } catch (NullPointerException npe){ throw npe; } catch (GroovyBugError e) { changeBugText(e,null); throw e; } catch (Exception e) { GroovyBugError gbe = new GroovyBugError(e); throw gbe; } } getErrorCollector().failIfErrors(); } private void changeBugText(GroovyBugError e, SourceUnit context) { e.setBugText("exception in phase '"+getPhaseDescription()+"' in source unit '"+((context!=null)?context.getName():"?")+"' "+e.getBugText()); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -