Strip code to the left and right in diagnostics for long lines
This commit is contained in:
parent
7b0085a613
commit
0e668e0496
@ -179,6 +179,7 @@ pub struct EmitterWriter {
|
||||
sm: Option<Lrc<SourceMapperDyn>>,
|
||||
short_message: bool,
|
||||
teach: bool,
|
||||
strip_margin: bool,
|
||||
ui_testing: bool,
|
||||
}
|
||||
|
||||
@ -201,6 +202,7 @@ pub fn stderr(color_config: ColorConfig,
|
||||
sm: source_map,
|
||||
short_message,
|
||||
teach,
|
||||
strip_margin: false,
|
||||
ui_testing: false,
|
||||
}
|
||||
}
|
||||
@ -217,6 +219,7 @@ pub fn new(
|
||||
sm: source_map,
|
||||
short_message,
|
||||
teach,
|
||||
strip_margin: false,
|
||||
ui_testing: false,
|
||||
}
|
||||
}
|
||||
@ -234,12 +237,29 @@ fn maybe_anonymized(&self, line_num: usize) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_source_line(&self,
|
||||
buffer: &mut StyledBuffer,
|
||||
file: Lrc<SourceFile>,
|
||||
line: &Line,
|
||||
width_offset: usize,
|
||||
code_offset: usize) -> Vec<(usize, Style)> {
|
||||
fn render_source_line(
|
||||
&self,
|
||||
buffer: &mut StyledBuffer,
|
||||
file: Lrc<SourceFile>,
|
||||
line: &Line,
|
||||
width_offset: usize,
|
||||
code_offset: usize,
|
||||
margin: usize,
|
||||
right_span_margin: usize
|
||||
) -> Vec<(usize, Style)> {
|
||||
// Draw:
|
||||
//
|
||||
// LL | ... code ...
|
||||
// | ^^-^ span label
|
||||
// | |
|
||||
// | secondary span label
|
||||
//
|
||||
// ^^ ^ ^^^ ^^^^ ^^^ we don't care about code too far to the right of a span, we trim it
|
||||
// | | | |
|
||||
// | | | actual code found in your source code and the spans we use to mark it
|
||||
// | | when there's too much wasted space to the left, we trim it to focus where it matters
|
||||
// | vertical divider between the column number and the code
|
||||
// column number
|
||||
if line.line_index == 0 {
|
||||
return Vec::new();
|
||||
}
|
||||
@ -251,12 +271,28 @@ fn render_source_line(&self,
|
||||
|
||||
let line_offset = buffer.num_lines();
|
||||
|
||||
// First create the source line we will highlight.
|
||||
buffer.puts(line_offset, code_offset, &source_string, Style::Quotation);
|
||||
buffer.puts(line_offset,
|
||||
0,
|
||||
&self.maybe_anonymized(line.line_index),
|
||||
Style::LineNumber);
|
||||
let left_margin = std::cmp::min(margin, source_string.len());
|
||||
let right_margin = if source_string.len() > right_span_margin + 120 {
|
||||
right_span_margin + 120
|
||||
} else {
|
||||
source_string.len()
|
||||
};
|
||||
// Create the source line we will highlight.
|
||||
buffer.puts(
|
||||
line_offset,
|
||||
code_offset,
|
||||
&source_string[left_margin..right_margin], // On long lines, we strip the source line
|
||||
Style::Quotation,
|
||||
);
|
||||
if margin > 0 { // We have stripped some code/whitespace from the beginning, make it clear.
|
||||
buffer.puts(line_offset, code_offset, "...", Style::LineNumber);
|
||||
}
|
||||
if right_margin != source_string.len() {
|
||||
// We have stripped some code after the right-most span end, make it clear we did so.
|
||||
let offset = code_offset + right_margin - left_margin;
|
||||
buffer.puts(line_offset, offset, "...", Style::LineNumber);
|
||||
}
|
||||
buffer.puts(line_offset, 0, &self.maybe_anonymized(line.line_index), Style::LineNumber);
|
||||
|
||||
draw_col_separator(buffer, line_offset, width_offset - 2);
|
||||
|
||||
@ -279,18 +315,13 @@ fn render_source_line(&self,
|
||||
if line.annotations.len() == 1 {
|
||||
if let Some(ref ann) = line.annotations.get(0) {
|
||||
if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
|
||||
if source_string.chars()
|
||||
.take(ann.start_col)
|
||||
.all(|c| c.is_whitespace()) {
|
||||
if source_string.chars().take(ann.start_col).all(|c| c.is_whitespace()) {
|
||||
let style = if ann.is_primary {
|
||||
Style::UnderlinePrimary
|
||||
} else {
|
||||
Style::UnderlineSecondary
|
||||
};
|
||||
buffer.putc(line_offset,
|
||||
width_offset + depth - 1,
|
||||
'/',
|
||||
style);
|
||||
buffer.putc(line_offset, width_offset + depth - 1, '/', style);
|
||||
return vec![(depth, style)];
|
||||
}
|
||||
}
|
||||
@ -515,13 +546,13 @@ fn render_source_line(&self,
|
||||
'_',
|
||||
line_offset + pos,
|
||||
width_offset + depth,
|
||||
code_offset + annotation.start_col,
|
||||
code_offset + annotation.start_col - margin,
|
||||
style);
|
||||
}
|
||||
_ if self.teach => {
|
||||
buffer.set_style_range(line_offset,
|
||||
code_offset + annotation.start_col,
|
||||
code_offset + annotation.end_col,
|
||||
code_offset + annotation.start_col - margin,
|
||||
code_offset + annotation.end_col - margin,
|
||||
style,
|
||||
annotation.is_primary);
|
||||
}
|
||||
@ -551,7 +582,7 @@ fn render_source_line(&self,
|
||||
if pos > 1 && (annotation.has_label() || annotation.takes_space()) {
|
||||
for p in line_offset + 1..=line_offset + pos {
|
||||
buffer.putc(p,
|
||||
code_offset + annotation.start_col,
|
||||
code_offset + annotation.start_col - margin,
|
||||
'|',
|
||||
style);
|
||||
}
|
||||
@ -595,9 +626,9 @@ fn render_source_line(&self,
|
||||
Style::LabelSecondary
|
||||
};
|
||||
let (pos, col) = if pos == 0 {
|
||||
(pos + 1, annotation.end_col + 1)
|
||||
(pos + 1, annotation.end_col + 1 - margin)
|
||||
} else {
|
||||
(pos + 2, annotation.start_col)
|
||||
(pos + 2, annotation.start_col - margin)
|
||||
};
|
||||
if let Some(ref label) = annotation.label {
|
||||
buffer.puts(line_offset + pos,
|
||||
@ -639,7 +670,7 @@ fn render_source_line(&self,
|
||||
};
|
||||
for p in annotation.start_col..annotation.end_col {
|
||||
buffer.putc(line_offset + 1,
|
||||
code_offset + p,
|
||||
code_offset + p - margin,
|
||||
underline,
|
||||
style);
|
||||
}
|
||||
@ -1037,6 +1068,51 @@ fn emit_message_default(
|
||||
// Contains the vertical lines' positions for active multiline annotations
|
||||
let mut multilines = FxHashMap::default();
|
||||
|
||||
// Get the left-side margin to remove it
|
||||
let mut margin = std::usize::MAX;
|
||||
for line_idx in 0..annotated_file.lines.len() {
|
||||
let file = annotated_file.file.clone();
|
||||
let line = &annotated_file.lines[line_idx];
|
||||
if let Some(source_string) = file.get_line(line.line_index - 1) {
|
||||
let leading_whitespace = source_string
|
||||
.chars()
|
||||
.take_while(|c| c.is_whitespace())
|
||||
.count();
|
||||
if source_string.chars().any(|c| !c.is_whitespace()) {
|
||||
margin = std::cmp::min(margin, leading_whitespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
if margin >= 20 { // On errors with generous margins, trim it
|
||||
margin = margin - 16; // Keep at least 4 spaces margin
|
||||
} else if margin == std::usize::MAX || !self.strip_margin {
|
||||
margin = 0;
|
||||
}
|
||||
|
||||
// Left-most column any visible span points at.
|
||||
let mut span_left_margin = std::usize::MAX;
|
||||
for line in &annotated_file.lines {
|
||||
for ann in &line.annotations {
|
||||
span_left_margin = std::cmp::min(span_left_margin, ann.start_col);
|
||||
span_left_margin = std::cmp::min(span_left_margin, ann.end_col);
|
||||
}
|
||||
}
|
||||
if span_left_margin == std::usize::MAX {
|
||||
span_left_margin = 0;
|
||||
}
|
||||
if span_left_margin > 160 {
|
||||
margin = std::cmp::max(margin, span_left_margin - 100);
|
||||
}
|
||||
|
||||
// Right-most column any visible span points at.
|
||||
let mut span_right_margin = 0;
|
||||
for line in &annotated_file.lines {
|
||||
for ann in &line.annotations {
|
||||
span_right_margin = std::cmp::max(span_right_margin, ann.start_col);
|
||||
span_right_margin = std::cmp::max(span_right_margin, ann.end_col);
|
||||
}
|
||||
}
|
||||
|
||||
// Next, output the annotate source for this file
|
||||
for line_idx in 0..annotated_file.lines.len() {
|
||||
let previous_buffer_line = buffer.num_lines();
|
||||
@ -1048,11 +1124,15 @@ fn emit_message_default(
|
||||
width_offset + annotated_file.multiline_depth + 1
|
||||
};
|
||||
|
||||
let depths = self.render_source_line(&mut buffer,
|
||||
annotated_file.file.clone(),
|
||||
&annotated_file.lines[line_idx],
|
||||
width_offset,
|
||||
code_offset);
|
||||
let depths = self.render_source_line(
|
||||
&mut buffer,
|
||||
annotated_file.file.clone(),
|
||||
&annotated_file.lines[line_idx],
|
||||
width_offset,
|
||||
code_offset,
|
||||
margin,
|
||||
span_right_margin,
|
||||
);
|
||||
|
||||
let mut to_add = FxHashMap::default();
|
||||
|
||||
@ -1107,9 +1187,15 @@ fn emit_message_default(
|
||||
draw_col_separator(&mut buffer,
|
||||
last_buffer_line_num,
|
||||
1 + max_line_num_len);
|
||||
let left_margin = std::cmp::min(margin, unannotated_line.len());
|
||||
let right_margin = if unannotated_line.len() > span_right_margin + 120 {
|
||||
span_right_margin + 120
|
||||
} else {
|
||||
unannotated_line.len()
|
||||
};
|
||||
buffer.puts(last_buffer_line_num,
|
||||
code_offset,
|
||||
&unannotated_line,
|
||||
&unannotated_line[left_margin..right_margin],
|
||||
Style::Quotation);
|
||||
|
||||
for (depth, style) in &multilines {
|
||||
|
@ -37,8 +37,8 @@ LL | asm!("mov sp, $0"::"r"(addr),
|
||||
error[E0669]: invalid value for constraint in inline assembly
|
||||
--> $DIR/inline-asm-bad-operand.rs:56:32
|
||||
|
|
||||
LL | "r"("hello e0669"));
|
||||
| ^^^^^^^^^^^^^
|
||||
LL | ... "r"("hello e0669"));
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
@ -38,8 +38,8 @@ LL | if let SoulHistory { corridors_of_light,
|
||||
warning: variable `hours_are_suns` is assigned to, but never used
|
||||
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:30
|
||||
|
|
||||
LL | mut hours_are_suns,
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | ... mut hours_are_suns,
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: consider using `_hours_are_suns` instead
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0615]: attempted to take value of method `get_x` on type `Point`
|
||||
--> $DIR/method-missing-call.rs:22:26
|
||||
|
|
||||
LL | .get_x;
|
||||
| ^^^^^ help: use parentheses to call the method: `get_x()`
|
||||
LL | ... .get_x;
|
||||
| ^^^^^ help: use parentheses to call the method: `get_x()`
|
||||
|
||||
error[E0615]: attempted to take value of method `filter_map` on type `std::iter::Filter<std::iter::Map<std::slice::Iter<'_, {integer}>, [closure@$DIR/method-missing-call.rs:27:20: 27:25]>, [closure@$DIR/method-missing-call.rs:28:23: 28:35]>`
|
||||
--> $DIR/method-missing-call.rs:29:16
|
||||
|
@ -1,11 +1,11 @@
|
||||
error[E0499]: cannot borrow `*f` as mutable more than once at a time
|
||||
--> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:20:27
|
||||
|
|
||||
LL | (f.c)(f, true);
|
||||
| ----- ^ second mutable borrow occurs here
|
||||
| |
|
||||
| first mutable borrow occurs here
|
||||
| first borrow later used by call
|
||||
LL | ... (f.c)(f, true);
|
||||
| ----- ^ second mutable borrow occurs here
|
||||
| |
|
||||
| first mutable borrow occurs here
|
||||
| first borrow later used by call
|
||||
|
||||
error[E0382]: borrow of moved value: `f`
|
||||
--> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:32:5
|
||||
|
@ -49,14 +49,14 @@ LL | fn fn_types(a: &'a isize,
|
||||
error[E0261]: use of undeclared lifetime name `'b`
|
||||
--> $DIR/regions-name-undeclared.rs:42:36
|
||||
|
|
||||
LL | &'b isize,
|
||||
| ^^ undeclared lifetime
|
||||
LL | ... &'b isize,
|
||||
| ^^ undeclared lifetime
|
||||
|
||||
error[E0261]: use of undeclared lifetime name `'b`
|
||||
--> $DIR/regions-name-undeclared.rs:45:36
|
||||
|
|
||||
LL | &'b isize)>,
|
||||
| ^^ undeclared lifetime
|
||||
LL | ... &'b isize)>,
|
||||
| ^^ undeclared lifetime
|
||||
|
||||
error[E0261]: use of undeclared lifetime name `'a`
|
||||
--> $DIR/regions-name-undeclared.rs:46:17
|
||||
|
Loading…
Reference in New Issue
Block a user