]> git.proxmox.com Git - rustc.git/blame - src/librustc_errors/diagnostic.rs
New upstream version 1.15.1+dfsg1
[rustc.git] / src / librustc_errors / diagnostic.rs
CommitLineData
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
11use CodeSuggestion;
12use Level;
13use RenderSpan;
14use RenderSpan::Suggestion;
15use std::fmt;
16use syntax_pos::{MultiSpan, Span};
17
18#[must_use]
19#[derive(Clone, Debug, PartialEq)]
20pub 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)]
30pub struct SubDiagnostic {
31 pub level: Level,
32 pub message: String,
33 pub span: MultiSpan,
34 pub render_span: Option<RenderSpan>,
35}
36
37impl 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}