codemap2_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 codemap2;
8//! extern crate codemap2_diagnostic;
9//! use codemap2::{CodeMap, DefaultFileData};
10//! use codemap2_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(DefaultFileData::new("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;
36pub extern crate codemap2;
37extern crate atty;
38
39pub use codemap2::*;
40
41mod lock;
42mod snippet;
43mod styled_buffer;
44mod emitter;
45
46pub use emitter::{ ColorConfig, Emitter };
47use termcolor::{ ColorSpec, Color };
48
49/// A diagnostic message.
50#[derive(Clone, Debug, PartialEq, Eq)]
51pub struct Diagnostic {
52 /// The severity of the message, used to set color scheme
53 pub level: Level,
54
55 /// Message used as the headline of the error
56 pub message: String,
57
58 /// A short error number or code
59 pub code: Option<String>,
60
61 /// Locations to underline in the code
62 pub spans: Vec<SpanLabel>,
63}
64
65/// A level representing the severity of a Diagnostic.
66///
67/// These result in different output styling.
68#[derive(Copy, Clone, PartialEq, Eq, Debug)]
69pub enum Level {
70 Bug,
71 Error,
72 Warning,
73 Note,
74 Help,
75}
76
77impl ::std::fmt::Display for Level {
78 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
79 self.to_str().fmt(f)
80 }
81}
82
83impl Level {
84 fn color(self) -> ColorSpec {
85 let mut spec = ColorSpec::new();
86 use self::Level::*;
87 match self {
88 Bug | Error => {
89 spec.set_fg(Some(Color::Red))
90 .set_intense(true);
91 }
92 Warning => {
93 spec.set_fg(Some(Color::Yellow))
94 .set_intense(cfg!(windows));
95 }
96 Note => {
97 spec.set_fg(Some(Color::Green))
98 .set_intense(true);
99 }
100 Help => {
101 spec.set_fg(Some(Color::Cyan))
102 .set_intense(true);
103 }
104 }
105 spec
106 }
107
108 pub fn to_str(self) -> &'static str {
109 use self::Level::*;
110
111 match self {
112 Bug => "error: internal compiler error",
113 Error => "error",
114 Warning => "warning",
115 Note => "note",
116 Help => "help",
117 }
118 }
119}
120
121/// A labeled region of the code related to a Diagnostic.
122#[derive(Clone, Debug, PartialEq, Eq)]
123pub struct SpanLabel {
124 /// The location in the code.
125 ///
126 /// This Span must come from the same CodeMap used to construct the Emitter.
127 pub span: Span,
128
129 /// A label used to provide context for the underlined code.
130 pub label: Option<String>,
131
132 /// A style used to set the character used for the underline.
133 pub style: SpanStyle,
134}
135
136/// Underline style for a SpanLabel.
137#[derive(Copy, Clone, PartialEq, Eq, Debug)]
138pub enum SpanStyle {
139 Primary,
140 Secondary,
141}