@@ -5,8 +5,7 @@ use crate::snippet;
55fn format_label ( label : Option < & str > , style : Option < DisplayTextStyle > ) -> Vec < DisplayTextFragment > {
66 let mut result = vec ! [ ] ;
77 if let Some ( label) = label {
8- let elements: Vec < & str > = label. split ( "__" ) . collect ( ) ;
9- for ( idx, element) in elements. iter ( ) . enumerate ( ) {
8+ for ( idx, element) in label. split ( "__" ) . enumerate ( ) {
109 let element_style = match style {
1110 Some ( s) => s,
1211 None => {
@@ -26,22 +25,22 @@ fn format_label(label: Option<&str>, style: Option<DisplayTextStyle>) -> Vec<Dis
2625 result
2726}
2827
29- fn format_title ( annotation : & snippet:: Annotation ) -> DisplayLine {
30- let label = annotation. label . clone ( ) . unwrap_or_default ( ) ;
28+ fn format_title ( annotation : snippet:: Annotation ) -> DisplayLine {
29+ let label = annotation. label . unwrap_or_default ( ) ;
3130 DisplayLine :: Raw ( DisplayRawLine :: Annotation {
3231 annotation : Annotation {
3332 annotation_type : DisplayAnnotationType :: from ( annotation. annotation_type ) ,
34- id : annotation. id . clone ( ) ,
33+ id : annotation. id ,
3534 label : format_label ( Some ( & label) , Some ( DisplayTextStyle :: Emphasis ) ) ,
3635 } ,
3736 source_aligned : false ,
3837 continuation : false ,
3938 } )
4039}
4140
42- fn format_annotation ( annotation : & snippet:: Annotation ) -> Vec < DisplayLine > {
41+ fn format_annotation ( annotation : snippet:: Annotation ) -> Vec < DisplayLine > {
4342 let mut result = vec ! [ ] ;
44- let label = annotation. label . clone ( ) . unwrap_or_default ( ) ;
43+ let label = annotation. label . unwrap_or_default ( ) ;
4544 for ( i, line) in label. lines ( ) . enumerate ( ) {
4645 result. push ( DisplayLine :: Raw ( DisplayRawLine :: Annotation {
4746 annotation : Annotation {
@@ -56,11 +55,14 @@ fn format_annotation(annotation: &snippet::Annotation) -> Vec<DisplayLine> {
5655 result
5756}
5857
59- fn format_slice ( slice : & snippet:: Slice , is_first : bool , has_footer : bool ) -> Vec < DisplayLine > {
58+ fn format_slice ( mut slice : snippet:: Slice , is_first : bool , has_footer : bool ) -> Vec < DisplayLine > {
59+ let main_range = slice. annotations . get ( 0 ) . map ( |x| x. range . 0 ) ;
60+ let row = slice. line_start ;
61+ let origin = slice. origin . take ( ) ;
6062 let mut body = format_body ( slice, has_footer) ;
63+ let header = format_header ( origin, main_range, row, & body, is_first) ;
6164 let mut result = vec ! [ ] ;
6265
63- let header = format_header ( slice, & body, is_first) ;
6466 if let Some ( header) = header {
6567 result. push ( header) ;
6668 }
@@ -69,46 +71,45 @@ fn format_slice(slice: &snippet::Slice, is_first: bool, has_footer: bool) -> Vec
6971}
7072
7173fn format_header (
72- slice : & snippet:: Slice ,
74+ origin : Option < String > ,
75+ main_range : Option < usize > ,
76+ mut row : usize ,
7377 body : & [ DisplayLine ] ,
7478 is_first : bool ,
7579) -> Option < DisplayLine > {
76- let main_annotation = slice. annotations . get ( 0 ) ;
77-
7880 let display_header = if is_first {
7981 DisplayHeaderType :: Initial
8082 } else {
8183 DisplayHeaderType :: Continuation
8284 } ;
8385
84- if let Some ( annotation ) = main_annotation {
86+ if let Some ( main_range ) = main_range {
8587 let mut col = 1 ;
86- let mut row = slice. line_start ;
8788
88- for item in body. iter ( ) {
89+ for item in body {
8990 if let DisplayLine :: Source {
9091 line : DisplaySourceLine :: Content { range, .. } ,
9192 ..
9293 } = item
9394 {
94- if annotation . range . 0 >= range. 0 && annotation . range . 0 <= range. 1 {
95- col = annotation . range . 0 - range. 0 + 1 ;
95+ if main_range >= range. 0 && main_range <= range. 1 {
96+ col = main_range - range. 0 + 1 ;
9697 break ;
9798 }
9899 row += 1 ;
99100 }
100101 }
101- if let Some ( ref path) = slice . origin {
102+ if let Some ( path) = origin {
102103 return Some ( DisplayLine :: Raw ( DisplayRawLine :: Origin {
103- path : path . to_string ( ) ,
104+ path,
104105 pos : Some ( ( row, col) ) ,
105106 header_type : display_header,
106107 } ) ) ;
107108 }
108109 }
109- if let Some ( ref path) = slice . origin {
110+ if let Some ( path) = origin {
110111 return Some ( DisplayLine :: Raw ( DisplayRawLine :: Origin {
111- path : path . to_string ( ) ,
112+ path,
112113 pos : None ,
113114 header_type : display_header,
114115 } ) ) ;
@@ -175,15 +176,30 @@ fn fold_body(body: &[DisplayLine]) -> Vec<DisplayLine> {
175176 new_body
176177}
177178
178- fn format_body ( slice : & snippet:: Slice , has_footer : bool ) -> Vec < DisplayLine > {
179- let mut body = vec ! [ ] ;
179+ fn format_body ( slice : snippet:: Slice , has_footer : bool ) -> Vec < DisplayLine > {
180+ let source_len = slice. source . chars ( ) . count ( ) ;
181+ if let Some ( bigger) = slice. annotations . iter ( ) . find_map ( |x| {
182+ if source_len < x. range . 1 {
183+ Some ( x. range )
184+ } else {
185+ None
186+ }
187+ } ) {
188+ panic ! (
189+ "SourceAnnotation range `{:?}` is bigger than source length `{}`" ,
190+ bigger, source_len
191+ )
192+ }
180193
194+ let mut body = vec ! [ ] ;
181195 let mut current_line = slice. line_start ;
182196 let mut current_index = 0 ;
183197 let mut line_index_ranges = vec ! [ ] ;
184198
185- for line in slice. source . lines ( ) {
186- let line_length = line. chars ( ) . count ( ) + 1 ;
199+ let lines = slice. source . lines ( ) ;
200+ let lines_len = lines. clone ( ) . count ( ) ;
201+ for ( i, line) in lines. enumerate ( ) {
202+ let line_length = line. chars ( ) . count ( ) ;
187203 let line_range = ( current_index, current_index + line_length) ;
188204 body. push ( DisplayLine :: Source {
189205 lineno : Some ( current_line) ,
@@ -195,13 +211,14 @@ fn format_body(slice: &snippet::Slice, has_footer: bool) -> Vec<DisplayLine> {
195211 } ) ;
196212 line_index_ranges. push ( line_range) ;
197213 current_line += 1 ;
198- current_index += line_length + 1 ;
214+ if i + 1 < lines_len {
215+ current_index += line_length + 1 ;
216+ }
199217 }
200218
201219 let mut annotation_line_count = 0 ;
202- let mut annotations = slice. annotations . clone ( ) ;
203- for idx in 0 ..body. len ( ) {
204- let ( line_start, line_end) = line_index_ranges[ idx] ;
220+ let mut annotations = slice. annotations ;
221+ for ( idx, ( line_start, line_end) ) in line_index_ranges. into_iter ( ) . enumerate ( ) {
205222 // It would be nice to use filter_drain here once it's stable.
206223 annotations = annotations
207224 . into_iter ( )
@@ -214,7 +231,10 @@ fn format_body(slice: &snippet::Slice, has_footer: bool) -> Vec<DisplayLine> {
214231 } ;
215232 match annotation. range {
216233 ( start, _) if start > line_end => true ,
217- ( start, end) if start >= line_start && end <= line_end => {
234+ ( start, end)
235+ if start >= line_start && end <= line_end
236+ || start == line_end && end - start <= 1 =>
237+ {
218238 let range = ( start - line_start, end - line_start) ;
219239 body. insert (
220240 body_idx + 1 ,
@@ -305,6 +325,7 @@ fn format_body(slice: &snippet::Slice, has_footer: bool) -> Vec<DisplayLine> {
305325 ) ,
306326 } ) ;
307327 }
328+
308329 let range = ( end - line_start, end - line_start + 1 ) ;
309330 body. insert (
310331 body_idx + 1 ,
@@ -368,22 +389,24 @@ fn format_body(slice: &snippet::Slice, has_footer: bool) -> Vec<DisplayLine> {
368389}
369390
370391impl From < snippet:: Snippet > for DisplayList {
371- fn from ( snippet : snippet:: Snippet ) -> Self {
392+ fn from (
393+ snippet:: Snippet {
394+ title,
395+ footer,
396+ slices,
397+ } : snippet:: Snippet ,
398+ ) -> Self {
372399 let mut body = vec ! [ ] ;
373- if let Some ( annotation) = snippet . title {
374- body. push ( format_title ( & annotation) ) ;
400+ if let Some ( annotation) = title {
401+ body. push ( format_title ( annotation) ) ;
375402 }
376403
377- for ( idx, slice) in snippet. slices . iter ( ) . enumerate ( ) {
378- body. append ( & mut format_slice (
379- & slice,
380- idx == 0 ,
381- !snippet. footer . is_empty ( ) ,
382- ) ) ;
404+ for ( idx, slice) in slices. into_iter ( ) . enumerate ( ) {
405+ body. append ( & mut format_slice ( slice, idx == 0 , !footer. is_empty ( ) ) ) ;
383406 }
384407
385- for annotation in snippet . footer {
386- body. append ( & mut format_annotation ( & annotation) ) ;
408+ for annotation in footer {
409+ body. append ( & mut format_annotation ( annotation) ) ;
387410 }
388411
389412 Self { body }
0 commit comments