@@ -21,6 +21,8 @@ use std::io::prelude::*;
2121use std:: io;
2222use std:: rc:: Rc ;
2323use term;
24+ use std:: collections:: HashMap ;
25+ use std:: cmp:: min;
2426
2527/// Emitter trait for emitting errors.
2628pub trait Emitter {
@@ -156,15 +158,6 @@ impl EmitterWriter {
156158 }
157159 let lo = cm. lookup_char_pos ( span_label. span . lo ) ;
158160 let mut hi = cm. lookup_char_pos ( span_label. span . hi ) ;
159- let mut is_minimized = false ;
160-
161- // If the span is long multi-line, simplify down to the span of one character
162- let max_multiline_span_length = 8 ;
163- if lo. line != hi. line && ( hi. line - lo. line ) > max_multiline_span_length {
164- hi. line = lo. line ;
165- hi. col = CharPos ( lo. col . 0 + 1 ) ;
166- is_minimized = true ;
167- }
168161
169162 // Watch out for "empty spans". If we get a span like 6..6, we
170163 // want to just display a `^` at 6, so convert that to
@@ -175,16 +168,7 @@ impl EmitterWriter {
175168 hi. col = CharPos ( lo. col . 0 + 1 ) ;
176169 }
177170
178- let mut ann = Annotation {
179- start_col : lo. col . 0 ,
180- end_col : hi. col . 0 ,
181- is_primary : span_label. is_primary ,
182- label : span_label. label . clone ( ) ,
183- annotation_type : AnnotationType :: Singleline ,
184- } ;
185- if is_minimized {
186- ann. annotation_type = AnnotationType :: Minimized ;
187- } else if lo. line != hi. line {
171+ let ann_type = if lo. line != hi. line {
188172 let ml = MultilineAnnotation {
189173 depth : 1 ,
190174 line_start : lo. line ,
@@ -194,8 +178,17 @@ impl EmitterWriter {
194178 is_primary : span_label. is_primary ,
195179 label : span_label. label . clone ( ) ,
196180 } ;
197- ann. annotation_type = AnnotationType :: Multiline ( ml. clone ( ) ) ;
198- multiline_annotations. push ( ( lo. file . clone ( ) , ml) ) ;
181+ multiline_annotations. push ( ( lo. file . clone ( ) , ml. clone ( ) ) ) ;
182+ AnnotationType :: Multiline ( ml)
183+ } else {
184+ AnnotationType :: Singleline
185+ } ;
186+ let ann = Annotation {
187+ start_col : lo. col . 0 ,
188+ end_col : hi. col . 0 ,
189+ is_primary : span_label. is_primary ,
190+ label : span_label. label . clone ( ) ,
191+ annotation_type : ann_type,
199192 } ;
200193
201194 if !ann. is_multiline ( ) {
@@ -233,9 +226,15 @@ impl EmitterWriter {
233226 max_depth = ann. depth ;
234227 }
235228 add_annotation_to_file ( & mut output, file. clone ( ) , ann. line_start , ann. as_start ( ) ) ;
236- for line in ann. line_start + 1 ..ann. line_end {
229+ let middle = min ( ann. line_start + 4 , ann. line_end ) ;
230+ for line in ann. line_start + 1 ..middle {
237231 add_annotation_to_file ( & mut output, file. clone ( ) , line, ann. as_line ( ) ) ;
238232 }
233+ if middle < ann. line_end - 1 {
234+ for line in ann. line_end - 1 ..ann. line_end {
235+ add_annotation_to_file ( & mut output, file. clone ( ) , line, ann. as_line ( ) ) ;
236+ }
237+ }
239238 add_annotation_to_file ( & mut output, file, ann. line_end , ann. as_end ( ) ) ;
240239 }
241240 for file_vec in output. iter_mut ( ) {
@@ -249,16 +248,11 @@ impl EmitterWriter {
249248 file : Rc < FileMap > ,
250249 line : & Line ,
251250 width_offset : usize ,
252- multiline_depth : usize ) {
251+ code_offset : usize ) -> Vec < ( usize , Style ) > {
253252 let source_string = file. get_line ( line. line_index - 1 )
254253 . unwrap_or ( "" ) ;
255254
256255 let line_offset = buffer. num_lines ( ) ;
257- let code_offset = if multiline_depth == 0 {
258- width_offset
259- } else {
260- width_offset + multiline_depth + 1
261- } ;
262256
263257 // First create the source line we will highlight.
264258 buffer. puts ( line_offset, code_offset, & source_string, Style :: Quotation ) ;
@@ -286,7 +280,7 @@ impl EmitterWriter {
286280 // previous borrow of `vec` occurs here
287281 //
288282 // For this reason, we group the lines into "highlight lines"
289- // and "annotations lines", where the highlight lines have the `~ `.
283+ // and "annotations lines", where the highlight lines have the `^ `.
290284
291285 // Sort the annotations by (start, end col)
292286 let mut annotations = line. annotations . clone ( ) ;
@@ -410,25 +404,9 @@ impl EmitterWriter {
410404 // If there are no annotations or the only annotations on this line are
411405 // MultilineLine, then there's only code being shown, stop processing.
412406 if line. annotations . is_empty ( ) || line. annotations . iter ( )
413- . filter ( |a| {
414- // Set the multiline annotation vertical lines to the left of
415- // the code in this line.
416- if let AnnotationType :: MultilineLine ( depth) = a. annotation_type {
417- buffer. putc ( line_offset,
418- width_offset + depth - 1 ,
419- '|' ,
420- if a. is_primary {
421- Style :: UnderlinePrimary
422- } else {
423- Style :: UnderlineSecondary
424- } ) ;
425- false
426- } else {
427- true
428- }
429- } ) . collect :: < Vec < _ > > ( ) . len ( ) == 0
407+ . filter ( |a| !a. is_line ( ) ) . collect :: < Vec < _ > > ( ) . len ( ) == 0
430408 {
431- return ;
409+ return vec ! [ ] ;
432410 }
433411
434412 // Write the colunmn separator.
@@ -483,16 +461,15 @@ impl EmitterWriter {
483461 }
484462 }
485463
486- // Write the vertical lines for multiline spans and for labels that are
487- // on a different line as the underline.
464+ // Write the vertical lines for labels that are on a different line as the underline.
488465 //
489466 // After this we will have:
490467 //
491468 // 2 | fn foo() {
492469 // | __________
493470 // | | |
494471 // | |
495- // 3 | |
472+ // 3 |
496473 // 4 | | }
497474 // | |_
498475 for & ( pos, annotation) in & annotations_position {
@@ -528,16 +505,6 @@ impl EmitterWriter {
528505 style) ;
529506 }
530507 }
531- AnnotationType :: MultilineLine ( depth) => {
532- // the first line will have already be filled when we checked
533- // wether there were any annotations for this line.
534- for p in line_offset + 1 ..line_offset + line_len + 2 {
535- buffer. putc ( p,
536- width_offset + depth - 1 ,
537- '|' ,
538- style) ;
539- }
540- }
541508 _ => ( ) ,
542509 }
543510 }
@@ -548,11 +515,11 @@ impl EmitterWriter {
548515 //
549516 // 2 | fn foo() {
550517 // | __________ starting here...
551- // | | |
552- // | | something about `foo`
553- // 3 | |
554- // 4 | | }
555- // | | _ ...ending here: test
518+ // | |
519+ // | something about `foo`
520+ // 3 |
521+ // 4 | }
522+ // | _ ...ending here: test
556523 for & ( pos, annotation) in & annotations_position {
557524 let style = if annotation. is_primary {
558525 Style :: LabelPrimary
@@ -591,11 +558,11 @@ impl EmitterWriter {
591558 //
592559 // 2 | fn foo() {
593560 // | ____-_____^ starting here...
594- // | | |
595- // | | something about `foo`
596- // 3 | |
597- // 4 | | }
598- // | | _^ ...ending here: test
561+ // | |
562+ // | something about `foo`
563+ // 3 |
564+ // 4 | }
565+ // | _^ ...ending here: test
599566 for & ( _, annotation) in & annotations_position {
600567 let ( underline, style) = if annotation. is_primary {
601568 ( '^' , Style :: UnderlinePrimary )
@@ -609,6 +576,20 @@ impl EmitterWriter {
609576 style) ;
610577 }
611578 }
579+ annotations_position. iter ( ) . filter_map ( |& ( _, annotation) | {
580+ match annotation. annotation_type {
581+ AnnotationType :: MultilineStart ( p) | AnnotationType :: MultilineEnd ( p) => {
582+ let style = if annotation. is_primary {
583+ Style :: LabelPrimary
584+ } else {
585+ Style :: LabelSecondary
586+ } ;
587+ Some ( ( p, style) )
588+ } ,
589+ _ => None
590+ }
591+
592+ } ) . collect :: < Vec < _ > > ( )
612593 }
613594
614595 fn get_multispan_max_line_num ( & mut self , msp : & MultiSpan ) -> usize {
@@ -902,22 +883,64 @@ impl EmitterWriter {
902883 let buffer_msg_line_offset = buffer. num_lines ( ) ;
903884 draw_col_separator_no_space ( & mut buffer, buffer_msg_line_offset, max_line_num_len + 1 ) ;
904885
886+ // Contains the vertical lines' positions for active multiline annotations
887+ let mut multilines = HashMap :: new ( ) ;
888+
905889 // Next, output the annotate source for this file
906890 for line_idx in 0 ..annotated_file. lines . len ( ) {
907- self . render_source_line ( & mut buffer,
908- annotated_file. file . clone ( ) ,
909- & annotated_file. lines [ line_idx] ,
910- 3 + max_line_num_len,
911- annotated_file. multiline_depth ) ;
891+ let previous_buffer_line = buffer. num_lines ( ) ;
892+
893+ let width_offset = 3 + max_line_num_len;
894+ let code_offset = if annotated_file. multiline_depth == 0 {
895+ width_offset
896+ } else {
897+ width_offset + annotated_file. multiline_depth + 1
898+ } ;
899+
900+ let depths = self . render_source_line ( & mut buffer,
901+ annotated_file. file . clone ( ) ,
902+ & annotated_file. lines [ line_idx] ,
903+ width_offset,
904+ code_offset) ;
912905
906+ let mut to_add = HashMap :: new ( ) ;
907+
908+ for ( depth, style) in depths {
909+ if multilines. get ( & depth) . is_some ( ) {
910+ multilines. remove ( & depth) ;
911+ } else {
912+ to_add. insert ( depth, style) ;
913+ }
914+ }
915+
916+ // Set the multiline annotation vertical lines to the left of
917+ // the code in this line.
918+ for ( depth, style) in & multilines {
919+ for line in previous_buffer_line..buffer. num_lines ( ) {
920+ draw_multiline_line ( & mut buffer,
921+ line,
922+ width_offset,
923+ * depth,
924+ * style) ;
925+ }
926+ }
913927 // check to see if we need to print out or elide lines that come between
914- // this annotated line and the next one
928+ // this annotated line and the next one.
915929 if line_idx < ( annotated_file. lines . len ( ) - 1 ) {
916930 let line_idx_delta = annotated_file. lines [ line_idx + 1 ] . line_index -
917931 annotated_file. lines [ line_idx] . line_index ;
918932 if line_idx_delta > 2 {
919933 let last_buffer_line_num = buffer. num_lines ( ) ;
920934 buffer. puts ( last_buffer_line_num, 0 , "..." , Style :: LineNumber ) ;
935+
936+ // Set the multiline annotation vertical lines on `...` bridging line.
937+ for ( depth, style) in & multilines {
938+ draw_multiline_line ( & mut buffer,
939+ last_buffer_line_num,
940+ width_offset,
941+ * depth,
942+ * style) ;
943+ }
921944 } else if line_idx_delta == 2 {
922945 let unannotated_line = annotated_file. file
923946 . get_line ( annotated_file. lines [ line_idx] . line_index )
@@ -932,11 +955,21 @@ impl EmitterWriter {
932955 Style :: LineNumber ) ;
933956 draw_col_separator ( & mut buffer, last_buffer_line_num, 1 + max_line_num_len) ;
934957 buffer. puts ( last_buffer_line_num,
935- 3 + max_line_num_len ,
958+ code_offset ,
936959 & unannotated_line,
937960 Style :: Quotation ) ;
961+
962+ for ( depth, style) in & multilines {
963+ draw_multiline_line ( & mut buffer,
964+ last_buffer_line_num,
965+ width_offset,
966+ * depth,
967+ * style) ;
968+ }
938969 }
939970 }
971+
972+ multilines. extend ( & to_add) ;
940973 }
941974 }
942975
@@ -1085,6 +1118,15 @@ fn draw_note_separator(buffer: &mut StyledBuffer, line: usize, col: usize) {
10851118 buffer. puts ( line, col, "= " , Style :: LineNumber ) ;
10861119}
10871120
1121+ fn draw_multiline_line ( buffer : & mut StyledBuffer ,
1122+ line : usize ,
1123+ offset : usize ,
1124+ depth : usize ,
1125+ style : Style )
1126+ {
1127+ buffer. putc ( line, offset + depth - 1 , '|' , style) ;
1128+ }
1129+
10881130fn num_overlap ( a_start : usize , a_end : usize , b_start : usize , b_end : usize , inclusive : bool ) -> bool {
10891131 let extra = if inclusive {
10901132 1
0 commit comments