Skip to content

Commit 38677c4

Browse files
committed
Modify the codemap code to use more slices and to information about
columns within a line, not just the line numbers. Also try to clarify and use the term `line_index` when 0-based.
1 parent 4e9361a commit 38677c4

File tree

2 files changed

+80
-36
lines changed

2 files changed

+80
-36
lines changed

src/libsyntax/codemap.rs

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -299,9 +299,20 @@ impl ExpnId {
299299

300300
pub type FileName = String;
301301

302+
pub struct LineInfo {
303+
/// Index of line, starting from 0.
304+
pub line_index: usize,
305+
306+
/// Column in line where span begins, starting from 0.
307+
pub start_col: CharPos,
308+
309+
/// Column in line where span ends, starting from 0, exclusive.
310+
pub end_col: CharPos,
311+
}
312+
302313
pub struct FileLines {
303314
pub file: Rc<FileMap>,
304-
pub lines: Vec<usize>
315+
pub lines: Vec<LineInfo>
305316
}
306317

307318
/// Identifies an offset of a multi-byte character in a FileMap
@@ -467,9 +478,9 @@ impl FileMap {
467478
lines.push(pos);
468479
}
469480

470-
/// get a line from the list of pre-computed line-beginnings
471-
///
472-
pub fn get_line(&self, line_number: usize) -> Option<String> {
481+
/// get a line from the list of pre-computed line-beginnings.
482+
/// line-number here is 0-based.
483+
pub fn get_line(&self, line_number: usize) -> Option<&str> {
473484
match self.src {
474485
Some(ref src) => {
475486
let lines = self.lines.borrow();
@@ -480,7 +491,7 @@ impl FileMap {
480491
match slice.find('\n') {
481492
Some(e) => &slice[..e],
482493
None => slice
483-
}.to_string()
494+
}
484495
})
485496
}
486497
None => None
@@ -649,10 +660,29 @@ impl CodeMap {
649660
pub fn span_to_lines(&self, sp: Span) -> FileLines {
650661
let lo = self.lookup_char_pos(sp.lo);
651662
let hi = self.lookup_char_pos(sp.hi);
652-
let mut lines = Vec::new();
653-
for i in lo.line - 1..hi.line {
654-
lines.push(i);
655-
};
663+
let mut lines = Vec::with_capacity(hi.line - lo.line + 1);
664+
665+
// The span starts partway through the first line,
666+
// but after that it starts from offset 0.
667+
let mut start_col = lo.col;
668+
669+
// For every line but the last, it extends from `start_col`
670+
// and to the end of the line. Be careful because the line
671+
// numbers in Loc are 1-based, so we subtract 1 to get 0-based
672+
// lines.
673+
for line_index in lo.line-1 .. hi.line-2 {
674+
let line_len = lo.file.get_line(line_index).map(|s| s.len()).unwrap_or(0);
675+
lines.push(LineInfo { line_index: line_index,
676+
start_col: start_col,
677+
end_col: CharPos::from_usize(line_len) });
678+
start_col = CharPos::from_usize(0);
679+
}
680+
681+
// For the last line, it extends from `start_col` to `hi.col`:
682+
lines.push(LineInfo { line_index: hi.line - 1,
683+
start_col: start_col,
684+
end_col: hi.col });
685+
656686
FileLines {file: lo.file, lines: lines}
657687
}
658688

src/libsyntax/diagnostic.rs

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -483,25 +483,39 @@ fn highlight_lines(err: &mut EmitterWriter,
483483
cm: &codemap::CodeMap,
484484
sp: Span,
485485
lvl: Level,
486-
lines: codemap::FileLines) -> io::Result<()> {
486+
lines: codemap::FileLines)
487+
-> io::Result<()>
488+
{
487489
let fm = &*lines.file;
488490

489-
let mut elided = false;
490-
let mut display_lines = &lines.lines[..];
491-
if display_lines.len() > MAX_LINES {
492-
display_lines = &display_lines[0..MAX_LINES];
493-
elided = true;
494-
}
491+
let line_strings: Option<Vec<&str>> =
492+
lines.lines.iter()
493+
.map(|info| fm.get_line(info.line_index))
494+
.collect();
495+
496+
let line_strings = match line_strings {
497+
None => { return Ok(()); }
498+
Some(line_strings) => line_strings
499+
};
500+
501+
// Display only the first MAX_LINES lines.
502+
let all_lines = lines.lines.len();
503+
let display_lines = cmp::min(all_lines, MAX_LINES);
504+
let display_line_infos = &lines.lines[..display_lines];
505+
let display_line_strings = &line_strings[..display_lines];
506+
495507
// Print the offending lines
496-
for &line_number in display_lines {
497-
if let Some(line) = fm.get_line(line_number) {
498-
try!(write!(&mut err.dst, "{}:{} {}\n", fm.name,
499-
line_number + 1, line));
500-
}
508+
for (line_info, line) in display_line_infos.iter().zip(display_line_strings.iter()) {
509+
try!(write!(&mut err.dst, "{}:{} {}\n",
510+
fm.name,
511+
line_info.line_index + 1,
512+
line));
501513
}
502-
if elided {
503-
let last_line = display_lines[display_lines.len() - 1];
504-
let s = format!("{}:{} ", fm.name, last_line + 1);
514+
515+
// If we elided something, put an ellipsis.
516+
if display_lines < all_lines {
517+
let last_line_index = display_line_infos.last().unwrap().line_index;
518+
let s = format!("{}:{} ", fm.name, last_line_index + 1);
505519
try!(write!(&mut err.dst, "{0:1$}...\n", "", s.len()));
506520
}
507521

@@ -510,7 +524,7 @@ fn highlight_lines(err: &mut EmitterWriter,
510524
if lines.lines.len() == 1 {
511525
let lo = cm.lookup_char_pos(sp.lo);
512526
let mut digits = 0;
513-
let mut num = (lines.lines[0] + 1) / 10;
527+
let mut num = (lines.lines[0].line_index + 1) / 10;
514528

515529
// how many digits must be indent past?
516530
while num > 0 { num /= 10; digits += 1; }
@@ -522,7 +536,7 @@ fn highlight_lines(err: &mut EmitterWriter,
522536
for _ in 0..skip {
523537
s.push(' ');
524538
}
525-
if let Some(orig) = fm.get_line(lines.lines[0]) {
539+
if let Some(orig) = fm.get_line(lines.lines[0].line_index) {
526540
let mut col = skip;
527541
let mut lastc = ' ';
528542
let mut iter = orig.chars().enumerate();
@@ -597,32 +611,32 @@ fn end_highlight_lines(w: &mut EmitterWriter,
597611

598612
let lines = &lines.lines[..];
599613
if lines.len() > MAX_LINES {
600-
if let Some(line) = fm.get_line(lines[0]) {
614+
if let Some(line) = fm.get_line(lines[0].line_index) {
601615
try!(write!(&mut w.dst, "{}:{} {}\n", fm.name,
602-
lines[0] + 1, line));
616+
lines[0].line_index + 1, line));
603617
}
604618
try!(write!(&mut w.dst, "...\n"));
605-
let last_line_number = lines[lines.len() - 1];
606-
if let Some(last_line) = fm.get_line(last_line_number) {
619+
let last_line_index = lines[lines.len() - 1].line_index;
620+
if let Some(last_line) = fm.get_line(last_line_index) {
607621
try!(write!(&mut w.dst, "{}:{} {}\n", fm.name,
608-
last_line_number + 1, last_line));
622+
last_line_index + 1, last_line));
609623
}
610624
} else {
611-
for &line_number in lines {
612-
if let Some(line) = fm.get_line(line_number) {
625+
for line_info in lines {
626+
if let Some(line) = fm.get_line(line_info.line_index) {
613627
try!(write!(&mut w.dst, "{}:{} {}\n", fm.name,
614-
line_number + 1, line));
628+
line_info.line_index + 1, line));
615629
}
616630
}
617631
}
618-
let last_line_start = format!("{}:{} ", fm.name, lines[lines.len()-1]+1);
632+
let last_line_start = format!("{}:{} ", fm.name, lines[lines.len()-1].line_index + 1);
619633
let hi = cm.lookup_char_pos(sp.hi);
620634
let skip = last_line_start.width(false);
621635
let mut s = String::new();
622636
for _ in 0..skip {
623637
s.push(' ');
624638
}
625-
if let Some(orig) = fm.get_line(lines[0]) {
639+
if let Some(orig) = fm.get_line(lines[0].line_index) {
626640
let iter = orig.chars().enumerate();
627641
for (pos, ch) in iter {
628642
// Span seems to use half-opened interval, so subtract 1

0 commit comments

Comments
 (0)