]>
Commit | Line | Data |
---|---|---|
c30ab7b3 SL |
1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | use CodeSuggestion; | |
12 | use Level; | |
13 | use RenderSpan; | |
14 | use RenderSpan::Suggestion; | |
15 | use std::fmt; | |
16 | use syntax_pos::{MultiSpan, Span}; | |
17 | ||
18 | #[must_use] | |
19 | #[derive(Clone, Debug, PartialEq)] | |
20 | pub struct Diagnostic { | |
21 | pub level: Level, | |
22 | pub message: String, | |
23 | pub code: Option<String>, | |
24 | pub span: MultiSpan, | |
25 | pub children: Vec<SubDiagnostic>, | |
26 | } | |
27 | ||
28 | /// For example a note attached to an error. | |
29 | #[derive(Clone, Debug, PartialEq)] | |
30 | pub struct SubDiagnostic { | |
31 | pub level: Level, | |
32 | pub message: String, | |
33 | pub span: MultiSpan, | |
34 | pub render_span: Option<RenderSpan>, | |
35 | } | |
36 | ||
37 | impl Diagnostic { | |
38 | pub fn new(level: Level, message: &str) -> Self { | |
39 | Diagnostic::new_with_code(level, None, message) | |
40 | } | |
41 | ||
42 | pub fn new_with_code(level: Level, code: Option<String>, message: &str) -> Self { | |
43 | Diagnostic { | |
44 | level: level, | |
45 | message: message.to_owned(), | |
46 | code: code, | |
47 | span: MultiSpan::new(), | |
48 | children: vec![], | |
49 | } | |
50 | } | |
51 | ||
52 | /// Cancel the diagnostic (a structured diagnostic must either be emitted or | |
53 | /// cancelled or it will panic when dropped). | |
54 | /// BEWARE: if this DiagnosticBuilder is an error, then creating it will | |
55 | /// bump the error count on the Handler and cancelling it won't undo that. | |
56 | /// If you want to decrement the error count you should use `Handler::cancel`. | |
57 | pub fn cancel(&mut self) { | |
58 | self.level = Level::Cancelled; | |
59 | } | |
60 | ||
61 | pub fn cancelled(&self) -> bool { | |
62 | self.level == Level::Cancelled | |
63 | } | |
64 | ||
65 | pub fn is_fatal(&self) -> bool { | |
66 | self.level == Level::Fatal | |
67 | } | |
68 | ||
69 | /// Add a span/label to be included in the resulting snippet. | |
70 | /// This is pushed onto the `MultiSpan` that was created when the | |
71 | /// diagnostic was first built. If you don't call this function at | |
72 | /// all, and you just supplied a `Span` to create the diagnostic, | |
73 | /// then the snippet will just include that `Span`, which is | |
74 | /// called the primary span. | |
75 | pub fn span_label(&mut self, span: Span, label: &fmt::Display) | |
76 | -> &mut Self { | |
77 | self.span.push_span_label(span, format!("{}", label)); | |
78 | self | |
79 | } | |
80 | ||
81 | pub fn note_expected_found(&mut self, | |
82 | label: &fmt::Display, | |
83 | expected: &fmt::Display, | |
84 | found: &fmt::Display) | |
85 | -> &mut Self | |
86 | { | |
87 | self.note_expected_found_extra(label, expected, found, &"", &"") | |
88 | } | |
89 | ||
90 | pub fn note_expected_found_extra(&mut self, | |
91 | label: &fmt::Display, | |
92 | expected: &fmt::Display, | |
93 | found: &fmt::Display, | |
94 | expected_extra: &fmt::Display, | |
95 | found_extra: &fmt::Display) | |
96 | -> &mut Self | |
97 | { | |
98 | // For now, just attach these as notes | |
99 | self.note(&format!("expected {} `{}`{}", label, expected, expected_extra)); | |
100 | self.note(&format!(" found {} `{}`{}", label, found, found_extra)); | |
101 | self | |
102 | } | |
103 | ||
104 | pub fn note(&mut self, msg: &str) -> &mut Self { | |
105 | self.sub(Level::Note, msg, MultiSpan::new(), None); | |
106 | self | |
107 | } | |
108 | ||
109 | pub fn span_note<S: Into<MultiSpan>>(&mut self, | |
110 | sp: S, | |
111 | msg: &str) | |
112 | -> &mut Self { | |
113 | self.sub(Level::Note, msg, sp.into(), None); | |
114 | self | |
115 | } | |
116 | ||
117 | pub fn warn(&mut self, msg: &str) -> &mut Self { | |
118 | self.sub(Level::Warning, msg, MultiSpan::new(), None); | |
119 | self | |
120 | } | |
121 | ||
122 | pub fn span_warn<S: Into<MultiSpan>>(&mut self, | |
123 | sp: S, | |
124 | msg: &str) | |
125 | -> &mut Self { | |
126 | self.sub(Level::Warning, msg, sp.into(), None); | |
127 | self | |
128 | } | |
129 | ||
130 | pub fn help(&mut self , msg: &str) -> &mut Self { | |
131 | self.sub(Level::Help, msg, MultiSpan::new(), None); | |
132 | self | |
133 | } | |
134 | ||
135 | pub fn span_help<S: Into<MultiSpan>>(&mut self, | |
136 | sp: S, | |
137 | msg: &str) | |
138 | -> &mut Self { | |
139 | self.sub(Level::Help, msg, sp.into(), None); | |
140 | self | |
141 | } | |
142 | ||
143 | /// Prints out a message with a suggested edit of the code. | |
144 | /// | |
145 | /// See `diagnostic::RenderSpan::Suggestion` for more information. | |
146 | pub fn span_suggestion<S: Into<MultiSpan>>(&mut self, | |
147 | sp: S, | |
148 | msg: &str, | |
149 | suggestion: String) | |
150 | -> &mut Self { | |
151 | self.sub(Level::Help, | |
152 | msg, | |
153 | MultiSpan::new(), | |
154 | Some(Suggestion(CodeSuggestion { | |
155 | msp: sp.into(), | |
156 | substitutes: vec![suggestion], | |
157 | }))); | |
158 | self | |
159 | } | |
160 | ||
161 | pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self { | |
162 | self.span = sp.into(); | |
163 | self | |
164 | } | |
165 | ||
166 | pub fn code(&mut self, s: String) -> &mut Self { | |
167 | self.code = Some(s); | |
168 | self | |
169 | } | |
170 | ||
171 | pub fn message(&self) -> &str { | |
172 | &self.message | |
173 | } | |
174 | ||
175 | pub fn level(&self) -> Level { | |
176 | self.level | |
177 | } | |
178 | ||
179 | /// Used by a lint. Copies over all details *but* the "main | |
180 | /// message". | |
181 | pub fn copy_details_not_message(&mut self, from: &Diagnostic) { | |
182 | self.span = from.span.clone(); | |
183 | self.code = from.code.clone(); | |
184 | self.children.extend(from.children.iter().cloned()) | |
185 | } | |
186 | ||
187 | /// Convenience function for internal use, clients should use one of the | |
188 | /// public methods above. | |
189 | fn sub(&mut self, | |
190 | level: Level, | |
191 | message: &str, | |
192 | span: MultiSpan, | |
193 | render_span: Option<RenderSpan>) { | |
194 | let sub = SubDiagnostic { | |
195 | level: level, | |
196 | message: message.to_owned(), | |
197 | span: span, | |
198 | render_span: render_span, | |
199 | }; | |
200 | self.children.push(sub); | |
201 | } | |
202 | } |