diff options
| author | Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> | 2017-05-09 10:04:24 +0200 |
|---|---|---|
| committer | Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> | 2017-05-10 13:20:26 +0200 |
| commit | 67d762d896c8748009d1843ebf9e2e0760ed33a0 (patch) | |
| tree | 5a7ccecb7b413d1a17cb2ed2933948325b32d8f6 /src/librustc_errors/lib.rs | |
| parent | 58b33ad70cdd11f9ce7b5874c6effab9627e51aa (diff) | |
| download | rust-67d762d896c8748009d1843ebf9e2e0760ed33a0.tar.gz rust-67d762d896c8748009d1843ebf9e2e0760ed33a0.zip | |
Refactor suggestion diagnostic API to allow for multiple suggestions
Diffstat (limited to 'src/librustc_errors/lib.rs')
| -rw-r--r-- | src/librustc_errors/lib.rs | 85 |
1 files changed, 54 insertions, 31 deletions
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index db8c9ac306b..8e378935094 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -65,8 +65,25 @@ pub enum RenderSpan { #[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub struct CodeSuggestion { - pub msp: MultiSpan, - pub substitutes: Vec<String>, + /// Each substitute can have multiple variants due to multiple + /// applicable suggestions + /// + /// `foo.bar` might be replaced with `a.b` or `x.y` by replacing + /// `foo` and `bar` on their own: + /// + /// ``` + /// vec![ + /// (0..3, vec!["a", "x"]), + /// (4..7, vec!["b", "y"]), + /// ] + /// ``` + /// + /// or by replacing the entire span: + /// + /// ``` + /// vec![(0..7, vec!["a.b", "x.y"])] + /// ``` + pub substitutes: Vec<(Span, Vec<String>)>, pub msg: String, } @@ -79,8 +96,8 @@ pub trait CodeMapper { } impl CodeSuggestion { - /// Returns the assembled code suggestion. - pub fn splice_lines(&self, cm: &CodeMapper) -> String { + /// Returns the assembled code suggestions. + pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<String> { use syntax_pos::{CharPos, Loc, Pos}; fn push_trailing(buf: &mut String, @@ -102,20 +119,22 @@ impl CodeSuggestion { } } - let mut primary_spans = self.msp.primary_spans().to_owned(); - - assert_eq!(primary_spans.len(), self.substitutes.len()); - if primary_spans.is_empty() { - return format!(""); + if self.substitutes.is_empty() { + return vec![String::new()]; } + let mut primary_spans: Vec<_> = self.substitutes + .iter() + .map(|&(sp, ref sub)| (sp, sub)) + .collect(); + // Assumption: all spans are in the same file, and all spans // are disjoint. Sort in ascending order. - primary_spans.sort_by_key(|sp| sp.lo); + primary_spans.sort_by_key(|sp| sp.0.lo); // Find the bounding span. - let lo = primary_spans.iter().map(|sp| sp.lo).min().unwrap(); - let hi = primary_spans.iter().map(|sp| sp.hi).min().unwrap(); + let lo = primary_spans.iter().map(|sp| sp.0.lo).min().unwrap(); + let hi = primary_spans.iter().map(|sp| sp.0.hi).min().unwrap(); let bounding_span = Span { lo: lo, hi: hi, @@ -138,33 +157,37 @@ impl CodeSuggestion { prev_hi.col = CharPos::from_usize(0); let mut prev_line = fm.get_line(lines.lines[0].line_index); - let mut buf = String::new(); + let mut bufs = vec![String::new(); self.substitutes[0].1.len()]; - for (sp, substitute) in primary_spans.iter().zip(self.substitutes.iter()) { + for (sp, substitutes) in primary_spans { let cur_lo = cm.lookup_char_pos(sp.lo); - if prev_hi.line == cur_lo.line { - push_trailing(&mut buf, prev_line, &prev_hi, Some(&cur_lo)); - } else { - push_trailing(&mut buf, prev_line, &prev_hi, None); - // push lines between the previous and current span (if any) - for idx in prev_hi.line..(cur_lo.line - 1) { - if let Some(line) = fm.get_line(idx) { - buf.push_str(line); - buf.push('\n'); + for (buf, substitute) in bufs.iter_mut().zip(substitutes) { + if prev_hi.line == cur_lo.line { + push_trailing(buf, prev_line, &prev_hi, Some(&cur_lo)); + } else { + push_trailing(buf, prev_line, &prev_hi, None); + // push lines between the previous and current span (if any) + for idx in prev_hi.line..(cur_lo.line - 1) { + if let Some(line) = fm.get_line(idx) { + buf.push_str(line); + buf.push('\n'); + } + } + if let Some(cur_line) = fm.get_line(cur_lo.line - 1) { + buf.push_str(&cur_line[..cur_lo.col.to_usize()]); } } - if let Some(cur_line) = fm.get_line(cur_lo.line - 1) { - buf.push_str(&cur_line[..cur_lo.col.to_usize()]); - } + buf.push_str(substitute); } - buf.push_str(substitute); prev_hi = cm.lookup_char_pos(sp.hi); prev_line = fm.get_line(prev_hi.line - 1); } - push_trailing(&mut buf, prev_line, &prev_hi, None); - // remove trailing newline - buf.pop(); - buf + for buf in &mut bufs { + push_trailing(buf, prev_line, &prev_hi, None); + // remove trailing newline + buf.pop(); + } + bufs } } |
