Emit both subexp and standalone sugg for postfix

This solves the TODO.
This commit is contained in:
Noah Lev 2022-02-17 14:52:52 -08:00
parent 7287f929b9
commit 62b8ea67b7
4 changed files with 70 additions and 31 deletions

View File

@ -160,8 +160,10 @@ pub fn no(&self) -> bool {
/// C-style `i++`, `--i`, etc.
#[derive(Debug, Copy, Clone)]
struct IncDecRecovery {
/// This increment/decrement is not a subexpression.
standalone: bool,
/// Is this increment/decrement its own statement?
///
/// This is `None` when we are unsure.
standalone: Option<bool>,
/// Is this an increment or decrement?
op: IncOrDec,
/// Is this pre- or postfix?
@ -1225,7 +1227,7 @@ pub(super) fn maybe_recover_from_prefix_increment(
prev_is_semi: bool,
) -> PResult<'a, P<Expr>> {
let kind = IncDecRecovery {
standalone: prev_is_semi,
standalone: Some(prev_is_semi),
op: IncOrDec::Inc,
fixity: UnaryFixity::Pre,
};
@ -1237,13 +1239,9 @@ pub(super) fn maybe_recover_from_postfix_increment(
&mut self,
operand_expr: P<Expr>,
op_span: Span,
prev_is_semi: bool,
) -> PResult<'a, P<Expr>> {
let kind = IncDecRecovery {
standalone: prev_is_semi,
op: IncOrDec::Inc,
fixity: UnaryFixity::Post,
};
let kind =
IncDecRecovery { standalone: None, op: IncOrDec::Inc, fixity: UnaryFixity::Post };
self.recover_from_inc_dec(operand_expr, kind, op_span)
}
@ -1272,25 +1270,44 @@ fn recover_from_inc_dec(
UnaryFixity::Post => (base.span.shrink_to_lo(), op_span),
};
if kind.standalone {
self.inc_dec_standalone_recovery(err, kind, spans)
} else {
let Ok(base_src) = self.span_to_snippet(base.span)
else { return help_base_case(err, base) };
match kind.fixity {
UnaryFixity::Pre => self.prefix_inc_dec_suggest(base_src, err, kind, spans),
UnaryFixity::Post => self.postfix_inc_dec_suggest(base_src, err, kind, spans),
match kind.standalone {
Some(true) => self.inc_dec_standalone_recovery(&mut err, kind, spans, false),
Some(false) => {
let Ok(base_src) = self.span_to_snippet(base.span)
else { return help_base_case(err, base) };
match kind.fixity {
UnaryFixity::Pre => {
self.prefix_inc_dec_suggest(base_src, &mut err, kind, spans)
}
UnaryFixity::Post => {
self.postfix_inc_dec_suggest(base_src, &mut err, kind, spans)
}
}
}
None => {
let Ok(base_src) = self.span_to_snippet(base.span)
else { return help_base_case(err, base) };
match kind.fixity {
UnaryFixity::Pre => {
self.prefix_inc_dec_suggest(base_src, &mut err, kind, spans)
}
UnaryFixity::Post => {
self.postfix_inc_dec_suggest(base_src, &mut err, kind, spans)
}
}
self.inc_dec_standalone_recovery(&mut err, kind, spans, true)
}
}
Err(err)
}
fn prefix_inc_dec_suggest(
&mut self,
base_src: String,
mut err: DiagnosticBuilder<'a>,
err: &mut DiagnosticBuilder<'a>,
kind: IncDecRecovery,
(pre_span, post_span): (Span, Span),
) -> PResult<'a, P<Expr>> {
) {
err.multipart_suggestion(
&format!("use `{}= 1` instead", kind.op.chr()),
vec![
@ -1299,16 +1316,15 @@ fn prefix_inc_dec_suggest(
],
Applicability::MachineApplicable,
);
Err(err)
}
fn postfix_inc_dec_suggest(
&mut self,
base_src: String,
mut err: DiagnosticBuilder<'a>,
err: &mut DiagnosticBuilder<'a>,
kind: IncDecRecovery,
(pre_span, post_span): (Span, Span),
) -> PResult<'a, P<Expr>> {
) {
err.multipart_suggestion(
&format!("use `{}= 1` instead", kind.op.chr()),
vec![
@ -1317,21 +1333,31 @@ fn postfix_inc_dec_suggest(
],
Applicability::MachineApplicable,
);
Err(err)
}
fn inc_dec_standalone_recovery(
&mut self,
mut err: DiagnosticBuilder<'a>,
err: &mut DiagnosticBuilder<'a>,
kind: IncDecRecovery,
(pre_span, post_span): (Span, Span),
) -> PResult<'a, P<Expr>> {
maybe_not_standalone: bool,
) {
let msg = if maybe_not_standalone {
"or, if you don't need to use it as an expression, change it to this".to_owned()
} else {
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(
&format!("use `{}= 1` instead", kind.op.chr()),
&msg,
vec![(pre_span, String::new()), (post_span, format!(" {}= 1", kind.op.chr()))],
Applicability::MachineApplicable,
applicability,
);
Err(err)
}
/// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`.

View File

@ -273,9 +273,7 @@ pub(super) fn parse_assoc_expr_with(
let op_span = self.prev_token.span.to(self.token.span);
// Eat the second `+`
self.bump();
// TODO: implement
let start_is_semi = false;
lhs = self.maybe_recover_from_postfix_increment(lhs, op_span, start_is_semi)?;
lhs = self.maybe_recover_from_postfix_increment(lhs, op_span)?;
continue;
}

View File

@ -8,6 +8,11 @@ help: use `+= 1` instead
|
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 += 1;
|
error: Rust has no postfix increment operator
--> $DIR/increment-autofix.rs:11:12
@ -19,6 +24,11 @@ help: use `+= 1` instead
|
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 += 1 < 5 {
|
error: Rust has no prefix increment operator
--> $DIR/increment-autofix.rs:19:5

View File

@ -8,6 +8,11 @@ help: use `+= 1` instead
|
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 += 1;
|
error: Rust has no prefix increment operator
--> $DIR/increment-notfixed.rs:18:5