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}
141