1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 pub use errors::emitter::ColorConfig;
14 use self::RenderSpan::*;
16 use codemap::{self, Span};
18 use errors::emitter::{Emitter, EmitterWriter};
20 use std::cell::{RefCell, Cell};
21 use std::{error, fmt};
22 use std::io::prelude::*;
31 /// A FullSpan renders with both with an initial line for the
32 /// message, prefixed by file:linenum, followed by a summary of
33 /// the source code covered by the span.
36 /// Similar to a FullSpan, but the cited position is the end of
37 /// the span, instead of the start. Used, at least, for telling
38 /// compiletest/runtest to look at the last line of the span
39 /// (since `end_highlight_lines` displays an arrow to the end
43 /// A suggestion renders with both with an initial line for the
44 /// message, prefixed by file:linenum, followed by a summary
45 /// of hypothetical source code, where the `String` is spliced
46 /// into the lines in place of the code covered by the span.
47 Suggestion(Span, String),
49 /// A FileLine renders with just a line for the message prefixed
55 fn span(&self) -> Span {
66 /// Used as a return value to signify a fatal error occurred. (It is also
67 /// used as the argument to panic at the moment, but that will eventually
69 #[derive(Copy, Clone, Debug)]
71 pub struct FatalError;
73 impl fmt::Display for FatalError {
74 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
75 write!(f, "parser fatal error")
79 impl error::Error for FatalError {
80 fn description(&self) -> &str {
81 "The parser has encountered a fatal error"
85 /// Signifies that the compiler died with an explicit call to `.bug`
86 /// or `.span_bug` rather than a failed assertion, etc.
87 #[derive(Copy, Clone, Debug)]
88 pub struct ExplicitBug;
90 impl fmt::Display for ExplicitBug {
91 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
92 write!(f, "parser internal bug")
96 impl error::Error for ExplicitBug {
97 fn description(&self) -> &str {
98 "The parser has encountered an internal bug"
102 /// Used for emitting structured error messages and other diagnostic information.
104 pub struct DiagnosticBuilder<'a> {
105 emitter: &'a RefCell<Box<Emitter>>,
108 code: Option<String>,
110 children: Vec<SubDiagnostic>,
113 /// For example a note attached to an error.
114 struct SubDiagnostic {
118 render_span: Option<RenderSpan>,
121 impl<'a> DiagnosticBuilder<'a> {
122 /// Emit the diagnostic.
123 pub fn emit(&mut self) {
124 if self.cancelled() {
128 self.emitter.borrow_mut().emit_struct(&self);
131 // if self.is_fatal() {
132 // panic!(FatalError);
136 /// Cancel the diagnostic (a structured diagnostic must either be emitted or
137 /// cancelled or it will panic when dropped).
138 /// BEWARE: if this DiagnosticBuilder is an error, then creating it will
139 /// bump the error count on the Handler and cancelling it won't undo that.
140 /// If you want to decrement the error count you should use `Handler::cancel`.
141 pub fn cancel(&mut self) {
142 self.level = Level::Cancelled;
145 pub fn cancelled(&self) -> bool {
146 self.level == Level::Cancelled
149 pub fn is_fatal(&self) -> bool {
150 self.level == Level::Fatal
153 pub fn note(&mut self , msg: &str) -> &mut DiagnosticBuilder<'a> {
154 self.sub(Level::Note, msg, None, None);
157 pub fn span_note(&mut self ,
160 -> &mut DiagnosticBuilder<'a> {
161 self.sub(Level::Note, msg, Some(sp), None);
164 pub fn help(&mut self , msg: &str) -> &mut DiagnosticBuilder<'a> {
165 self.sub(Level::Help, msg, None, None);
168 pub fn span_help(&mut self ,
171 -> &mut DiagnosticBuilder<'a> {
172 self.sub(Level::Help, msg, Some(sp), None);
175 /// Prints out a message with a suggested edit of the code.
177 /// See `diagnostic::RenderSpan::Suggestion` for more information.
178 pub fn span_suggestion(&mut self ,
182 -> &mut DiagnosticBuilder<'a> {
183 self.sub(Level::Help, msg, Some(sp), Some(Suggestion(sp, suggestion)));
186 pub fn span_end_note(&mut self ,
189 -> &mut DiagnosticBuilder<'a> {
190 self.sub(Level::Note, msg, Some(sp), Some(EndSpan(sp)));
193 pub fn fileline_note(&mut self ,
196 -> &mut DiagnosticBuilder<'a> {
197 self.sub(Level::Note, msg, Some(sp), Some(FileLine(sp)));
200 pub fn fileline_help(&mut self ,
203 -> &mut DiagnosticBuilder<'a> {
204 self.sub(Level::Help, msg, Some(sp), Some(FileLine(sp)));
208 pub fn span(&mut self, sp: Span) -> &mut Self {
209 self.span = Some(sp);
213 pub fn code(&mut self, s: String) -> &mut Self {
218 /// Convenience function for internal use, clients should use one of the
219 /// struct_* methods on Handler.
220 fn new(emitter: &'a RefCell<Box<Emitter>>,
222 message: &str) -> DiagnosticBuilder<'a> {
226 message: message.to_owned(),
233 /// Convenience function for internal use, clients should use one of the
234 /// public methods above.
239 render_span: Option<RenderSpan>) {
240 let sub = SubDiagnostic {
242 message: message.to_owned(),
244 render_span: render_span,
246 self.children.push(sub);
250 impl<'a> fmt::Debug for DiagnosticBuilder<'a> {
251 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
256 /// Destructor bomb - a DiagnosticBuilder must be either emitted or cancelled or
258 impl<'a> Drop for DiagnosticBuilder<'a> {
260 if !self.cancelled() {
261 self.emitter.borrow_mut().emit(None, "Error constructed but not emitted", None, Bug);
267 /// A handler deals with errors; certain errors
268 /// (fatal, bug, unimpl) may cause immediate exit,
269 /// others log errors for later reporting.
271 err_count: Cell<usize>,
272 emit: RefCell<Box<Emitter>>,
273 pub can_emit_warnings: bool,
274 treat_err_as_bug: bool,
275 delayed_span_bug: RefCell<Option<(codemap::Span, String)>>,
280 pub fn new(color_config: ColorConfig,
281 registry: Option<diagnostics::registry::Registry>,
282 can_emit_warnings: bool,
283 treat_err_as_bug: bool,
284 cm: Rc<codemap::CodeMap>)
286 let emitter = Box::new(EmitterWriter::stderr(color_config, registry, cm));
287 Handler::with_emitter(can_emit_warnings, treat_err_as_bug, emitter)
290 pub fn with_emitter(can_emit_warnings: bool,
291 treat_err_as_bug: bool,
292 e: Box<Emitter>) -> Handler {
294 err_count: Cell::new(0),
295 emit: RefCell::new(e),
296 can_emit_warnings: can_emit_warnings,
297 treat_err_as_bug: treat_err_as_bug,
298 delayed_span_bug: RefCell::new(None),
302 pub fn struct_dummy<'a>(&'a self) -> DiagnosticBuilder<'a> {
303 DiagnosticBuilder::new(&self.emit, Level::Cancelled, "")
306 pub fn struct_span_warn<'a>(&'a self,
309 -> DiagnosticBuilder<'a> {
310 let mut result = DiagnosticBuilder::new(&self.emit, Level::Warning, msg);
312 if !self.can_emit_warnings {
317 pub fn struct_span_warn_with_code<'a>(&'a self,
321 -> DiagnosticBuilder<'a> {
322 let mut result = DiagnosticBuilder::new(&self.emit, Level::Warning, msg);
324 result.code(code.to_owned());
325 if !self.can_emit_warnings {
330 pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
331 let mut result = DiagnosticBuilder::new(&self.emit, Level::Warning, msg);
332 if !self.can_emit_warnings {
337 pub fn struct_span_err<'a>(&'a self,
340 -> DiagnosticBuilder<'a> {
341 self.bump_err_count();
342 let mut result = DiagnosticBuilder::new(&self.emit, Level::Error, msg);
346 pub fn struct_span_err_with_code<'a>(&'a self,
350 -> DiagnosticBuilder<'a> {
351 self.bump_err_count();
352 let mut result = DiagnosticBuilder::new(&self.emit, Level::Error, msg);
354 result.code(code.to_owned());
357 pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
358 self.bump_err_count();
359 DiagnosticBuilder::new(&self.emit, Level::Error, msg)
361 pub fn struct_span_fatal<'a>(&'a self,
364 -> DiagnosticBuilder<'a> {
365 self.bump_err_count();
366 let mut result = DiagnosticBuilder::new(&self.emit, Level::Fatal, msg);
370 pub fn struct_span_fatal_with_code<'a>(&'a self,
374 -> DiagnosticBuilder<'a> {
375 self.bump_err_count();
376 let mut result = DiagnosticBuilder::new(&self.emit, Level::Fatal, msg);
378 result.code(code.to_owned());
381 pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
382 self.bump_err_count();
383 DiagnosticBuilder::new(&self.emit, Level::Fatal, msg)
386 pub fn cancel(&mut self, err: &mut DiagnosticBuilder) {
387 if err.level == Level::Error || err.level == Level::Fatal {
388 assert!(self.has_errors());
389 self.err_count.set(self.err_count.get() + 1);
394 pub fn span_fatal(&self, sp: Span, msg: &str) -> FatalError {
395 if self.treat_err_as_bug {
396 self.span_bug(sp, msg);
398 self.emit(Some(sp), msg, Fatal);
399 self.bump_err_count();
402 pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> FatalError {
403 if self.treat_err_as_bug {
404 self.span_bug(sp, msg);
406 self.emit_with_code(Some(sp), msg, code, Fatal);
407 self.bump_err_count();
410 pub fn span_err(&self, sp: Span, msg: &str) {
411 if self.treat_err_as_bug {
412 self.span_bug(sp, msg);
414 self.emit(Some(sp), msg, Error);
415 self.bump_err_count();
417 pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
418 if self.treat_err_as_bug {
419 self.span_bug(sp, msg);
421 self.emit_with_code(Some(sp), msg, code, Error);
422 self.bump_err_count();
424 pub fn span_warn(&self, sp: Span, msg: &str) {
425 self.emit(Some(sp), msg, Warning);
427 pub fn span_warn_with_code(&self, sp: Span, msg: &str, code: &str) {
428 self.emit_with_code(Some(sp), msg, code, Warning);
430 pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
431 self.emit(Some(sp), msg, Bug);
434 pub fn delay_span_bug(&self, sp: Span, msg: &str) {
435 let mut delayed = self.delayed_span_bug.borrow_mut();
436 *delayed = Some((sp, msg.to_string()));
438 pub fn span_bug_no_panic(&self, sp: Span, msg: &str) {
439 self.emit(Some(sp), msg, Bug);
440 self.bump_err_count();
442 pub fn span_note_without_error(&self, sp: Span, msg: &str) {
443 self.emit.borrow_mut().emit(Some(sp), msg, None, Note);
445 pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
446 self.span_bug(sp, &format!("unimplemented {}", msg));
448 pub fn fatal(&self, msg: &str) -> FatalError {
449 if self.treat_err_as_bug {
452 self.emit.borrow_mut().emit(None, msg, None, Fatal);
453 self.bump_err_count();
456 pub fn err(&self, msg: &str) {
457 if self.treat_err_as_bug {
460 self.emit.borrow_mut().emit(None, msg, None, Error);
461 self.bump_err_count();
463 pub fn warn(&self, msg: &str) {
464 self.emit.borrow_mut().emit(None, msg, None, Warning);
466 pub fn note_without_error(&self, msg: &str) {
467 self.emit.borrow_mut().emit(None, msg, None, Note);
469 pub fn bug(&self, msg: &str) -> ! {
470 self.emit.borrow_mut().emit(None, msg, None, Bug);
473 pub fn unimpl(&self, msg: &str) -> ! {
474 self.bug(&format!("unimplemented {}", msg));
477 pub fn bump_err_count(&self) {
478 self.err_count.set(self.err_count.get() + 1);
481 pub fn err_count(&self) -> usize {
485 pub fn has_errors(&self) -> bool {
486 self.err_count.get() > 0
489 pub fn abort_if_errors(&self) {
491 match self.err_count.get() {
493 let delayed_bug = self.delayed_span_bug.borrow();
495 Some((span, ref errmsg)) => {
496 self.span_bug(span, errmsg);
503 1 => s = "aborting due to previous error".to_string(),
505 s = format!("aborting due to {} previous errors",
506 self.err_count.get());
510 panic!(self.fatal(&s));
517 if lvl == Warning && !self.can_emit_warnings { return }
518 self.emit.borrow_mut().emit(sp, msg, None, lvl);
521 pub fn emit_with_code(&self,
526 if lvl == Warning && !self.can_emit_warnings { return }
527 self.emit.borrow_mut().emit(sp, msg, Some(code), lvl);
530 pub fn custom_emit(&self, sp: RenderSpan, msg: &str, lvl: Level) {
531 if lvl == Warning && !self.can_emit_warnings { return }
532 self.emit.borrow_mut().custom_emit(sp, msg, lvl);
537 #[derive(Copy, PartialEq, Clone, Debug)]
548 impl fmt::Display for Level {
549 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
550 use std::fmt::Display;
553 Bug => "error: internal compiler error".fmt(f),
554 Fatal | Error => "error".fmt(f),
555 Warning => "warning".fmt(f),
556 Note => "note".fmt(f),
557 Help => "help".fmt(f),
558 Cancelled => unreachable!(),
564 fn color(self) -> term::color::Color {
566 Bug | Fatal | Error => term::color::BRIGHT_RED,
567 Warning => term::color::BRIGHT_YELLOW,
568 Note => term::color::BRIGHT_GREEN,
569 Help => term::color::BRIGHT_CYAN,
570 Cancelled => unreachable!(),
575 pub fn expect<T, M>(diag: &Handler, opt: Option<T>, msg: M) -> T where
576 M: FnOnce() -> String,
580 None => diag.bug(&msg()),