mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
fix(formatter): break parens of (a + b)[c] like (a + b).c (#28199)
```js // before (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb)[c]; // after ( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb )[c]; ```
This commit is contained in:
1 parent
b8f4f34bba
commit
72a54cf447
8 files changed
+129
-26
No files matched your search
@@ -1167,3 +1167,36 @@ x =
|
||||
|
||||
An own-line comment before a member's `.` stays before it, for `.b` and `.#b` alike.
|
||||
Prettier moves it before the object for `.b`, and after the `.` for `.#b`; both cross a token.
|
||||
|
||||
## computed-member-object-paren-break
|
||||
|
||||
- Why: uniform-rule (same construct, same output: `(a + b).c` and `(await a)[c]`)
|
||||
- Pin: `tests/fixtures/js/parenthesis/computed-member-object-paren-break.js`
|
||||
- Conformance: `js/ternaries/indent-after-paren.js`
|
||||
|
||||
```js
|
||||
// input (printWidth: 80)
|
||||
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb)[c];
|
||||
(someCondition ? someVeryLongConsequentValueeeeeeeeeeeeeeeeeeee : someVeryLongAlternateValueeeeeeeeeee)[c];
|
||||
|
||||
// ours: the same as `.c`
|
||||
(
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
)[c];
|
||||
(someCondition
|
||||
? someVeryLongConsequentValueeeeeeeeeeeeeeeeeeee
|
||||
: someVeryLongAlternateValueeeeeeeeeee
|
||||
)[c];
|
||||
|
||||
// prettier
|
||||
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb)[c];
|
||||
(someCondition
|
||||
? someVeryLongConsequentValueeeeeeeeeeeeeeeeeeee
|
||||
: someVeryLongAlternateValueeeeeeeeeee)[c];
|
||||
```
|
||||
|
||||
A binary-like or conditional object of a member breaks its parens the same way for `.c`, `[c]` and `?.[c]`.
|
||||
Prettier does so for `.c` only, while an `await` / `as` object breaks them for `[c]` too.
|
||||
The computed property (`a[b + c]`) keeps its own layout.
|
||||
@@ -66,11 +66,6 @@ impl<'parent, 'a> AstNodes<'parent, 'a> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Check if this is a non-computed member expression: `a.b` or `a.#b`
|
||||
pub fn is_non_computed_member_expression(&self) -> bool {
|
||||
matches!(self, AstNodes::StaticMemberExpression(_) | AstNodes::PrivateFieldExpression(_))
|
||||
}
|
||||
|
||||
/// Check if this is a binary-like expression: `a || b`, `a + b`, or `#x in b`
|
||||
pub fn is_binary_like(&self) -> bool {
|
||||
matches!(
|
||||
|
||||
@@ -224,7 +224,7 @@ impl<'a> Format<'a, JsFormatContext<'a>> for BinaryLikeExpression<'a, '_> {
|
||||
}
|
||||
|
||||
// Add a group with a soft block indent in cases where it is necessary to parenthesize the binary expression.
|
||||
// For example, `(a+b)(call)`, `!(a + b)`, `(a + b).test`.
|
||||
// For example, `(a+b)(call)`, `!(a + b)`, `(a + b).test`, `(a + b)[test]`.
|
||||
let is_inside_parenthesis = match parent {
|
||||
// The unary's own comment parens already provide the group and indent
|
||||
AstNodes::UnaryExpression(unary) if unary_argument_takes_comment_parens(unary, f) => {
|
||||
@@ -232,7 +232,7 @@ impl<'a> Format<'a, JsFormatContext<'a>> for BinaryLikeExpression<'a, '_> {
|
||||
}
|
||||
AstNodes::UnaryExpression(_) => true,
|
||||
_ => {
|
||||
parent.is_non_computed_member_expression()
|
||||
parent.is_member_object_span(self.span())
|
||||
|| parent.is_call_like_callee_span(self.span())
|
||||
}
|
||||
};
|
||||
|
||||
@@ -36,11 +36,6 @@ impl<'a> ConditionalLike<'a, '_> {
|
||||
ConditionalLike::TSConditionalType(ty) => ty.parent(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_conditional_expression(&self) -> bool {
|
||||
matches!(self, ConditionalLike::ConditionalExpression(_))
|
||||
}
|
||||
}
|
||||
|
||||
/// Layout information for a conditional expression to determine formatting strategy
|
||||
@@ -339,14 +334,6 @@ impl<'a> FormatConditionalLike<'a, '_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this is the root conditional expression and the parent is a non-computed member: `.b` or `.#b`
|
||||
#[inline]
|
||||
fn is_parent_static_member_expression(&self, layout: ConditionalLayout) -> bool {
|
||||
layout.is_root()
|
||||
&& self.is_conditional_expression()
|
||||
&& self.parent().is_non_computed_member_expression()
|
||||
}
|
||||
|
||||
/// Formats the test part of the conditional
|
||||
fn format_test<'f>(&self, f: &mut JsFormatter<'f, 'a>, layout: ConditionalLayout) {
|
||||
let format_inner = format_with(|f| {
|
||||
@@ -550,16 +537,16 @@ impl<'a> Format<'a, JsFormatContext<'a>> for FormatConditionalLike<'a, '_> {
|
||||
|
||||
format_tail_with_indent.fmt(f);
|
||||
|
||||
// Add a soft line break in front of the closing `)` in case the parent is a static member expression
|
||||
// Add a soft line break in front of the closing `)` in case it is the object of a member expression
|
||||
// ```text
|
||||
// (veryLongCondition
|
||||
// ? a
|
||||
// : b // <- enforce line break here if the conditional breaks
|
||||
// ).more
|
||||
// ).more // or `)[more]`
|
||||
// ```
|
||||
if !should_extra_indent
|
||||
&& !is_jsx_chain
|
||||
&& self.is_parent_static_member_expression(layout)
|
||||
&& self.parent().is_member_object_span(self.span())
|
||||
{
|
||||
write!(f, [soft_line_break()]);
|
||||
}
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// DIVERGENCES.md#computed-member-object-paren-break
|
||||
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb).c;
|
||||
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb)[c];
|
||||
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa || bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb)?.[c];
|
||||
(someCondition ? someVeryLongConsequentValueeeeeeeeeeeeeeeeeeee : someVeryLongAlternateValueeeeeeeeeee).c;
|
||||
(someCondition ? someVeryLongConsequentValueeeeeeeeeeeeeeeeeeee : someVeryLongAlternateValueeeeeeeeeee)[c];
|
||||
|
||||
// The property keeps its own layout
|
||||
xxxxxxxxxx[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb];
|
||||
Vendored
+78
@@ -0,0 +1,78 @@
|
||||
---
|
||||
source: crates/oxc_formatter/tests/fixtures/mod.rs
|
||||
---
|
||||
==================== Input ====================
|
||||
// DIVERGENCES.md#computed-member-object-paren-break
|
||||
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb).c;
|
||||
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb)[c];
|
||||
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa || bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb)?.[c];
|
||||
(someCondition ? someVeryLongConsequentValueeeeeeeeeeeeeeeeeeee : someVeryLongAlternateValueeeeeeeeeee).c;
|
||||
(someCondition ? someVeryLongConsequentValueeeeeeeeeeeeeeeeeeee : someVeryLongAlternateValueeeeeeeeeee)[c];
|
||||
|
||||
// The property keeps its own layout
|
||||
xxxxxxxxxx[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb];
|
||||
|
||||
==================== Output ====================
|
||||
------------------
|
||||
{ printWidth: 80 }
|
||||
------------------
|
||||
// DIVERGENCES.md#computed-member-object-paren-break
|
||||
(
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
).c;
|
||||
(
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
)[c];
|
||||
(
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ||
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
)?.[c];
|
||||
(someCondition
|
||||
? someVeryLongConsequentValueeeeeeeeeeeeeeeeeeee
|
||||
: someVeryLongAlternateValueeeeeeeeeee
|
||||
).c;
|
||||
(someCondition
|
||||
? someVeryLongConsequentValueeeeeeeeeeeeeeeeeeee
|
||||
: someVeryLongAlternateValueeeeeeeeeee
|
||||
)[c];
|
||||
|
||||
// The property keeps its own layout
|
||||
xxxxxxxxxx[
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
];
|
||||
|
||||
-------------------
|
||||
{ printWidth: 100 }
|
||||
-------------------
|
||||
// DIVERGENCES.md#computed-member-object-paren-break
|
||||
(
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
).c;
|
||||
(
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
)[c];
|
||||
(
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ||
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
)?.[c];
|
||||
(someCondition
|
||||
? someVeryLongConsequentValueeeeeeeeeeeeeeeeeeee
|
||||
: someVeryLongAlternateValueeeeeeeeeee
|
||||
).c;
|
||||
(someCondition
|
||||
? someVeryLongConsequentValueeeeeeeeeeeeeeeeeeee
|
||||
: someVeryLongAlternateValueeeeeeeeeee
|
||||
)[c];
|
||||
|
||||
// The property keeps its own layout
|
||||
xxxxxxxxxx[
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
];
|
||||
|
||||
===================== End =====================
|
||||
@@ -2,7 +2,7 @@
|
||||
source: crates/oxc_formatter/tests/conformance.rs
|
||||
expression: report
|
||||
---
|
||||
js compatibility: 1033/1123 (91.99%), 23 files skipped
|
||||
js compatibility: 1029/1123 (91.63%), 23 files skipped
|
||||
|
||||
# Failed
|
||||
|
||||
@@ -55,6 +55,7 @@ js compatibility: 1033/1123 (91.99%), 23 files skipped
|
||||
| js/switch/comments.js | 💥 | 94.74% |
|
||||
| js/template-literals/expression-break.js | 💥 | 80.00% |
|
||||
| js/template-literals/expressions.js | 💥 | 97.64% |
|
||||
| js/ternaries/indent-after-paren.js | 💥💥💥💥 | 99.14% |
|
||||
| js/test-declarations/jest-each.js | 💥💥 | 95.71% |
|
||||
| js/trailing-comma/trailing_whitespace.js | 💥💥💥 | 96.55% |
|
||||
| js/try/try.js | 💥 | 44.44% |
|
||||
|
||||
@@ -44,9 +44,9 @@ pdf.mjs:
|
||||
|
||||
antd.js:
|
||||
file size: 6686316 # 6.69 MB
|
||||
sys allocs: 74785
|
||||
sys allocs: 74784
|
||||
sys reallocs: 351
|
||||
sys deallocs: 74784
|
||||
sys deallocs: 74783
|
||||
sys alloc bytes: 23137418 # 23.14 MB
|
||||
sys peak growth: 13710144 # 13.71 MB
|
||||
arena allocs: 120676
|
||||
|
||||
Reference in new issue
Block a user