Address PR reviews

This commit is contained in:
Oliver Schneider 2017-05-11 15:26:22 +02:00
parent f859f2585b
commit 644ce5e535
4 changed files with 59 additions and 40 deletions

View file

@ -9,6 +9,7 @@
// except according to those terms. // except according to those terms.
use CodeSuggestion; use CodeSuggestion;
use Substitution;
use Level; use Level;
use RenderSpan; use RenderSpan;
use std::fmt; use std::fmt;
@ -205,7 +206,10 @@ impl Diagnostic {
/// See `diagnostic::CodeSuggestion` for more information. /// See `diagnostic::CodeSuggestion` for more information.
pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self { pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
self.suggestions.push(CodeSuggestion { self.suggestions.push(CodeSuggestion {
substitutes: vec![(sp, vec![suggestion])], substitution_parts: vec![Substitution {
span: sp,
substitutions: vec![suggestion],
}],
msg: msg.to_owned(), msg: msg.to_owned(),
}); });
self self
@ -213,7 +217,10 @@ impl Diagnostic {
pub fn span_suggestions(&mut self, sp: Span, msg: &str, suggestions: Vec<String>) -> &mut Self { pub fn span_suggestions(&mut self, sp: Span, msg: &str, suggestions: Vec<String>) -> &mut Self {
self.suggestions.push(CodeSuggestion { self.suggestions.push(CodeSuggestion {
substitutes: vec![(sp, suggestions)], substitution_parts: vec![Substitution {
span: sp,
substitutions: suggestions,
}],
msg: msg.to_owned(), msg: msg.to_owned(),
}); });
self self

View file

@ -35,38 +35,32 @@ impl Emitter for EmitterWriter {
let mut primary_span = db.span.clone(); let mut primary_span = db.span.clone();
let mut children = db.children.clone(); let mut children = db.children.clone();
if db.suggestions.len() == 1 { if let Some((sugg, rest)) = db.suggestions.split_first() {
let sugg = &db.suggestions[0]; if rest.is_empty() &&
// don't display multispans as labels // don't display multipart suggestions as labels
if sugg.substitutes.len() == 1 && sugg.substitution_parts.len() == 1 &&
// don't display multi-suggestions as labels // don't display multi-suggestions as labels
sugg.substitutes[0].1.len() == 1 && sugg.substitutions() == 1 &&
// don't display long messages as labels // don't display long messages as labels
sugg.msg.split_whitespace().count() < 10 && sugg.msg.split_whitespace().count() < 10 &&
// don't display multiline suggestions as labels // don't display multiline suggestions as labels
sugg.substitutes[0].1[0].find('\n').is_none() { sugg.substitution_parts[0].substitutions[0].find('\n').is_none() {
let msg = format!("help: {} `{}`", sugg.msg, sugg.substitutes[0].1[0]); let substitution = &sugg.substitution_parts[0].substitutions[0];
primary_span.push_span_label(sugg.substitutes[0].0, msg); let msg = format!("help: {} `{}`", sugg.msg, substitution);
primary_span.push_span_label(sugg.substitution_spans().next().unwrap(), msg);
} else { } else {
children.push(SubDiagnostic { // if there are multiple suggestions, print them all in full
level: Level::Help, // to be consistent. We could try to figure out if we can
message: Vec::new(), // make one (or the first one) inline, but that would give
span: MultiSpan::new(), // undue importance to a semi-random suggestion
render_span: Some(Suggestion(sugg.clone())), for sugg in &db.suggestions {
}); children.push(SubDiagnostic {
} level: Level::Help,
} else { message: Vec::new(),
// if there are multiple suggestions, print them all in full span: MultiSpan::new(),
// to be consistent. We could try to figure out if we can render_span: Some(Suggestion(sugg.clone())),
// make one (or the first one) inline, but that would give });
// undue importance to a semi-random suggestion }
for sugg in &db.suggestions {
children.push(SubDiagnostic {
level: Level::Help,
message: Vec::new(),
span: MultiSpan::new(),
render_span: Some(Suggestion(sugg.clone())),
});
} }
} }
@ -1073,7 +1067,7 @@ impl EmitterWriter {
-> io::Result<()> { -> io::Result<()> {
use std::borrow::Borrow; use std::borrow::Borrow;
let primary_span = suggestion.substitutes[0].0; let primary_span = suggestion.substitution_spans().next().unwrap();
if let Some(ref cm) = self.cm { if let Some(ref cm) = self.cm {
let mut buffer = StyledBuffer::new(); let mut buffer = StyledBuffer::new();

View file

@ -23,6 +23,7 @@
#![feature(staged_api)] #![feature(staged_api)]
#![feature(range_contains)] #![feature(range_contains)]
#![feature(libc)] #![feature(libc)]
#![feature(conservative_impl_trait)]
extern crate term; extern crate term;
extern crate libc; extern crate libc;
@ -83,10 +84,17 @@ pub struct CodeSuggestion {
/// ``` /// ```
/// vec![(0..7, vec!["a.b", "x.y"])] /// vec![(0..7, vec!["a.b", "x.y"])]
/// ``` /// ```
pub substitutes: Vec<(Span, Vec<String>)>, pub substitution_parts: Vec<Substitution>,
pub msg: String, pub msg: String,
} }
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
/// See the docs on `CodeSuggestion::substitutions`
pub struct Substitution {
pub span: Span,
pub substitutions: Vec<String>,
}
pub trait CodeMapper { pub trait CodeMapper {
fn lookup_char_pos(&self, pos: BytePos) -> Loc; fn lookup_char_pos(&self, pos: BytePos) -> Loc;
fn span_to_lines(&self, sp: Span) -> FileLinesResult; fn span_to_lines(&self, sp: Span) -> FileLinesResult;
@ -96,6 +104,16 @@ pub trait CodeMapper {
} }
impl CodeSuggestion { impl CodeSuggestion {
/// Returns the number of substitutions
fn substitutions(&self) -> usize {
self.substitution_parts[0].substitutions.len()
}
/// Returns the number of substitutions
pub fn substitution_spans<'a>(&'a self) -> impl Iterator<Item = Span> + 'a {
self.substitution_parts.iter().map(|sub| sub.span)
}
/// Returns the assembled code suggestions. /// Returns the assembled code suggestions.
pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<String> { pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<String> {
use syntax_pos::{CharPos, Loc, Pos}; use syntax_pos::{CharPos, Loc, Pos};
@ -119,13 +137,13 @@ impl CodeSuggestion {
} }
} }
if self.substitutes.is_empty() { if self.substitution_parts.is_empty() {
return vec![String::new()]; return vec![String::new()];
} }
let mut primary_spans: Vec<_> = self.substitutes let mut primary_spans: Vec<_> = self.substitution_parts
.iter() .iter()
.map(|&(sp, ref sub)| (sp, sub)) .map(|sub| (sub.span, &sub.substitutions))
.collect(); .collect();
// Assumption: all spans are in the same file, and all spans // Assumption: all spans are in the same file, and all spans
@ -157,7 +175,7 @@ impl CodeSuggestion {
prev_hi.col = CharPos::from_usize(0); prev_hi.col = CharPos::from_usize(0);
let mut prev_line = fm.get_line(lines.lines[0].line_index); let mut prev_line = fm.get_line(lines.lines[0].line_index);
let mut bufs = vec![String::new(); self.substitutes[0].1.len()]; let mut bufs = vec![String::new(); self.substitutions()];
for (sp, substitutes) in primary_spans { for (sp, substitutes) in primary_spans {
let cur_lo = cm.lookup_char_pos(sp.lo); let cur_lo = cm.lookup_char_pos(sp.lo);

View file

@ -279,12 +279,12 @@ impl DiagnosticSpan {
fn from_suggestion(suggestion: &CodeSuggestion, je: &JsonEmitter) fn from_suggestion(suggestion: &CodeSuggestion, je: &JsonEmitter)
-> Vec<DiagnosticSpan> { -> Vec<DiagnosticSpan> {
suggestion.substitutes suggestion.substitution_parts
.iter() .iter()
.flat_map(|&(span, ref suggestion)| { .flat_map(|substitution| {
suggestion.iter().map(move |suggestion| { substitution.substitutions.iter().map(move |suggestion| {
let span_label = SpanLabel { let span_label = SpanLabel {
span, span: substitution.span,
is_primary: true, is_primary: true,
label: None, label: None,
}; };
@ -301,7 +301,7 @@ impl DiagnosticSpan {
RenderSpan::FullSpan(ref msp) => RenderSpan::FullSpan(ref msp) =>
DiagnosticSpan::from_multispan(msp, je), DiagnosticSpan::from_multispan(msp, je),
// regular diagnostics don't produce this anymore // regular diagnostics don't produce this anymore
// will be removed in a later commit // FIXME(oli_obk): remove it entirely
RenderSpan::Suggestion(_) => unreachable!(), RenderSpan::Suggestion(_) => unreachable!(),
} }
} }