@@ -594,12 +594,22 @@ fn highlight_lines(err: &mut EmitterWriter,
594594 let display_line_infos = & lines. lines [ ..display_lines] ;
595595 let display_line_strings = & line_strings[ ..display_lines] ;
596596
597+ // Calculate the widest number to format evenly and fix #11715
598+ assert ! ( display_line_infos. len( ) > 0 ) ;
599+ let mut max_line_num = display_line_infos[ display_line_infos. len ( ) - 1 ] . line_index + 1 ;
600+ let mut digits = 0 ;
601+ while max_line_num > 0 {
602+ max_line_num /= 10 ;
603+ digits += 1 ;
604+ }
605+
597606 // Print the offending lines
598607 for ( line_info, line) in display_line_infos. iter ( ) . zip ( display_line_strings) {
599- try!( write ! ( & mut err. dst, "{}:{} {}\n " ,
608+ try!( write ! ( & mut err. dst, "{}:{:>width$ } {}\n " ,
600609 fm. name,
601610 line_info. line_index + 1 ,
602- line) ) ;
611+ line,
612+ width=digits) ) ;
603613 }
604614
605615 // If we elided something, put an ellipsis.
@@ -795,3 +805,64 @@ pub fn expect<T, M>(diag: &SpanHandler, opt: Option<T>, msg: M) -> T where
795805 None => diag. handler ( ) . bug ( & msg ( ) ) ,
796806 }
797807}
808+
809+ #[ cfg( test) ]
810+ mod test {
811+ use super :: { EmitterWriter , highlight_lines, Level } ;
812+ use codemap:: { mk_sp, CodeMap , BytePos } ;
813+ use std:: sync:: { Arc , Mutex } ;
814+ use std:: io:: { self , Write } ;
815+ use std:: str:: from_utf8;
816+
817+ // Diagnostic doesn't align properly in span where line number increases by one digit
818+ #[ test]
819+ fn test_hilight_suggestion_issue_11715 ( ) {
820+ struct Sink ( Arc < Mutex < Vec < u8 > > > ) ;
821+ impl Write for Sink {
822+ fn write ( & mut self , data : & [ u8 ] ) -> io:: Result < usize > {
823+ Write :: write ( & mut * self . 0 . lock ( ) . unwrap ( ) , data)
824+ }
825+ fn flush ( & mut self ) -> io:: Result < ( ) > { Ok ( ( ) ) }
826+ }
827+ let data = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
828+ let mut ew = EmitterWriter :: new ( Box :: new ( Sink ( data. clone ( ) ) ) , None ) ;
829+ let cm = CodeMap :: new ( ) ;
830+ let content = "abcdefg
831+ koksi
832+ line3
833+ line4
834+ cinq
835+ line6
836+ line7
837+ line8
838+ line9
839+ line10
840+ e-lä-vän
841+ tolv
842+ dreizehn
843+ " ;
844+ let file = cm. new_filemap ( "dummy.txt" . to_string ( ) , content. to_string ( ) ) ;
845+ for ( i, b) in content. bytes ( ) . enumerate ( ) {
846+ if b == b'\n' {
847+ file. next_line ( BytePos ( i as u32 ) ) ;
848+ }
849+ }
850+ let start = file. lines . borrow ( ) [ 7 ] ;
851+ let end = file. lines . borrow ( ) [ 11 ] ;
852+ let sp = mk_sp ( start, end) ;
853+ let lvl = Level :: Error ;
854+ println ! ( "span_to_lines" ) ;
855+ let lines = cm. span_to_lines ( sp) ;
856+ println ! ( "highlight_lines" ) ;
857+ highlight_lines ( & mut ew, & cm, sp, lvl, lines) . unwrap ( ) ;
858+ println ! ( "done" ) ;
859+ let vec = data. lock ( ) . unwrap ( ) . clone ( ) ;
860+ let vec: & [ u8 ] = & vec;
861+ println ! ( "{}" , from_utf8( vec) . unwrap( ) ) ;
862+ assert_eq ! ( vec, "dummy.txt: 8 \n \
863+ dummy.txt: 9 \n \
864+ dummy.txt:10 \n \
865+ dummy.txt:11 \n \
866+ dummy.txt:12 \n ". as_bytes( ) ) ;
867+ }
868+ }
0 commit comments