提交 47883245 编写于 作者: J jjg

8003299: Cleanup javac Log support for deferred diagnostics

Reviewed-by: mcimadamore, jfranck
上级 27ba529c
......@@ -1360,11 +1360,8 @@ public class Attr extends JCTree.Visitor {
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 @@ public class Attr extends JCTree.Visitor {
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) &&
......
......@@ -249,28 +249,25 @@ public class DeferredAttr extends JCTree.Visitor {
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
......
......@@ -213,24 +213,21 @@ public class Flow {
}
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);
}
}
}
......
......@@ -1018,6 +1018,8 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
*/
boolean processAnnotations = false;
Log.DeferredDiagnosticHandler deferredDiagnosticHandler;
/**
* Object to handle annotation processing.
*/
......@@ -1048,7 +1050,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
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 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
// 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 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
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 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
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 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
}
}
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;
}
......
......@@ -781,6 +781,8 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
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 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
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 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
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 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
}
/** 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 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
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 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
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 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
// 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 class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
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 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
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;
......
......@@ -73,6 +73,95 @@ public class Log extends AbstractLog {
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 @@ public class Log extends AbstractLog {
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 @@ public class Log extends AbstractLog {
context.get(DiagnosticListener.class);
this.diagListener = dl;
diagnosticHandler = new DefaultDiagnosticHandler();
messages = JavacMessages.instance(context);
messages.add(Main.javacBundleName);
......@@ -305,6 +395,17 @@ public class Log extends AbstractLog {
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 @@ public class Log extends AbstractLog {
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());
if (expectDiagKeys != null)
expectDiagKeys.remove(diagnostic.getCode());
switch (diagnostic.getType()) {
case FRAGMENT:
throw new IllegalArgumentException();
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 class Log extends AbstractLog {
}
}
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.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册