Add fix for tabs. Move error unit tests->ui tests

This commit is contained in:
Jonathan Turner 2016-07-13 17:53:42 -04:00
parent 2e8e73cb95
commit 1fd014a965
17 changed files with 414 additions and 772 deletions

View File

@ -26,10 +26,27 @@ impl StyledBuffer {
}
}
pub fn render(&self) -> Vec<Vec<StyledString>> {
pub fn copy_tabs(&mut self, row: usize) {
if row < self.text.len() {
for i in row+1..self.text.len() {
for j in 0..self.text[i].len() {
if self.text[row].len() > j &&
self.text[row][j] == '\t' &&
self.text[i][j] == ' ' {
self.text[i][j] = '\t';
}
}
}
}
}
pub fn render(&mut self) -> Vec<Vec<StyledString>> {
let mut output: Vec<Vec<StyledString>> = vec![];
let mut styled_vec: Vec<StyledString> = vec![];
//before we render, do a little patch-up work to support tabs
self.copy_tabs(3);
for (row, row_style) in self.text.iter().zip(&self.styles) {
let mut current_style = Style::NoStyle;
let mut current_text = String::new();
@ -78,11 +95,7 @@ impl StyledBuffer {
} else {
let mut i = self.text[line].len();
while i < col {
let s = match self.text[0].get(i) {
Some(&'\t') => '\t',
_ => ' ',
};
self.text[line].push(s);
self.text[line].push(' ');
self.styles[line].push(Style::NoStyle);
i += 1;
}

View File

@ -827,12 +827,7 @@ impl CodeMapper for CodeMap {
#[cfg(test)]
mod tests {
use super::*;
use errors::{Level, CodeSuggestion};
use errors::emitter::EmitterWriter;
use errors::snippet::{SnippetData, RenderedLine, FormatMode};
use std::sync::{Arc, Mutex};
use std::io::{self, Write};
use std::str::from_utf8;
use std::rc::Rc;
#[test]
@ -1130,12 +1125,12 @@ mod tests {
}
}
fn make_string(lines: &[RenderedLine]) -> String {
fn make_string(lines: Vec<Vec<StyledString>>) -> String {
lines.iter()
.flat_map(|rl| {
rl.text.iter()
.map(|s| &s.text[..])
.chain(Some("\n"))
rl.iter()
.map(|s| &s.text[..])
.chain(Some("\n"))
})
.collect()
}
@ -1219,761 +1214,4 @@ r"blork2.rs:2:1: 2:12
";
assert_eq!(sstr, res_str);
}
struct Sink(Arc<Mutex<Vec<u8>>>);
impl Write for Sink {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
Write::write(&mut *self.0.lock().unwrap(), data)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
// Diagnostic doesn't align properly in span where line number increases by one digit
#[test]
fn test_hilight_suggestion_issue_11715() {
let data = Arc::new(Mutex::new(Vec::new()));
let cm = Rc::new(CodeMap::new());
let mut ew = EmitterWriter::new(Box::new(Sink(data.clone())),
None,
Some(cm.clone()),
FormatMode::NewErrorFormat);
let content = "abcdefg
koksi
line3
line4
cinq
line6
line7
line8
line9
line10
e--vän
tolv
dreizehn
";
let file = cm.new_filemap_and_lines("dummy.txt", None, content);
let start = file.lines.borrow()[10];
let end = file.lines.borrow()[11];
let sp = mk_sp(start, end);
let lvl = Level::Error;
println!("highlight_lines");
ew.highlight_lines(&sp.into(), lvl).unwrap();
println!("done");
let vec = data.lock().unwrap().clone();
let vec: &[u8] = &vec;
let str = from_utf8(vec).unwrap();
println!("r#\"\n{}\"#", str);
assert_eq!(str, &r#"
--> dummy.txt:11:1
|
11 | e--vän
| ^
"#[1..]);
}
#[test]
fn test_single_span_splice() {
// Test that a `MultiSpan` containing a single span splices a substition correctly
let cm = CodeMap::new();
let inputtext = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n";
let selection = " \n ~~\n~~~\n~~~~~ \n \n";
cm.new_filemap_and_lines("blork.rs", None, inputtext);
let sp = span_from_selection(inputtext, selection);
let msp: MultiSpan = sp.into();
// check that we are extracting the text we thought we were extracting
assert_eq!(&cm.span_to_snippet(sp).unwrap(), "BB\nCCC\nDDDDD");
let substitute = "ZZZZZZ".to_owned();
let expected = "bbbbZZZZZZddddd";
let suggest = CodeSuggestion {
msp: msp,
substitutes: vec![substitute],
};
assert_eq!(suggest.splice_lines(&cm), expected);
}
#[test]
fn test_multi_span_splice() {
// Test that a `MultiSpan` containing multiple spans splices a substition correctly
let cm = CodeMap::new();
let inputtext = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n";
let selection1 = " \n \n \n \n ~ \n"; // intentionally out of order
let selection2 = " \n ~~\n~~~\n~~~~~ \n \n";
cm.new_filemap_and_lines("blork.rs", None, inputtext);
let sp1 = span_from_selection(inputtext, selection1);
let sp2 = span_from_selection(inputtext, selection2);
let msp: MultiSpan = MultiSpan::from_spans(vec![sp1, sp2]);
let expected = "bbbbZZZZZZddddd\neXYZe";
let suggest = CodeSuggestion {
msp: msp,
substitutes: vec!["ZZZZZZ".to_owned(),
"XYZ".to_owned()]
};
assert_eq!(suggest.splice_lines(&cm), expected);
}
#[test]
fn test_multispan_highlight() {
let data = Arc::new(Mutex::new(Vec::new()));
let cm = Rc::new(CodeMap::new());
let mut diag = EmitterWriter::new(Box::new(Sink(data.clone())),
None,
Some(cm.clone()),
FormatMode::NewErrorFormat);
let inp = "_____aaaaaa____bbbbbb__cccccdd_";
let sp1 = " ~~~~~~ ";
let sp2 = " ~~~~~~ ";
let sp3 = " ~~~~~ ";
let sp4 = " ~~~~ ";
let sp34 = " ~~~~~~~ ";
let expect_start = &r#"
--> dummy.txt:1:6
|
1 | _____aaaaaa____bbbbbb__cccccdd_
| ^^^^^^ ^^^^^^ ^^^^^^^
"#[1..];
let span = |sp, expected| {
let sp = span_from_selection(inp, sp);
assert_eq!(&cm.span_to_snippet(sp).unwrap(), expected);
sp
};
cm.new_filemap_and_lines("dummy.txt", None, inp);
let sp1 = span(sp1, "aaaaaa");
let sp2 = span(sp2, "bbbbbb");
let sp3 = span(sp3, "ccccc");
let sp4 = span(sp4, "ccdd");
let sp34 = span(sp34, "cccccdd");
let spans = vec![sp1, sp2, sp3, sp4];
let test = |expected, highlight: &mut FnMut()| {
data.lock().unwrap().clear();
highlight();
let vec = data.lock().unwrap().clone();
let actual = from_utf8(&vec[..]).unwrap();
println!("actual=\n{}", actual);
assert_eq!(actual, expected);
};
let msp = MultiSpan::from_spans(vec![sp1, sp2, sp34]);
test(expect_start, &mut || {
diag.highlight_lines(&msp, Level::Error).unwrap();
});
test(expect_start, &mut || {
let msp = MultiSpan::from_spans(spans.clone());
diag.highlight_lines(&msp, Level::Error).unwrap();
});
}
#[test]
fn test_huge_multispan_highlight() {
let data = Arc::new(Mutex::new(Vec::new()));
let cm = Rc::new(CodeMap::new());
let mut diag = EmitterWriter::new(Box::new(Sink(data.clone())),
None,
Some(cm.clone()),
FormatMode::NewErrorFormat);
let inp = "aaaaa\n\
aaaaa\n\
aaaaa\n\
bbbbb\n\
ccccc\n\
xxxxx\n\
yyyyy\n\
_____\n\
ddd__eee_\n\
elided\n\
__f_gg";
let file = cm.new_filemap_and_lines("dummy.txt", None, inp);
let span = |lo, hi, (off_lo, off_hi)| {
let lines = file.lines.borrow();
let (mut lo, mut hi): (BytePos, BytePos) = (lines[lo], lines[hi]);
lo.0 += off_lo;
hi.0 += off_hi;
mk_sp(lo, hi)
};
let sp0 = span(4, 6, (0, 5));
let sp1 = span(0, 6, (0, 5));
let sp2 = span(8, 8, (0, 3));
let sp3 = span(8, 8, (5, 8));
let sp4 = span(10, 10, (2, 3));
let sp5 = span(10, 10, (4, 6));
let expect0 = &r#"
--> dummy.txt:5:1
|
5 | ccccc
| ^
...
9 | ddd__eee_
| ^^^ ^^^
10 | elided
11 | __f_gg
| ^ ^^
"#[1..];
let expect = &r#"
--> dummy.txt:1:1
|
1 | aaaaa
| ^
...
9 | ddd__eee_
| ^^^ ^^^
10 | elided
11 | __f_gg
| ^ ^^
"#[1..];
macro_rules! test {
($expected: expr, $highlight: expr) => ({
data.lock().unwrap().clear();
$highlight();
let vec = data.lock().unwrap().clone();
let actual = from_utf8(&vec[..]).unwrap();
println!("actual:");
println!("{}", actual);
println!("expected:");
println!("{}", $expected);
assert_eq!(&actual[..], &$expected[..]);
});
}
let msp0 = MultiSpan::from_spans(vec![sp0, sp2, sp3, sp4, sp5]);
let msp = MultiSpan::from_spans(vec![sp1, sp2, sp3, sp4, sp5]);
test!(expect0, || {
diag.highlight_lines(&msp0, Level::Error).unwrap();
});
test!(expect, || {
diag.highlight_lines(&msp, Level::Error).unwrap();
});
}
#[test]
fn tab() {
let file_text = "
fn foo() {
\tbar;
}
";
let cm = Rc::new(CodeMap::new());
let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let span_bar = cm.span_substr(&foo, file_text, "bar", 0);
let mut snippet = SnippetData::new(cm, Some(span_bar), FormatMode::NewErrorFormat);
snippet.push(span_bar, true, None);
let lines = snippet.render_lines();
let text = make_string(&lines);
assert_eq!(&text[..], &"
--> foo.rs:3:2
|
3 | \tbar;
| \t^^^
"[1..]);
}
#[test]
fn one_line() {
let file_text = r#"
fn foo() {
vec.push(vec.pop().unwrap());
}
"#;
let cm = Rc::new(CodeMap::new());
let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let span_vec0 = cm.span_substr(&foo, file_text, "vec", 0);
let span_vec1 = cm.span_substr(&foo, file_text, "vec", 1);
let span_semi = cm.span_substr(&foo, file_text, ";", 0);
let mut snippet = SnippetData::new(cm, None, FormatMode::NewErrorFormat);
snippet.push(span_vec0, false, Some(format!("previous borrow of `vec` occurs here")));
snippet.push(span_vec1, false, Some(format!("error occurs here")));
snippet.push(span_semi, false, Some(format!("previous borrow ends here")));
let lines = snippet.render_lines();
println!("{:#?}", lines);
let text: String = make_string(&lines);
println!("text=\n{}", text);
assert_eq!(&text[..], &r#"
::: foo.rs
|
3 | vec.push(vec.pop().unwrap());
| --- --- - previous borrow ends here
| | |
| | error occurs here
| previous borrow of `vec` occurs here
"#[1..]);
}
#[test]
fn two_files() {
let file_text_foo = r#"
fn foo() {
vec.push(vec.pop().unwrap());
}
"#;
let file_text_bar = r#"
fn bar() {
// these blank links here
// serve to ensure that the line numbers
// from bar.rs
// require more digits
vec.push();
// this line will get elided
vec.pop().unwrap());
}
"#;
let cm = Rc::new(CodeMap::new());
let foo_map = cm.new_filemap_and_lines("foo.rs", None, file_text_foo);
let span_foo_vec0 = cm.span_substr(&foo_map, file_text_foo, "vec", 0);
let span_foo_vec1 = cm.span_substr(&foo_map, file_text_foo, "vec", 1);
let span_foo_semi = cm.span_substr(&foo_map, file_text_foo, ";", 0);
let bar_map = cm.new_filemap_and_lines("bar.rs", None, file_text_bar);
let span_bar_vec0 = cm.span_substr(&bar_map, file_text_bar, "vec", 0);
let span_bar_vec1 = cm.span_substr(&bar_map, file_text_bar, "vec", 1);
let span_bar_semi = cm.span_substr(&bar_map, file_text_bar, ";", 0);
let mut snippet = SnippetData::new(cm, Some(span_foo_vec1), FormatMode::NewErrorFormat);
snippet.push(span_foo_vec0, false, Some(format!("a")));
snippet.push(span_foo_vec1, true, Some(format!("b")));
snippet.push(span_foo_semi, false, Some(format!("c")));
snippet.push(span_bar_vec0, false, Some(format!("d")));
snippet.push(span_bar_vec1, false, Some(format!("e")));
snippet.push(span_bar_semi, false, Some(format!("f")));
let lines = snippet.render_lines();
println!("{:#?}", lines);
let text: String = make_string(&lines);
println!("text=\n{}", text);
// Note that the `|` remain aligned across both files:
assert_eq!(&text[..], &r#"
--> foo.rs:3:14
|
3 | vec.push(vec.pop().unwrap());
| --- ^^^ - c
| | |
| | b
| a
::: bar.rs
|
17 | vec.push();
| --- - f
| |
| d
...
21 | vec.pop().unwrap());
| --- e
"#[1..]);
}
#[test]
fn multi_line() {
let file_text = r#"
fn foo() {
let name = find_id(&data, 22).unwrap();
// Add one more item we forgot to the vector. Silly us.
data.push(Data { name: format!("Hera"), id: 66 });
// Print everything out.
println!("Name: {:?}", name);
println!("Data: {:?}", data);
}
"#;
let cm = Rc::new(CodeMap::new());
let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let span_data0 = cm.span_substr(&foo, file_text, "data", 0);
let span_data1 = cm.span_substr(&foo, file_text, "data", 1);
let span_rbrace = cm.span_substr(&foo, file_text, "}", 3);
let mut snippet = SnippetData::new(cm, None, FormatMode::NewErrorFormat);
snippet.push(span_data0, false, Some(format!("immutable borrow begins here")));
snippet.push(span_data1, false, Some(format!("mutable borrow occurs here")));
snippet.push(span_rbrace, false, Some(format!("immutable borrow ends here")));
let lines = snippet.render_lines();
println!("{:#?}", lines);
let text: String = make_string(&lines);
println!("text=\n{}", text);
assert_eq!(&text[..], &r#"
::: foo.rs
|
3 | let name = find_id(&data, 22).unwrap();
| ---- immutable borrow begins here
...
6 | data.push(Data { name: format!("Hera"), id: 66 });
| ---- mutable borrow occurs here
...
11 | }
| - immutable borrow ends here
"#[1..]);
}
#[test]
fn overlapping() {
let file_text = r#"
fn foo() {
vec.push(vec.pop().unwrap());
}
"#;
let cm = Rc::new(CodeMap::new());
let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let span0 = cm.span_substr(&foo, file_text, "vec.push", 0);
let span1 = cm.span_substr(&foo, file_text, "vec", 0);
let span2 = cm.span_substr(&foo, file_text, "ec.push", 0);
let span3 = cm.span_substr(&foo, file_text, "unwrap", 0);
let mut snippet = SnippetData::new(cm, None, FormatMode::NewErrorFormat);
snippet.push(span0, false, Some(format!("A")));
snippet.push(span1, false, Some(format!("B")));
snippet.push(span2, false, Some(format!("C")));
snippet.push(span3, false, Some(format!("D")));
let lines = snippet.render_lines();
println!("{:#?}", lines);
let text: String = make_string(&lines);
println!("text=r#\"\n{}\".trim_left()", text);
assert_eq!(&text[..], &r#"
::: foo.rs
|
3 | vec.push(vec.pop().unwrap());
| -------- ------ D
| ||
| |C
| A
| B
"#[1..]);
}
#[test]
fn one_line_out_of_order() {
let file_text = r#"
fn foo() {
vec.push(vec.pop().unwrap());
}
"#;
let cm = Rc::new(CodeMap::new());
let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let span_vec0 = cm.span_substr(&foo, file_text, "vec", 0);
let span_vec1 = cm.span_substr(&foo, file_text, "vec", 1);
let span_semi = cm.span_substr(&foo, file_text, ";", 0);
// intentionally don't push the snippets left to right
let mut snippet = SnippetData::new(cm, None, FormatMode::NewErrorFormat);
snippet.push(span_vec1, false, Some(format!("error occurs here")));
snippet.push(span_vec0, false, Some(format!("previous borrow of `vec` occurs here")));
snippet.push(span_semi, false, Some(format!("previous borrow ends here")));
let lines = snippet.render_lines();
println!("{:#?}", lines);
let text: String = make_string(&lines);
println!("text=r#\"\n{}\".trim_left()", text);
assert_eq!(&text[..], &r#"
::: foo.rs
|
3 | vec.push(vec.pop().unwrap());
| --- --- - previous borrow ends here
| | |
| | error occurs here
| previous borrow of `vec` occurs here
"#[1..]);
}
#[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());
let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let span_vec0 = cm.span_substr(&foo, file_text, "vec", 3);
let span_vec1 = cm.span_substr(&foo, file_text, "vec", 8);
let mut snippet = SnippetData::new(cm, None, FormatMode::NewErrorFormat);
snippet.push(span_vec0, false, Some(format!("`vec` moved here because it \
has type `collections::vec::Vec<i32>`")));
snippet.push(span_vec1, false, Some(format!("use of moved value: `vec`")));
let lines = snippet.render_lines();
println!("{:#?}", lines);
let text: String = make_string(&lines);
println!("text=r#\"\n{}\".trim_left()", text);
assert_eq!(&text[..], &r#"
::: foo.rs
|
4 | let mut vec2 = vec;
| --- `vec` moved here because it has type `collections::vec::Vec<i32>`
...
9 | vec.push(7);
| --- use of moved value: `vec`
"#[1..]);
}
#[test]
fn spans_without_labels() {
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());
let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let mut snippet = SnippetData::new(cm.clone(), None, FormatMode::NewErrorFormat);
for i in 0..4 {
let span_veci = cm.span_substr(&foo, file_text, "vec", i);
snippet.push(span_veci, false, None);
}
let lines = snippet.render_lines();
let text: String = make_string(&lines);
println!("text=&r#\"\n{}\n\"#[1..]", text);
assert_eq!(text, &r#"
::: foo.rs
|
3 | let mut vec = vec![0, 1, 2];
| --- ---
4 | let mut vec2 = vec;
| --- ---
"#[1..]);
}
#[test]
fn span_long_selection() {
let file_text = r#"
impl SomeTrait for () {
fn foo(x: u32) {
// impl 1
// impl 2
// impl 3
}
}
"#;
let cm = Rc::new(CodeMap::new());
let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let mut snippet = SnippetData::new(cm.clone(), None, FormatMode::NewErrorFormat);
let fn_span = cm.span_substr(&foo, file_text, "fn", 0);
let rbrace_span = cm.span_substr(&foo, file_text, "}", 0);
snippet.push(splice(fn_span, rbrace_span), false, None);
let lines = snippet.render_lines();
let text: String = make_string(&lines);
println!("r#\"\n{}\"", text);
assert_eq!(text, &r#"
::: foo.rs
|
3 | fn foo(x: u32) {
| -
"#[1..]);
}
#[test]
fn span_overlap_label() {
// Test that we don't put `x_span` to the right of its highlight,
// since there is another highlight that overlaps it.
let file_text = r#"
fn foo(x: u32) {
}
}
"#;
let cm = Rc::new(CodeMap::new());
let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let mut snippet = SnippetData::new(cm.clone(), None, FormatMode::NewErrorFormat);
let fn_span = cm.span_substr(&foo, file_text, "fn foo(x: u32)", 0);
let x_span = cm.span_substr(&foo, file_text, "x", 0);
snippet.push(fn_span, false, Some(format!("fn_span")));
snippet.push(x_span, false, Some(format!("x_span")));
let lines = snippet.render_lines();
let text: String = make_string(&lines);
println!("r#\"\n{}\"", text);
assert_eq!(text, &r#"
::: foo.rs
|
2 | fn foo(x: u32) {
| --------------
| | |
| | x_span
| fn_span
"#[1..]);
}
#[test]
fn span_overlap_label2() {
// Test that we don't put `x_span` to the right of its highlight,
// since there is another highlight that overlaps it. In this
// case, the overlap is only at the beginning, but it's still
// better to show the beginning more clearly.
let file_text = r#"
fn foo(x: u32) {
}
}
"#;
let cm = Rc::new(CodeMap::new());
let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let mut snippet = SnippetData::new(cm.clone(), None, FormatMode::NewErrorFormat);
let fn_span = cm.span_substr(&foo, file_text, "fn foo(x", 0);
let x_span = cm.span_substr(&foo, file_text, "x: u32)", 0);
snippet.push(fn_span, false, Some(format!("fn_span")));
snippet.push(x_span, false, Some(format!("x_span")));
let lines = snippet.render_lines();
let text: String = make_string(&lines);
println!("r#\"\n{}\"", text);
assert_eq!(text, &r#"
::: foo.rs
|
2 | fn foo(x: u32) {
| --------------
| | |
| | x_span
| fn_span
"#[1..]);
}
#[test]
fn span_overlap_label3() {
// Test that we don't put `x_span` to the right of its highlight,
// since there is another highlight that overlaps it. In this
// case, the overlap is only at the beginning, but it's still
// better to show the beginning more clearly.
let file_text = r#"
fn foo() {
let closure = || {
inner
};
}
}
"#;
let cm = Rc::new(CodeMap::new());
let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let mut snippet = SnippetData::new(cm.clone(), None, FormatMode::NewErrorFormat);
let closure_span = {
let closure_start_span = cm.span_substr(&foo, file_text, "||", 0);
let closure_end_span = cm.span_substr(&foo, file_text, "}", 0);
splice(closure_start_span, closure_end_span)
};
let inner_span = cm.span_substr(&foo, file_text, "inner", 0);
snippet.push(closure_span, false, Some(format!("foo")));
snippet.push(inner_span, false, Some(format!("bar")));
let lines = snippet.render_lines();
let text: String = make_string(&lines);
println!("r#\"\n{}\"", text);
assert_eq!(text, &r#"
::: foo.rs
|
3 | let closure = || {
| - foo
4 | inner
| ----- bar
"#[1..]);
}
#[test]
fn span_empty() {
// In one of the unit tests, we found that the parser sometimes
// gives empty spans, and in particular it supplied an EOF span
// like this one, which points at the very end. We want to
// fallback gracefully in this case.
let file_text = r#"
fn main() {
struct Foo;
impl !Sync for Foo {}
unsafe impl Send for &'static Foo {
// error: cross-crate traits with a default impl, like `core::marker::Send`,
// can only be implemented for a struct/enum type, not
// `&'static Foo`
}"#;
let cm = Rc::new(CodeMap::new());
let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let mut rbrace_span = cm.span_substr(&foo, file_text, "}", 1);
rbrace_span.lo = rbrace_span.hi;
let mut snippet = SnippetData::new(cm.clone(),
Some(rbrace_span),
FormatMode::NewErrorFormat);
snippet.push(rbrace_span, false, None);
let lines = snippet.render_lines();
let text: String = make_string(&lines);
println!("r#\"\n{}\"", text);
assert_eq!(text, &r#"
--> foo.rs:11:2
|
11 | }
| -
"#[1..]);
}
}

View File

@ -0,0 +1,19 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
#![feature(optin_builtin_traits)]
fn main() {
struct Foo;
impl !Sync for Foo {}
unsafe impl Send for &'static Foo { }
}

View File

@ -0,0 +1,8 @@
error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `&'static main::Foo`
--> $DIR/empty_span.rs:18:5
|
18 | unsafe impl Send for &'static Foo { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View File

@ -0,0 +1,104 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
fn main() {
let x = "foo";
let y = &mut x;
}

View File

@ -0,0 +1,11 @@
error: cannot borrow immutable local variable `x` as mutable
--> $DIR/huge_multispan_highlight.rs:100:18
|
14 | let x = "foo";
| - use `mut x` here to make mutable
...
100 | let y = &mut x;
| ^ cannot borrow mutably
error: aborting due to previous error

View File

@ -0,0 +1,104 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
fn main() {
let mut x = "foo";
let y = &mut x;
let z = &mut x;
}

View File

@ -0,0 +1,12 @@
error[E0499]: cannot borrow `x` as mutable more than once at a time
--> $DIR/issue-11715.rs:100:18
|
99 | let y = &mut x;
| - first mutable borrow occurs here
100 | let z = &mut x;
| ^ second mutable borrow occurs here
101 | }
| - first borrow ends here
error: aborting due to previous error

View File

@ -0,0 +1,16 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
fn main() {
let mut v = vec![Some("foo"), Some("bar")];
v.push(v.pop().unwrap());
}

View File

@ -0,0 +1,11 @@
error[E0499]: cannot borrow `v` as mutable more than once at a time
--> $DIR/one_line.rs:15:12
|
15 | v.push(v.pop().unwrap());
| - ^ - first borrow ends here
| | |
| | second mutable borrow occurs here
| first mutable borrow occurs here
error: aborting due to previous error

View File

@ -0,0 +1,24 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
#[derive(Debug)]
struct Foo { }
struct S {f:String}
impl Drop for S {
fn drop(&mut self) { println!("{}", self.f); }
}
fn main() {
match (S {f:"foo".to_string()}) {
S {f:_s} => {}
}
}

View File

@ -0,0 +1,11 @@
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
--> $DIR/overlapping_spans.rs:22:9
|
22 | S {f:_s} => {}
| ^^^^^--^
| | |
| | hint: to prevent move, use `ref _s` or `ref mut _s`
| cannot move out of here
error: aborting due to previous error

View File

@ -0,0 +1,16 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
// ignore-tidy-tab
fn main() {
bar;
}

View File

@ -0,0 +1,8 @@
error[E0425]: unresolved name `bar`
--> $DIR/tab.rs:14:2
|
14 | \tbar;
| \t^^^
error: aborting due to previous error

View File

@ -0,0 +1,18 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
include!("two_files_data.rs");
struct Baz { }
impl Bar for Baz { }
fn main() { }

View File

@ -0,0 +1,13 @@
error[E0404]: `Bar` is not a trait
--> $DIR/two_files.rs:16:6
|
16 | impl Bar for Baz { }
| ^^^ `Bar` is not a trait
|
::: $DIR/two_files_data.rs
|
15 | type Bar = Foo;
| --------------- type aliases cannot be used for traits
error: cannot continue compilation due to previous error

View File

@ -0,0 +1,16 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
// ignore-test
trait Foo { }
type Bar = Foo;