@@ -18,6 +18,7 @@ use codemap;
18
18
use diagnostics;
19
19
20
20
use std:: cell:: { RefCell , Cell } ;
21
+ use std:: cmp;
21
22
use std:: fmt;
22
23
use std:: io:: prelude:: * ;
23
24
use std:: io;
@@ -28,7 +29,7 @@ use libc;
28
29
/// maximum number of lines we will print for each error; arbitrary.
29
30
const MAX_LINES : usize = 6 ;
30
31
31
- #[ derive( Clone , Copy ) ]
32
+ #[ derive( Clone ) ]
32
33
pub enum RenderSpan {
33
34
/// A FullSpan renders with both with an initial line for the
34
35
/// message, prefixed by file:linenum, followed by a summary of
@@ -42,6 +43,12 @@ pub enum RenderSpan {
42
43
/// of the span).
43
44
EndSpan ( Span ) ,
44
45
46
+ /// A suggestion renders with both with an initial line for the
47
+ /// message, prefixed by file:linenum, followed by a summary
48
+ /// of hypothetical source code, where the `String` is spliced
49
+ /// into the lines in place of the code covered by the span.
50
+ Suggestion ( Span , String ) ,
51
+
45
52
/// A FileLine renders with just a line for the message prefixed
46
53
/// by file:linenum.
47
54
FileLine ( Span ) ,
@@ -51,6 +58,7 @@ impl RenderSpan {
51
58
fn span ( & self ) -> Span {
52
59
match * self {
53
60
FullSpan ( s) |
61
+ Suggestion ( s, _) |
54
62
EndSpan ( s) |
55
63
FileLine ( s) =>
56
64
s
@@ -124,6 +132,12 @@ impl SpanHandler {
124
132
pub fn span_help ( & self , sp : Span , msg : & str ) {
125
133
self . handler . emit ( Some ( ( & self . cm , sp) ) , msg, Help ) ;
126
134
}
135
+ /// Prints out a message with a suggested edit of the code.
136
+ ///
137
+ /// See `diagnostic::RenderSpan::Suggestion` for more information.
138
+ pub fn span_suggestion ( & self , sp : Span , msg : & str , suggestion : String ) {
139
+ self . handler . custom_emit ( & self . cm , Suggestion ( sp, suggestion) , msg, Help ) ;
140
+ }
127
141
pub fn fileline_note ( & self , sp : Span , msg : & str ) {
128
142
self . handler . custom_emit ( & self . cm , FileLine ( sp) , msg, Note ) ;
129
143
}
@@ -455,6 +469,9 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan,
455
469
EndSpan ( _) => {
456
470
try!( end_highlight_lines ( dst, cm, sp, lvl, cm. span_to_lines ( sp) ) ) ;
457
471
}
472
+ Suggestion ( _, ref suggestion) => {
473
+ try!( highlight_suggestion ( dst, cm, sp, suggestion) ) ;
474
+ }
458
475
FileLine ( ..) => {
459
476
// no source text in this case!
460
477
}
@@ -479,6 +496,53 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan,
479
496
Ok ( ( ) )
480
497
}
481
498
499
+ fn highlight_suggestion ( err : & mut EmitterWriter ,
500
+ cm : & codemap:: CodeMap ,
501
+ sp : Span ,
502
+ suggestion : & str )
503
+ -> io:: Result < ( ) >
504
+ {
505
+ let lines = cm. span_to_lines ( sp) ;
506
+ assert ! ( !lines. lines. is_empty( ) ) ;
507
+
508
+ // To build up the result, we want to take the snippet from the first
509
+ // line that precedes the span, prepend that with the suggestion, and
510
+ // then append the snippet from the last line that trails the span.
511
+ let fm = & lines. file ;
512
+
513
+ let first_line = & lines. lines [ 0 ] ;
514
+ let prefix = fm. get_line ( first_line. line_index )
515
+ . map ( |l| & l[ ..first_line. start_col . 0 ] )
516
+ . unwrap_or ( "" ) ;
517
+
518
+ let last_line = lines. lines . last ( ) . unwrap ( ) ;
519
+ let suffix = fm. get_line ( last_line. line_index )
520
+ . map ( |l| & l[ last_line. end_col . 0 ..] )
521
+ . unwrap_or ( "" ) ;
522
+
523
+ let complete = format ! ( "{}{}{}" , prefix, suggestion, suffix) ;
524
+
525
+ // print the suggestion without any line numbers, but leave
526
+ // space for them. This helps with lining up with previous
527
+ // snippets from the actual error being reported.
528
+ let line_num_space = format ! ( "{0:1$}" , "" , format!( "{}" , first_line. line_index+1 ) . len( ) ) ;
529
+ let fm = & * lines. file ;
530
+ let mut lines = complete. lines ( ) ;
531
+ for line in lines. by_ref ( ) . take ( MAX_LINES ) {
532
+ try!( write ! ( & mut err. dst, "{}:{} {}\n " , fm. name, line_num_space, line) ) ;
533
+ }
534
+
535
+ // if we elided some lines, add an ellipsis
536
+ if lines. next ( ) . is_some ( ) {
537
+ try!( write ! ( & mut err. dst, "{0:1$} {2} ...\n " ,
538
+ "" ,
539
+ fm. name. len( ) ,
540
+ line_num_space) ) ;
541
+ }
542
+
543
+ Ok ( ( ) )
544
+ }
545
+
482
546
fn highlight_lines ( err : & mut EmitterWriter ,
483
547
cm : & codemap:: CodeMap ,
484
548
sp : Span ,
0 commit comments