codemap_diagnostic/
lib.rs

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
35extern crate termcolor;
36extern crate codemap;
37
38use codemap::Span;
39
40mod lock;
41mod snippet;
42mod styled_buffer;
43mod emitter;
44
45pub use emitter::{ ColorConfig, Emitter };
46use termcolor::{ ColorSpec, Color };
47
48/// A diagnostic message.
49#[derive(Clone, Debug, PartialEq, Eq)]
50pub 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)]
68pub enum Level {
69    Bug,
70    Error,
71    Warning,
72    Note,
73    Help,
74}
75
76impl ::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
82impl 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)]
122pub 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)]
137pub enum SpanStyle {
138    Primary,
139    Secondary,
140}