about summary refs log tree commit diff
path: root/src/librustc_errors
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-10-11 12:26:32 -0400
committerNiko Matsakis <niko@alum.mit.edu>2016-11-01 14:07:45 -0400
commit888a92cef37342c7878028eda967c85eb15afe43 (patch)
treea26e908f88eac00cf57ed7123b80f761ec1c68c5 /src/librustc_errors
parent75bc8bfa922e533f111e54b0d841d85d61c7f317 (diff)
downloadrust-888a92cef37342c7878028eda967c85eb15afe43.tar.gz
rust-888a92cef37342c7878028eda967c85eb15afe43.zip
separate Diagnostic from DiagnosticBuilder
Diffstat (limited to 'src/librustc_errors')
-rw-r--r--src/librustc_errors/diagnostic.rs190
-rw-r--r--src/librustc_errors/diagnostic_builder.rs164
-rw-r--r--src/librustc_errors/lib.rs219
3 files changed, 358 insertions, 215 deletions
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
new file mode 100644
index 00000000000..dab8fb665ac
--- /dev/null
+++ b/src/librustc_errors/diagnostic.rs
@@ -0,0 +1,190 @@
+use CodeSuggestion;
+use Level;
+use RenderSpan;
+use RenderSpan::Suggestion;
+use std::fmt;
+use syntax_pos::{MultiSpan, Span};
+
+#[must_use]
+#[derive(Clone)]
+pub struct Diagnostic {
+    pub level: Level,
+    pub message: String,
+    pub code: Option<String>,
+    pub span: MultiSpan,
+    pub children: Vec<SubDiagnostic>,
+}
+
+/// For example a note attached to an error.
+#[derive(Clone)]
+pub struct SubDiagnostic {
+    pub level: Level,
+    pub message: String,
+    pub span: MultiSpan,
+    pub render_span: Option<RenderSpan>,
+}
+
+impl Diagnostic {
+    pub fn new(level: Level, message: &str) -> Self {
+        Diagnostic::new_with_code(level, None, message)
+    }
+
+    pub fn new_with_code(level: Level, code: Option<String>, message: &str) -> Self {
+        Diagnostic {
+            level: level,
+            message: message.to_owned(),
+            code: code,
+            span: MultiSpan::new(),
+            children: vec![],
+        }
+    }
+
+    /// Cancel the diagnostic (a structured diagnostic must either be emitted or
+    /// cancelled or it will panic when dropped).
+    /// BEWARE: if this DiagnosticBuilder is an error, then creating it will
+    /// bump the error count on the Handler and cancelling it won't undo that.
+    /// If you want to decrement the error count you should use `Handler::cancel`.
+    pub fn cancel(&mut self) {
+        self.level = Level::Cancelled;
+    }
+
+    pub fn cancelled(&self) -> bool {
+        self.level == Level::Cancelled
+    }
+
+    pub fn is_fatal(&self) -> bool {
+        self.level == Level::Fatal
+    }
+
+    /// Add a span/label to be included in the resulting snippet.
+    /// This is pushed onto the `MultiSpan` that was created when the
+    /// diagnostic was first built. If you don't call this function at
+    /// all, and you just supplied a `Span` to create the diagnostic,
+    /// then the snippet will just include that `Span`, which is
+    /// called the primary span.
+    pub fn span_label(&mut self, span: Span, label: &fmt::Display)
+                      -> &mut Self {
+        self.span.push_span_label(span, format!("{}", label));
+        self
+    }
+
+    pub fn note_expected_found(&mut self,
+                               label: &fmt::Display,
+                               expected: &fmt::Display,
+                               found: &fmt::Display)
+                               -> &mut Self
+    {
+        self.note_expected_found_extra(label, expected, found, &"", &"")
+    }
+
+    pub fn note_expected_found_extra(&mut self,
+                                     label: &fmt::Display,
+                                     expected: &fmt::Display,
+                                     found: &fmt::Display,
+                                     expected_extra: &fmt::Display,
+                                     found_extra: &fmt::Display)
+                                     -> &mut Self
+    {
+        // For now, just attach these as notes
+        self.note(&format!("expected {} `{}`{}", label, expected, expected_extra));
+        self.note(&format!("   found {} `{}`{}", label, found, found_extra));
+        self
+    }
+
+    pub fn note(&mut self, msg: &str) -> &mut Self {
+        self.sub(Level::Note, msg, MultiSpan::new(), None);
+        self
+    }
+
+    pub fn span_note<S: Into<MultiSpan>>(&mut self,
+                                         sp: S,
+                                         msg: &str)
+                                         -> &mut Self {
+        self.sub(Level::Note, msg, sp.into(), None);
+        self
+    }
+
+    pub fn warn(&mut self, msg: &str) -> &mut Self {
+        self.sub(Level::Warning, msg, MultiSpan::new(), None);
+        self
+    }
+
+    pub fn span_warn<S: Into<MultiSpan>>(&mut self,
+                                         sp: S,
+                                         msg: &str)
+                                         -> &mut Self {
+        self.sub(Level::Warning, msg, sp.into(), None);
+        self
+    }
+
+    pub fn help(&mut self , msg: &str) -> &mut Self {
+        self.sub(Level::Help, msg, MultiSpan::new(), None);
+        self
+    }
+
+    pub fn span_help<S: Into<MultiSpan>>(&mut self,
+                                         sp: S,
+                                         msg: &str)
+                                         -> &mut Self {
+        self.sub(Level::Help, msg, sp.into(), None);
+        self
+    }
+
+    /// Prints out a message with a suggested edit of the code.
+    ///
+    /// See `diagnostic::RenderSpan::Suggestion` for more information.
+    pub fn span_suggestion<S: Into<MultiSpan>>(&mut self,
+                                               sp: S,
+                                               msg: &str,
+                                               suggestion: String)
+                                               -> &mut Self {
+        self.sub(Level::Help,
+                 msg,
+                 MultiSpan::new(),
+                 Some(Suggestion(CodeSuggestion {
+                     msp: sp.into(),
+                     substitutes: vec![suggestion],
+                 })));
+        self
+    }
+
+    pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
+        self.span = sp.into();
+        self
+    }
+
+    pub fn code(&mut self, s: String) -> &mut Self {
+        self.code = Some(s);
+        self
+    }
+
+    pub fn message(&self) -> &str {
+        &self.message
+    }
+
+    pub fn level(&self) -> Level {
+        self.level
+    }
+
+    /// Convenience function for internal use, clients should use one of the
+    /// public methods above.
+    fn sub(&mut self,
+           level: Level,
+           message: &str,
+           span: MultiSpan,
+           render_span: Option<RenderSpan>) {
+        let sub = SubDiagnostic {
+            level: level,
+            message: message.to_owned(),
+            span: span,
+            render_span: render_span,
+        };
+        self.children.push(sub);
+    }
+}
+
+impl fmt::Debug for Diagnostic {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.message.fmt(f)
+    }
+}
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
new file mode 100644
index 00000000000..69532823f5a
--- /dev/null
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -0,0 +1,164 @@
+use Diagnostic;
+use Level;
+use Handler;
+use std::fmt::{self, Debug};
+use std::ops::{Deref, DerefMut};
+use std::thread::panicking;
+use syntax_pos::{MultiSpan, Span};
+
+/// Used for emitting structured error messages and other diagnostic information.
+#[must_use]
+#[derive(Clone)]
+pub struct DiagnosticBuilder<'a> {
+    handler: &'a Handler,
+    diagnostic: Diagnostic,
+}
+
+/// In general, the `DiagnosticBuilder` uses deref to allow access to
+/// the fields and methods of the embedded `diagnostic` in a
+/// transparent way.  *However,* many of the methods are intended to
+/// be used in a chained way, and hence ought to return `self`. In
+/// that case, we can't just naively forward to the method on the
+/// `diagnostic`, because the return type would be a `&Diagnostic`
+/// instead of a `&DiagnosticBuilder<'a>`. This `forward!` macro makes
+/// it easy to declare such methods on the builder.
+macro_rules! forward {
+    // Forward pattern for &self -> &Self
+    (pub fn $n:ident(&self, $($name:ident: $ty:ty),*) -> &Self) => {
+        pub fn $n(&self, $($name: $ty),*) -> &Self {
+            self.diagnostic.$n($($name),*);
+            self
+        }
+    };
+
+    // Forward pattern for &mut self -> &mut Self
+    (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),*) -> &mut Self) => {
+        pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
+            self.diagnostic.$n($($name),*);
+            self
+        }
+    };
+
+    // Forward pattern for &mut self -> &mut Self, with S: Into<MultiSpan>
+    // type parameter. No obvious way to make this more generic.
+    (pub fn $n:ident<S: Into<MultiSpan>>(&mut self, $($name:ident: $ty:ty),*) -> &mut Self) => {
+        pub fn $n<S: Into<MultiSpan>>(&mut self, $($name: $ty),*) -> &mut Self {
+            self.diagnostic.$n($($name),*);
+            self
+        }
+    };
+}
+
+impl<'a> Deref for DiagnosticBuilder<'a> {
+    type Target = Diagnostic;
+
+    fn deref(&self) -> &Diagnostic {
+        &self.diagnostic
+    }
+}
+
+impl<'a> DerefMut for DiagnosticBuilder<'a> {
+    fn deref_mut(&mut self) -> &mut Diagnostic {
+        &mut self.diagnostic
+    }
+}
+
+impl<'a> DiagnosticBuilder<'a> {
+    /// Emit the diagnostic.
+    pub fn emit(&mut self) {
+        if self.cancelled() {
+            return;
+        }
+
+        self.handler.emitter.borrow_mut().emit(&self);
+        self.cancel();
+        self.handler.panic_if_treat_err_as_bug();
+
+        // if self.is_fatal() {
+        //     panic!(FatalError);
+        // }
+    }
+
+    /// Add a span/label to be included in the resulting snippet.
+    /// This is pushed onto the `MultiSpan` that was created when the
+    /// diagnostic was first built. If you don't call this function at
+    /// all, and you just supplied a `Span` to create the diagnostic,
+    /// then the snippet will just include that `Span`, which is
+    /// called the primary span.
+    forward!(pub fn span_label(&mut self, span: Span, label: &fmt::Display)
+                               -> &mut Self);
+
+    forward!(pub fn note_expected_found(&mut self,
+                                        label: &fmt::Display,
+                                        expected: &fmt::Display,
+                                        found: &fmt::Display)
+                                        -> &mut Self);
+
+    forward!(pub fn note_expected_found_extra(&mut self,
+                                              label: &fmt::Display,
+                                              expected: &fmt::Display,
+                                              found: &fmt::Display,
+                                              expected_extra: &fmt::Display,
+                                              found_extra: &fmt::Display)
+                                              -> &mut Self);
+
+    forward!(pub fn note(&mut self, msg: &str) -> &mut Self);
+    forward!(pub fn span_note<S: Into<MultiSpan>>(&mut self,
+                                                  sp: S,
+                                                  msg: &str)
+                                                  -> &mut Self);
+    forward!(pub fn warn(&mut self, msg: &str) -> &mut Self);
+    forward!(pub fn span_warn<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self);
+    forward!(pub fn help(&mut self , msg: &str) -> &mut Self);
+    forward!(pub fn span_help<S: Into<MultiSpan>>(&mut self,
+                                                  sp: S,
+                                                  msg: &str)
+                                                  -> &mut Self);
+    forward!(pub fn span_suggestion<S: Into<MultiSpan>>(&mut self,
+                                                        sp: S,
+                                                        msg: &str,
+                                                        suggestion: String)
+                                                        -> &mut Self);
+    forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
+    forward!(pub fn code(&mut self, s: String) -> &mut Self);
+
+    /// Convenience function for internal use, clients should use one of the
+    /// struct_* methods on Handler.
+    pub fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> {
+        DiagnosticBuilder::new_with_code(handler, level, None, message)
+    }
+
+    /// Convenience function for internal use, clients should use one of the
+    /// struct_* methods on Handler.
+    pub fn new_with_code(handler: &'a Handler,
+                         level: Level,
+                         code: Option<String>,
+                         message: &str)
+                         -> DiagnosticBuilder<'a> {
+        DiagnosticBuilder {
+            handler: handler,
+            diagnostic: Diagnostic::new_with_code(level, code, message)
+        }
+    }
+}
+
+impl<'a> Debug for DiagnosticBuilder<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.diagnostic.fmt(f)
+    }
+}
+
+/// Destructor bomb - a DiagnosticBuilder must be either emitted or cancelled or
+/// we emit a bug.
+impl<'a> Drop for DiagnosticBuilder<'a> {
+    fn drop(&mut self) {
+        if !panicking() && !self.cancelled() {
+            let mut db = DiagnosticBuilder::new(self.handler,
+                                                Level::Bug,
+                                                "Error constructed but not emitted");
+            db.emit();
+            panic!();
+        }
+    }
+}
+
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 25b314256b0..203b96d9f9a 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -39,15 +39,15 @@ extern crate syntax_pos;
 pub use emitter::ColorConfig;
 
 use self::Level::*;
-use self::RenderSpan::*;
 
 use emitter::{Emitter, EmitterWriter};
 
 use std::cell::{RefCell, Cell};
 use std::{error, fmt};
 use std::rc::Rc;
-use std::thread::panicking;
 
+pub mod diagnostic;
+pub mod diagnostic_builder;
 pub mod emitter;
 pub mod snippet;
 pub mod registry;
@@ -211,219 +211,8 @@ impl error::Error for ExplicitBug {
     }
 }
 
-/// Used for emitting structured error messages and other diagnostic information.
-#[must_use]
-#[derive(Clone)]
-pub struct DiagnosticBuilder<'a> {
-    handler: &'a Handler,
-    pub level: Level,
-    pub message: String,
-    pub code: Option<String>,
-    pub span: MultiSpan,
-    pub children: Vec<SubDiagnostic>,
-}
-
-/// For example a note attached to an error.
-#[derive(Clone)]
-pub struct SubDiagnostic {
-    pub level: Level,
-    pub message: String,
-    pub span: MultiSpan,
-    pub render_span: Option<RenderSpan>,
-}
-
-impl<'a> DiagnosticBuilder<'a> {
-    /// Emit the diagnostic.
-    pub fn emit(&mut self) {
-        if self.cancelled() {
-            return;
-        }
-
-        self.handler.emitter.borrow_mut().emit(&self);
-        self.cancel();
-        self.handler.panic_if_treat_err_as_bug();
-
-        // if self.is_fatal() {
-        //     panic!(FatalError);
-        // }
-    }
-
-    /// Cancel the diagnostic (a structured diagnostic must either be emitted or
-    /// cancelled or it will panic when dropped).
-    /// BEWARE: if this DiagnosticBuilder is an error, then creating it will
-    /// bump the error count on the Handler and cancelling it won't undo that.
-    /// If you want to decrement the error count you should use `Handler::cancel`.
-    pub fn cancel(&mut self) {
-        self.level = Level::Cancelled;
-    }
-
-    pub fn cancelled(&self) -> bool {
-        self.level == Level::Cancelled
-    }
-
-    pub fn is_fatal(&self) -> bool {
-        self.level == Level::Fatal
-    }
-
-    /// Add a span/label to be included in the resulting snippet.
-    /// This is pushed onto the `MultiSpan` that was created when the
-    /// diagnostic was first built. If you don't call this function at
-    /// all, and you just supplied a `Span` to create the diagnostic,
-    /// then the snippet will just include that `Span`, which is
-    /// called the primary span.
-    pub fn span_label(&mut self, span: Span, label: &fmt::Display) -> &mut DiagnosticBuilder<'a> {
-        self.span.push_span_label(span, format!("{}", label));
-        self
-    }
-
-    pub fn note_expected_found(&mut self,
-                               label: &fmt::Display,
-                               expected: &fmt::Display,
-                               found: &fmt::Display)
-                               -> &mut DiagnosticBuilder<'a> {
-        self.note_expected_found_extra(label, expected, found, &"", &"")
-    }
-
-    pub fn note_expected_found_extra(&mut self,
-                                     label: &fmt::Display,
-                                     expected: &fmt::Display,
-                                     found: &fmt::Display,
-                                     expected_extra: &fmt::Display,
-                                     found_extra: &fmt::Display)
-                                     -> &mut DiagnosticBuilder<'a> {
-        // For now, just attach these as notes
-        self.note(&format!("expected {} `{}`{}", label, expected, expected_extra));
-        self.note(&format!("   found {} `{}`{}", label, found, found_extra));
-        self
-    }
-
-    pub fn note(&mut self, msg: &str) -> &mut DiagnosticBuilder<'a> {
-        self.sub(Level::Note, msg, MultiSpan::new(), None);
-        self
-    }
-    pub fn span_note<S: Into<MultiSpan>>(&mut self,
-                                         sp: S,
-                                         msg: &str)
-                                         -> &mut DiagnosticBuilder<'a> {
-        self.sub(Level::Note, msg, sp.into(), None);
-        self
-    }
-    pub fn warn(&mut self, msg: &str) -> &mut DiagnosticBuilder<'a> {
-        self.sub(Level::Warning, msg, MultiSpan::new(), None);
-        self
-    }
-    pub fn span_warn<S: Into<MultiSpan>>(&mut self,
-                                         sp: S,
-                                         msg: &str)
-                                         -> &mut DiagnosticBuilder<'a> {
-        self.sub(Level::Warning, msg, sp.into(), None);
-        self
-    }
-    pub fn help(&mut self, msg: &str) -> &mut DiagnosticBuilder<'a> {
-        self.sub(Level::Help, msg, MultiSpan::new(), None);
-        self
-    }
-    pub fn span_help<S: Into<MultiSpan>>(&mut self,
-                                         sp: S,
-                                         msg: &str)
-                                         -> &mut DiagnosticBuilder<'a> {
-        self.sub(Level::Help, msg, sp.into(), None);
-        self
-    }
-    /// Prints out a message with a suggested edit of the code.
-    ///
-    /// See `diagnostic::RenderSpan::Suggestion` for more information.
-    pub fn span_suggestion<S: Into<MultiSpan>>(&mut self,
-                                               sp: S,
-                                               msg: &str,
-                                               suggestion: String)
-                                               -> &mut DiagnosticBuilder<'a> {
-        self.sub(Level::Help,
-                 msg,
-                 MultiSpan::new(),
-                 Some(Suggestion(CodeSuggestion {
-                     msp: sp.into(),
-                     substitutes: vec![suggestion],
-                 })));
-        self
-    }
-
-    pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
-        self.span = sp.into();
-        self
-    }
-
-    pub fn code(&mut self, s: String) -> &mut Self {
-        self.code = Some(s);
-        self
-    }
-
-    pub fn message(&self) -> &str {
-        &self.message
-    }
-
-    pub fn level(&self) -> Level {
-        self.level
-    }
-
-    /// Convenience function for internal use, clients should use one of the
-    /// struct_* methods on Handler.
-    fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> {
-        DiagnosticBuilder::new_with_code(handler, level, None, message)
-    }
-
-    /// Convenience function for internal use, clients should use one of the
-    /// struct_* methods on Handler.
-    fn new_with_code(handler: &'a Handler,
-                     level: Level,
-                     code: Option<String>,
-                     message: &str)
-                     -> DiagnosticBuilder<'a> {
-        DiagnosticBuilder {
-            handler: handler,
-            level: level,
-            message: message.to_owned(),
-            code: code,
-            span: MultiSpan::new(),
-            children: vec![],
-        }
-    }
-
-    /// Convenience function for internal use, clients should use one of the
-    /// public methods above.
-    fn sub(&mut self,
-           level: Level,
-           message: &str,
-           span: MultiSpan,
-           render_span: Option<RenderSpan>) {
-        let sub = SubDiagnostic {
-            level: level,
-            message: message.to_owned(),
-            span: span,
-            render_span: render_span,
-        };
-        self.children.push(sub);
-    }
-}
-
-impl<'a> fmt::Debug for DiagnosticBuilder<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.message.fmt(f)
-    }
-}
-
-/// Destructor bomb - a DiagnosticBuilder must be either emitted or cancelled or
-/// we emit a bug.
-impl<'a> Drop for DiagnosticBuilder<'a> {
-    fn drop(&mut self) {
-        if !panicking() && !self.cancelled() {
-            let mut db =
-                DiagnosticBuilder::new(self.handler, Bug, "Error constructed but not emitted");
-            db.emit();
-            panic!();
-        }
-    }
-}
+pub use diagnostic::{Diagnostic, SubDiagnostic};
+pub use diagnostic_builder::DiagnosticBuilder;
 
 /// A handler deals with errors; certain errors
 /// (fatal, bug, unimpl) may cause immediate exit,