Use multipart_suggestions
This records that the suggestions are mutually-exclusive (i.e., only one should be applied).
This commit is contained in:
parent
ef74796178
commit
725cde42d5
3 changed files with 54 additions and 60 deletions
|
@ -218,6 +218,27 @@ impl std::fmt::Display for UnaryFixity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MultiSugg {
|
||||||
|
msg: String,
|
||||||
|
patches: Vec<(Span, String)>,
|
||||||
|
applicability: Applicability,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MultiSugg {
|
||||||
|
fn emit(self, err: &mut DiagnosticBuilder<'_>) {
|
||||||
|
err.multipart_suggestion(&self.msg, self.patches, self.applicability);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Overrides individual messages and applicabilities.
|
||||||
|
fn emit_many(
|
||||||
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
|
msg: &str,
|
||||||
|
applicability: Applicability,
|
||||||
|
suggestions: impl Iterator<Item = Self>,
|
||||||
|
) {
|
||||||
|
err.multipart_suggestions(msg, suggestions.map(|s| s.patches), applicability);
|
||||||
|
}
|
||||||
|
}
|
||||||
// SnapshotParser is used to create a snapshot of the parser
|
// SnapshotParser is used to create a snapshot of the parser
|
||||||
// without causing duplicate errors being emitted when the `Parser`
|
// without causing duplicate errors being emitted when the `Parser`
|
||||||
// is dropped.
|
// is dropped.
|
||||||
|
@ -1281,33 +1302,33 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
match kind.standalone {
|
match kind.standalone {
|
||||||
IsStandalone::Standalone => {
|
IsStandalone::Standalone => self.inc_dec_standalone_suggest(kind, spans).emit(&mut err),
|
||||||
self.inc_dec_standalone_recovery(&mut err, kind, spans, false)
|
|
||||||
}
|
|
||||||
IsStandalone::Subexpr => {
|
IsStandalone::Subexpr => {
|
||||||
let Ok(base_src) = self.span_to_snippet(base.span)
|
let Ok(base_src) = self.span_to_snippet(base.span)
|
||||||
else { return help_base_case(err, base) };
|
else { return help_base_case(err, base) };
|
||||||
match kind.fixity {
|
match kind.fixity {
|
||||||
UnaryFixity::Pre => {
|
UnaryFixity::Pre => {
|
||||||
self.prefix_inc_dec_suggest(base_src, &mut err, kind, spans)
|
self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
|
||||||
}
|
}
|
||||||
UnaryFixity::Post => {
|
UnaryFixity::Post => {
|
||||||
self.postfix_inc_dec_suggest(base_src, &mut err, kind, spans)
|
self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IsStandalone::Maybe => {
|
IsStandalone::Maybe => {
|
||||||
let Ok(base_src) = self.span_to_snippet(base.span)
|
let Ok(base_src) = self.span_to_snippet(base.span)
|
||||||
else { return help_base_case(err, base) };
|
else { return help_base_case(err, base) };
|
||||||
match kind.fixity {
|
let sugg1 = match kind.fixity {
|
||||||
UnaryFixity::Pre => {
|
UnaryFixity::Pre => self.prefix_inc_dec_suggest(base_src, kind, spans),
|
||||||
self.prefix_inc_dec_suggest(base_src, &mut err, kind, spans)
|
UnaryFixity::Post => self.postfix_inc_dec_suggest(base_src, kind, spans),
|
||||||
}
|
};
|
||||||
UnaryFixity::Post => {
|
let sugg2 = self.inc_dec_standalone_suggest(kind, spans);
|
||||||
self.postfix_inc_dec_suggest(base_src, &mut err, kind, spans)
|
MultiSugg::emit_many(
|
||||||
}
|
&mut err,
|
||||||
}
|
"use `+= 1` instead",
|
||||||
self.inc_dec_standalone_recovery(&mut err, kind, spans, true)
|
Applicability::MaybeIncorrect,
|
||||||
|
[sugg1, sugg2].into_iter(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err)
|
Err(err)
|
||||||
|
@ -1316,61 +1337,46 @@ impl<'a> Parser<'a> {
|
||||||
fn prefix_inc_dec_suggest(
|
fn prefix_inc_dec_suggest(
|
||||||
&mut self,
|
&mut self,
|
||||||
base_src: String,
|
base_src: String,
|
||||||
err: &mut DiagnosticBuilder<'a>,
|
|
||||||
kind: IncDecRecovery,
|
kind: IncDecRecovery,
|
||||||
(pre_span, post_span): (Span, Span),
|
(pre_span, post_span): (Span, Span),
|
||||||
) {
|
) -> MultiSugg {
|
||||||
err.multipart_suggestion(
|
MultiSugg {
|
||||||
&format!("use `{}= 1` instead", kind.op.chr()),
|
msg: format!("use `{}= 1` instead", kind.op.chr()),
|
||||||
vec![
|
patches: vec![
|
||||||
(pre_span, "{ ".to_string()),
|
(pre_span, "{ ".to_string()),
|
||||||
(post_span, format!(" {}= 1; {} }}", kind.op.chr(), base_src)),
|
(post_span, format!(" {}= 1; {} }}", kind.op.chr(), base_src)),
|
||||||
],
|
],
|
||||||
Applicability::MachineApplicable,
|
applicability: Applicability::MachineApplicable,
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn postfix_inc_dec_suggest(
|
fn postfix_inc_dec_suggest(
|
||||||
&mut self,
|
&mut self,
|
||||||
base_src: String,
|
base_src: String,
|
||||||
err: &mut DiagnosticBuilder<'a>,
|
|
||||||
kind: IncDecRecovery,
|
kind: IncDecRecovery,
|
||||||
(pre_span, post_span): (Span, Span),
|
(pre_span, post_span): (Span, Span),
|
||||||
) {
|
) -> MultiSugg {
|
||||||
let tmp_var = if base_src.trim() == "tmp" { "tmp_" } else { "tmp" };
|
let tmp_var = if base_src.trim() == "tmp" { "tmp_" } else { "tmp" };
|
||||||
err.multipart_suggestion(
|
MultiSugg {
|
||||||
&format!("use `{}= 1` instead", kind.op.chr()),
|
msg: format!("use `{}= 1` instead", kind.op.chr()),
|
||||||
vec![
|
patches: vec![
|
||||||
(pre_span, format!("{{ let {} = ", tmp_var)),
|
(pre_span, format!("{{ let {} = ", tmp_var)),
|
||||||
(post_span, format!("; {} {}= 1; {} }}", base_src, kind.op.chr(), tmp_var)),
|
(post_span, format!("; {} {}= 1; {} }}", base_src, kind.op.chr(), tmp_var)),
|
||||||
],
|
],
|
||||||
Applicability::HasPlaceholders,
|
applicability: Applicability::HasPlaceholders,
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inc_dec_standalone_recovery(
|
fn inc_dec_standalone_suggest(
|
||||||
&mut self,
|
&mut self,
|
||||||
err: &mut DiagnosticBuilder<'a>,
|
|
||||||
kind: IncDecRecovery,
|
kind: IncDecRecovery,
|
||||||
(pre_span, post_span): (Span, Span),
|
(pre_span, post_span): (Span, Span),
|
||||||
maybe_not_standalone: bool,
|
) -> MultiSugg {
|
||||||
) {
|
MultiSugg {
|
||||||
let msg = if maybe_not_standalone {
|
msg: format!("use `{}= 1` instead", kind.op.chr()),
|
||||||
"or, if you don't need to use it as an expression, change it to this".to_owned()
|
patches: vec![(pre_span, String::new()), (post_span, format!(" {}= 1", kind.op.chr()))],
|
||||||
} else {
|
applicability: Applicability::MachineApplicable,
|
||||||
format!("use `{}= 1` instead", kind.op.chr())
|
}
|
||||||
};
|
|
||||||
let applicability = if maybe_not_standalone {
|
|
||||||
// FIXME: Unspecified isn't right, but it's the least wrong option
|
|
||||||
Applicability::Unspecified
|
|
||||||
} else {
|
|
||||||
Applicability::MachineApplicable
|
|
||||||
};
|
|
||||||
err.multipart_suggestion(
|
|
||||||
&msg,
|
|
||||||
vec![(pre_span, String::new()), (post_span, format!(" {}= 1", kind.op.chr()))],
|
|
||||||
applicability,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`.
|
/// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`.
|
||||||
|
|
|
@ -8,8 +8,6 @@ help: use `+= 1` instead
|
||||||
|
|
|
|
||||||
LL | { let tmp = i; i += 1; tmp };
|
LL | { let tmp = i; i += 1; tmp };
|
||||||
| +++++++++++ ~~~~~~~~~~~~~~~
|
| +++++++++++ ~~~~~~~~~~~~~~~
|
||||||
help: or, if you don't need to use it as an expression, change it to this
|
|
||||||
|
|
|
||||||
LL - i++;
|
LL - i++;
|
||||||
LL + i += 1;
|
LL + i += 1;
|
||||||
|
|
|
|
||||||
|
@ -24,8 +22,6 @@ help: use `+= 1` instead
|
||||||
|
|
|
|
||||||
LL | while { let tmp = i; i += 1; tmp } < 5 {
|
LL | while { let tmp = i; i += 1; tmp } < 5 {
|
||||||
| +++++++++++ ~~~~~~~~~~~~~~~
|
| +++++++++++ ~~~~~~~~~~~~~~~
|
||||||
help: or, if you don't need to use it as an expression, change it to this
|
|
||||||
|
|
|
||||||
LL - while i++ < 5 {
|
LL - while i++ < 5 {
|
||||||
LL + while i += 1 < 5 {
|
LL + while i += 1 < 5 {
|
||||||
|
|
|
|
||||||
|
@ -40,8 +36,6 @@ help: use `+= 1` instead
|
||||||
|
|
|
|
||||||
LL | { let tmp_ = tmp; tmp += 1; tmp_ };
|
LL | { let tmp_ = tmp; tmp += 1; tmp_ };
|
||||||
| ++++++++++++ ~~~~~~~~~~~~~~~~~~
|
| ++++++++++++ ~~~~~~~~~~~~~~~~~~
|
||||||
help: or, if you don't need to use it as an expression, change it to this
|
|
||||||
|
|
|
||||||
LL - tmp++;
|
LL - tmp++;
|
||||||
LL + tmp += 1;
|
LL + tmp += 1;
|
||||||
|
|
|
|
||||||
|
@ -56,8 +50,6 @@ help: use `+= 1` instead
|
||||||
|
|
|
|
||||||
LL | while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
|
LL | while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
|
||||||
| ++++++++++++ ~~~~~~~~~~~~~~~~~~
|
| ++++++++++++ ~~~~~~~~~~~~~~~~~~
|
||||||
help: or, if you don't need to use it as an expression, change it to this
|
|
||||||
|
|
|
||||||
LL - while tmp++ < 5 {
|
LL - while tmp++ < 5 {
|
||||||
LL + while tmp += 1 < 5 {
|
LL + while tmp += 1 < 5 {
|
||||||
|
|
|
|
||||||
|
|
|
@ -8,8 +8,6 @@ help: use `+= 1` instead
|
||||||
|
|
|
|
||||||
LL | { let tmp = foo.bar.qux; foo.bar.qux += 1; tmp };
|
LL | { let tmp = foo.bar.qux; foo.bar.qux += 1; tmp };
|
||||||
| +++++++++++ ~~~~~~~~~~~~~~~~~~~~~~~~~
|
| +++++++++++ ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
help: or, if you don't need to use it as an expression, change it to this
|
|
||||||
|
|
|
||||||
LL - foo.bar.qux++;
|
LL - foo.bar.qux++;
|
||||||
LL + foo.bar.qux += 1;
|
LL + foo.bar.qux += 1;
|
||||||
|
|
|
|
||||||
|
@ -24,8 +22,6 @@ help: use `+= 1` instead
|
||||||
|
|
|
|
||||||
LL | { let tmp = s.tmp; s.tmp += 1; tmp };
|
LL | { let tmp = s.tmp; s.tmp += 1; tmp };
|
||||||
| +++++++++++ ~~~~~~~~~~~~~~~~~~~
|
| +++++++++++ ~~~~~~~~~~~~~~~~~~~
|
||||||
help: or, if you don't need to use it as an expression, change it to this
|
|
||||||
|
|
|
||||||
LL - s.tmp++;
|
LL - s.tmp++;
|
||||||
LL + s.tmp += 1;
|
LL + s.tmp += 1;
|
||||||
|
|
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue