From fc774e629fd805ef46566894da482ed8be680303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 11 Jan 2017 13:55:41 -0800 Subject: [PATCH] Teach Diagnostics to highlight text --- src/librustc/lint/context.rs | 2 +- src/librustc_driver/test.rs | 4 +- src/librustc_errors/diagnostic.rs | 56 ++++++++-- src/librustc_errors/emitter.rs | 101 +++++++++++++----- src/librustc_errors/snippet.rs | 1 + src/librustc_trans/back/write.rs | 4 +- src/libsyntax/json.rs | 20 ++-- .../proc-macro/signature.rs | 1 - src/test/compile-fail/issue-27942.rs | 2 - src/test/compile-fail/issue-37884.rs | 1 - .../reordered-type-param.stderr | 2 +- .../mismatched_types}/E0053.rs | 0 src/test/ui/mismatched_types/E0053.stderr | 23 ++++ .../mismatched_types}/E0409.rs | 0 src/test/ui/mismatched_types/E0409.stderr | 19 ++++ .../mismatched_types}/issue-19109.rs | 0 .../ui/mismatched_types/issue-19109.stderr | 11 ++ .../ui/mismatched_types/issue-35030.stderr | 2 +- .../ui/mismatched_types/issue-38371.stderr | 6 +- src/test/ui/mismatched_types/main.stderr | 2 +- .../mismatched_types}/overloaded-calls-bad.rs | 0 .../overloaded-calls-bad.stderr | 23 ++++ .../trait-bounds-cant-coerce.rs | 0 .../trait-bounds-cant-coerce.stderr | 11 ++ .../trait-impl-fn-incompatibility.stderr | 2 +- .../ui/resolve/token-error-correct-3.stderr | 2 +- src/test/ui/span/coerce-suggestions.stderr | 10 +- src/test/ui/span/issue-27522.stderr | 2 +- src/test/ui/span/move-closure.stderr | 2 +- 29 files changed, 242 insertions(+), 67 deletions(-) rename src/test/{compile-fail => ui/mismatched_types}/E0053.rs (100%) create mode 100644 src/test/ui/mismatched_types/E0053.stderr rename src/test/{compile-fail => ui/mismatched_types}/E0409.rs (100%) create mode 100644 src/test/ui/mismatched_types/E0409.stderr rename src/test/{compile-fail => ui/mismatched_types}/issue-19109.rs (100%) create mode 100644 src/test/ui/mismatched_types/issue-19109.stderr rename src/test/{compile-fail => ui/mismatched_types}/overloaded-calls-bad.rs (100%) create mode 100644 src/test/ui/mismatched_types/overloaded-calls-bad.stderr rename src/test/{compile-fail => ui/mismatched_types}/trait-bounds-cant-coerce.rs (100%) create mode 100644 src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 7d85f3607b597..4b731ed7a706a 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -562,7 +562,7 @@ pub trait LintContext<'tcx>: Sized { let span = early_lint.diagnostic.span.primary_span().expect("early lint w/o primary span"); let mut err = self.struct_span_lint(early_lint.id.lint, span, - &early_lint.diagnostic.message); + &early_lint.diagnostic.message()); err.copy_details_not_message(&early_lint.diagnostic); err.emit(); } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index ede35d052ad51..4ce5f96f171ed 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -79,9 +79,9 @@ fn remove_message(e: &mut ExpectErrorEmitter, msg: &str, lvl: Level) { impl Emitter for ExpectErrorEmitter { fn emit(&mut self, db: &DiagnosticBuilder) { - remove_message(self, &db.message, db.level); + remove_message(self, &db.message(), db.level); for child in &db.children { - remove_message(self, &child.message, child.level); + remove_message(self, &child.message(), child.level); } } } diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 730ca8f9e2e44..ac39af2018998 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -14,12 +14,13 @@ use RenderSpan; use RenderSpan::Suggestion; use std::fmt; use syntax_pos::{MultiSpan, Span}; +use snippet::Style; #[must_use] #[derive(Clone, Debug, PartialEq)] pub struct Diagnostic { pub level: Level, - pub message: String, + pub message: Vec<(String, Style)>, pub code: Option, pub span: MultiSpan, pub children: Vec, @@ -29,7 +30,7 @@ pub struct Diagnostic { #[derive(Clone, Debug, PartialEq)] pub struct SubDiagnostic { pub level: Level, - pub message: String, + pub message: Vec<(String, Style)>, pub span: MultiSpan, pub render_span: Option, } @@ -42,7 +43,7 @@ impl Diagnostic { pub fn new_with_code(level: Level, code: Option, message: &str) -> Self { Diagnostic { level: level, - message: message.to_owned(), + message: vec![(message.to_owned(), Style::NoStyle)], code: code, span: MultiSpan::new(), children: vec![], @@ -96,8 +97,14 @@ impl Diagnostic { -> &mut Self { // For now, just attach these as notes - self.note(&format!("expected {} `{}`{}", label, expected, expected_extra)); - self.note(&format!(" found {} `{}`{}", label, found, found_extra)); + self.highlighted_note(vec![ + (format!("expected {} `", label), Style::NoStyle), + (format!("{}", expected), Style::Highlight), + (format!("`{}\n", expected_extra), Style::NoStyle), + (format!(" found {} `", label), Style::NoStyle), + (format!("{}", found), Style::Highlight), + (format!("`{}", found_extra), Style::NoStyle), + ]); self } @@ -106,6 +113,11 @@ impl Diagnostic { self } + pub fn highlighted_note(&mut self, msg: Vec<(String, Style)>) -> &mut Self { + self.sub_with_highlights(Level::Note, msg, MultiSpan::new(), None); + self + } + pub fn span_note>(&mut self, sp: S, msg: &str) @@ -168,7 +180,11 @@ impl Diagnostic { self } - pub fn message(&self) -> &str { + pub fn message(&self) -> String { + self.message.iter().map(|i| i.0.to_owned()).collect::() + } + + pub fn styled_message(&self) -> &Vec<(String, Style)> { &self.message } @@ -193,10 +209,36 @@ impl Diagnostic { render_span: Option) { let sub = SubDiagnostic { level: level, - message: message.to_owned(), + message: vec![(message.to_owned(), Style::NoStyle)], span: span, render_span: render_span, }; self.children.push(sub); } + + /// Convenience function for internal use, clients should use one of the + /// public methods above. + fn sub_with_highlights(&mut self, + level: Level, + message: Vec<(String, Style)>, + span: MultiSpan, + render_span: Option) { + let sub = SubDiagnostic { + level: level, + message: message, + span: span, + render_span: render_span, + }; + self.children.push(sub); + } +} + +impl SubDiagnostic { + pub fn message(&self) -> String { + self.message.iter().map(|i| i.0.to_owned()).collect::() + } + + pub fn styled_message(&self) -> &Vec<(String, Style)> { + &self.message + } } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 77c6c36836417..5d758d322c748 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -33,7 +33,11 @@ impl Emitter for EmitterWriter { let mut primary_span = db.span.clone(); let mut children = db.children.clone(); self.fix_multispans_in_std_macros(&mut primary_span, &mut children); - self.emit_messages_default(&db.level, &db.message, &db.code, &primary_span, &children); + self.emit_messages_default(&db.level, + &db.styled_message(), + &db.code, + &primary_span, + &children); } } @@ -695,8 +699,8 @@ impl EmitterWriter { if spans_updated { children.push(SubDiagnostic { level: Level::Note, - message: "this error originates in a macro outside of the current crate" - .to_string(), + message: vec![("this error originates in a macro outside of the current crate" + .to_string(), Style::NoStyle)], span: MultiSpan::new(), render_span: None, }); @@ -704,8 +708,14 @@ impl EmitterWriter { } /// Add a left margin to every line but the first, given a padding length and the label being - /// displayed. - fn msg_with_padding(&self, msg: &str, padding: usize, label: &str) -> String { + /// displayed, keeping the provided highlighting. + fn msg_to_buffer(&self, + buffer: &mut StyledBuffer, + msg: &Vec<(String, Style)>, + padding: usize, + label: &str, + override_style: Option