221 /** |
225 /** |
222 * Handler for initial dispatch of diagnostics. |
226 * Handler for initial dispatch of diagnostics. |
223 */ |
227 */ |
224 private DiagnosticHandler diagnosticHandler; |
228 private DiagnosticHandler diagnosticHandler; |
225 |
229 |
226 /** Construct a log with given I/O redirections. |
230 /** Get the Log instance for this context. */ |
227 */ |
231 public static Log instance(Context context) { |
|
232 Log instance = context.get(logKey); |
|
233 if (instance == null) |
|
234 instance = new Log(context); |
|
235 return instance; |
|
236 } |
|
237 |
|
238 /** |
|
239 * Register a Context.Factory to create a Log. |
|
240 */ |
|
241 public static void preRegister(Context context, PrintWriter w) { |
|
242 context.put(Log.class, (Context.Factory<Log>) (c -> new Log(c, w))); |
|
243 } |
|
244 |
|
245 /** |
|
246 * Construct a log with default settings. |
|
247 * If no streams are set in the context, the log will be initialized to use |
|
248 * System.out for normal output, and System.err for all diagnostic output. |
|
249 * If one stream is set in the context, with either Log.outKey or Log.errKey, |
|
250 * it will be used for all output. |
|
251 * Otherwise, the log will be initialized to use both streams found in the context. |
|
252 */ |
|
253 protected Log(Context context) { |
|
254 this(context, initWriters(context)); |
|
255 } |
|
256 |
|
257 /** |
|
258 * Initialize a map of writers based on values found in the context |
|
259 * @param context the context in which to find writers to use |
|
260 * @return a map of writers |
|
261 */ |
|
262 private static Map<WriterKind, PrintWriter> initWriters(Context context) { |
|
263 PrintWriter out = context.get(outKey); |
|
264 PrintWriter err = context.get(errKey); |
|
265 if (out == null && err == null) { |
|
266 out = new PrintWriter(System.out, true); |
|
267 err = new PrintWriter(System.err, true); |
|
268 return initWriters(out, err); |
|
269 } else if (out == null || err == null) { |
|
270 PrintWriter pw = (out != null) ? out : err; |
|
271 return initWriters(pw, pw); |
|
272 } else { |
|
273 return initWriters(out, err); |
|
274 } |
|
275 } |
|
276 |
|
277 /** |
|
278 * Construct a log with all output sent to a single output stream. |
|
279 */ |
|
280 protected Log(Context context, PrintWriter writer) { |
|
281 this(context, initWriters(writer, writer)); |
|
282 } |
|
283 |
|
284 /** |
|
285 * Construct a log. |
|
286 * The log will be initialized to use stdOut for normal output, and stdErr |
|
287 * for all diagnostic output. |
|
288 */ |
|
289 protected Log(Context context, PrintWriter out, PrintWriter err) { |
|
290 this(context, initWriters(out, err)); |
|
291 } |
|
292 |
|
293 /** |
|
294 * Initialize a writer map for a stream for normal output, and a stream for diagnostics. |
|
295 * @param out a stream to be used for normal output |
|
296 * @param err a stream to be used for diagnostic messages, such as errors, warnings, etc |
|
297 * @return a map of writers |
|
298 */ |
|
299 private static Map<WriterKind, PrintWriter> initWriters(PrintWriter out, PrintWriter err) { |
|
300 Map<WriterKind, PrintWriter> writers = new EnumMap<>(WriterKind.class); |
|
301 writers.put(WriterKind.ERROR, err); |
|
302 writers.put(WriterKind.WARNING, err); |
|
303 writers.put(WriterKind.NOTICE, err); |
|
304 |
|
305 writers.put(WriterKind.STDOUT, out); |
|
306 writers.put(WriterKind.STDERR, err); |
|
307 |
|
308 return writers; |
|
309 } |
|
310 |
|
311 /** |
|
312 * Construct a log with given I/O redirections. |
|
313 * @deprecated |
|
314 * This constructor is provided to support the supported but now-deprecated javadoc entry point |
|
315 * com.sun.tools.javadoc.Main.execute(String programName, |
|
316 * PrintWriter errWriter, PrintWriter warnWriter, PrintWriter noticeWriter, |
|
317 * String defaultDocletClassName, String... args) |
|
318 */ |
|
319 @Deprecated |
228 protected Log(Context context, PrintWriter errWriter, PrintWriter warnWriter, PrintWriter noticeWriter) { |
320 protected Log(Context context, PrintWriter errWriter, PrintWriter warnWriter, PrintWriter noticeWriter) { |
|
321 this(context, initWriters(errWriter, warnWriter, noticeWriter)); |
|
322 } |
|
323 |
|
324 /** |
|
325 * Initialize a writer map with different streams for different types of diagnostics. |
|
326 * @param errWriter a stream for writing error messages |
|
327 * @param warnWriter a stream for writing warning messages |
|
328 * @param noticeWriter a stream for writing notice messages |
|
329 * @return a map of writers |
|
330 * @deprecated This method exists to support a supported but now deprecated javadoc entry point. |
|
331 */ |
|
332 @Deprecated |
|
333 private static Map<WriterKind, PrintWriter> initWriters(PrintWriter errWriter, PrintWriter warnWriter, PrintWriter noticeWriter) { |
|
334 Map<WriterKind, PrintWriter> writers = new EnumMap<>(WriterKind.class); |
|
335 writers.put(WriterKind.ERROR, errWriter); |
|
336 writers.put(WriterKind.WARNING, warnWriter); |
|
337 writers.put(WriterKind.NOTICE, noticeWriter); |
|
338 |
|
339 writers.put(WriterKind.STDOUT, noticeWriter); |
|
340 writers.put(WriterKind.STDERR, errWriter); |
|
341 |
|
342 return writers; |
|
343 } |
|
344 |
|
345 /** |
|
346 * Creates a log. |
|
347 * @param context the context in which the log should be registered |
|
348 * @param writers a map of writers that can be accessed by the kind of writer required |
|
349 */ |
|
350 private Log(Context context, Map<WriterKind, PrintWriter> writers) { |
229 super(JCDiagnostic.Factory.instance(context)); |
351 super(JCDiagnostic.Factory.instance(context)); |
230 context.put(logKey, this); |
352 context.put(logKey, this); |
231 this.errWriter = errWriter; |
353 this.writers = writers; |
232 this.warnWriter = warnWriter; |
|
233 this.noticeWriter = noticeWriter; |
|
234 |
354 |
235 @SuppressWarnings("unchecked") // FIXME |
355 @SuppressWarnings("unchecked") // FIXME |
236 DiagnosticListener<? super JavaFileObject> dl = |
356 DiagnosticListener<? super JavaFileObject> dl = |
237 context.get(DiagnosticListener.class); |
357 context.get(DiagnosticListener.class); |
238 this.diagListener = dl; |
358 this.diagListener = dl; |
291 */ |
412 */ |
292 protected int getDefaultMaxWarnings() { |
413 protected int getDefaultMaxWarnings() { |
293 return 100; |
414 return 100; |
294 } |
415 } |
295 |
416 |
296 /** The default writer for diagnostics |
|
297 */ |
|
298 static PrintWriter defaultWriter(Context context) { |
|
299 PrintWriter result = context.get(outKey); |
|
300 if (result == null) |
|
301 context.put(outKey, result = new PrintWriter(System.err)); |
|
302 return result; |
|
303 } |
|
304 |
|
305 /** Construct a log with default settings. |
|
306 */ |
|
307 protected Log(Context context) { |
|
308 this(context, defaultWriter(context)); |
|
309 } |
|
310 |
|
311 /** Construct a log with all output redirected. |
|
312 */ |
|
313 protected Log(Context context, PrintWriter defaultWriter) { |
|
314 this(context, defaultWriter, defaultWriter, defaultWriter); |
|
315 } |
|
316 |
|
317 /** Get the Log instance for this context. */ |
|
318 public static Log instance(Context context) { |
|
319 Log instance = context.get(logKey); |
|
320 if (instance == null) |
|
321 instance = new Log(context); |
|
322 return instance; |
|
323 } |
|
324 |
|
325 /** |
|
326 * Register a Context.Factory to create a Log. |
|
327 */ |
|
328 public static void preRegister(Context context, PrintWriter w) { |
|
329 context.put(Log.class, (Context.Factory<Log>) (c -> new Log(c, w))); |
|
330 } |
|
331 |
|
332 /** The number of errors encountered so far. |
417 /** The number of errors encountered so far. |
333 */ |
418 */ |
334 public int nerrors = 0; |
419 public int nerrors = 0; |
335 |
420 |
336 /** The number of warnings encountered so far. |
421 /** The number of warnings encountered so far. |
369 public void setDiagnosticFormatter(DiagnosticFormatter<JCDiagnostic> diagFormatter) { |
454 public void setDiagnosticFormatter(DiagnosticFormatter<JCDiagnostic> diagFormatter) { |
370 this.diagFormatter = diagFormatter; |
455 this.diagFormatter = diagFormatter; |
371 } |
456 } |
372 |
457 |
373 public PrintWriter getWriter(WriterKind kind) { |
458 public PrintWriter getWriter(WriterKind kind) { |
374 switch (kind) { |
459 return writers.get(kind); |
375 case NOTICE: return noticeWriter; |
|
376 case WARNING: return warnWriter; |
|
377 case ERROR: return errWriter; |
|
378 default: throw new IllegalArgumentException(); |
|
379 } |
|
380 } |
460 } |
381 |
461 |
382 public void setWriter(WriterKind kind, PrintWriter pw) { |
462 public void setWriter(WriterKind kind, PrintWriter pw) { |
383 Assert.checkNonNull(pw); |
463 Assert.checkNonNull(pw); |
384 switch (kind) { |
464 writers.put(kind, pw); |
385 case NOTICE: noticeWriter = pw; break; |
|
386 case WARNING: warnWriter = pw; break; |
|
387 case ERROR: errWriter = pw; break; |
|
388 default: throw new IllegalArgumentException(); |
|
389 } |
|
390 } |
465 } |
391 |
466 |
392 public void setWriters(PrintWriter pw) { |
467 public void setWriters(PrintWriter pw) { |
393 noticeWriter = warnWriter = errWriter = Assert.checkNonNull(pw); |
468 Assert.checkNonNull(pw); |
|
469 for (WriterKind k: WriterKind.values()) |
|
470 writers.put(k, pw); |
394 } |
471 } |
395 |
472 |
396 /** |
473 /** |
397 * Replace the specified diagnostic handler with the |
474 * Replace the specified diagnostic handler with the |
398 * handler that was current at the time this handler was created. |
475 * handler that was current at the time this handler was created. |
468 writer.println("^"); |
545 writer.println("^"); |
469 writer.flush(); |
546 writer.flush(); |
470 } |
547 } |
471 |
548 |
472 public void printNewline() { |
549 public void printNewline() { |
|
550 PrintWriter noticeWriter = writers.get(WriterKind.NOTICE); |
473 noticeWriter.println(); |
551 noticeWriter.println(); |
474 } |
552 } |
475 |
553 |
476 public void printNewline(WriterKind wk) { |
554 public void printNewline(WriterKind wk) { |
477 getWriter(wk).println(); |
555 getWriter(wk).println(); |
478 } |
556 } |
479 |
557 |
480 public void printLines(String key, Object... args) { |
558 public void printLines(String key, Object... args) { |
|
559 PrintWriter noticeWriter = writers.get(WriterKind.NOTICE); |
481 printRawLines(noticeWriter, localize(key, args)); |
560 printRawLines(noticeWriter, localize(key, args)); |
482 } |
561 } |
483 |
562 |
484 public void printLines(PrefixKind pk, String key, Object... args) { |
563 public void printLines(PrefixKind pk, String key, Object... args) { |
|
564 PrintWriter noticeWriter = writers.get(WriterKind.NOTICE); |
485 printRawLines(noticeWriter, localize(pk, key, args)); |
565 printRawLines(noticeWriter, localize(pk, key, args)); |
486 } |
566 } |
487 |
567 |
488 public void printLines(WriterKind wk, String key, Object... args) { |
568 public void printLines(WriterKind wk, String key, Object... args) { |
489 printRawLines(getWriter(wk), localize(key, args)); |
569 printRawLines(getWriter(wk), localize(key, args)); |
681 * and quick prototyping |
767 * and quick prototyping |
682 ***************************************************************************/ |
768 ***************************************************************************/ |
683 |
769 |
684 /** print an error or warning message: |
770 /** print an error or warning message: |
685 */ |
771 */ |
686 private void printRawError(int pos, String msg) { |
772 private void printRawDiag(PrintWriter pw, String prefix, int pos, String msg) { |
687 if (source == null || pos == Position.NOPOS) { |
773 if (source == null || pos == Position.NOPOS) { |
688 printRawLines(errWriter, "error: " + msg); |
774 printRawLines(pw, prefix + msg); |
689 } else { |
775 } else { |
690 int line = source.getLineNumber(pos); |
776 int line = source.getLineNumber(pos); |
691 JavaFileObject file = source.getFile(); |
777 JavaFileObject file = source.getFile(); |
692 if (file != null) |
778 if (file != null) |
693 printRawLines(errWriter, |
779 printRawLines(pw, |
694 file.getName() + ":" + |
780 file.getName() + ":" + |
695 line + ": " + msg); |
781 line + ": " + msg); |
696 printErrLine(pos, errWriter); |
782 printErrLine(pos, pw); |
697 } |
783 } |
698 errWriter.flush(); |
784 pw.flush(); |
699 } |
785 } |
700 |
786 |
701 /** report an error: |
787 /** report an error: |
702 */ |
788 */ |
703 public void rawError(int pos, String msg) { |
789 public void rawError(int pos, String msg) { |
|
790 PrintWriter errWriter = writers.get(WriterKind.ERROR); |
704 if (nerrors < MaxErrors && shouldReport(currentSourceFile(), pos)) { |
791 if (nerrors < MaxErrors && shouldReport(currentSourceFile(), pos)) { |
705 printRawError(pos, msg); |
792 printRawDiag(errWriter, "error: ", pos, msg); |
706 prompt(); |
793 prompt(); |
707 nerrors++; |
794 nerrors++; |
708 } |
795 } |
709 errWriter.flush(); |
796 errWriter.flush(); |
710 } |
797 } |
711 |
798 |
712 /** report a warning: |
799 /** report a warning: |
713 */ |
800 */ |
714 public void rawWarning(int pos, String msg) { |
801 public void rawWarning(int pos, String msg) { |
|
802 PrintWriter warnWriter = writers.get(WriterKind.ERROR); |
715 if (nwarnings < MaxWarnings && emitWarnings) { |
803 if (nwarnings < MaxWarnings && emitWarnings) { |
716 printRawError(pos, "warning: " + msg); |
804 printRawDiag(warnWriter, "warning: ", pos, msg); |
717 } |
805 } |
718 prompt(); |
806 prompt(); |
719 nwarnings++; |
807 nwarnings++; |
720 errWriter.flush(); |
808 warnWriter.flush(); |
721 } |
809 } |
722 |
810 |
723 public static String format(String fmt, Object... args) { |
811 public static String format(String fmt, Object... args) { |
724 return String.format((java.util.Locale)null, fmt, args); |
812 return String.format((java.util.Locale)null, fmt, args); |
725 } |
813 } |