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.
This commit is contained in:
Philipp Hansch 2019-09-01 12:15:33 +02:00
parent 2d851b3318
commit 84ccbe2076
No known key found for this signature in database
GPG key ID: 82AA61CAA11397E6
2 changed files with 32 additions and 12 deletions

View file

@ -30,10 +30,8 @@ pub struct AnnotateSnippetEmitterWriter {
impl Emitter for AnnotateSnippetEmitterWriter { impl Emitter for AnnotateSnippetEmitterWriter {
/// The entry point for the diagnostics generation /// The entry point for the diagnostics generation
fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) {
let primary_span = db.span.clone();
let children = db.children.clone(); let children = db.children.clone();
// FIXME(#59346): Collect suggestions (see emitter.rs) let (primary_span, suggestions) = self.primary_span_formatted(&db);
let suggestions: &[_] = &[];
// FIXME(#59346): Add `fix_multispans_in_std_macros` function from emitter.rs // FIXME(#59346): Add `fix_multispans_in_std_macros` function from emitter.rs

View file

@ -191,16 +191,25 @@ pub trait Emitter {
fn should_show_explain(&self) -> bool { fn should_show_explain(&self) -> bool {
true true
} }
}
impl Emitter for EmitterWriter { /// Formats the substitutions of the primary_span
fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { ///
/// 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 primary_span = db.span.clone();
let mut children = db.children.clone();
let mut suggestions: &[_] = &[];
if let Some((sugg, rest)) = db.suggestions.split_first() { if let Some((sugg, rest)) = db.suggestions.split_first() {
if rest.is_empty() && if rest.is_empty() &&
// ^ if there is only one suggestion
// don't display multi-suggestions as labels // don't display multi-suggestions as labels
sugg.substitutions.len() == 1 && sugg.substitutions.len() == 1 &&
// don't display multipart suggestions as labels // 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 substitution = &sugg.substitutions[0].parts[0].snippet.trim();
let msg = if substitution.len() == 0 || sugg.style.hide_inline() { let msg = if substitution.len() == 0 || sugg.style.hide_inline() {
// This substitution is only removal or we explicitly don't want to show the // This substitution is only removal OR we explicitly don't want to show the
// code inline, don't show it // code inline (`hide_inline`). Therefore, we don't show the substitution.
format!("help: {}", sugg.msg) format!("help: {}", sugg.msg)
} else { } else {
// Show the default suggestion text with the substitution
format!("help: {}: `{}`", sugg.msg, substitution) format!("help: {}: `{}`", sugg.msg, substitution)
}; };
primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg); primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg);
// We return only the modified primary_span
(primary_span, &[])
} else { } else {
// if there are multiple suggestions, print them all in full // if there are multiple suggestions, print them all in full
// to be consistent. We could try to figure out if we can // to be consistent. We could try to figure out if we can
// make one (or the first one) inline, but that would give // make one (or the first one) inline, but that would give
// undue importance to a semi-random suggestion // 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, self.fix_multispans_in_std_macros(&mut primary_span,
&mut children, &mut children,