1
Fork 0

only emit ^ at the start of a multi-line error

as a result, simplify elision code
This commit is contained in:
Niko Matsakis 2016-04-26 09:33:38 -07:00
parent 24f4b151b1
commit 1fdbfcdbd0
3 changed files with 67 additions and 143 deletions

View file

@ -543,7 +543,7 @@ mod test {
dreizehn dreizehn
"; ";
let file = cm.new_filemap_and_lines("dummy.txt", content); let file = cm.new_filemap_and_lines("dummy.txt", content);
let start = file.lines.borrow()[7]; let start = file.lines.borrow()[10];
let end = file.lines.borrow()[11]; let end = file.lines.borrow()[11];
let sp = mk_sp(start, end); let sp = mk_sp(start, end);
let lvl = Level::Error; let lvl = Level::Error;
@ -555,12 +555,9 @@ mod test {
let str = from_utf8(vec).unwrap(); let str = from_utf8(vec).unwrap();
println!("r#\"\n{}\"#", str); println!("r#\"\n{}\"#", str);
assert_eq!(str, &r#" assert_eq!(str, &r#"
--> dummy.txt:8:1 --> dummy.txt:11:1
8 |> line8
|> ^^^^^^^^^^^^^
...
11 |> e--vän 11 |> e--vän
|> ^^^^^^^^^^^^^^^^ |> ^
"#[1..]); "#[1..]);
} }
@ -696,9 +693,8 @@ mod test {
let expect0 = &r#" let expect0 = &r#"
--> dummy.txt:5:1 --> dummy.txt:5:1
5 |> ccccc 5 |> ccccc
|> ^^^^^ |> ^
... ...
8 |> _____
9 |> ddd__eee_ 9 |> ddd__eee_
|> ^^^ ^^^ |> ^^^ ^^^
10 |> elided 10 |> elided
@ -709,9 +705,8 @@ mod test {
let expect = &r#" let expect = &r#"
--> dummy.txt:1:1 --> dummy.txt:1:1
1 |> aaaaa 1 |> aaaaa
|> ^^^^^ |> ^
... ...
8 |> _____
9 |> ddd__eee_ 9 |> ddd__eee_
|> ^^^ ^^^ |> ^^^ ^^^
10 |> elided 10 |> elided

View file

@ -49,7 +49,7 @@ struct Annotation {
/// column. /// column.
start_col: usize, start_col: usize,
/// End column within the line. /// End column within the line (exclusive)
end_col: usize, end_col: usize,
/// Is this annotation derived from primary span /// Is this annotation derived from primary span
@ -349,24 +349,40 @@ impl FileInfo {
label: Option<String>) { label: Option<String>) {
assert!(lines.len() > 0); assert!(lines.len() > 0);
// If a span covers multiple lines, just put the label on the // If a span covers multiple lines, we reduce it to a single
// first one. This is a sort of arbitrary choice and not // point at the start of the span. This means that instead
// obviously correct. // of producing output like this:
let (line0, remaining_lines) = lines.split_first().unwrap(); //
let index = self.ensure_source_line(line0.line_index); // ```
self.lines[index].push_annotation(line0.start_col, // --> foo.rs:2:1
line0.end_col, // 2 |> fn conflicting_items<'grammar>(state: &LR0State<'grammar>)
// |> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// 3 |> -> Set<LR0Item<'grammar>>
// |> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// (and so on)
// ```
//
// we produce:
//
// ```
// --> foo.rs:2:1
// 2 |> fn conflicting_items<'grammar>(state: &LR0State<'grammar>)
// ^
// ```
//
// Basically, although this loses information, multi-line spans just
// never look good.
let (line, start_col, end_col) = if lines.len() == 1 {
(lines[0].line_index, lines[0].start_col, lines[0].end_col)
} else {
(lines[0].line_index, lines[0].start_col, CharPos(lines[0].start_col.0 + 1))
};
let index = self.ensure_source_line(line);
self.lines[index].push_annotation(start_col,
end_col,
is_primary, is_primary,
label); label);
for line in remaining_lines {
if line.end_col > line.start_col {
let index = self.ensure_source_line(line.line_index);
self.lines[index].push_annotation(line.start_col,
line.end_col,
is_primary,
None);
}
}
} }
/// Ensure that we have a `Line` struct corresponding to /// Ensure that we have a `Line` struct corresponding to
@ -414,57 +430,10 @@ impl FileInfo {
} }
fn render_file_lines(&self, codemap: &Rc<CodeMap>) -> Vec<RenderedLine> { fn render_file_lines(&self, codemap: &Rc<CodeMap>) -> Vec<RenderedLine> {
// Group our lines by those with annotations and those without // As a first step, we elide any instance of more than one
let mut lines_iter = self.lines.iter().peekable(); // continuous unannotated line.
let mut line_groups = vec![];
loop {
match lines_iter.next() {
None => break,
Some(line) if line.annotations.is_empty() => {
// Collect unannotated group
let mut unannotated_group : Vec<&Line> = vec![];
unannotated_group.push(line);
loop {
let next_line =
match lines_iter.peek() {
None => break,
Some(x) if !x.annotations.is_empty() => break,
Some(x) => x.clone()
};
unannotated_group.push(next_line);
lines_iter.next();
}
line_groups.push((false, unannotated_group));
}
Some(line) => {
// Collect annotated group
let mut annotated_group : Vec<&Line> = vec![];
annotated_group.push(line);
loop {
let next_line =
match lines_iter.peek() {
None => break,
Some(x) if x.annotations.is_empty() => break,
Some(x) => x.clone()
};
annotated_group.push(next_line);
lines_iter.next();
}
line_groups.push((true, annotated_group));
}
}
}
let mut lines_iter = self.lines.iter();
let mut output = vec![]; let mut output = vec![];
// First insert the name of the file. // First insert the name of the file.
@ -493,65 +462,30 @@ impl FileInfo {
} }
} }
for &(is_annotated, ref group) in line_groups.iter() { let mut next_line = lines_iter.next();
if is_annotated { while next_line.is_some() {
let mut annotation_ends_at_eol = false; // Consume lines with annotations.
let mut prev_ends_at_eol = false; while let Some(line) = next_line {
let mut elide_unlabeled_region = false; if line.annotations.is_empty() { break; }
output.append(&mut self.render_line(line));
next_line = lines_iter.next();
}
for group_line in group.iter() { // Emit lines without annotations, but only if they are
let source_string_len = // followed by a line with an annotation.
self.file.get_line(group_line.line_index) let unannotated_line = next_line;
.map(|s| s.len()) let mut unannotated_lines = 0;
.unwrap_or(0); while let Some(line) = next_line {
if !line.annotations.is_empty() { break; }
for annotation in &group_line.annotations { unannotated_lines += 1;
if annotation.end_col == source_string_len { next_line = lines_iter.next();
annotation_ends_at_eol = true; }
} if unannotated_lines > 1 {
} output.push(RenderedLine::from((String::new(),
Style::NoStyle,
let is_single_unlabeled_annotated_line = RenderedLineKind::Elision)));
if group_line.annotations.len() == 1 { } else if let Some(line) = unannotated_line {
if let Some(annotation) = group_line.annotations.first() { output.append(&mut self.render_line(line));
match annotation.label {
Some(_) => false,
None => annotation.start_col == 0 &&
annotation.end_col == source_string_len
}
} else {
false
}
} else {
false
};
if prev_ends_at_eol && is_single_unlabeled_annotated_line {
if !elide_unlabeled_region {
output.push(RenderedLine::from((String::new(),
Style::NoStyle,
RenderedLineKind::Elision)));
elide_unlabeled_region = true;
prev_ends_at_eol = true;
}
continue;
}
let mut v = self.render_line(group_line);
output.append(&mut v);
prev_ends_at_eol = annotation_ends_at_eol;
}
} else {
if group.len() > 1 {
output.push(RenderedLine::from((String::new(),
Style::NoStyle,
RenderedLineKind::Elision)));
} else {
let mut v: Vec<RenderedLine> =
group.iter().flat_map(|line| self.render_line(line)).collect();
output.append(&mut v);
}
} }
} }

View file

@ -406,8 +406,7 @@ impl SomeTrait for () {
assert_eq!(text, &r#" assert_eq!(text, &r#"
>>>>>> foo.rs >>>>>> foo.rs
3 |> fn foo(x: u32) { 3 |> fn foo(x: u32) {
|> ---------------- |> -
...
"#[1..]); "#[1..]);
} }
@ -515,12 +514,8 @@ fn span_overlap_label3() {
assert_eq!(text, &r#" assert_eq!(text, &r#"
>>>> foo.rs >>>> foo.rs
3 |> let closure = || { 3 |> let closure = || {
|> ---- foo |> - foo
4 |> inner 4 |> inner
|> ---------------- |> ---- bar
|> |
|> bar
5 |> };
|> --------
"#[1..]); "#[1..]);
} }