From ae54121ee2939987f74f5c8afbea1c11f1f402de Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Thu, 31 Mar 2016 17:19:40 -0700 Subject: [PATCH 1/2] Add support for elision in structured error messages --- src/libsyntax/errors/snippet/mod.rs | 76 ++++++++++++++++++++++++++++ src/libsyntax/errors/snippet/test.rs | 73 ++++++++++++++++++-------- 2 files changed, 129 insertions(+), 20 deletions(-) diff --git a/src/libsyntax/errors/snippet/mod.rs b/src/libsyntax/errors/snippet/mod.rs index baace4d704fc6..b211d704947cd 100644 --- a/src/libsyntax/errors/snippet/mod.rs +++ b/src/libsyntax/errors/snippet/mod.rs @@ -55,6 +55,7 @@ pub struct RenderedLine { pub enum RenderedLineKind { SourceText, Highlights, + Elision, } use self::RenderedLineKind::*; @@ -98,9 +99,84 @@ impl SnippetData { } pub fn render_lines(&self) -> Vec { + let mut line_groups = vec![]; + + //Group our lines by those with annotations and those without + let mut lines_iter = self.lines.iter().peekable(); + + 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() + }; + + lines_iter.next(); + + unannotated_group.push(next_line); + } + + 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() + }; + + lines_iter.next(); + + annotated_group.push(next_line); + } + + line_groups.push((true, annotated_group)); + } + } + } + + let mut output = vec![]; + for &(is_annotated, ref group) in line_groups.iter() { + if is_annotated { + let mut v: Vec = + group.iter().flat_map(|line| self.render_line(line)).collect(); + output.append(&mut v); + } + else { + if group.len() > 1 { + output.push(RenderedLine::from((String::from("..."), Elision))); + } + else { + let mut v: Vec = + group.iter().flat_map(|line| self.render_line(line)).collect(); + output.append(&mut v); + } + } + } + + output + /* self.lines.iter() .flat_map(|line| self.render_line(line)) .collect() + */ } fn render_line(&self, line: &Line) -> Vec { diff --git a/src/libsyntax/errors/snippet/test.rs b/src/libsyntax/errors/snippet/test.rs index 7cf9e6142b1cb..43bf70af8848a 100644 --- a/src/libsyntax/errors/snippet/test.rs +++ b/src/libsyntax/errors/snippet/test.rs @@ -128,12 +128,8 @@ fn foo() { kind: Highlights }, RenderedLine { - text: "", - kind: SourceText - }, - RenderedLine { - text: " // Add one more item we forgot to the vector. Silly us.", - kind: SourceText + text: "...", + kind: Elision }, RenderedLine { text: " data.push(Data { name: format!(\"Hera\"), id: 66 });", @@ -144,20 +140,8 @@ fn foo() { kind: Highlights }, RenderedLine { - text: "", - kind: SourceText - }, - RenderedLine { - text: " // Print everything out.", - kind: SourceText - }, - RenderedLine { - text: " println!(\"Name: {:?}\", name);", - kind: SourceText - }, - RenderedLine { - text: " println!(\"Data: {:?}\", data);", - kind: SourceText + text: "...", + kind: Elision }, RenderedLine { text: "}", @@ -269,3 +253,52 @@ fn foo() { ]"#); } +#[test] +fn elide_unnecessary_lines() { + let file_text = r#" +fn foo() { + let mut vec = vec![0, 1, 2]; + let mut vec2 = vec; + vec2.push(3); + vec2.push(4); + vec2.push(5); + vec2.push(6); + vec.push(7); +} +"#; + + let cm = Rc::new(CodeMap::new()); + cm.new_filemap_and_lines("foo.rs", file_text); + let span_vec0 = cm.span_substr(file_text, "vec", 3); + let span_vec1 = cm.span_substr(file_text, "vec", 8); + + let mut snippet = SnippetData::new(cm); + snippet.push(span_vec0, Some(format!("`vec` moved here because it has type `collections::vec::Vec`, which is moved by default"))); + snippet.push(span_vec1, Some(format!("use of moved value: `vec`"))); + + let lines = snippet.render_lines(); + println!("{:#?}", lines); + assert_eq!(format!("\n{:#?}", lines), r#" +[ + RenderedLine { + text: " let mut vec2 = vec;", + kind: SourceText + }, + RenderedLine { + text: " ~~~ `vec` moved here because it has type `collections::vec::Vec`, which is moved by default", + kind: Highlights + }, + RenderedLine { + text: "...", + kind: Elision + }, + RenderedLine { + text: " vec.push(7);", + kind: SourceText + }, + RenderedLine { + text: " ~~~ use of moved value: `vec`", + kind: Highlights + } +]"#); +} \ No newline at end of file From ff2868d85b2cbc1911a8ec410f0b686cbea9924d Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Thu, 31 Mar 2016 17:24:59 -0700 Subject: [PATCH 2/2] Remove commented out code and reorder for readability --- src/libsyntax/errors/snippet/mod.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/libsyntax/errors/snippet/mod.rs b/src/libsyntax/errors/snippet/mod.rs index b211d704947cd..34693d4690869 100644 --- a/src/libsyntax/errors/snippet/mod.rs +++ b/src/libsyntax/errors/snippet/mod.rs @@ -121,9 +121,8 @@ impl SnippetData { Some(x) => x.clone() }; - lines_iter.next(); - unannotated_group.push(next_line); + lines_iter.next(); } line_groups.push((false, unannotated_group)); @@ -142,9 +141,8 @@ impl SnippetData { Some(x) => x.clone() }; - lines_iter.next(); - annotated_group.push(next_line); + lines_iter.next(); } line_groups.push((true, annotated_group)); @@ -172,11 +170,6 @@ impl SnippetData { } output - /* - self.lines.iter() - .flat_map(|line| self.render_line(line)) - .collect() - */ } fn render_line(&self, line: &Line) -> Vec {