Skip to content

Commit e7c7a18

Browse files
committed
adapt JSON to new model
Each Span now carries a `is_primary` boolean along with an optional label. If there are multiple labels for a span, it will appear multiple times.
1 parent a20ee76 commit e7c7a18

File tree

2 files changed

+119
-130
lines changed

2 files changed

+119
-130
lines changed

src/libsyntax/errors/json.rs

Lines changed: 83 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
// FIXME spec the JSON output properly.
2121

2222

23-
use codemap::{self, Span, MacroBacktrace, MultiSpan, CodeMap};
23+
use codemap::{self, MacroBacktrace, Span, SpanLabel, MultiSpan, CodeMap};
2424
use diagnostics::registry::Registry;
2525
use errors::{Level, DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion};
2626
use errors::emitter::Emitter;
@@ -53,20 +53,13 @@ impl JsonEmitter {
5353
}
5454

5555
impl Emitter for JsonEmitter {
56-
fn emit(&mut self, span: Option<&MultiSpan>, msg: &str, code: Option<&str>, level: Level) {
56+
fn emit(&mut self, span: &MultiSpan, msg: &str, code: Option<&str>, level: Level) {
5757
let data = Diagnostic::new(span, msg, code, level, self);
5858
if let Err(e) = writeln!(&mut self.dst, "{}", as_json(&data)) {
5959
panic!("failed to print diagnostics: {:?}", e);
6060
}
6161
}
6262

63-
fn custom_emit(&mut self, sp: &RenderSpan, msg: &str, level: Level) {
64-
let data = Diagnostic::from_render_span(sp, msg, level, self);
65-
if let Err(e) = writeln!(&mut self.dst, "{}", as_json(&data)) {
66-
panic!("failed to print diagnostics: {:?}", e);
67-
}
68-
}
69-
7063
fn emit_struct(&mut self, db: &DiagnosticBuilder) {
7164
let data = Diagnostic::from_diagnostic_builder(db, self);
7265
if let Err(e) = writeln!(&mut self.dst, "{}", as_json(&data)) {
@@ -104,8 +97,13 @@ struct DiagnosticSpan {
10497
/// 1-based, character offset.
10598
column_start: usize,
10699
column_end: usize,
100+
/// Is this a "primary" span -- meaning the point, or one of the points,
101+
/// where the error occurred?
102+
is_primary: bool,
107103
/// Source text from the start of line_start to the end of line_end.
108104
text: Vec<DiagnosticSpanLine>,
105+
/// Label that should be placed at this location (if any)
106+
label: Option<String>,
109107
/// If we are suggesting a replacement, this will contain text
110108
/// that should be sliced in atop this span. You may prefer to
111109
/// load the fully rendered version from the parent `Diagnostic`,
@@ -148,7 +146,7 @@ struct DiagnosticCode {
148146
}
149147

150148
impl<'a> Diagnostic<'a> {
151-
fn new(msp: Option<&MultiSpan>,
149+
fn new(msp: &MultiSpan,
152150
msg: &'a str,
153151
code: Option<&str>,
154152
level: Level,
@@ -158,35 +156,20 @@ impl<'a> Diagnostic<'a> {
158156
message: msg,
159157
code: DiagnosticCode::map_opt_string(code.map(|c| c.to_owned()), je),
160158
level: level.to_str(),
161-
spans: msp.map_or(vec![], |msp| DiagnosticSpan::from_multispan(msp, je)),
159+
spans: DiagnosticSpan::from_multispan(msp, je),
162160
children: vec![],
163161
rendered: None,
164162
}
165163
}
166164

167-
fn from_render_span(span: &RenderSpan,
168-
msg: &'a str,
169-
level: Level,
170-
je: &JsonEmitter)
171-
-> Diagnostic<'a> {
172-
Diagnostic {
173-
message: msg,
174-
code: None,
175-
level: level.to_str(),
176-
spans: DiagnosticSpan::from_render_span(span, je),
177-
children: vec![],
178-
rendered: je.render(span),
179-
}
180-
}
181-
182165
fn from_diagnostic_builder<'c>(db: &'c DiagnosticBuilder,
183166
je: &JsonEmitter)
184167
-> Diagnostic<'c> {
185168
Diagnostic {
186169
message: &db.message,
187170
code: DiagnosticCode::map_opt_string(db.code.clone(), je),
188171
level: db.level.to_str(),
189-
spans: db.span.as_ref().map_or(vec![], |sp| DiagnosticSpan::from_multispan(sp, je)),
172+
spans: DiagnosticSpan::from_multispan(&db.span, je),
190173
children: db.children.iter().map(|c| {
191174
Diagnostic::from_sub_diagnostic(c, je)
192175
}).collect(),
@@ -201,8 +184,7 @@ impl<'a> Diagnostic<'a> {
201184
level: db.level.to_str(),
202185
spans: db.render_span.as_ref()
203186
.map(|sp| DiagnosticSpan::from_render_span(sp, je))
204-
.or_else(|| db.span.as_ref().map(|s| DiagnosticSpan::from_multispan(s, je)))
205-
.unwrap_or(vec![]),
187+
.unwrap_or_else(|| DiagnosticSpan::from_multispan(&db.span, je)),
206188
children: vec![],
207189
rendered: db.render_span.as_ref()
208190
.and_then(|rsp| je.render(rsp)),
@@ -211,44 +193,68 @@ impl<'a> Diagnostic<'a> {
211193
}
212194

213195
impl DiagnosticSpan {
214-
fn from_span(span: Span, suggestion: Option<&String>, je: &JsonEmitter)
215-
-> DiagnosticSpan {
196+
fn from_span_label(span: SpanLabel,
197+
suggestion: Option<&String>,
198+
je: &JsonEmitter)
199+
-> DiagnosticSpan {
200+
Self::from_span_etc(span.span,
201+
span.is_primary,
202+
span.label,
203+
suggestion,
204+
je)
205+
}
206+
207+
fn from_span_etc(span: Span,
208+
is_primary: bool,
209+
label: Option<String>,
210+
suggestion: Option<&String>,
211+
je: &JsonEmitter)
212+
-> DiagnosticSpan {
216213
// obtain the full backtrace from the `macro_backtrace`
217214
// helper; in some ways, it'd be better to expand the
218215
// backtrace ourselves, but the `macro_backtrace` helper makes
219216
// some decision, such as dropping some frames, and I don't
220217
// want to duplicate that logic here.
221218
let backtrace = je.cm.macro_backtrace(span).into_iter();
222-
DiagnosticSpan::from_span_and_backtrace(span, suggestion, backtrace, je)
219+
DiagnosticSpan::from_span_full(span,
220+
is_primary,
221+
label,
222+
suggestion,
223+
backtrace,
224+
je)
223225
}
224226

225-
fn from_span_and_backtrace(span: Span,
226-
suggestion: Option<&String>,
227-
mut backtrace: vec::IntoIter<MacroBacktrace>,
228-
je: &JsonEmitter)
229-
-> DiagnosticSpan {
227+
fn from_span_full(span: Span,
228+
is_primary: bool,
229+
label: Option<String>,
230+
suggestion: Option<&String>,
231+
mut backtrace: vec::IntoIter<MacroBacktrace>,
232+
je: &JsonEmitter)
233+
-> DiagnosticSpan {
230234
let start = je.cm.lookup_char_pos(span.lo);
231235
let end = je.cm.lookup_char_pos(span.hi);
232-
let backtrace_step =
233-
backtrace.next()
234-
.map(|bt| {
235-
let call_site =
236-
Self::from_span_and_backtrace(bt.call_site,
237-
None,
238-
backtrace,
239-
je);
240-
let def_site_span = bt.def_site_span.map(|sp| {
241-
Self::from_span_and_backtrace(sp,
242-
None,
243-
vec![].into_iter(),
244-
je)
245-
});
246-
Box::new(DiagnosticSpanMacroExpansion {
247-
span: call_site,
248-
macro_decl_name: bt.macro_decl_name,
249-
def_site_span: def_site_span,
250-
})
251-
});
236+
let backtrace_step = backtrace.next().map(|bt| {
237+
let call_site =
238+
Self::from_span_full(bt.call_site,
239+
false,
240+
None,
241+
None,
242+
backtrace,
243+
je);
244+
let def_site_span = bt.def_site_span.map(|sp| {
245+
Self::from_span_full(sp,
246+
false,
247+
None,
248+
None,
249+
vec![].into_iter(),
250+
je)
251+
});
252+
Box::new(DiagnosticSpanMacroExpansion {
253+
span: call_site,
254+
macro_decl_name: bt.macro_decl_name,
255+
def_site_span: def_site_span,
256+
})
257+
});
252258
DiagnosticSpan {
253259
file_name: start.file.name.clone(),
254260
byte_start: span.lo.0,
@@ -257,53 +263,42 @@ impl DiagnosticSpan {
257263
line_end: end.line,
258264
column_start: start.col.0 + 1,
259265
column_end: end.col.0 + 1,
266+
is_primary: is_primary,
260267
text: DiagnosticSpanLine::from_span(span, je),
261268
suggested_replacement: suggestion.cloned(),
262269
expansion: backtrace_step,
270+
label: label,
263271
}
264272
}
265273

266274
fn from_multispan(msp: &MultiSpan, je: &JsonEmitter) -> Vec<DiagnosticSpan> {
267-
msp.spans.iter().map(|&span| Self::from_span(span, None, je)).collect()
275+
msp.span_labels()
276+
.into_iter()
277+
.map(|span_str| Self::from_span_label(span_str, None, je))
278+
.collect()
268279
}
269280

270281
fn from_suggestion(suggestion: &CodeSuggestion, je: &JsonEmitter)
271282
-> Vec<DiagnosticSpan> {
272-
assert_eq!(suggestion.msp.spans.len(), suggestion.substitutes.len());
273-
suggestion.msp.spans.iter()
274-
.zip(&suggestion.substitutes)
275-
.map(|(&span, suggestion)| {
276-
DiagnosticSpan::from_span(span, Some(suggestion), je)
277-
})
278-
.collect()
283+
assert_eq!(suggestion.msp.span_labels().len(), suggestion.substitutes.len());
284+
suggestion.msp.span_labels()
285+
.into_iter()
286+
.zip(&suggestion.substitutes)
287+
.map(|(span_label, suggestion)| {
288+
DiagnosticSpan::from_span_label(span_label,
289+
Some(suggestion),
290+
je)
291+
})
292+
.collect()
279293
}
280294

281295
fn from_render_span(rsp: &RenderSpan, je: &JsonEmitter) -> Vec<DiagnosticSpan> {
282296
match *rsp {
283297
RenderSpan::FileLine(ref msp) |
284-
RenderSpan::FullSpan(ref msp) => {
285-
DiagnosticSpan::from_multispan(msp, je)
286-
}
287-
RenderSpan::Suggestion(ref suggestion) => {
288-
DiagnosticSpan::from_suggestion(suggestion, je)
289-
}
290-
RenderSpan::EndSpan(ref msp) => {
291-
msp.spans.iter().map(|&span| {
292-
let end = je.cm.lookup_char_pos(span.hi);
293-
DiagnosticSpan {
294-
file_name: end.file.name.clone(),
295-
byte_start: span.hi.0,
296-
byte_end: span.hi.0,
297-
line_start: end.line,
298-
line_end: end.line,
299-
column_start: end.col.0 + 1,
300-
column_end: end.col.0 + 1,
301-
text: DiagnosticSpanLine::from_span_end(span, je),
302-
suggested_replacement: None,
303-
expansion: None,
304-
}
305-
}).collect()
306-
}
298+
RenderSpan::FullSpan(ref msp) =>
299+
DiagnosticSpan::from_multispan(msp, je),
300+
RenderSpan::Suggestion(ref suggestion) =>
301+
DiagnosticSpan::from_suggestion(suggestion, je),
307302
}
308303
}
309304
}
@@ -340,34 +335,6 @@ impl DiagnosticSpanLine {
340335
})
341336
.unwrap_or(vec![])
342337
}
343-
344-
/// Create a list of DiagnosticSpanLines from span - the result covers all
345-
/// of `span`, but the highlight is zero-length and at the end of `span`.
346-
fn from_span_end(span: Span, je: &JsonEmitter) -> Vec<DiagnosticSpanLine> {
347-
je.cm.span_to_lines(span)
348-
.map(|lines| {
349-
let fm = &*lines.file;
350-
lines.lines.iter()
351-
.enumerate()
352-
.map(|(i, line)| {
353-
// Invariant - CodeMap::span_to_lines
354-
// will not return extra context lines
355-
// - the last line returned is the last
356-
// line of `span`.
357-
let highlight = if i == lines.lines.len() - 1 {
358-
(line.end_col.0 + 1, line.end_col.0 + 1)
359-
} else {
360-
(0, 0)
361-
};
362-
DiagnosticSpanLine::line_from_filemap(fm,
363-
line.line_index,
364-
highlight.0,
365-
highlight.1)
366-
})
367-
.collect()
368-
})
369-
.unwrap_or(vec![])
370-
}
371338
}
372339

373340
impl DiagnosticCode {
@@ -396,9 +363,6 @@ impl JsonEmitter {
396363
RenderSpan::Suggestion(ref suggestion) => {
397364
Some(suggestion.splice_lines(&self.cm))
398365
}
399-
RenderSpan::EndSpan(_) => {
400-
None
401-
}
402366
}
403367
}
404368
}

0 commit comments

Comments
 (0)