@@ -19,12 +19,16 @@ use extra::term;
19
19
20
20
static BUG_REPORT_URL : & ' static str =
21
21
"http://static.rust-lang.org/doc/master/complement-bugreport.html" ;
22
+ // maximum number of lines we will print for each error; arbitrary.
23
+ static MAX_LINES : uint = 6 u;
22
24
23
25
pub trait Emitter {
24
26
fn emit ( & self ,
25
27
cmsp : Option < ( & codemap:: CodeMap , Span ) > ,
26
28
msg : & str ,
27
29
lvl : Level ) ;
30
+ fn custom_emit ( & self , cm : & codemap:: CodeMap ,
31
+ sp : Span , msg : & str , lvl : Level ) ;
28
32
}
29
33
30
34
/// This structure is used to signify that a task has failed with a fatal error
@@ -55,6 +59,9 @@ impl SpanHandler {
55
59
pub fn span_note ( @self , sp : Span , msg : & str ) {
56
60
self . handler . emit ( Some ( ( & * self . cm , sp) ) , msg, Note ) ;
57
61
}
62
+ pub fn span_end_note ( @self , sp : Span , msg : & str ) {
63
+ self . handler . custom_emit ( & * self . cm , sp, msg, Note ) ;
64
+ }
58
65
pub fn span_bug ( @self , sp : Span , msg : & str ) -> ! {
59
66
self . span_fatal ( sp, ice_msg ( msg) ) ;
60
67
}
@@ -122,6 +129,10 @@ impl Handler {
122
129
lvl: Level) {
123
130
self.emit.emit(cmsp, msg, lvl);
124
131
}
132
+ pub fn custom_emit(@self, cm: &codemap::CodeMap,
133
+ sp: Span, msg: &str, lvl: Level) {
134
+ self.emit.custom_emit(cm, sp, msg, lvl);
135
+ }
125
136
}
126
137
127
138
pub fn ice_msg(msg: &str) -> ~str {
@@ -239,17 +250,34 @@ impl Emitter for DefaultEmitter {
239
250
msg : & str ,
240
251
lvl : Level ) {
241
252
match cmsp {
242
- Some ( ( cm, sp) ) => {
243
- let sp = cm. adjust_span ( sp) ;
244
- let ss = cm. span_to_str ( sp) ;
245
- let lines = cm. span_to_lines ( sp) ;
246
- print_diagnostic ( ss, lvl, msg) ;
247
- highlight_lines ( cm, sp, lvl, lines) ;
248
- print_macro_backtrace ( cm, sp) ;
249
- }
253
+ Some ( ( cm, sp) ) => emit ( cm, sp, msg, lvl, false ) ,
250
254
None => print_diagnostic ( "" , lvl, msg) ,
251
255
}
252
256
}
257
+
258
+ fn custom_emit ( & self , cm : & codemap:: CodeMap ,
259
+ sp : Span , msg : & str , lvl : Level ) {
260
+ emit ( cm, sp, msg, lvl, true ) ;
261
+ }
262
+ }
263
+
264
+ fn emit ( cm : & codemap:: CodeMap , sp : Span ,
265
+ msg : & str , lvl : Level , custom : bool ) {
266
+ let ss = cm. span_to_str ( sp) ;
267
+ let lines = cm. span_to_lines ( sp) ;
268
+ if custom {
269
+ // we want to tell compiletest/runtest to look at the last line of the
270
+ // span (since `custom_highlight_lines` displays an arrow to the end of
271
+ // the span)
272
+ let span_end = Span { lo : sp. hi , hi : sp. hi , expn_info : sp. expn_info } ;
273
+ let ses = cm. span_to_str ( span_end) ;
274
+ print_diagnostic ( ses, lvl, msg) ;
275
+ custom_highlight_lines ( cm, sp, lvl, lines) ;
276
+ } else {
277
+ print_diagnostic ( ss, lvl, msg) ;
278
+ highlight_lines ( cm, sp, lvl, lines) ;
279
+ }
280
+ print_macro_backtrace ( cm, sp) ;
253
281
}
254
282
255
283
fn highlight_lines ( cm : & codemap:: CodeMap ,
@@ -260,12 +288,10 @@ fn highlight_lines(cm: &codemap::CodeMap,
260
288
let mut err = io:: stderr ( ) ;
261
289
let err = & mut err as & mut io:: Writer ;
262
290
263
- // arbitrarily only print up to six lines of the error
264
- let max_lines = 6 u;
265
291
let mut elided = false ;
266
292
let mut display_lines = lines. lines . as_slice ( ) ;
267
- if display_lines. len ( ) > max_lines {
268
- display_lines = display_lines. slice ( 0 u, max_lines ) ;
293
+ if display_lines. len ( ) > MAX_LINES {
294
+ display_lines = display_lines. slice ( 0 u, MAX_LINES ) ;
269
295
elided = true ;
270
296
}
271
297
// Print the offending lines
@@ -319,6 +345,44 @@ fn highlight_lines(cm: &codemap::CodeMap,
319
345
}
320
346
}
321
347
348
+ // Here are the differences between this and the normal `highlight_lines`:
349
+ // `custom_highlight_lines` will always put arrow on the last byte of the
350
+ // span (instead of the first byte). Also, when the span is too long (more
351
+ // than 6 lines), `custom_highlight_lines` will print the first line, then
352
+ // dot dot dot, then last line, whereas `highlight_lines` prints the first
353
+ // six lines.
354
+ fn custom_highlight_lines ( cm : & codemap:: CodeMap ,
355
+ sp : Span ,
356
+ lvl : Level ,
357
+ lines : & codemap:: FileLines ) {
358
+ let fm = lines. file ;
359
+ let mut err = io:: stderr ( ) ;
360
+ let err = & mut err as & mut io:: Writer ;
361
+
362
+ let lines = lines. lines . as_slice ( ) ;
363
+ if lines. len ( ) > MAX_LINES {
364
+ write ! ( err, "{}:{} {}\n " , fm. name,
365
+ lines[ 0 ] + 1 , fm. get_line( lines[ 0 ] as int) ) ;
366
+ write ! ( err, "...\n " ) ;
367
+ let last_line = lines[ lines. len ( ) -1 ] ;
368
+ write ! ( err, "{}:{} {}\n " , fm. name,
369
+ last_line + 1 , fm. get_line( last_line as int) ) ;
370
+ } else {
371
+ for line in lines. iter ( ) {
372
+ write ! ( err, "{}:{} {}\n " , fm. name,
373
+ * line + 1 , fm. get_line( * line as int) ) ;
374
+ }
375
+ }
376
+ let last_line_start = format ! ( "{}:{} " , fm. name, lines[ lines. len( ) -1 ] +1 ) ;
377
+ let hi = cm. lookup_char_pos ( sp. hi ) ;
378
+ // Span seems to use half-opened interval, so subtract 1
379
+ let skip = last_line_start. len ( ) + hi. col . to_uint ( ) - 1 ;
380
+ let mut s = ~"";
381
+ skip. times ( || s. push_char ( ' ' ) ) ;
382
+ s. push_char ( '^' ) ;
383
+ print_maybe_styled ( s + "\n " , term:: attr:: ForegroundColor ( lvl. color ( ) ) ) ;
384
+ }
385
+
322
386
fn print_macro_backtrace ( cm : & codemap:: CodeMap , sp : Span ) {
323
387
for ei in sp. expn_info . iter ( ) {
324
388
let ss = ei. callee . span . as_ref ( ) . map_or ( ~"", |span| cm. span_to_str ( * span) ) ;
0 commit comments