Minimize single span suggestions into a note
This commit is contained in:
parent
0777c757a6
commit
0e920fde4f
6 changed files with 47 additions and 28 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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),
|
||||||
_ => ()
|
_ => ()
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue