8003299: Cleanup javac Log support for deferred diagnostics
authorjjg
Tue, 13 Nov 2012 15:09:15 -0800
changeset 14538 384681be798f
parent 14537 ad188879b6fe
child 14539 507556c4e622
8003299: Cleanup javac Log support for deferred diagnostics Reviewed-by: mcimadamore, jfranck
langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java
langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java
langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
langtools/src/share/classes/com/sun/tools/javac/util/Log.java
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Nov 13 08:06:00 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Nov 13 15:09:15 2012 -0800
@@ -1360,11 +1360,8 @@
             types.asSuper(resource, syms.autoCloseableType.tsym) != null &&
             !types.isSameType(resource, syms.autoCloseableType)) { // Don't emit warning for AutoCloseable itself
             Symbol close = syms.noSymbol;
-            Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
-            Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;
+            Log.DiagnosticHandler discardHandler = new Log.DiscardDiagnosticHandler(log);
             try {
-                log.deferAll();
-                log.deferredDiagnostics = ListBuffer.lb();
                 close = rs.resolveQualifiedMethod(pos,
                         env,
                         resource,
@@ -1373,8 +1370,7 @@
                         List.<Type>nil());
             }
             finally {
-                log.deferredDiagFilter = prevDeferDiagsFilter;
-                log.deferredDiagnostics = prevDeferredDiags;
+                log.popDiagnosticHandler(discardHandler);
             }
             if (close.kind == MTH &&
                     close.overrides(syms.autoCloseableClose, resource.tsym, types, true) &&
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Tue Nov 13 08:06:00 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Tue Nov 13 15:09:15 2012 -0800
@@ -249,28 +249,25 @@
         JCTree newTree = new TreeCopier<Object>(make).copy(tree);
         Env<AttrContext> speculativeEnv = env.dup(newTree, env.info.dup(env.info.scope.dupUnshared()));
         speculativeEnv.info.scope.owner = env.info.scope.owner;
-        Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
-        Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;
         final JavaFileObject currentSource = log.currentSourceFile();
+        Log.DeferredDiagnosticHandler deferredDiagnosticHandler =
+                new Log.DeferredDiagnosticHandler(log, new Filter<JCDiagnostic>() {
+            public boolean accepts(JCDiagnostic t) {
+                return t.getDiagnosticSource().getFile().equals(currentSource);
+            }
+        });
         try {
-            log.deferredDiagnostics = new ListBuffer<JCDiagnostic>();
-            log.deferredDiagFilter = new Filter<JCDiagnostic>() {
-                public boolean accepts(JCDiagnostic t) {
-                    return t.getDiagnosticSource().getFile().equals(currentSource);
-                }
-            };
             attr.attribTree(newTree, speculativeEnv, resultInfo);
             unenterScanner.scan(newTree);
             return newTree;
         } catch (Abort ex) {
             //if some very bad condition occurred during deferred attribution
             //we should dump all errors before killing javac
-            log.reportDeferredDiagnostics();
+            deferredDiagnosticHandler.reportDeferredDiagnostics();
             throw ex;
         } finally {
             unenterScanner.scan(newTree);
-            log.deferredDiagFilter = prevDeferDiagsFilter;
-            log.deferredDiagnostics = prevDeferredDiags;
+            log.popDiagnosticHandler(deferredDiagnosticHandler);
         }
     }
     //where
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java	Tue Nov 13 08:06:00 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java	Tue Nov 13 15:09:15 2012 -0800
@@ -213,24 +213,21 @@
     }
 
     public void analyzeLambda(Env<AttrContext> env, JCLambda that, TreeMaker make, boolean speculative) {
-        java.util.Queue<JCDiagnostic> prevDeferredDiagnostics = log.deferredDiagnostics;
-        Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
+        Log.DiagnosticHandler diagHandler = null;
         //we need to disable diagnostics temporarily; the problem is that if
         //a lambda expression contains e.g. an unreachable statement, an error
         //message will be reported and will cause compilation to skip the flow analyis
         //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
         //related errors, which will allow for more errors to be detected
         if (!speculative) {
-            log.deferAll();
-            log.deferredDiagnostics = ListBuffer.lb();
+            diagHandler = new Log.DiscardDiagnosticHandler(log);
         }
         try {
             new AliveAnalyzer().analyzeTree(env, that, make);
             new FlowAnalyzer().analyzeTree(env, that, make);
         } finally {
             if (!speculative) {
-                log.deferredDiagFilter = prevDeferDiagsFilter;
-                log.deferredDiagnostics = prevDeferredDiagnostics;
+                log.popDiagnosticHandler(diagHandler);
             }
         }
     }
--- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Tue Nov 13 08:06:00 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Tue Nov 13 15:09:15 2012 -0800
@@ -1018,6 +1018,8 @@
      */
     boolean processAnnotations = false;
 
+    Log.DeferredDiagnosticHandler deferredDiagnosticHandler;
+
     /**
      * Object to handle annotation processing.
      */
@@ -1048,7 +1050,7 @@
                 genEndPos = true;
                 if (!taskListener.isEmpty())
                     taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
-                log.deferAll();
+                deferredDiagnosticHandler = new Log.DeferredDiagnosticHandler(log);
             } else { // free resources
                 procEnvImpl.close();
             }
@@ -1079,7 +1081,8 @@
             // or other errors during enter which cannot be fixed by running
             // any annotation processors.
             if (unrecoverableError()) {
-                log.reportDeferredDiagnostics();
+                deferredDiagnosticHandler.reportDeferredDiagnostics();
+                log.popDiagnosticHandler(deferredDiagnosticHandler);
                 return this;
             }
         }
@@ -1102,10 +1105,12 @@
                 log.error("proc.no.explicit.annotation.processing.requested",
                           classnames);
             }
-            log.reportDeferredDiagnostics();
+            Assert.checkNull(deferredDiagnosticHandler);
             return this; // continue regular compilation
         }
 
+        Assert.checkNonNull(deferredDiagnosticHandler);
+
         try {
             List<ClassSymbol> classSymbols = List.nil();
             List<PackageSymbol> pckSymbols = List.nil();
@@ -1115,7 +1120,8 @@
                 if (!explicitAnnotationProcessingRequested()) {
                     log.error("proc.no.explicit.annotation.processing.requested",
                               classnames);
-                    log.reportDeferredDiagnostics();
+                    deferredDiagnosticHandler.reportDeferredDiagnostics();
+                    log.popDiagnosticHandler(deferredDiagnosticHandler);
                     return this; // TODO: Will this halt compilation?
                 } else {
                     boolean errors = false;
@@ -1148,33 +1154,36 @@
                         }
                     }
                     if (errors) {
-                        log.reportDeferredDiagnostics();
+                        deferredDiagnosticHandler.reportDeferredDiagnostics();
+                        log.popDiagnosticHandler(deferredDiagnosticHandler);
                         return this;
                     }
                 }
             }
             try {
-                JavaCompiler c = procEnvImpl.doProcessing(context, roots, classSymbols, pckSymbols);
+                JavaCompiler c = procEnvImpl.doProcessing(context, roots, classSymbols, pckSymbols,
+                        deferredDiagnosticHandler);
                 if (c != this)
                     annotationProcessingOccurred = c.annotationProcessingOccurred = true;
                 // doProcessing will have handled deferred diagnostics
-                Assert.check(c.log.deferredDiagFilter == null
-                        && c.log.deferredDiagnostics.size() == 0);
                 return c;
             } finally {
                 procEnvImpl.close();
             }
         } catch (CompletionFailure ex) {
             log.error("cant.access", ex.sym, ex.getDetailValue());
-            log.reportDeferredDiagnostics();
+            deferredDiagnosticHandler.reportDeferredDiagnostics();
+            log.popDiagnosticHandler(deferredDiagnosticHandler);
             return this;
         }
     }
 
     private boolean unrecoverableError() {
-        for (JCDiagnostic d: log.deferredDiagnostics) {
-            if (d.getKind() == JCDiagnostic.Kind.ERROR && !d.isFlagSet(RECOVERABLE))
-                return true;
+        if (deferredDiagnosticHandler != null) {
+            for (JCDiagnostic d: deferredDiagnosticHandler.getDiagnostics()) {
+                if (d.getKind() == JCDiagnostic.Kind.ERROR && !d.isFlagSet(RECOVERABLE))
+                    return true;
+            }
         }
         return false;
     }
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Tue Nov 13 08:06:00 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Tue Nov 13 15:09:15 2012 -0800
@@ -781,6 +781,8 @@
         final JavaCompiler compiler;
         /** The log for the round. */
         final Log log;
+        /** The diagnostic handler for the round. */
+        final Log.DeferredDiagnosticHandler deferredDiagnosticHandler;
 
         /** The ASTs to be compiled. */
         List<JCCompilationUnit> roots;
@@ -798,7 +800,8 @@
         int nMessagerErrors;
 
         /** Create a round (common code). */
-        private Round(Context context, int number, int priorErrors, int priorWarnings) {
+        private Round(Context context, int number, int priorErrors, int priorWarnings,
+                Log.DeferredDiagnosticHandler deferredDiagnosticHandler) {
             this.context = context;
             this.number = number;
 
@@ -806,7 +809,12 @@
             log = Log.instance(context);
             log.nerrors = priorErrors;
             log.nwarnings += priorWarnings;
-            log.deferAll();
+            if (number == 1) {
+                Assert.checkNonNull(deferredDiagnosticHandler);
+                this.deferredDiagnosticHandler = deferredDiagnosticHandler;
+            } else {
+                this.deferredDiagnosticHandler = new Log.DeferredDiagnosticHandler(log);
+            }
 
             // the following is for the benefit of JavacProcessingEnvironment.getContext()
             JavacProcessingEnvironment.this.context = context;
@@ -817,8 +825,9 @@
         }
 
         /** Create the first round. */
-        Round(Context context, List<JCCompilationUnit> roots, List<ClassSymbol> classSymbols) {
-            this(context, 1, 0, 0);
+        Round(Context context, List<JCCompilationUnit> roots, List<ClassSymbol> classSymbols,
+                Log.DeferredDiagnosticHandler deferredDiagnosticHandler) {
+            this(context, 1, 0, 0, deferredDiagnosticHandler);
             this.roots = roots;
             genClassFiles = new HashMap<String,JavaFileObject>();
 
@@ -841,7 +850,8 @@
             this(prev.nextContext(),
                     prev.number+1,
                     prev.nMessagerErrors,
-                    prev.compiler.log.nwarnings);
+                    prev.compiler.log.nwarnings,
+                    null);
             this.genClassFiles = prev.genClassFiles;
 
             List<JCCompilationUnit> parsedFiles = compiler.parseFiles(newSourceFiles);
@@ -912,7 +922,7 @@
             if (messager.errorRaised())
                 return true;
 
-            for (JCDiagnostic d: log.deferredDiagnostics) {
+            for (JCDiagnostic d: deferredDiagnosticHandler.getDiagnostics()) {
                 switch (d.getKind()) {
                     case WARNING:
                         if (werror)
@@ -1006,7 +1016,8 @@
                 // suppress errors, which are all presumed to be transient resolve errors
                 kinds.remove(JCDiagnostic.Kind.ERROR);
             }
-            log.reportDeferredDiagnostics(kinds);
+            deferredDiagnosticHandler.reportDeferredDiagnostics(kinds);
+            log.popDiagnosticHandler(deferredDiagnosticHandler);
         }
 
         /** Print info about this round. */
@@ -1112,7 +1123,8 @@
     public JavaCompiler doProcessing(Context context,
                                      List<JCCompilationUnit> roots,
                                      List<ClassSymbol> classSymbols,
-                                     Iterable<? extends PackageSymbol> pckSymbols) {
+                                     Iterable<? extends PackageSymbol> pckSymbols,
+                                     Log.DeferredDiagnosticHandler deferredDiagnosticHandler) {
         log = Log.instance(context);
 
         Set<PackageSymbol> specifiedPackages = new LinkedHashSet<PackageSymbol>();
@@ -1120,7 +1132,7 @@
             specifiedPackages.add(psym);
         this.specifiedPackages = Collections.unmodifiableSet(specifiedPackages);
 
-        Round round = new Round(context, roots, classSymbols);
+        Round round = new Round(context, roots, classSymbols, deferredDiagnosticHandler);
 
         boolean errorStatus;
         boolean moreToDo;
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java	Tue Nov 13 08:06:00 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java	Tue Nov 13 15:09:15 2012 -0800
@@ -73,6 +73,95 @@
         final String value;
     }
 
+    /**
+     * DiagnosticHandler's provide the initial handling for diagnostics.
+     * When a diagnostic handler is created and has been initialized, it
+     * should install itself as the current diagnostic handler. When a
+     * client has finished using a handler, the client should call
+     * {@code log.removeDiagnosticHandler();}
+     *
+     * Note that javax.tools.DiagnosticListener (if set) is called later in the
+     * diagnostic pipeline.
+     */
+    public static abstract class DiagnosticHandler {
+        /**
+         * The previously installed diagnostic handler.
+         */
+        protected DiagnosticHandler prev;
+
+        /**
+         * Install this diagnostic handler as the current one,
+         * recording the previous one.
+         */
+        protected void install(Log log) {
+            prev = log.diagnosticHandler;
+            log.diagnosticHandler = this;
+        }
+
+        /**
+         * Handle a diagnostic.
+         */
+        public abstract void report(JCDiagnostic diag);
+    }
+
+    /**
+     * A DiagnosticHandler that discards all diagnostics.
+     */
+    public static class DiscardDiagnosticHandler extends DiagnosticHandler {
+        public DiscardDiagnosticHandler(Log log) {
+            install(log);
+        }
+
+        public void report(JCDiagnostic diag) { }
+    }
+
+    /**
+     * A DiagnosticHandler that can defer some or all diagnostics,
+     * by buffering them for later examination and/or reporting.
+     * If a diagnostic is not deferred, or is subsequently reported
+     * with reportAllDiagnostics(), it will be reported to the previously
+     * active diagnostic handler.
+     */
+    public static class DeferredDiagnosticHandler extends DiagnosticHandler {
+        private Queue<JCDiagnostic> deferred = ListBuffer.lb();
+        private final Filter<JCDiagnostic> filter;
+
+        public DeferredDiagnosticHandler(Log log) {
+            this(log, null);
+        }
+
+        public DeferredDiagnosticHandler(Log log, Filter<JCDiagnostic> filter) {
+            this.filter = filter;
+            install(log);
+        }
+
+        public void report(JCDiagnostic diag) {
+            if (filter == null || filter.accepts(diag))
+                deferred.add(diag);
+            else
+                prev.report(diag);
+        }
+
+        public Queue<JCDiagnostic> getDiagnostics() {
+            return deferred;
+        }
+
+        /** Report all deferred diagnostics. */
+        public void reportDeferredDiagnostics() {
+            reportDeferredDiagnostics(EnumSet.allOf(JCDiagnostic.Kind.class));
+        }
+
+        /** Report selected deferred diagnostics. */
+        public void reportDeferredDiagnostics(Set<JCDiagnostic.Kind> kinds) {
+            JCDiagnostic d;
+            while ((d = deferred.poll()) != null) {
+                if (kinds.contains(d.getKind()))
+                    prev.report(d);
+            }
+            deferred = null; // prevent accidental ongoing use
+        }
+    }
+
     public enum WriterKind { NOTICE, WARNING, ERROR };
 
     protected PrintWriter errWriter;
@@ -128,10 +217,9 @@
     private JavacMessages messages;
 
     /**
-     * Deferred diagnostics
++     * Handler for initial dispatch of diagnostics.
      */
-    public Filter<JCDiagnostic> deferredDiagFilter;
-    public Queue<JCDiagnostic> deferredDiagnostics = new ListBuffer<JCDiagnostic>();
+    private DiagnosticHandler diagnosticHandler;
 
     /** Construct a log with given I/O redirections.
      */
@@ -147,6 +235,8 @@
             context.get(DiagnosticListener.class);
         this.diagListener = dl;
 
+        diagnosticHandler = new DefaultDiagnosticHandler();
+
         messages = JavacMessages.instance(context);
         messages.add(Main.javacBundleName);
 
@@ -305,6 +395,17 @@
         this.sourceMap = other.sourceMap;
     }
 
+    /**
+     * Replace the specified diagnostic handler with the
+     * handler that was current at the time this handler was created.
+     * The given handler must be the currently installed handler;
+     * it must be specified explicitly for clarity and consistency checking.
+     */
+    public void popDiagnosticHandler(DiagnosticHandler h) {
+        Assert.check(diagnosticHandler == h);
+        diagnosticHandler = h.prev;
+    }
+
     /** Flush the logs
      */
     public void flush() {
@@ -443,64 +544,54 @@
         nwarnings++;
     }
 
-    /** Report all deferred diagnostics, and clear the deferDiagnostics flag. */
-    public void reportDeferredDiagnostics() {
-        reportDeferredDiagnostics(EnumSet.allOf(JCDiagnostic.Kind.class));
-    }
-
-    /** Report selected deferred diagnostics, and clear the deferDiagnostics flag. */
-    public void reportDeferredDiagnostics(Set<JCDiagnostic.Kind> kinds) {
-        deferredDiagFilter = null;
-        JCDiagnostic d;
-        while ((d = deferredDiagnostics.poll()) != null) {
-            if (kinds.contains(d.getKind()))
-                report(d);
-        }
-    }
+    /**
+     * Primary method to report a diagnostic.
+     * @param diagnostic
+     */
+    public void report(JCDiagnostic diagnostic) {
+        diagnosticHandler.report(diagnostic);
+     }
 
     /**
      * Common diagnostic handling.
      * The diagnostic is counted, and depending on the options and how many diagnostics have been
      * reported so far, the diagnostic may be handed off to writeDiagnostic.
      */
-    public void report(JCDiagnostic diagnostic) {
-        if (deferredDiagFilter != null && deferredDiagFilter.accepts(diagnostic)) {
-            deferredDiagnostics.add(diagnostic);
-            return;
-        }
+    private class DefaultDiagnosticHandler extends DiagnosticHandler {
+        public void report(JCDiagnostic diagnostic) {
+            if (expectDiagKeys != null)
+                expectDiagKeys.remove(diagnostic.getCode());
+
+            switch (diagnostic.getType()) {
+            case FRAGMENT:
+                throw new IllegalArgumentException();
 
-        if (expectDiagKeys != null)
-            expectDiagKeys.remove(diagnostic.getCode());
-
-        switch (diagnostic.getType()) {
-        case FRAGMENT:
-            throw new IllegalArgumentException();
+            case NOTE:
+                // Print out notes only when we are permitted to report warnings
+                // Notes are only generated at the end of a compilation, so should be small
+                // in number.
+                if ((emitWarnings || diagnostic.isMandatory()) && !suppressNotes) {
+                    writeDiagnostic(diagnostic);
+                }
+                break;
 
-        case NOTE:
-            // Print out notes only when we are permitted to report warnings
-            // Notes are only generated at the end of a compilation, so should be small
-            // in number.
-            if ((emitWarnings || diagnostic.isMandatory()) && !suppressNotes) {
-                writeDiagnostic(diagnostic);
-            }
-            break;
+            case WARNING:
+                if (emitWarnings || diagnostic.isMandatory()) {
+                    if (nwarnings < MaxWarnings) {
+                        writeDiagnostic(diagnostic);
+                        nwarnings++;
+                    }
+                }
+                break;
 
-        case WARNING:
-            if (emitWarnings || diagnostic.isMandatory()) {
-                if (nwarnings < MaxWarnings) {
+            case ERROR:
+                if (nerrors < MaxErrors
+                    && shouldReport(diagnostic.getSource(), diagnostic.getIntPosition())) {
                     writeDiagnostic(diagnostic);
-                    nwarnings++;
+                    nerrors++;
                 }
+                break;
             }
-            break;
-
-        case ERROR:
-            if (nerrors < MaxErrors
-                && shouldReport(diagnostic.getSource(), diagnostic.getIntPosition())) {
-                writeDiagnostic(diagnostic);
-                nerrors++;
-            }
-            break;
         }
     }
 
@@ -551,18 +642,6 @@
         }
     }
 
-    public void deferAll() {
-        deferredDiagFilter = new Filter<JCDiagnostic>() {
-            public boolean accepts(JCDiagnostic t) {
-                return true;
-            }
-        };
-    }
-
-    public void deferNone() {
-        deferredDiagFilter = null;
-    }
-
     /** Find a localized string in the resource bundle.
      *  Because this method is static, it ignores the locale.
      *  Use localize(key, args) when possible.