@@ -18,6 +18,7 @@ use codemap;
1818use diagnostics;
1919
2020use std:: cell:: { RefCell , Cell } ;
21+ use std:: cmp;
2122use std:: fmt;
2223use std:: io:: prelude:: * ;
2324use std:: io;
@@ -28,7 +29,7 @@ use libc;
2829/// maximum number of lines we will print for each error; arbitrary.
2930const MAX_LINES : usize = 6 ;
3031
31- #[ derive( Clone , Copy ) ]
32+ #[ derive( Clone ) ]
3233pub enum RenderSpan {
3334 /// A FullSpan renders with both with an initial line for the
3435 /// message, prefixed by file:linenum, followed by a summary of
@@ -42,6 +43,12 @@ pub enum RenderSpan {
4243 /// of the span).
4344 EndSpan ( Span ) ,
4445
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+
4552 /// A FileLine renders with just a line for the message prefixed
4653 /// by file:linenum.
4754 FileLine ( Span ) ,
@@ -51,6 +58,7 @@ impl RenderSpan {
5158 fn span ( & self ) -> Span {
5259 match * self {
5360 FullSpan ( s) |
61+ Suggestion ( s, _) |
5462 EndSpan ( s) |
5563 FileLine ( s) =>
5664 s
@@ -124,6 +132,12 @@ impl SpanHandler {
124132 pub fn span_help ( & self , sp : Span , msg : & str ) {
125133 self . handler . emit ( Some ( ( & self . cm , sp) ) , msg, Help ) ;
126134 }
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+ }
127141 pub fn fileline_note ( & self , sp : Span , msg : & str ) {
128142 self . handler . custom_emit ( & self . cm , FileLine ( sp) , msg, Note ) ;
129143 }
@@ -455,6 +469,9 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan,
455469 EndSpan ( _) => {
456470 try!( end_highlight_lines ( dst, cm, sp, lvl, cm. span_to_lines ( sp) ) ) ;
457471 }
472+ Suggestion ( _, ref suggestion) => {
473+ try!( highlight_suggestion ( dst, cm, sp, suggestion) ) ;
474+ }
458475 FileLine ( ..) => {
459476 // no source text in this case!
460477 }
@@ -479,6 +496,53 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan,
479496 Ok ( ( ) )
480497}
481498
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 fm = & * lines. file ;
529+ let mut lines = complete. lines ( ) ;
530+ for ( line, line_index) in lines. by_ref ( ) . take ( MAX_LINES ) . zip ( first_line. line_index ..) {
531+ let elided_line_num = format ! ( "{}" , line_index+1 ) ;
532+ try!( write ! ( & mut err. dst, "{0}:{1:2$} {3}\n " ,
533+ fm. name, "" , elided_line_num. len( ) , line) ) ;
534+ }
535+
536+ // if we elided some lines, add an ellipsis
537+ if lines. next ( ) . is_some ( ) {
538+ let elided_line_num = format ! ( "{}" , first_line. line_index + MAX_LINES + 1 ) ;
539+ try!( write ! ( & mut err. dst, "{0:1$} {0:2$} ...\n " ,
540+ "" , fm. name. len( ) , elided_line_num. len( ) ) ) ;
541+ }
542+
543+ Ok ( ( ) )
544+ }
545+
482546fn highlight_lines ( err : & mut EmitterWriter ,
483547 cm : & codemap:: CodeMap ,
484548 sp : Span ,
0 commit comments