Skip to content

Commit

Permalink
Merge pull request #1828 from dtolnay/prevnextoperator
Browse files Browse the repository at this point in the history
Track previous and next operator's precedence in fixup context
  • Loading branch information
dtolnay authored Jan 1, 2025
2 parents 0919c99 + 7e8a56a commit 9dd90b7
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 15 deletions.
57 changes: 45 additions & 12 deletions src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3303,10 +3303,10 @@ pub(crate) mod printing {
fn print_expr_assign(e: &ExprAssign, tokens: &mut TokenStream, fixup: FixupContext) {
outer_attrs_to_tokens(&e.attrs, tokens);
let (left_prec, left_fixup) =
fixup.leftmost_subexpression_with_operator(&e.left, false, false);
fixup.leftmost_subexpression_with_operator(&e.left, false, false, Precedence::Assign);
print_subexpression(&e.left, left_prec <= Precedence::Range, tokens, left_fixup);
e.eq_token.to_tokens(tokens);
let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.right);
let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.right, Precedence::Assign);
print_subexpression(
&e.right,
right_prec < Precedence::Assign,
Expand Down Expand Up @@ -3377,8 +3377,15 @@ pub(crate) mod printing {
BinOp::Shl(_) | BinOp::Lt(_) => true,
_ => false,
},
#[cfg(feature = "full")]
binop_prec,
);

let (right_prec, right_fixup) = fixup.rightmost_subexpression(
&e.right,
#[cfg(feature = "full")]
binop_prec,
);
let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.right);
let (left_needs_group, right_needs_group) = match binop_prec {
Precedence::Assign => (left_prec <= Precedence::Range, right_prec < binop_prec),
Precedence::Compare => (left_prec <= binop_prec, right_prec <= binop_prec),
Expand Down Expand Up @@ -3423,7 +3430,7 @@ pub(crate) mod printing {
// ^---------------------------------^
e.label.is_none() && classify::expr_leading_label(value),
tokens,
fixup.rightmost_subexpression_fixup(),
fixup.rightmost_subexpression_fixup(Precedence::Jump),
);
}
}
Expand All @@ -3443,6 +3450,8 @@ pub(crate) mod printing {
#[cfg(feature = "full")]
true,
false,
#[cfg(feature = "full")]
Precedence::Unambiguous,
);
let needs_group = if let Expr::Field(func) = &*e.func {
func.member.is_named()
Expand Down Expand Up @@ -3470,6 +3479,8 @@ pub(crate) mod printing {
#[cfg(feature = "full")]
false,
false,
#[cfg(feature = "full")]
Precedence::Cast,
);
print_subexpression(&e.expr, left_prec < Precedence::Cast, tokens, left_fixup);
e.as_token.to_tokens(tokens);
Expand Down Expand Up @@ -3499,7 +3510,11 @@ pub(crate) mod printing {
if matches!(e.output, ReturnType::Default)
|| matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
{
print_expr(&e.body, tokens, fixup.rightmost_subexpression_fixup());
print_expr(
&e.body,
tokens,
fixup.rightmost_subexpression_fixup(Precedence::Jump),
);
} else {
token::Brace::default().surround(tokens, |tokens| {
print_expr(&e.body, tokens, FixupContext::new_stmt());
Expand Down Expand Up @@ -3630,6 +3645,8 @@ pub(crate) mod printing {
#[cfg(feature = "full")]
true,
false,
#[cfg(feature = "full")]
Precedence::Unambiguous,
);
print_subexpression(
&e.expr,
Expand Down Expand Up @@ -3789,12 +3806,12 @@ pub(crate) mod printing {
outer_attrs_to_tokens(&e.attrs, tokens);
if let Some(start) = &e.start {
let (left_prec, left_fixup) =
fixup.leftmost_subexpression_with_operator(start, true, false);
fixup.leftmost_subexpression_with_operator(start, true, false, Precedence::Range);
print_subexpression(start, left_prec <= Precedence::Range, tokens, left_fixup);
}
e.limits.to_tokens(tokens);
if let Some(end) = &e.end {
let (right_prec, right_fixup) = fixup.rightmost_subexpression(end);
let (right_prec, right_fixup) = fixup.rightmost_subexpression(end, Precedence::Range);
print_subexpression(end, right_prec <= Precedence::Range, tokens, right_fixup);
}
}
Expand All @@ -3813,7 +3830,7 @@ pub(crate) mod printing {
e.and_token.to_tokens(tokens);
e.raw.to_tokens(tokens);
e.mutability.to_tokens(tokens);
let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr);
let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Prefix);
print_subexpression(
&e.expr,
right_prec < Precedence::Prefix,
Expand All @@ -3833,7 +3850,11 @@ pub(crate) mod printing {
outer_attrs_to_tokens(&e.attrs, tokens);
e.and_token.to_tokens(tokens);
e.mutability.to_tokens(tokens);
let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr);
let (right_prec, right_fixup) = fixup.rightmost_subexpression(
&e.expr,
#[cfg(feature = "full")]
Precedence::Prefix,
);
print_subexpression(
&e.expr,
right_prec < Precedence::Prefix,
Expand Down Expand Up @@ -3868,7 +3889,11 @@ pub(crate) mod printing {
outer_attrs_to_tokens(&e.attrs, tokens);
e.return_token.to_tokens(tokens);
if let Some(expr) = &e.expr {
print_expr(expr, tokens, fixup.rightmost_subexpression_fixup());
print_expr(
expr,
tokens,
fixup.rightmost_subexpression_fixup(Precedence::Jump),
);
}
}

Expand Down Expand Up @@ -3945,7 +3970,11 @@ pub(crate) mod printing {
fn print_expr_unary(e: &ExprUnary, tokens: &mut TokenStream, fixup: FixupContext) {
outer_attrs_to_tokens(&e.attrs, tokens);
e.op.to_tokens(tokens);
let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr);
let (right_prec, right_fixup) = fixup.rightmost_subexpression(
&e.expr,
#[cfg(feature = "full")]
Precedence::Prefix,
);
print_subexpression(
&e.expr,
right_prec < Precedence::Prefix,
Expand Down Expand Up @@ -3995,7 +4024,11 @@ pub(crate) mod printing {
outer_attrs_to_tokens(&e.attrs, tokens);
e.yield_token.to_tokens(tokens);
if let Some(expr) = &e.expr {
print_expr(expr, tokens, fixup.rightmost_subexpression_fixup());
print_expr(
expr,
tokens,
fixup.rightmost_subexpression_fixup(Precedence::Jump),
);
}
}

Expand Down
34 changes: 31 additions & 3 deletions src/fixup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ use crate::expr::Expr;
use crate::precedence::Precedence;

pub(crate) struct FixupContext {
#[cfg(feature = "full")]
#[allow(dead_code)]
previous_operator: Precedence,
#[cfg(feature = "full")]
#[allow(dead_code)]
next_operator: Precedence,

// Print expression such that it can be parsed back as a statement
// consisting of the original expression.
//
Expand Down Expand Up @@ -132,6 +139,10 @@ impl FixupContext {
/// The default amount of fixing is minimal fixing. Fixups should be turned
/// on in a targeted fashion where needed.
pub const NONE: Self = FixupContext {
#[cfg(feature = "full")]
previous_operator: Precedence::MIN,
#[cfg(feature = "full")]
next_operator: Precedence::MIN,
#[cfg(feature = "full")]
stmt: false,
#[cfg(feature = "full")]
Expand Down Expand Up @@ -199,8 +210,11 @@ impl FixupContext {
expr: &Expr,
#[cfg(feature = "full")] next_operator_can_begin_expr: bool,
next_operator_can_begin_generics: bool,
#[cfg(feature = "full")] precedence: Precedence,
) -> (Precedence, Self) {
let fixup = FixupContext {
#[cfg(feature = "full")]
next_operator: precedence,
#[cfg(feature = "full")]
stmt: false,
#[cfg(feature = "full")]
Expand Down Expand Up @@ -229,6 +243,8 @@ impl FixupContext {
/// subexpressions.
pub fn leftmost_subexpression_with_dot(self, expr: &Expr) -> (Precedence, Self) {
let fixup = FixupContext {
#[cfg(feature = "full")]
next_operator: Precedence::Unambiguous,
#[cfg(feature = "full")]
stmt: self.stmt || self.leftmost_subexpression_in_stmt,
#[cfg(feature = "full")]
Expand Down Expand Up @@ -261,13 +277,25 @@ impl FixupContext {
///
/// Not every expression has a rightmost subexpression. For example neither
/// `[$b]` nor `$a.f($b)` have one.
pub fn rightmost_subexpression(self, expr: &Expr) -> (Precedence, Self) {
let fixup = self.rightmost_subexpression_fixup();
pub fn rightmost_subexpression(
self,
expr: &Expr,
#[cfg(feature = "full")] precedence: Precedence,
) -> (Precedence, Self) {
let fixup = self.rightmost_subexpression_fixup(
#[cfg(feature = "full")]
precedence,
);
(fixup.precedence(expr), fixup)
}

pub fn rightmost_subexpression_fixup(self) -> Self {
pub fn rightmost_subexpression_fixup(
self,
#[cfg(feature = "full")] precedence: Precedence,
) -> Self {
FixupContext {
#[cfg(feature = "full")]
previous_operator: precedence,
#[cfg(feature = "full")]
stmt: false,
#[cfg(feature = "full")]
Expand Down

0 comments on commit 9dd90b7

Please sign in to comment.