commit
ac134f7ca4
2 changed files with 90 additions and 23 deletions
|
@ -483,42 +483,61 @@ fn highlight_lines(err: &mut EmitterWriter,
|
|||
// how many digits must be indent past?
|
||||
while num > 0 { num /= 10; digits += 1; }
|
||||
|
||||
// indent past |name:## | and the 0-offset column location
|
||||
let left = fm.name.len() + digits + lo.col.to_usize() + 3;
|
||||
let mut s = String::new();
|
||||
// Skip is the number of characters we need to skip because they are
|
||||
// part of the 'filename:line ' part of the previous line.
|
||||
let skip = fm.name.len() + digits + 3;
|
||||
let skip = fm.name.width(false) + digits + 3;
|
||||
for _ in 0..skip {
|
||||
s.push(' ');
|
||||
}
|
||||
if let Some(orig) = fm.get_line(lines.lines[0]) {
|
||||
for pos in 0..left - skip {
|
||||
let cur_char = orig.as_bytes()[pos] as char;
|
||||
let mut col = skip;
|
||||
let mut lastc = ' ';
|
||||
let mut iter = orig.chars().enumerate();
|
||||
for (pos, ch) in iter.by_ref() {
|
||||
lastc = ch;
|
||||
if pos >= lo.col.to_usize() { break; }
|
||||
// Whenever a tab occurs on the previous line, we insert one on
|
||||
// the error-point-squiggly-line as well (instead of a space).
|
||||
// That way the squiggly line will usually appear in the correct
|
||||
// position.
|
||||
match cur_char {
|
||||
'\t' => s.push('\t'),
|
||||
_ => s.push(' '),
|
||||
};
|
||||
match ch {
|
||||
'\t' => {
|
||||
col += 8 - col%8;
|
||||
s.push('\t');
|
||||
},
|
||||
c => for _ in 0..c.width(false).unwrap_or(0) {
|
||||
col += 1;
|
||||
s.push(' ');
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try!(write!(&mut err.dst, "{}", s));
|
||||
let mut s = String::from_str("^");
|
||||
let hi = cm.lookup_char_pos(sp.hi);
|
||||
if hi.col != lo.col {
|
||||
// the ^ already takes up one space
|
||||
let num_squigglies = hi.col.to_usize() - lo.col.to_usize() - 1;
|
||||
for _ in 0..num_squigglies {
|
||||
s.push('~');
|
||||
try!(write!(&mut err.dst, "{}", s));
|
||||
let mut s = String::from_str("^");
|
||||
let count = match lastc {
|
||||
// Most terminals have a tab stop every eight columns by default
|
||||
'\t' => 8 - col%8,
|
||||
_ => lastc.width(false).unwrap_or(1),
|
||||
};
|
||||
col += count;
|
||||
s.extend(::std::iter::repeat('~').take(count - 1));
|
||||
let hi = cm.lookup_char_pos(sp.hi);
|
||||
if hi.col != lo.col {
|
||||
for (pos, ch) in iter {
|
||||
if pos >= hi.col.to_usize() { break; }
|
||||
let count = match ch {
|
||||
'\t' => 8 - col%8,
|
||||
_ => ch.width(false).unwrap_or(0),
|
||||
};
|
||||
col += count;
|
||||
s.extend(::std::iter::repeat('~').take(count));
|
||||
}
|
||||
}
|
||||
try!(print_maybe_styled(err,
|
||||
&format!("{}\n", s)[],
|
||||
term::attr::ForegroundColor(lvl.color())));
|
||||
}
|
||||
try!(print_maybe_styled(err,
|
||||
&format!("{}\n", s)[],
|
||||
term::attr::ForegroundColor(lvl.color())));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -559,12 +578,28 @@ fn custom_highlight_lines(w: &mut EmitterWriter,
|
|||
}
|
||||
let last_line_start = format!("{}:{} ", fm.name, lines[lines.len()-1]+1);
|
||||
let hi = cm.lookup_char_pos(sp.hi);
|
||||
// Span seems to use half-opened interval, so subtract 1
|
||||
let skip = last_line_start.len() + hi.col.to_usize() - 1;
|
||||
let skip = last_line_start.width(false);
|
||||
let mut s = String::new();
|
||||
for _ in 0..skip {
|
||||
s.push(' ');
|
||||
}
|
||||
if let Some(orig) = fm.get_line(lines[0]) {
|
||||
let iter = orig.chars().enumerate();
|
||||
for (pos, ch) in iter {
|
||||
// Span seems to use half-opened interval, so subtract 1
|
||||
if pos >= hi.col.to_usize() - 1 { break; }
|
||||
// Whenever a tab occurs on the previous line, we insert one on
|
||||
// the error-point-squiggly-line as well (instead of a space).
|
||||
// That way the squiggly line will usually appear in the correct
|
||||
// position.
|
||||
match ch {
|
||||
'\t' => s.push('\t'),
|
||||
c => for _ in 0..c.width(false).unwrap_or(0) {
|
||||
s.push(' ');
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
s.push('^');
|
||||
s.push('\n');
|
||||
print_maybe_styled(w,
|
||||
|
|
|
@ -65,4 +65,36 @@ fn main() {
|
|||
.collect::<String>());
|
||||
assert!(err.contains(expected_span.as_slice()));
|
||||
}
|
||||
|
||||
// Test multi-column characters and tabs
|
||||
{
|
||||
let _ = write!(&mut File::create(&main_file).unwrap(),
|
||||
r#"extern "路濫狼á́́" fn foo() {{}} extern "路濫狼á́" fn bar() {{}}"#);
|
||||
}
|
||||
|
||||
// Extra characters. Every line is preceded by `filename:lineno <actual code>`
|
||||
let offset = main_file.as_str().unwrap().len() + 3;
|
||||
|
||||
let result = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(format!("{} {}",
|
||||
rustc,
|
||||
main_file.as_str()
|
||||
.unwrap()).as_slice())
|
||||
.output().unwrap();
|
||||
|
||||
let err = String::from_utf8_lossy(result.error.as_slice());
|
||||
|
||||
// Test both the length of the snake and the leading spaces up to it
|
||||
|
||||
// First snake is 8 ~s long, with 7 preceding spaces (excluding file name/line offset)
|
||||
let expected_span = format!("\n{}^{}\n",
|
||||
repeat(" ").take(offset + 7).collect::<String>(),
|
||||
repeat("~").take(8).collect::<String>());
|
||||
assert!(err.contains(expected_span.as_slice()));
|
||||
// Second snake is 8 ~s long, with 36 preceding spaces
|
||||
let expected_span = format!("\n{}^{}\n",
|
||||
repeat(" ").take(offset + 36).collect::<String>(),
|
||||
repeat("~").take(8).collect::<String>());
|
||||
assert!(err.contains(expected_span.as_slice()));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue