@@ -57,6 +57,80 @@ impl HumanReadableErrorType {
57
57
}
58
58
}
59
59
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
+
60
134
const ANONYMIZED_LINE_NUM : & str = "LL" ;
61
135
62
136
/// Emitter trait for emitting errors.
@@ -179,7 +253,6 @@ pub struct EmitterWriter {
179
253
sm : Option < Lrc < SourceMapperDyn > > ,
180
254
short_message : bool ,
181
255
teach : bool ,
182
- strip_margin : bool ,
183
256
ui_testing : bool ,
184
257
}
185
258
@@ -202,7 +275,6 @@ impl EmitterWriter {
202
275
sm : source_map,
203
276
short_message,
204
277
teach,
205
- strip_margin : false ,
206
278
ui_testing : false ,
207
279
}
208
280
}
@@ -219,7 +291,6 @@ impl EmitterWriter {
219
291
sm : source_map,
220
292
short_message,
221
293
teach,
222
- strip_margin : false ,
223
294
ui_testing : false ,
224
295
}
225
296
}
@@ -244,8 +315,7 @@ impl EmitterWriter {
244
315
line : & Line ,
245
316
width_offset : usize ,
246
317
code_offset : usize ,
247
- margin : usize ,
248
- right_span_margin : usize
318
+ mut margin : Margin ,
249
319
) -> Vec < ( usize , Style ) > {
250
320
// Draw:
251
321
//
@@ -260,6 +330,7 @@ impl EmitterWriter {
260
330
// | | when there's too much wasted space to the left, we trim it to focus where it matters
261
331
// | vertical divider between the column number and the code
262
332
// column number
333
+
263
334
if line. line_index == 0 {
264
335
return Vec :: new ( ) ;
265
336
}
@@ -271,26 +342,27 @@ impl EmitterWriter {
271
342
272
343
let line_offset = buffer. num_lines ( ) ;
273
344
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 ( ) ;
280
347
// Create the source line we will highlight.
281
348
buffer. puts (
282
349
line_offset,
283
350
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 ] ,
285
353
Style :: Quotation ,
286
354
) ;
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.
288
356
buffer. puts ( line_offset, code_offset, "..." , Style :: LineNumber ) ;
289
357
}
290
- if right_margin != source_string . len ( ) {
358
+ if margin . was_cut_right ( ) {
291
359
// 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
+ ) ;
294
366
}
295
367
buffer. puts ( line_offset, 0 , & self . maybe_anonymized ( line. line_index ) , Style :: LineNumber ) ;
296
368
@@ -546,13 +618,13 @@ impl EmitterWriter {
546
618
'_' ,
547
619
line_offset + pos,
548
620
width_offset + depth,
549
- code_offset + annotation. start_col - margin,
621
+ code_offset + annotation. start_col - margin. computed_left ,
550
622
style) ;
551
623
}
552
624
_ if self . teach => {
553
625
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 ,
556
628
style,
557
629
annotation. is_primary ) ;
558
630
}
@@ -582,7 +654,7 @@ impl EmitterWriter {
582
654
if pos > 1 && ( annotation. has_label ( ) || annotation. takes_space ( ) ) {
583
655
for p in line_offset + 1 ..=line_offset + pos {
584
656
buffer. putc ( p,
585
- code_offset + annotation. start_col - margin,
657
+ code_offset + annotation. start_col - margin. computed_left ,
586
658
'|' ,
587
659
style) ;
588
660
}
@@ -626,9 +698,9 @@ impl EmitterWriter {
626
698
Style :: LabelSecondary
627
699
} ;
628
700
let ( pos, col) = if pos == 0 {
629
- ( pos + 1 , annotation. end_col + 1 - margin)
701
+ ( pos + 1 , annotation. end_col + 1 - margin. computed_left )
630
702
} else {
631
- ( pos + 2 , annotation. start_col - margin)
703
+ ( pos + 2 , annotation. start_col - margin. computed_left )
632
704
} ;
633
705
if let Some ( ref label) = annotation. label {
634
706
buffer. puts ( line_offset + pos,
@@ -670,7 +742,7 @@ impl EmitterWriter {
670
742
} ;
671
743
for p in annotation. start_col ..annotation. end_col {
672
744
buffer. putc ( line_offset + 1 ,
673
- code_offset + p - margin,
745
+ code_offset + p - margin. computed_left ,
674
746
underline,
675
747
style) ;
676
748
}
@@ -1010,22 +1082,30 @@ impl EmitterWriter {
1010
1082
let buffer_msg_line_offset = buffer. num_lines ( ) ;
1011
1083
1012
1084
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
+ ) ;
1019
1095
for _ in 0 ..max_line_num_len {
1020
1096
buffer. prepend ( buffer_msg_line_offset, " " , Style :: NoStyle ) ;
1021
1097
}
1022
1098
} 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
+ ) ;
1029
1109
}
1030
1110
} else if !self . short_message {
1031
1111
// remember where we are in the output buffer for easy reference
@@ -1069,7 +1149,7 @@ impl EmitterWriter {
1069
1149
let mut multilines = FxHashMap :: default ( ) ;
1070
1150
1071
1151
// Get the left-side margin to remove it
1072
- let mut margin = std:: usize:: MAX ;
1152
+ let mut whitespace_margin = std:: usize:: MAX ;
1073
1153
for line_idx in 0 ..annotated_file. lines . len ( ) {
1074
1154
let file = annotated_file. file . clone ( ) ;
1075
1155
let line = & annotated_file. lines [ line_idx] ;
@@ -1079,14 +1159,15 @@ impl EmitterWriter {
1079
1159
. take_while ( |c| c. is_whitespace ( ) )
1080
1160
. count ( ) ;
1081
1161
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
+ ) ;
1083
1166
}
1084
1167
}
1085
1168
}
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 ;
1090
1171
}
1091
1172
1092
1173
// Left-most column any visible span points at.
@@ -1100,18 +1181,27 @@ impl EmitterWriter {
1100
1181
if span_left_margin == std:: usize:: MAX {
1101
1182
span_left_margin = 0 ;
1102
1183
}
1103
- if span_left_margin > 160 {
1104
- margin = std:: cmp:: max ( margin, span_left_margin - 100 ) ;
1105
- }
1106
1184
1107
1185
// Right-most column any visible span points at.
1108
1186
let mut span_right_margin = 0 ;
1187
+ let mut label_right_margin = 0 ;
1109
1188
for line in & annotated_file. lines {
1110
1189
for ann in & line. annotations {
1111
1190
span_right_margin = std:: cmp:: max ( span_right_margin, ann. start_col ) ;
1112
1191
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
+ ) ;
1113
1197
}
1114
1198
}
1199
+ let margin = Margin :: new (
1200
+ whitespace_margin,
1201
+ span_left_margin,
1202
+ span_right_margin,
1203
+ label_right_margin,
1204
+ ) ;
1115
1205
1116
1206
// Next, output the annotate source for this file
1117
1207
for line_idx in 0 ..annotated_file. lines . len ( ) {
@@ -1131,7 +1221,6 @@ impl EmitterWriter {
1131
1221
width_offset,
1132
1222
code_offset,
1133
1223
margin,
1134
- span_right_margin,
1135
1224
) ;
1136
1225
1137
1226
let mut to_add = FxHashMap :: default ( ) ;
@@ -1179,24 +1268,29 @@ impl EmitterWriter {
1179
1268
1180
1269
let last_buffer_line_num = buffer. num_lines ( ) ;
1181
1270
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
+ ) ;
1200
1294
1201
1295
for ( depth, style) in & multilines {
1202
1296
draw_multiline_line ( & mut buffer,
0 commit comments