]>
Commit | Line | Data |
---|---|---|
9fa01778 | 1 | use crate::Span; |
ea8adc8c | 2 | |
ea8adc8c | 3 | /// An enum representing a diagnostic level. |
b7449926 | 4 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] |
ea8adc8c | 5 | #[derive(Copy, Clone, Debug)] |
b7449926 | 6 | #[non_exhaustive] |
ea8adc8c XL |
7 | pub enum Level { |
8 | /// An error. | |
9 | Error, | |
10 | /// A warning. | |
11 | Warning, | |
12 | /// A note. | |
13 | Note, | |
14 | /// A help message. | |
15 | Help, | |
b7449926 XL |
16 | } |
17 | ||
18 | /// Trait implemented by types that can be converted into a set of `Span`s. | |
19 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] | |
20 | pub trait MultiSpan { | |
21 | /// Converts `self` into a `Vec<Span>`. | |
22 | fn into_spans(self) -> Vec<Span>; | |
23 | } | |
24 | ||
25 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] | |
26 | impl MultiSpan for Span { | |
27 | fn into_spans(self) -> Vec<Span> { | |
28 | vec![self] | |
29 | } | |
30 | } | |
31 | ||
32 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] | |
33 | impl MultiSpan for Vec<Span> { | |
34 | fn into_spans(self) -> Vec<Span> { | |
35 | self | |
36 | } | |
37 | } | |
38 | ||
39 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] | |
40 | impl<'a> MultiSpan for &'a [Span] { | |
41 | fn into_spans(self) -> Vec<Span> { | |
42 | self.to_vec() | |
43 | } | |
ea8adc8c XL |
44 | } |
45 | ||
46 | /// A structure representing a diagnostic message and associated children | |
47 | /// messages. | |
b7449926 | 48 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] |
ea8adc8c XL |
49 | #[derive(Clone, Debug)] |
50 | pub struct Diagnostic { | |
51 | level: Level, | |
52 | message: String, | |
b7449926 | 53 | spans: Vec<Span>, |
dfeec247 | 54 | children: Vec<Diagnostic>, |
ea8adc8c XL |
55 | } |
56 | ||
57 | macro_rules! diagnostic_child_methods { | |
74b04a01 | 58 | ($spanned:ident, $regular:ident, $level:expr) => { |
b7449926 | 59 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] |
94222f64 XL |
60 | #[doc = concat!("Adds a new child diagnostics message to `self` with the [`", |
61 | stringify!($level), "`] level, and the given `spans` and `message`.")] | |
b7449926 | 62 | pub fn $spanned<S, T>(mut self, spans: S, message: T) -> Diagnostic |
74b04a01 XL |
63 | where |
64 | S: MultiSpan, | |
65 | T: Into<String>, | |
b7449926 XL |
66 | { |
67 | self.children.push(Diagnostic::spanned(spans, $level, message)); | |
ea8adc8c XL |
68 | self |
69 | } | |
70 | ||
b7449926 | 71 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] |
94222f64 XL |
72 | #[doc = concat!("Adds a new child diagnostic message to `self` with the [`", |
73 | stringify!($level), "`] level, and the given `message`.")] | |
ea8adc8c XL |
74 | pub fn $regular<T: Into<String>>(mut self, message: T) -> Diagnostic { |
75 | self.children.push(Diagnostic::new($level, message)); | |
76 | self | |
77 | } | |
74b04a01 | 78 | }; |
ea8adc8c XL |
79 | } |
80 | ||
b7449926 XL |
81 | /// Iterator over the children diagnostics of a `Diagnostic`. |
82 | #[derive(Debug, Clone)] | |
83 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] | |
9fa01778 | 84 | pub struct Children<'a>(std::slice::Iter<'a, Diagnostic>); |
b7449926 XL |
85 | |
86 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] | |
87 | impl<'a> Iterator for Children<'a> { | |
88 | type Item = &'a Diagnostic; | |
89 | ||
90 | fn next(&mut self) -> Option<Self::Item> { | |
91 | self.0.next() | |
92 | } | |
93 | } | |
94 | ||
95 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] | |
ea8adc8c | 96 | impl Diagnostic { |
9fa01778 | 97 | /// Creates a new diagnostic with the given `level` and `message`. |
b7449926 | 98 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] |
ea8adc8c | 99 | pub fn new<T: Into<String>>(level: Level, message: T) -> Diagnostic { |
74b04a01 | 100 | Diagnostic { level, message: message.into(), spans: vec![], children: vec![] } |
ea8adc8c XL |
101 | } |
102 | ||
9fa01778 | 103 | /// Creates a new diagnostic with the given `level` and `message` pointing to |
b7449926 XL |
104 | /// the given set of `spans`. |
105 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] | |
106 | pub fn spanned<S, T>(spans: S, level: Level, message: T) -> Diagnostic | |
dfeec247 XL |
107 | where |
108 | S: MultiSpan, | |
109 | T: Into<String>, | |
b7449926 | 110 | { |
74b04a01 | 111 | Diagnostic { level, message: message.into(), spans: spans.into_spans(), children: vec![] } |
ea8adc8c XL |
112 | } |
113 | ||
114 | diagnostic_child_methods!(span_error, error, Level::Error); | |
115 | diagnostic_child_methods!(span_warning, warning, Level::Warning); | |
116 | diagnostic_child_methods!(span_note, note, Level::Note); | |
117 | diagnostic_child_methods!(span_help, help, Level::Help); | |
118 | ||
119 | /// Returns the diagnostic `level` for `self`. | |
b7449926 | 120 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] |
ea8adc8c XL |
121 | pub fn level(&self) -> Level { |
122 | self.level | |
123 | } | |
124 | ||
b7449926 XL |
125 | /// Sets the level in `self` to `level`. |
126 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] | |
127 | pub fn set_level(&mut self, level: Level) { | |
128 | self.level = level; | |
129 | } | |
130 | ||
131 | /// Returns the message in `self`. | |
132 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] | |
133 | pub fn message(&self) -> &str { | |
134 | &self.message | |
135 | } | |
136 | ||
137 | /// Sets the message in `self` to `message`. | |
138 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] | |
139 | pub fn set_message<T: Into<String>>(&mut self, message: T) { | |
140 | self.message = message.into(); | |
141 | } | |
142 | ||
143 | /// Returns the `Span`s in `self`. | |
144 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] | |
145 | pub fn spans(&self) -> &[Span] { | |
146 | &self.spans | |
147 | } | |
148 | ||
149 | /// Sets the `Span`s in `self` to `spans`. | |
150 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] | |
151 | pub fn set_spans<S: MultiSpan>(&mut self, spans: S) { | |
152 | self.spans = spans.into_spans(); | |
153 | } | |
154 | ||
155 | /// Returns an iterator over the children diagnostics of `self`. | |
156 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] | |
9fa01778 | 157 | pub fn children(&self) -> Children<'_> { |
b7449926 XL |
158 | Children(self.children.iter()) |
159 | } | |
160 | ||
ea8adc8c | 161 | /// Emit the diagnostic. |
b7449926 | 162 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] |
ea8adc8c | 163 | pub fn emit(self) { |
9fa01778 XL |
164 | fn to_internal(spans: Vec<Span>) -> crate::bridge::client::MultiSpan { |
165 | let mut multi_span = crate::bridge::client::MultiSpan::new(); | |
a1dfa0c6 XL |
166 | for span in spans { |
167 | multi_span.push(span.0); | |
168 | } | |
169 | multi_span | |
b7449926 XL |
170 | } |
171 | ||
9fa01778 | 172 | let mut diag = crate::bridge::client::Diagnostic::new( |
a1dfa0c6 XL |
173 | self.level, |
174 | &self.message[..], | |
175 | to_internal(self.spans), | |
176 | ); | |
177 | for c in self.children { | |
178 | diag.sub(c.level, &c.message[..], to_internal(c.spans)); | |
8faf50e0 | 179 | } |
a1dfa0c6 | 180 | diag.emit(); |
ea8adc8c XL |
181 | } |
182 | } |