/** * 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 { // GRECLIPSE: start /*old{ Iterator classNodes = getPrimaryClassNodes(body.needSortedInput()).iterator(); }*/ // newcode List primaryClassNodes = getPrimaryClassNodes(body.needSortedInput()); Iterator classNodes = primaryClassNodes.iterator(); // end while (classNodes.hasNext()) { SourceUnit context = null; try { ClassNode classNode = (ClassNode) classNodes.next(); context = classNode.getModule().getContext(); // GRECLIPSE get to the bottom of this - why are operations running multiple times that // should only run once? if (context == null || context.phase < phase || (context.phase == phase && !context.phaseComplete)) { int offset = 1; Iterator<InnerClassNode> iterator = classNode.getInnerClasses(); while (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) { 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 call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { optimizer.visitClass( classNode, source); // GROOVY-4272: repositioned it here from staticImport if (!classNode.isSynthetic()) { GenericsVisitor genericsVisitor = new GenericsVisitor(source); genericsVisitor.visitClass(classNode); } // // Run the Verifier on the outer class // try { verifier.visitClass(classNode); } catch (GroovyRuntimeException rpe) { ASTNode node = rpe.getNode(); getErrorCollector() .addError( new SyntaxException( rpe.getMessage(), node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()), source); } LabelVerifier lv = new LabelVerifier(source); lv.visitClass(classNode); ClassCompletionVerifier completionVerifier = new ClassCompletionVerifier(source); completionVerifier.visitClass(classNode); ExtendedVerifier xverifier = new ExtendedVerifier(source); xverifier.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); AsmClassGenerator generator = new AsmClassGenerator(source, context, visitor, sourceName); // // Run the generation and create the class (if required) // // GRECLIPSE: if there are errors, don't generate code. // code gen can fail unexpectedly if there was an earlier error. if (!source.getErrorCollector().hasErrors()) { // end generator.visitClass(classNode); byte[] bytes = ((ClassWriter) visitor).toByteArray(); /// GRECLIPSE: start: added classNode, sourceUnit /*old{ generatedClasses.add(new GroovyClass(classNode.getName(), bytes)); }*/ // newcode generatedClasses.add(new GroovyClass(classNode.getName(), bytes, classNode, source)); // end // // 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()); } // GRECLIPSE: if there are errors, don't generate code } // end }