| 1 | //! A library for formatting compiler error messages, |
| 2 | //! [extracted from rustc](https://github.com/rust-lang/rust/tree/master/src/librustc_errors) |
| 3 | //! and built on the types from the [codemap](https://github.com/kevinmehall/codemap) crate. |
| 4 | //! |
| 5 | //! # Example |
| 6 | //! ``` |
| 7 | //! extern crate codemap; |
| 8 | //! extern crate codemap_diagnostic; |
| 9 | //! use codemap::CodeMap; |
| 10 | //! use codemap_diagnostic::{ Level, SpanLabel, SpanStyle, Diagnostic, ColorConfig, Emitter }; |
| 11 | //! |
| 12 | //! fn main() { |
| 13 | //! let code = "foo + bar" ; |
| 14 | //! let mut codemap = CodeMap::new(); |
| 15 | //! let file_span = codemap.add_file("test.rs" .to_owned(), code.to_owned()).span; |
| 16 | //! let name_span = file_span.subspan(0, 3); |
| 17 | //! |
| 18 | //! let label = SpanLabel { |
| 19 | //! span: name_span, |
| 20 | //! style: SpanStyle::Primary, |
| 21 | //! label: Some("undefined variable" .to_owned()) |
| 22 | //! }; |
| 23 | //! let d = Diagnostic { |
| 24 | //! level: Level::Error, |
| 25 | //! message: "cannot find value `foo` in this scope" .to_owned(), |
| 26 | //! code: Some("C000" .to_owned()), |
| 27 | //! spans: vec![label] |
| 28 | //! }; |
| 29 | //! |
| 30 | //! let mut emitter = Emitter::stderr(ColorConfig::Always, Some(&codemap)); |
| 31 | //! emitter.emit(&[d]); |
| 32 | //! } |
| 33 | //! ``` |
| 34 | |
| 35 | extern crate termcolor; |
| 36 | extern crate codemap; |
| 37 | |
| 38 | use codemap::Span; |
| 39 | |
| 40 | mod lock; |
| 41 | mod snippet; |
| 42 | mod styled_buffer; |
| 43 | mod emitter; |
| 44 | |
| 45 | pub use emitter::{ ColorConfig, Emitter }; |
| 46 | use termcolor::{ ColorSpec, Color }; |
| 47 | |
| 48 | /// A diagnostic message. |
| 49 | #[derive (Clone, Debug, PartialEq, Eq)] |
| 50 | pub struct Diagnostic { |
| 51 | /// The severity of the message, used to set color scheme |
| 52 | pub level: Level, |
| 53 | |
| 54 | /// Message used as the headline of the error |
| 55 | pub message: String, |
| 56 | |
| 57 | /// A short error number or code |
| 58 | pub code: Option<String>, |
| 59 | |
| 60 | /// Locations to underline in the code |
| 61 | pub spans: Vec<SpanLabel>, |
| 62 | } |
| 63 | |
| 64 | /// A level representing the severity of a Diagnostic. |
| 65 | /// |
| 66 | /// These result in different output styling. |
| 67 | #[derive (Copy, Clone, PartialEq, Eq, Debug)] |
| 68 | pub enum Level { |
| 69 | Bug, |
| 70 | Error, |
| 71 | Warning, |
| 72 | Note, |
| 73 | Help, |
| 74 | } |
| 75 | |
| 76 | impl ::std::fmt::Display for Level { |
| 77 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { |
| 78 | self.to_str().fmt(f) |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | impl Level { |
| 83 | fn color(self) -> ColorSpec { |
| 84 | let mut spec = ColorSpec::new(); |
| 85 | use self::Level::*; |
| 86 | match self { |
| 87 | Bug | Error => { |
| 88 | spec.set_fg(Some(Color::Red)) |
| 89 | .set_intense(true); |
| 90 | } |
| 91 | Warning => { |
| 92 | spec.set_fg(Some(Color::Yellow)) |
| 93 | .set_intense(cfg!(windows)); |
| 94 | } |
| 95 | Note => { |
| 96 | spec.set_fg(Some(Color::Green)) |
| 97 | .set_intense(true); |
| 98 | } |
| 99 | Help => { |
| 100 | spec.set_fg(Some(Color::Cyan)) |
| 101 | .set_intense(true); |
| 102 | } |
| 103 | } |
| 104 | spec |
| 105 | } |
| 106 | |
| 107 | pub fn to_str(self) -> &'static str { |
| 108 | use self::Level::*; |
| 109 | |
| 110 | match self { |
| 111 | Bug => "error: internal compiler error" , |
| 112 | Error => "error" , |
| 113 | Warning => "warning" , |
| 114 | Note => "note" , |
| 115 | Help => "help" , |
| 116 | } |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | /// A labeled region of the code related to a Diagnostic. |
| 121 | #[derive (Clone, Debug, PartialEq, Eq)] |
| 122 | pub struct SpanLabel { |
| 123 | /// The location in the code. |
| 124 | /// |
| 125 | /// This Span must come from the same CodeMap used to construct the Emitter. |
| 126 | pub span: Span, |
| 127 | |
| 128 | /// A label used to provide context for the underlined code. |
| 129 | pub label: Option<String>, |
| 130 | |
| 131 | /// A style used to set the character used for the underline. |
| 132 | pub style: SpanStyle, |
| 133 | } |
| 134 | |
| 135 | /// Underline style for a SpanLabel. |
| 136 | #[derive (Copy, Clone, PartialEq, Eq, Debug)] |
| 137 | pub enum SpanStyle { |
| 138 | Primary, |
| 139 | Secondary, |
| 140 | } |
| 141 | |