1
Fork 0

Minimize single span suggestions into a note

This commit is contained in:
Oliver Schneider 2017-03-24 17:31:41 +01:00
parent 0777c757a6
commit 0e920fde4f
No known key found for this signature in database
GPG key ID: A69F8D225B3AD7D9
6 changed files with 47 additions and 28 deletions

View file

@ -11,7 +11,6 @@
use CodeSuggestion; use CodeSuggestion;
use Level; use Level;
use RenderSpan; use RenderSpan;
use RenderSpan::Suggestion;
use std::fmt; use std::fmt;
use syntax_pos::{MultiSpan, Span}; use syntax_pos::{MultiSpan, Span};
use snippet::Style; use snippet::Style;
@ -24,6 +23,7 @@ pub struct Diagnostic {
pub code: Option<String>, pub code: Option<String>,
pub span: MultiSpan, pub span: MultiSpan,
pub children: Vec<SubDiagnostic>, pub children: Vec<SubDiagnostic>,
pub suggestion: Option<CodeSuggestion>,
} }
/// For example a note attached to an error. /// For example a note attached to an error.
@ -87,6 +87,7 @@ impl Diagnostic {
code: code, code: code,
span: MultiSpan::new(), span: MultiSpan::new(),
children: vec![], children: vec![],
suggestion: None,
} }
} }
@ -202,19 +203,14 @@ impl Diagnostic {
/// Prints out a message with a suggested edit of the code. /// Prints out a message with a suggested edit of the code.
/// ///
/// See `diagnostic::RenderSpan::Suggestion` for more information. /// See `diagnostic::CodeSuggestion` for more information.
pub fn span_suggestion<S: Into<MultiSpan>>(&mut self, pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
sp: S, assert!(self.suggestion.is_none());
msg: &str, self.suggestion = Some(CodeSuggestion {
suggestion: String)
-> &mut Self {
self.sub(Level::Help,
msg,
MultiSpan::new(),
Some(Suggestion(CodeSuggestion {
msp: sp.into(), msp: sp.into(),
substitutes: vec![suggestion], substitutes: vec![suggestion],
}))); msg: msg.to_owned(),
});
self self
} }

View file

@ -141,8 +141,8 @@ impl<'a> DiagnosticBuilder<'a> {
sp: S, sp: S,
msg: &str) msg: &str)
-> &mut Self); -> &mut Self);
forward!(pub fn span_suggestion<S: Into<MultiSpan>>(&mut self, forward!(pub fn span_suggestion(&mut self,
sp: S, sp: Span,
msg: &str, msg: &str,
suggestion: String) suggestion: String)
-> &mut Self); -> &mut Self);

View file

@ -34,6 +34,22 @@ impl Emitter for EmitterWriter {
fn emit(&mut self, db: &DiagnosticBuilder) { fn emit(&mut self, db: &DiagnosticBuilder) {
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 let Some(sugg) = db.suggestion.clone() {
assert_eq!(sugg.msp.primary_spans().len(), sugg.substitutes.len());
if sugg.substitutes.len() == 1 {
let msg = format!("{} `{}`", sugg.msg, sugg.substitutes[0]);
primary_span.push_span_label(sugg.msp.primary_spans()[0], msg);
} else {
children.push(SubDiagnostic {
level: Level::Help,
message: Vec::new(),
span: MultiSpan::new(),
render_span: Some(Suggestion(sugg)),
});
}
}
self.fix_multispans_in_std_macros(&mut primary_span, &mut children); self.fix_multispans_in_std_macros(&mut primary_span, &mut children);
self.emit_messages_default(&db.level, self.emit_messages_default(&db.level,
&db.styled_message(), &db.styled_message(),
@ -756,7 +772,7 @@ impl EmitterWriter {
/// displayed, keeping the provided highlighting. /// displayed, keeping the provided highlighting.
fn msg_to_buffer(&self, fn msg_to_buffer(&self,
buffer: &mut StyledBuffer, buffer: &mut StyledBuffer,
msg: &Vec<(String, Style)>, msg: &[(String, Style)],
padding: usize, padding: usize,
label: &str, label: &str,
override_style: Option<Style>) { override_style: Option<Style>) {
@ -1022,7 +1038,6 @@ impl EmitterWriter {
fn emit_suggestion_default(&mut self, fn emit_suggestion_default(&mut self,
suggestion: &CodeSuggestion, suggestion: &CodeSuggestion,
level: &Level, level: &Level,
msg: &Vec<(String, Style)>,
max_line_num_len: usize) max_line_num_len: usize)
-> io::Result<()> { -> io::Result<()> {
use std::borrow::Borrow; use std::borrow::Borrow;
@ -1034,7 +1049,7 @@ impl EmitterWriter {
buffer.append(0, &level.to_string(), Style::Level(level.clone())); buffer.append(0, &level.to_string(), Style::Level(level.clone()));
buffer.append(0, ": ", Style::HeaderMsg); buffer.append(0, ": ", Style::HeaderMsg);
self.msg_to_buffer(&mut buffer, self.msg_to_buffer(&mut buffer,
msg, &[(suggestion.msg.to_owned(), Style::NoStyle)],
max_line_num_len, max_line_num_len,
"suggestion", "suggestion",
Some(Style::HeaderMsg)); Some(Style::HeaderMsg));
@ -1099,7 +1114,6 @@ impl EmitterWriter {
Some(Suggestion(ref cs)) => { Some(Suggestion(ref cs)) => {
match self.emit_suggestion_default(cs, match self.emit_suggestion_default(cs,
&child.level, &child.level,
&child.styled_message(),
max_line_num_len) { max_line_num_len) {
Err(e) => panic!("failed to emit error: {}", e), Err(e) => panic!("failed to emit error: {}", e),
_ => () _ => ()

View file

@ -67,6 +67,7 @@ pub enum RenderSpan {
pub struct CodeSuggestion { pub struct CodeSuggestion {
pub msp: MultiSpan, pub msp: MultiSpan,
pub substitutes: Vec<String>, pub substitutes: Vec<String>,
pub msg: String,
} }
pub trait CodeMapper { pub trait CodeMapper {

View file

@ -3804,9 +3804,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let snip = tcx.sess.codemap().span_to_snippet(base.span); let snip = tcx.sess.codemap().span_to_snippet(base.span);
if let Ok(snip) = snip { if let Ok(snip) = snip {
err.span_suggestion(expr.span, err.span_suggestion(expr.span,
"to access tuple elements, \ "to access tuple elements, use",
use tuple indexing syntax \
as shown",
format!("{}.{}", snip, i)); format!("{}.{}", snip, i));
needs_note = false; needs_note = false;
} }

View file

@ -22,8 +22,9 @@
use codemap::CodeMap; use codemap::CodeMap;
use syntax_pos::{self, MacroBacktrace, Span, SpanLabel, MultiSpan}; use syntax_pos::{self, MacroBacktrace, Span, SpanLabel, MultiSpan};
use errors::registry::Registry; use errors::registry::Registry;
use errors::{DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion, CodeMapper}; use errors::{Level, DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion, CodeMapper};
use errors::emitter::Emitter; use errors::emitter::Emitter;
use errors::snippet::Style;
use std::rc::Rc; use std::rc::Rc;
use std::io::{self, Write}; use std::io::{self, Write};
@ -152,12 +153,21 @@ impl Diagnostic {
fn from_diagnostic_builder(db: &DiagnosticBuilder, fn from_diagnostic_builder(db: &DiagnosticBuilder,
je: &JsonEmitter) je: &JsonEmitter)
-> Diagnostic { -> Diagnostic {
let sugg = db.suggestion.as_ref().map(|sugg| {
SubDiagnostic {
level: Level::Help,
message: vec![(sugg.msg.clone(), Style::NoStyle)],
span: MultiSpan::new(),
render_span: Some(RenderSpan::Suggestion(sugg.clone())),
}
});
let sugg = sugg.as_ref();
Diagnostic { Diagnostic {
message: db.message(), message: db.message(),
code: DiagnosticCode::map_opt_string(db.code.clone(), je), code: DiagnosticCode::map_opt_string(db.code.clone(), je),
level: db.level.to_str(), level: db.level.to_str(),
spans: DiagnosticSpan::from_multispan(&db.span, je), spans: DiagnosticSpan::from_multispan(&db.span, je),
children: db.children.iter().map(|c| { children: db.children.iter().chain(sugg).map(|c| {
Diagnostic::from_sub_diagnostic(c, je) Diagnostic::from_sub_diagnostic(c, je)
}).collect(), }).collect(),
rendered: None, rendered: None,