From 84ccbe2076cf37bc13c32a89ccc57a57281b8708 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 1 Sep 2019 12:15:33 +0200 Subject: [PATCH] librustc_errors: Extract sugg/subst handling into method An initial refactoring before working on #61809. This moves the whole block into a method so that it can be reused in the annotate-snippet output. It's already used in the new emitter, but there's no UI tests with suggestions included in this PR. A first look at some UI tests with suggestions showed that there's some more work to do in [annotate-snippet-rs][annotate-snippet-rs] before the new output is closer to the current one. --- .../annotate_snippet_emitter_writer.rs | 4 +- src/librustc_errors/emitter.rs | 40 ++++++++++++++----- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs index 255af3122e70c..3bed5d81dc514 100644 --- a/src/librustc_errors/annotate_snippet_emitter_writer.rs +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -30,10 +30,8 @@ pub struct AnnotateSnippetEmitterWriter { impl Emitter for AnnotateSnippetEmitterWriter { /// The entry point for the diagnostics generation fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { - let primary_span = db.span.clone(); let children = db.children.clone(); - // FIXME(#59346): Collect suggestions (see emitter.rs) - let suggestions: &[_] = &[]; + let (primary_span, suggestions) = self.primary_span_formatted(&db); // FIXME(#59346): Add `fix_multispans_in_std_macros` function from emitter.rs diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 77d373e7a8ca8..0a9c927ef40a1 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -191,16 +191,25 @@ pub trait Emitter { fn should_show_explain(&self) -> bool { true } -} -impl Emitter for EmitterWriter { - fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { + /// Formats the substitutions of the primary_span + /// + /// The are a lot of conditions to this method, but in short: + /// + /// * If the current `Diagnostic` has only one visible `CodeSuggestion`, + /// we format the `help` suggestion depending on the content of the + /// substitutions. In that case, we return the modified span only. + /// + /// * If the current `Diagnostic` has multiple suggestions, + /// we return the original `primary_span` and the original suggestions. + fn primary_span_formatted<'a>( + &mut self, + db: &'a DiagnosticBuilder<'_> + ) -> (MultiSpan, &'a [CodeSuggestion]) { let mut primary_span = db.span.clone(); - let mut children = db.children.clone(); - let mut suggestions: &[_] = &[]; - if let Some((sugg, rest)) = db.suggestions.split_first() { if rest.is_empty() && + // ^ if there is only one suggestion // don't display multi-suggestions as labels sugg.substitutions.len() == 1 && // don't display multipart suggestions as labels @@ -216,21 +225,34 @@ impl Emitter for EmitterWriter { { let substitution = &sugg.substitutions[0].parts[0].snippet.trim(); let msg = if substitution.len() == 0 || sugg.style.hide_inline() { - // This substitution is only removal or we explicitly don't want to show the - // code inline, don't show it + // This substitution is only removal OR we explicitly don't want to show the + // code inline (`hide_inline`). Therefore, we don't show the substitution. format!("help: {}", sugg.msg) } else { + // Show the default suggestion text with the substitution format!("help: {}: `{}`", sugg.msg, substitution) }; primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg); + + // We return only the modified primary_span + (primary_span, &[]) } else { // if there are multiple suggestions, print them all in full // to be consistent. We could try to figure out if we can // make one (or the first one) inline, but that would give // undue importance to a semi-random suggestion - suggestions = &db.suggestions; + (primary_span, &db.suggestions) } + } else { + (primary_span, &db.suggestions) } + } +} + +impl Emitter for EmitterWriter { + fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { + let mut children = db.children.clone(); + let (mut primary_span, suggestions) = self.primary_span_formatted(&db); self.fix_multispans_in_std_macros(&mut primary_span, &mut children,