use CodeSuggestion;
use Level;
use RenderSpan;
-use RenderSpan::Suggestion;
use std::fmt;
use syntax_pos::{MultiSpan, Span};
use snippet::Style;
pub code: Option<String>,
pub span: MultiSpan,
pub children: Vec<SubDiagnostic>,
+ pub suggestion: Option<CodeSuggestion>,
}
/// For example a note attached to an error.
code: code,
span: MultiSpan::new(),
children: vec![],
+ suggestion: None,
}
}
/// Prints out a message with a suggested edit of the code.
///
- /// See `diagnostic::RenderSpan::Suggestion` for more information.
- pub fn span_suggestion<S: Into<MultiSpan>>(&mut self,
- sp: S,
- msg: &str,
- suggestion: String)
- -> &mut Self {
- self.sub(Level::Help,
- msg,
- MultiSpan::new(),
- Some(Suggestion(CodeSuggestion {
- msp: sp.into(),
- substitutes: vec![suggestion],
- })));
+ /// See `diagnostic::CodeSuggestion` for more information.
+ pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
+ assert!(self.suggestion.is_none());
+ self.suggestion = Some(CodeSuggestion {
+ msp: sp.into(),
+ substitutes: vec![suggestion],
+ msg: msg.to_owned(),
+ });
self
}
sp: S,
msg: &str)
-> &mut Self);
- forward!(pub fn span_suggestion<S: Into<MultiSpan>>(&mut self,
- sp: S,
- msg: &str,
- suggestion: String)
- -> &mut Self);
+ forward!(pub fn span_suggestion(&mut self,
+ sp: Span,
+ msg: &str,
+ suggestion: String)
+ -> &mut Self);
forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
forward!(pub fn code(&mut self, s: String) -> &mut Self);
fn emit(&mut self, db: &DiagnosticBuilder) {
let mut primary_span = db.span.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.emit_messages_default(&db.level,
&db.styled_message(),
/// displayed, keeping the provided highlighting.
fn msg_to_buffer(&self,
buffer: &mut StyledBuffer,
- msg: &Vec<(String, Style)>,
+ msg: &[(String, Style)],
padding: usize,
label: &str,
override_style: Option<Style>) {
fn emit_suggestion_default(&mut self,
suggestion: &CodeSuggestion,
level: &Level,
- msg: &Vec<(String, Style)>,
max_line_num_len: usize)
-> io::Result<()> {
use std::borrow::Borrow;
buffer.append(0, &level.to_string(), Style::Level(level.clone()));
buffer.append(0, ": ", Style::HeaderMsg);
self.msg_to_buffer(&mut buffer,
- msg,
+ &[(suggestion.msg.to_owned(), Style::NoStyle)],
max_line_num_len,
"suggestion",
Some(Style::HeaderMsg));
Some(Suggestion(ref cs)) => {
match self.emit_suggestion_default(cs,
&child.level,
- &child.styled_message(),
max_line_num_len) {
Err(e) => panic!("failed to emit error: {}", e),
_ => ()
pub struct CodeSuggestion {
pub msp: MultiSpan,
pub substitutes: Vec<String>,
+ pub msg: String,
}
pub trait CodeMapper {
let snip = tcx.sess.codemap().span_to_snippet(base.span);
if let Ok(snip) = snip {
err.span_suggestion(expr.span,
- "to access tuple elements, \
- use tuple indexing syntax \
- as shown",
+ "to access tuple elements, use",
format!("{}.{}", snip, i));
needs_note = false;
}
use codemap::CodeMap;
use syntax_pos::{self, MacroBacktrace, Span, SpanLabel, MultiSpan};
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::snippet::Style;
use std::rc::Rc;
use std::io::{self, Write};
fn from_diagnostic_builder(db: &DiagnosticBuilder,
je: &JsonEmitter)
-> 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 {
message: db.message(),
code: DiagnosticCode::map_opt_string(db.code.clone(), je),
level: db.level.to_str(),
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)
}).collect(),
rendered: None,