JDK-6403468 : JSR269: processors raising errors doesn't result in nonzero exit code
  • Type: Bug
  • Component: core-libs
  • Sub-Component: javax.annotation.processing
  • Affected Version: 6
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2006-03-24
  • Updated: 2010-04-02
  • Resolved: 2006-05-30
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6
6 b86Fixed
Related Reports
Relates :  
Relates :  
Description
Even when a processor raises an error, a zero exist status can be returned from the javac process.  A processor raises an error should always be considered an erroneous exist status.

Comments
SUGGESTED FIX src/share/classes/com/sun/tools/javac/main>sccs sccsdiff -r1.101 -r1.102 JavaCompiler.java ------- JavaCompiler.java ------- 415a416,421 > > /** Whether or not any parse errors have occurred. > */ > public boolean parseErrors() { > return parseErrors; > } 450a457 > int initialErrorCount = log.nerrors; 453a461 > parseErrors |= (log.nerrors > initialErrorCount); 616a625,627 > > /** Track whether any errors occurred while parsing source text. */ > private boolean parseErrors = false; 791,793d801 < if (processors != null) < // FIXME: should be removed when merging with Joe's changes of b83 < System.err.println("Got annotation processors: " + processors); 800c808 < procEnvImpl = new JavacProcessingEnvironment(context); --- > procEnvImpl = new JavacProcessingEnvironment(context, processors); 808c816 < keepComments = true; --- > keepComments = true; 810a819,820 > > src/share/classes/com/sun/tools/javac/processing>sccs sccsdiff -r1.18 -r1.19 JavacProcessingEnvironment.java ------- JavacProcessingEnvironment.java ------- 113c113 < public JavacProcessingEnvironment(Context context) { --- > public JavacProcessingEnvironment(Context context, Iterable<? extends Processor> processors) { 133c133 < initProcessorIterator(context); --- > initProcessorIterator(context, processors); 148,149c148 < // TODO: Should accomodate a passed-in Processor object < private void initProcessorIterator(Context context) { --- > private void initProcessorIterator(Context context, Iterable<? extends Processor> processors) { 152c151 < Iterator<Processor> processorIterator; --- > Iterator<? extends Processor> processorIterator; 166a166,167 > } else if (processors != null) { > processorIterator = processors.iterator(); 380,385d380 < /* < * Compare the ordinal positions of the two kinds of < * enums; the Source enum's first value is "1.2" so its < * ordinal is offset by 2 compared to the corresponding < * SourceVersion enum. < */ 508c503 < Iterator<Processor> processorIterator; --- > Iterator<? extends Processor> processorIterator; 515c510 < DiscoveredProcessors(Iterator<Processor> processorIterator) { --- > DiscoveredProcessors(Iterator<? extends Processor> processorIterator) { 521,523c516,518 < public void discovery(Context context, < java.util.Set<TypeElement> annotationsPresent, < java.util.List<ClassSymbol> topLevelClasses) { --- > private void discoverAndRunProcs(Context context, > java.util.Set<TypeElement> annotationsPresent, > java.util.List<ClassSymbol> topLevelClasses) { 658a654 > 682c678 < // Use annotation processing to compute set of annotation present --- > // Use annotation processing to compute the set of annotations present 691d686 < boolean lastRound = false; 699c694 < --- > runAround: 703,715c698,700 < < if (printRounds || verbose) { < xout.format("Round %d:" + < "%n\tinput files: {%s}" + < "%n\tannotations: %s" + < "%n\tlast round: %b%n", < roundNumber, < topLevelClasses.toString(", "), < annotationsPresent, < lastRound); < } < < if (taskListener != null) --- > printRoundInfo(xout, roundNumber, topLevelClasses, annotationsPresent, false); > > if (taskListener != null) 717c702 < --- > 719,739c704 < if (!lastRound) { < discovery(currentContext, < annotationsPresent, < topLevelClasses); < // annotationsPresentInSource = com.sun.tools.javac.util.List.nil(); < annotationsPresent = new LinkedHashSet<TypeElement>(); < topLevelClasses = com.sun.tools.javac.util.List.nil(); < < // System.out.println("moreToDo? : " + moreToDo()); < // System.out.println("error raised? : " + errorRaised()); < < lastRound = !moreToDo(); < } else { < Set<? extends TypeElement> emptyTypeElements = Collections.emptySet(); < RoundEnvironment renv = new JavacRoundEnvironment(true, < errorStatus, < emptyTypeElements); < // System.out.println("Running contributing procs for last round..."); < discoveredProcs.iterator().runContributingProcs(renv); < break; < } --- > discoverAndRunProcs(currentContext, annotationsPresent, topLevelClasses); 741c706 < if (taskListener != null) --- > if (taskListener != null) 744d708 < 746,748c710,723 < errorStatus = errorRaised(); < compiler.close(); < currentContext = contextForNextRound(currentContext, true); --- > /* > * Processors for round n have run to completion. Prepare > * for round (n+1) by checked for errors raised by > * annotation processors and then checking for syntax > * errors on any generated source files. > */ > if (messager.errorRaised()) { > errorStatus = true; > break runAround; > } else { > if (moreToDo()) { > // annotationsPresentInSource = com.sun.tools.javac.util.List.nil(); > annotationsPresent = new LinkedHashSet<TypeElement>(); > topLevelClasses = com.sun.tools.javac.util.List.nil(); 750c725,728 < JavaFileManager fileManager = currentContext.get(JavaFileManager.class); --- > compiler.close(); > currentContext = contextForNextRound(currentContext, true); > > JavaFileManager fileManager = currentContext.get(JavaFileManager.class); 752,757c730,735 < com.sun.tools.javac.util.List<JavaFileObject> fileObjects = < com.sun.tools.javac.util.List.nil(); < for (JavaFileObject jfo : filer.getGeneratedSourceFileObjects() ) { < aggregateSourceFileObjects = aggregateSourceFileObjects.prepend(jfo); < fileObjects = fileObjects.prepend(jfo); < } --- > com.sun.tools.javac.util.List<JavaFileObject> fileObjects = > com.sun.tools.javac.util.List.nil(); > for (JavaFileObject jfo : filer.getGeneratedSourceFileObjects() ) { > aggregateSourceFileObjects = aggregateSourceFileObjects.prepend(jfo); > fileObjects = fileObjects.prepend(jfo); > } 759,763c737,746 < < compiler = JavaCompiler.instance(currentContext); < com.sun.tools.javac.util.List<JCCompilationUnit> parsedFiles = < compiler.parseFiles(fileObjects); < parsedFiles = compiler.enterTrees(parsedFiles); --- > compiler = JavaCompiler.instance(currentContext); > com.sun.tools.javac.util.List<JCCompilationUnit> parsedFiles = > compiler.parseFiles(fileObjects); > > // Check for errors after parsing > if (compiler.parseErrors()) { > errorStatus = true; > break runAround; > } else { > parsedFiles = compiler.enterTrees(parsedFiles); 765,767c748,751 < // annotationsPresentInSource = < // collector.findAnnotations(parsedFiles); < topLevelClasses = getTopLevelClasses(parsedFiles); --- > // annotationsPresentInSource = > // collector.findAnnotations(parsedFiles); > topLevelClasses = getTopLevelClasses(parsedFiles); > topLevelClasses = enterNewClassFiles(currentContext, topLevelClasses); 769,777c753,755 < ClassReader reader = ClassReader.instance(currentContext); < Name.Table names = Name.Table.instance(currentContext); < for (Map.Entry<String,JavaFileObject> entry : filer.getGeneratedClasses().entrySet()) { < ClassSymbol cs = reader.enterClass(names.fromString(entry.getKey())); < < assert cs.completer != null : cs; < assert cs.classfile == null : cs.classfile; < assert cs.sourcefile == null : cs.sourcefile; < cs.classfile = entry.getValue(); --- > annotationsPresent = new LinkedHashSet<TypeElement>(); > for (ClassSymbol classSym : topLevelClasses) > annotationComputer.scan(classSym, annotationsPresent); 779c757,760 < topLevelClasses = topLevelClasses.prepend(cs); --- > updateProcessingState(currentContext, false); > } > } else > break runAround; // No new files 781,791d761 < < annotationsPresent = new LinkedHashSet<TypeElement>(); < for (ClassSymbol classSym : topLevelClasses) < annotationComputer.scan(classSym, annotationsPresent); < < // System.out.println("\tTop level classes: " + topLevelClasses.toString(", ")); < filer.newRound(currentContext, lastRound); < messager.newRound(currentContext); < < elementUtils.setContext(currentContext); < typeUtils.setContext(currentContext); 792a763 > runLastRound(xout, roundNumber, errorStatus, taskListener); 797c768 < filer.newRound(currentContext, lastRound); --- > filer.newRound(currentContext, true); 801c772,783 < errorStatus = errorRaised(); --- > /* > * If an annotation processor raises an error in a round, > * that round runs to completion and one last round occurs. > * The last round may also occur because no more source or > * class files have been generated. Therefore, if an error > * was raised on either of the last *two* rounds, the compile > * should exit with a nonzero exit code. The current value of > * errorStatus holds whether or not an error was raised on the > * second to last round; errorRaised() gives the error status > * of the last round. > */ > errorStatus = errorStatus || messager.errorRaised(); 802a785 > 806,808c789,791 < if (taskListener != null) < taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING)); < --- > if (taskListener != null) > taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING)); > 809a793 > compiler.log.nerrors += messager.errorCount(); 835a820,853 > // Call the last round of annotation processing > private void runLastRound(PrintWriter xout, > int roundNumber, > boolean errorStatus, > TaskListener taskListener) throws IOException { > roundNumber++; > com.sun.tools.javac.util.List<ClassSymbol> noTopLevelClasses = > com.sun.tools.javac.util.List.nil(); > Set<TypeElement> noAnnotations = Collections.emptySet(); > printRoundInfo(xout, roundNumber, noTopLevelClasses, noAnnotations, true); > > Set<? extends TypeElement> emptyTypeElements = Collections.emptySet(); > RoundEnvironment renv = new JavacRoundEnvironment(true, > errorStatus, > emptyTypeElements); > if (taskListener != null) > taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); > > try { > discoveredProcs.iterator().runContributingProcs(renv); > } finally { > if (taskListener != null) > taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); > } > } > > private void updateProcessingState(Context currentContext, boolean lastRound) { > filer.newRound(currentContext, lastRound); > messager.newRound(currentContext); > > elementUtils.setContext(currentContext); > typeUtils.setContext(currentContext); > } > 841a860,894 > private void printRoundInfo(PrintWriter xout, > int roundNumber, > com.sun.tools.javac.util.List<ClassSymbol> topLevelClasses, > Set<TypeElement> annotationsPresent, > boolean lastRound) { > if (printRounds || verbose) { > xout.format("Round %d:" + > "%n\tinput files: {%s}" + > "%n\tannotations: %s" + > "%n\tlast round: %b%n", > roundNumber, > topLevelClasses.toString(", "), > annotationsPresent, > lastRound); > } > } > > private com.sun.tools.javac.util.List<ClassSymbol> enterNewClassFiles(Context currentContext, > com.sun.tools.javac.util.List<ClassSymbol> topLevelClasses) { > ClassReader reader = ClassReader.instance(currentContext); > Name.Table names = Name.Table.instance(currentContext); > > for (Map.Entry<String,JavaFileObject> entry : filer.getGeneratedClasses().entrySet()) { > ClassSymbol cs = reader.enterClass(names.fromString(entry.getKey())); > > assert cs.completer != null : cs; > assert cs.classfile == null : cs.classfile; > assert cs.sourcefile == null : cs.sourcefile; > cs.classfile = entry.getValue(); > > topLevelClasses = topLevelClasses.prepend(cs); > } > return topLevelClasses; > } > 1032,1033c1085,1086 < public boolean moreToDo() { < return filer.newFiles() && !messager.errorRaised(); --- > private boolean moreToDo() { > return filer.newFiles(); 1036,1040d1088 < // TODO: Should some flavor's of log's error be checked here too? < public boolean errorRaised() { < return messager.errorRaised(); < } < 1206c1254 < for(String s : optionName.split("\\.")) { --- > for(String s : optionName.split("\\.", -1)) { src/share/classes/com/sun/tools/javac/processing>sccs sccsdiff -r1.7 -r1.8 JavacMessager.java ------- JavacMessager.java ------- 145a146,149 > public int errorCount() { > return errorCount; > } >
24-05-2006

EVALUATION Must be fixed.
24-03-2006