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 } ;
2424use diagnostics:: registry:: Registry ;
2525use errors:: { Level , DiagnosticBuilder , SubDiagnostic , RenderSpan , CodeSuggestion } ;
2626use errors:: emitter:: Emitter ;
@@ -53,20 +53,13 @@ impl JsonEmitter {
5353}
5454
5555impl 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
150148impl < ' 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
213195impl 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
373340impl 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