20
20
// FIXME spec the JSON output properly.
21
21
22
22
23
- use codemap:: { self , Span , MacroBacktrace , MultiSpan , CodeMap } ;
23
+ use codemap:: { self , MacroBacktrace , Span , SpanLabel , MultiSpan , CodeMap } ;
24
24
use diagnostics:: registry:: Registry ;
25
25
use errors:: { Level , DiagnosticBuilder , SubDiagnostic , RenderSpan , CodeSuggestion } ;
26
26
use errors:: emitter:: Emitter ;
@@ -53,20 +53,13 @@ impl JsonEmitter {
53
53
}
54
54
55
55
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 ) {
57
57
let data = Diagnostic :: new ( span, msg, code, level, self ) ;
58
58
if let Err ( e) = writeln ! ( & mut self . dst, "{}" , as_json( & data) ) {
59
59
panic ! ( "failed to print diagnostics: {:?}" , e) ;
60
60
}
61
61
}
62
62
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
-
70
63
fn emit_struct ( & mut self , db : & DiagnosticBuilder ) {
71
64
let data = Diagnostic :: from_diagnostic_builder ( db, self ) ;
72
65
if let Err ( e) = writeln ! ( & mut self . dst, "{}" , as_json( & data) ) {
@@ -104,8 +97,13 @@ struct DiagnosticSpan {
104
97
/// 1-based, character offset.
105
98
column_start : usize ,
106
99
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 ,
107
103
/// Source text from the start of line_start to the end of line_end.
108
104
text : Vec < DiagnosticSpanLine > ,
105
+ /// Label that should be placed at this location (if any)
106
+ label : Option < String > ,
109
107
/// If we are suggesting a replacement, this will contain text
110
108
/// that should be sliced in atop this span. You may prefer to
111
109
/// load the fully rendered version from the parent `Diagnostic`,
@@ -148,7 +146,7 @@ struct DiagnosticCode {
148
146
}
149
147
150
148
impl < ' a > Diagnostic < ' a > {
151
- fn new ( msp : Option < & MultiSpan > ,
149
+ fn new ( msp : & MultiSpan ,
152
150
msg : & ' a str ,
153
151
code : Option < & str > ,
154
152
level : Level ,
@@ -158,35 +156,20 @@ impl<'a> Diagnostic<'a> {
158
156
message : msg,
159
157
code : DiagnosticCode :: map_opt_string ( code. map ( |c| c. to_owned ( ) ) , je) ,
160
158
level : level. to_str ( ) ,
161
- spans : msp . map_or ( vec ! [ ] , |msp| DiagnosticSpan :: from_multispan ( msp, je) ) ,
159
+ spans : DiagnosticSpan :: from_multispan ( msp, je) ,
162
160
children : vec ! [ ] ,
163
161
rendered : None ,
164
162
}
165
163
}
166
164
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
-
182
165
fn from_diagnostic_builder < ' c > ( db : & ' c DiagnosticBuilder ,
183
166
je : & JsonEmitter )
184
167
-> Diagnostic < ' c > {
185
168
Diagnostic {
186
169
message : & db. message ,
187
170
code : DiagnosticCode :: map_opt_string ( db. code . clone ( ) , je) ,
188
171
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) ,
190
173
children : db. children . iter ( ) . map ( |c| {
191
174
Diagnostic :: from_sub_diagnostic ( c, je)
192
175
} ) . collect ( ) ,
@@ -201,8 +184,7 @@ impl<'a> Diagnostic<'a> {
201
184
level : db. level . to_str ( ) ,
202
185
spans : db. render_span . as_ref ( )
203
186
. 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) ) ,
206
188
children : vec ! [ ] ,
207
189
rendered : db. render_span . as_ref ( )
208
190
. and_then ( |rsp| je. render ( rsp) ) ,
@@ -211,44 +193,68 @@ impl<'a> Diagnostic<'a> {
211
193
}
212
194
213
195
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 {
216
213
// obtain the full backtrace from the `macro_backtrace`
217
214
// helper; in some ways, it'd be better to expand the
218
215
// backtrace ourselves, but the `macro_backtrace` helper makes
219
216
// some decision, such as dropping some frames, and I don't
220
217
// want to duplicate that logic here.
221
218
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)
223
225
}
224
226
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 {
230
234
let start = je. cm . lookup_char_pos ( span. lo ) ;
231
235
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
+ } ) ;
252
258
DiagnosticSpan {
253
259
file_name : start. file . name . clone ( ) ,
254
260
byte_start : span. lo . 0 ,
@@ -257,53 +263,42 @@ impl DiagnosticSpan {
257
263
line_end : end. line ,
258
264
column_start : start. col . 0 + 1 ,
259
265
column_end : end. col . 0 + 1 ,
266
+ is_primary : is_primary,
260
267
text : DiagnosticSpanLine :: from_span ( span, je) ,
261
268
suggested_replacement : suggestion. cloned ( ) ,
262
269
expansion : backtrace_step,
270
+ label : label,
263
271
}
264
272
}
265
273
266
274
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 ( )
268
279
}
269
280
270
281
fn from_suggestion ( suggestion : & CodeSuggestion , je : & JsonEmitter )
271
282
-> 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 ( )
279
293
}
280
294
281
295
fn from_render_span ( rsp : & RenderSpan , je : & JsonEmitter ) -> Vec < DiagnosticSpan > {
282
296
match * rsp {
283
297
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) ,
307
302
}
308
303
}
309
304
}
@@ -340,34 +335,6 @@ impl DiagnosticSpanLine {
340
335
} )
341
336
. unwrap_or ( vec ! [ ] )
342
337
}
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
- }
371
338
}
372
339
373
340
impl DiagnosticCode {
@@ -396,9 +363,6 @@ impl JsonEmitter {
396
363
RenderSpan :: Suggestion ( ref suggestion) => {
397
364
Some ( suggestion. splice_lines ( & self . cm ) )
398
365
}
399
- RenderSpan :: EndSpan ( _) => {
400
- None
401
- }
402
366
}
403
367
}
404
368
}
0 commit comments