From aa024d93349d05e4a6d5d09613ad4c09fa9afdb4 Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Tue, 21 Oct 2025 04:36:33 +0000 Subject: [PATCH] feat(formatter): wrap parenthesis for `AssignmentExpression` that are inside `ComputedMemberExpression` (#14834) related: https://github.com/oxc-project/oxc/discussions/14669#discussioncomment-14723451 --- crates/oxc_formatter/src/parentheses/expression.rs | 4 ++-- .../tests/fixtures/js/assignments/parenthesis.js | 1 + .../tests/fixtures/js/assignments/parenthesis.js.snap | 10 ++++++++++ .../tests/fixtures/js/comments/computed-member.js.snap | 4 ++-- 4 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 crates/oxc_formatter/tests/fixtures/js/assignments/parenthesis.js create mode 100644 crates/oxc_formatter/tests/fixtures/js/assignments/parenthesis.js.snap diff --git a/crates/oxc_formatter/src/parentheses/expression.rs b/crates/oxc_formatter/src/parentheses/expression.rs index 0f90a0edcf87a..e53fa97a6a944 100644 --- a/crates/oxc_formatter/src/parentheses/expression.rs +++ b/crates/oxc_formatter/src/parentheses/expression.rs @@ -551,9 +551,9 @@ impl NeedsParentheses<'_> for AstNode<'_, AssignmentExpression<'_>> { // - `a = (b = c)` = nested assignments don't need extra parens AstNodes::AssignmentExpression(_) => false, // Computed member expressions: need parens when assignment is the object - // - `obj[a = b]` = no parens needed for property + // - `obj[(a = b)]` parens needed for explicitness // - `(a = b)[obj]` = parens needed for object - AstNodes::ComputedMemberExpression(member) => member.object.span() == self.span(), + AstNodes::ComputedMemberExpression(member) => true, // For statements, no parens needed in initializer or update sections: // - `for (a = 1; ...; a = 2) {}` = both assignments don't need parens AstNodes::ForStatement(stmt) => { diff --git a/crates/oxc_formatter/tests/fixtures/js/assignments/parenthesis.js b/crates/oxc_formatter/tests/fixtures/js/assignments/parenthesis.js new file mode 100644 index 0000000000000..a42195804f81d --- /dev/null +++ b/crates/oxc_formatter/tests/fixtures/js/assignments/parenthesis.js @@ -0,0 +1 @@ +object[key = "a" + "b"]; diff --git a/crates/oxc_formatter/tests/fixtures/js/assignments/parenthesis.js.snap b/crates/oxc_formatter/tests/fixtures/js/assignments/parenthesis.js.snap new file mode 100644 index 0000000000000..80d67f1f7c7bc --- /dev/null +++ b/crates/oxc_formatter/tests/fixtures/js/assignments/parenthesis.js.snap @@ -0,0 +1,10 @@ +--- +source: crates/oxc_formatter/tests/fixtures/mod.rs +--- +==================== Input ==================== +object[key = "a" + "b"]; + +==================== Output ==================== +object[(key = "a" + "b")]; + +===================== End ===================== diff --git a/crates/oxc_formatter/tests/fixtures/js/comments/computed-member.js.snap b/crates/oxc_formatter/tests/fixtures/js/comments/computed-member.js.snap index 878da46615931..592c80b7edac6 100644 --- a/crates/oxc_formatter/tests/fixtures/js/comments/computed-member.js.snap +++ b/crates/oxc_formatter/tests/fixtures/js/comments/computed-member.js.snap @@ -18,7 +18,7 @@ prop[ ] = shouldCast; let handler = - props[handlerName = toHandlerKey(event)] || // also try camelCase event handler (#2249) - props[handlerName = toHandlerKey(camelize(event))]; + props[(handlerName = toHandlerKey(event))] || // also try camelCase event handler (#2249) + props[(handlerName = toHandlerKey(camelize(event)))]; ===================== End =====================