@@ -57,6 +57,80 @@ impl HumanReadableErrorType {
5757 }
5858}
5959
60+ #[ derive( Clone , Copy , Debug ) ]
61+ struct Margin {
62+ pub whitespace_left : usize ,
63+ pub span_left : usize ,
64+ pub span_right : usize ,
65+ pub line_len : usize ,
66+ pub computed_left : usize ,
67+ pub computed_right : usize ,
68+ pub column_width : usize ,
69+ pub label_right : usize ,
70+ }
71+
72+ impl Margin {
73+ fn new (
74+ whitespace_left : usize ,
75+ span_left : usize ,
76+ span_right : usize ,
77+ label_right : usize ,
78+ ) -> Self {
79+ Margin {
80+ whitespace_left,
81+ span_left,
82+ span_right,
83+ line_len : 0 ,
84+ computed_left : 0 ,
85+ computed_right : 0 ,
86+ column_width : 140 ,
87+ label_right,
88+ }
89+ }
90+
91+ fn was_cut_left ( & self ) -> bool {
92+ self . computed_left > 0
93+ }
94+
95+ fn was_cut_right ( & self ) -> bool {
96+ self . computed_right < self . line_len
97+ }
98+
99+ fn compute ( & mut self ) {
100+ self . computed_left = if self . whitespace_left > 20 {
101+ self . whitespace_left - 16 // We want some padding.
102+ } else {
103+ 0
104+ } ;
105+ self . computed_right = self . column_width + self . computed_left ;
106+
107+ if self . computed_right - self . computed_left > self . column_width {
108+ // Trimming only whitespace isn't enough, let's get craftier.
109+ if self . label_right - self . whitespace_left <= self . column_width {
110+ self . computed_left = self . whitespace_left ;
111+ self . computed_right = self . computed_left + self . column_width ;
112+ } else if self . label_right - self . span_left - 20 <= self . column_width {
113+ self . computed_left = self . span_left - 20 ;
114+ self . computed_right = self . computed_left + self . column_width ;
115+ } else if self . label_right - self . span_left <= self . column_width {
116+ self . computed_left = self . span_left ;
117+ self . computed_right = self . computed_left + self . column_width ;
118+ } else if self . span_right - self . span_left <= self . column_width {
119+ self . computed_left = self . span_left ;
120+ self . computed_right = self . computed_left + self . column_width ;
121+ } else { // mostly give up but still don't show the full line
122+ self . computed_left = self . span_left ;
123+ self . computed_right = self . span_right ;
124+ }
125+ }
126+ self . computed_left = std:: cmp:: min ( self . computed_left , self . line_len ) ;
127+ if self . computed_right > self . line_len {
128+ self . computed_right = self . line_len ;
129+ }
130+ self . computed_right = std:: cmp:: min ( self . computed_right , self . line_len ) ;
131+ }
132+ }
133+
60134const ANONYMIZED_LINE_NUM : & str = "LL" ;
61135
62136/// Emitter trait for emitting errors.
@@ -179,7 +253,6 @@ pub struct EmitterWriter {
179253 sm : Option < Lrc < SourceMapperDyn > > ,
180254 short_message : bool ,
181255 teach : bool ,
182- strip_margin : bool ,
183256 ui_testing : bool ,
184257}
185258
@@ -202,7 +275,6 @@ impl EmitterWriter {
202275 sm : source_map,
203276 short_message,
204277 teach,
205- strip_margin : false ,
206278 ui_testing : false ,
207279 }
208280 }
@@ -219,7 +291,6 @@ impl EmitterWriter {
219291 sm : source_map,
220292 short_message,
221293 teach,
222- strip_margin : false ,
223294 ui_testing : false ,
224295 }
225296 }
@@ -244,8 +315,7 @@ impl EmitterWriter {
244315 line : & Line ,
245316 width_offset : usize ,
246317 code_offset : usize ,
247- margin : usize ,
248- right_span_margin : usize
318+ mut margin : Margin ,
249319 ) -> Vec < ( usize , Style ) > {
250320 // Draw:
251321 //
@@ -260,6 +330,7 @@ impl EmitterWriter {
260330 // | | when there's too much wasted space to the left, we trim it to focus where it matters
261331 // | vertical divider between the column number and the code
262332 // column number
333+
263334 if line. line_index == 0 {
264335 return Vec :: new ( ) ;
265336 }
@@ -271,26 +342,27 @@ impl EmitterWriter {
271342
272343 let line_offset = buffer. num_lines ( ) ;
273344
274- let left_margin = std:: cmp:: min ( margin, source_string. len ( ) ) ;
275- let right_margin = if source_string. len ( ) > right_span_margin + 120 {
276- right_span_margin + 120
277- } else {
278- source_string. len ( )
279- } ;
345+ margin. line_len = source_string. len ( ) ;
346+ margin. compute ( ) ;
280347 // Create the source line we will highlight.
281348 buffer. puts (
282349 line_offset,
283350 code_offset,
284- & source_string[ left_margin..right_margin] , // On long lines, we strip the source line
351+ // On long lines, we strip the source line
352+ & source_string[ margin. computed_left ..margin. computed_right ] ,
285353 Style :: Quotation ,
286354 ) ;
287- if margin > 0 { // We have stripped some code/whitespace from the beginning, make it clear.
355+ if margin. was_cut_left ( ) { // We have stripped some code/whitespace from the beginning, make it clear.
288356 buffer. puts ( line_offset, code_offset, "..." , Style :: LineNumber ) ;
289357 }
290- if right_margin != source_string . len ( ) {
358+ if margin . was_cut_right ( ) {
291359 // We have stripped some code after the right-most span end, make it clear we did so.
292- let offset = code_offset + right_margin - left_margin;
293- buffer. puts ( line_offset, offset, "..." , Style :: LineNumber ) ;
360+ buffer. puts (
361+ line_offset,
362+ margin. computed_right - margin. computed_left + code_offset,
363+ "..." ,
364+ Style :: LineNumber ,
365+ ) ;
294366 }
295367 buffer. puts ( line_offset, 0 , & self . maybe_anonymized ( line. line_index ) , Style :: LineNumber ) ;
296368
@@ -546,13 +618,13 @@ impl EmitterWriter {
546618 '_' ,
547619 line_offset + pos,
548620 width_offset + depth,
549- code_offset + annotation. start_col - margin,
621+ code_offset + annotation. start_col - margin. computed_left ,
550622 style) ;
551623 }
552624 _ if self . teach => {
553625 buffer. set_style_range ( line_offset,
554- code_offset + annotation. start_col - margin,
555- code_offset + annotation. end_col - margin,
626+ code_offset + annotation. start_col - margin. computed_left ,
627+ code_offset + annotation. end_col - margin. computed_left ,
556628 style,
557629 annotation. is_primary ) ;
558630 }
@@ -582,7 +654,7 @@ impl EmitterWriter {
582654 if pos > 1 && ( annotation. has_label ( ) || annotation. takes_space ( ) ) {
583655 for p in line_offset + 1 ..=line_offset + pos {
584656 buffer. putc ( p,
585- code_offset + annotation. start_col - margin,
657+ code_offset + annotation. start_col - margin. computed_left ,
586658 '|' ,
587659 style) ;
588660 }
@@ -626,9 +698,9 @@ impl EmitterWriter {
626698 Style :: LabelSecondary
627699 } ;
628700 let ( pos, col) = if pos == 0 {
629- ( pos + 1 , annotation. end_col + 1 - margin)
701+ ( pos + 1 , annotation. end_col + 1 - margin. computed_left )
630702 } else {
631- ( pos + 2 , annotation. start_col - margin)
703+ ( pos + 2 , annotation. start_col - margin. computed_left )
632704 } ;
633705 if let Some ( ref label) = annotation. label {
634706 buffer. puts ( line_offset + pos,
@@ -670,7 +742,7 @@ impl EmitterWriter {
670742 } ;
671743 for p in annotation. start_col ..annotation. end_col {
672744 buffer. putc ( line_offset + 1 ,
673- code_offset + p - margin,
745+ code_offset + p - margin. computed_left ,
674746 underline,
675747 style) ;
676748 }
@@ -1010,22 +1082,30 @@ impl EmitterWriter {
10101082 let buffer_msg_line_offset = buffer. num_lines ( ) ;
10111083
10121084 buffer. prepend ( buffer_msg_line_offset, "--> " , Style :: LineNumber ) ;
1013- buffer. append ( buffer_msg_line_offset,
1014- & format ! ( "{}:{}:{}" ,
1015- loc. file. name,
1016- sm. doctest_offset_line( & loc. file. name, loc. line) ,
1017- loc. col. 0 + 1 ) ,
1018- Style :: LineAndColumn ) ;
1085+ buffer. append (
1086+ buffer_msg_line_offset,
1087+ & format ! (
1088+ "{}:{}:{}" ,
1089+ loc. file. name,
1090+ sm. doctest_offset_line( & loc. file. name, loc. line) ,
1091+ loc. col. 0 + 1 ,
1092+ ) ,
1093+ Style :: LineAndColumn ,
1094+ ) ;
10191095 for _ in 0 ..max_line_num_len {
10201096 buffer. prepend ( buffer_msg_line_offset, " " , Style :: NoStyle ) ;
10211097 }
10221098 } else {
1023- buffer. prepend ( 0 ,
1024- & format ! ( "{}:{}:{}: " ,
1025- loc. file. name,
1026- sm. doctest_offset_line( & loc. file. name, loc. line) ,
1027- loc. col. 0 + 1 ) ,
1028- Style :: LineAndColumn ) ;
1099+ buffer. prepend (
1100+ 0 ,
1101+ & format ! (
1102+ "{}:{}:{}: " ,
1103+ loc. file. name,
1104+ sm. doctest_offset_line( & loc. file. name, loc. line) ,
1105+ loc. col. 0 + 1 ,
1106+ ) ,
1107+ Style :: LineAndColumn ,
1108+ ) ;
10291109 }
10301110 } else if !self . short_message {
10311111 // remember where we are in the output buffer for easy reference
@@ -1069,7 +1149,7 @@ impl EmitterWriter {
10691149 let mut multilines = FxHashMap :: default ( ) ;
10701150
10711151 // Get the left-side margin to remove it
1072- let mut margin = std:: usize:: MAX ;
1152+ let mut whitespace_margin = std:: usize:: MAX ;
10731153 for line_idx in 0 ..annotated_file. lines . len ( ) {
10741154 let file = annotated_file. file . clone ( ) ;
10751155 let line = & annotated_file. lines [ line_idx] ;
@@ -1079,14 +1159,15 @@ impl EmitterWriter {
10791159 . take_while ( |c| c. is_whitespace ( ) )
10801160 . count ( ) ;
10811161 if source_string. chars ( ) . any ( |c| !c. is_whitespace ( ) ) {
1082- margin = std:: cmp:: min ( margin, leading_whitespace) ;
1162+ whitespace_margin = std:: cmp:: min (
1163+ whitespace_margin,
1164+ leading_whitespace,
1165+ ) ;
10831166 }
10841167 }
10851168 }
1086- if margin >= 20 { // On errors with generous margins, trim it
1087- margin = margin - 16 ; // Keep at least 4 spaces margin
1088- } else if margin == std:: usize:: MAX || !self . strip_margin {
1089- margin = 0 ;
1169+ if whitespace_margin == std:: usize:: MAX {
1170+ whitespace_margin = 0 ;
10901171 }
10911172
10921173 // Left-most column any visible span points at.
@@ -1100,18 +1181,27 @@ impl EmitterWriter {
11001181 if span_left_margin == std:: usize:: MAX {
11011182 span_left_margin = 0 ;
11021183 }
1103- if span_left_margin > 160 {
1104- margin = std:: cmp:: max ( margin, span_left_margin - 100 ) ;
1105- }
11061184
11071185 // Right-most column any visible span points at.
11081186 let mut span_right_margin = 0 ;
1187+ let mut label_right_margin = 0 ;
11091188 for line in & annotated_file. lines {
11101189 for ann in & line. annotations {
11111190 span_right_margin = std:: cmp:: max ( span_right_margin, ann. start_col ) ;
11121191 span_right_margin = std:: cmp:: max ( span_right_margin, ann. end_col ) ;
1192+ label_right_margin = std:: cmp:: max (
1193+ label_right_margin,
1194+ // TODO: account for labels not in the same line
1195+ ann. end_col + ann. label . as_ref ( ) . map ( |l| l. len ( ) + 1 ) . unwrap_or ( 0 ) ,
1196+ ) ;
11131197 }
11141198 }
1199+ let margin = Margin :: new (
1200+ whitespace_margin,
1201+ span_left_margin,
1202+ span_right_margin,
1203+ label_right_margin,
1204+ ) ;
11151205
11161206 // Next, output the annotate source for this file
11171207 for line_idx in 0 ..annotated_file. lines . len ( ) {
@@ -1131,7 +1221,6 @@ impl EmitterWriter {
11311221 width_offset,
11321222 code_offset,
11331223 margin,
1134- span_right_margin,
11351224 ) ;
11361225
11371226 let mut to_add = FxHashMap :: default ( ) ;
@@ -1179,24 +1268,29 @@ impl EmitterWriter {
11791268
11801269 let last_buffer_line_num = buffer. num_lines ( ) ;
11811270
1182- buffer. puts ( last_buffer_line_num,
1183- 0 ,
1184- & self . maybe_anonymized ( annotated_file. lines [ line_idx + 1 ]
1185- . line_index - 1 ) ,
1186- Style :: LineNumber ) ;
1187- draw_col_separator ( & mut buffer,
1188- last_buffer_line_num,
1189- 1 + max_line_num_len) ;
1190- let left_margin = std:: cmp:: min ( margin, unannotated_line. len ( ) ) ;
1191- let right_margin = if unannotated_line. len ( ) > span_right_margin + 120 {
1192- span_right_margin + 120
1193- } else {
1194- unannotated_line. len ( )
1195- } ;
1196- buffer. puts ( last_buffer_line_num,
1197- code_offset,
1198- & unannotated_line[ left_margin..right_margin] ,
1199- Style :: Quotation ) ;
1271+ buffer. puts (
1272+ last_buffer_line_num,
1273+ 0 ,
1274+ & self . maybe_anonymized (
1275+ annotated_file. lines [ line_idx + 1 ] . line_index - 1 ,
1276+ ) ,
1277+ Style :: LineNumber ,
1278+ ) ;
1279+ draw_col_separator (
1280+ & mut buffer,
1281+ last_buffer_line_num,
1282+ 1 + max_line_num_len,
1283+ ) ;
1284+
1285+ let mut margin = margin;
1286+ margin. line_len = unannotated_line. len ( ) ;
1287+ margin. compute ( ) ;
1288+ buffer. puts (
1289+ last_buffer_line_num,
1290+ code_offset,
1291+ & unannotated_line[ margin. computed_left ..margin. computed_right ] ,
1292+ Style :: Quotation ,
1293+ ) ;
12001294
12011295 for ( depth, style) in & multilines {
12021296 draw_multiline_line ( & mut buffer,
0 commit comments