mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
fix(formatter): keep more parens around TSInstantiationExpression (#27811)
Like `(make<T>)<U>();`.
This commit is contained in:
1 parent
5b6ae62ffa
commit
de110ced8b
4 files changed
+80
-3
No files matched your search
@@ -813,16 +813,22 @@ Before an optional call's `?.`, Prettier moves an own-line comment into the argu
|
||||
```ts
|
||||
// input
|
||||
const a = (make<T>)!;
|
||||
(make<T>)<U>();
|
||||
x = (make<T>) + y;
|
||||
export default (class {})<string>;
|
||||
(class {})<string>;
|
||||
|
||||
// ours
|
||||
const a = (make<T>)!;
|
||||
(make<T>)<U>();
|
||||
x = (make<T>) + y;
|
||||
export default (class {})<string>;
|
||||
(class {})<string>;
|
||||
|
||||
// prettier
|
||||
const a = make<T>!;
|
||||
make<T><U>();
|
||||
x = make<T> + y;
|
||||
export default class {}<string>;
|
||||
class {}<string>;
|
||||
```
|
||||
@@ -831,6 +837,10 @@ Prettier drops the parens around an instantiation expression before `!`,
|
||||
and the ones that keep a leading `class`/`function` from starting a declaration or statement.
|
||||
Fixed in Prettier `main` by prettier/prettier#20177, which we follow except after `export default` (DIVERGENCES.md#export-default-leftmost-parens).
|
||||
|
||||
Prettier `main` still drops them before type arguments (`make<T><U>()` does not parse)
|
||||
and before a binary `+`, `-`, `<` or `>`-led operator, also when `make<T>` only ends the left operand
|
||||
(`make<T> + y` and `a + make<T> - y` parse as `make < T > +y`).
|
||||
|
||||
## export-default-leftmost-parens
|
||||
|
||||
- Why: uniform-rule (same construct, same output: expression statement)
|
||||
|
||||
@@ -921,15 +921,50 @@ impl NeedsParentheses<'_> for AstNode<'_, TSInstantiationExpression<'_>> {
|
||||
AstNodes::StaticMemberExpression(expr) => &expr.object,
|
||||
AstNodes::ComputedMemberExpression(expr) => &expr.object,
|
||||
AstNodes::PrivateFieldExpression(expr) => &expr.object,
|
||||
// `(f<T>)!`, since `f<T>!` does not parse
|
||||
AstNodes::TSNonNullExpression(_) => return true,
|
||||
_ => return false,
|
||||
// `(f<T>)!`, `(f<T>)<U>` and `(f<T>)<U>()`, since `f<T>!`, `f<T><U>` and `f<T><U>()` do not parse
|
||||
AstNodes::TSNonNullExpression(_) | AstNodes::TSInstantiationExpression(_) => {
|
||||
return true;
|
||||
}
|
||||
AstNodes::CallExpression(expr) if expr.type_arguments.is_some() => &expr.callee,
|
||||
AstNodes::NewExpression(expr) if expr.type_arguments.is_some() => &expr.callee,
|
||||
AstNodes::TaggedTemplateExpression(expr) if expr.type_arguments.is_some() => &expr.tag,
|
||||
_ => return is_followed_by_comparison_or_sign(self),
|
||||
};
|
||||
|
||||
self.span == object.span()
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the instantiation expression ends the left operand of `+`, `-`, `<` or `>`-led operators:
|
||||
/// TypeScript reads `f<T> + x` as `f < T > +x` and rejects `f<T> < x`,
|
||||
/// also when `f<T>` only ends the operand (`(a + f<T>) - x`, `(typeof f<T>) + x`).
|
||||
fn is_followed_by_comparison_or_sign(node: &AstNode<'_, TSInstantiationExpression<'_>>) -> bool {
|
||||
let mut span = node.span;
|
||||
let mut parent = node.parent();
|
||||
loop {
|
||||
match parent {
|
||||
AstNodes::BinaryExpression(expr) if expr.right.span() == span => {
|
||||
(span, parent) = (expr.span, expr.parent());
|
||||
}
|
||||
AstNodes::UnaryExpression(expr) => (span, parent) = (expr.span, expr.parent()),
|
||||
AstNodes::BinaryExpression(expr) => {
|
||||
return expr.left.span() == span
|
||||
&& matches!(
|
||||
expr.operator,
|
||||
BinaryOperator::Addition
|
||||
| BinaryOperator::Subtraction
|
||||
| BinaryOperator::LessThan
|
||||
| BinaryOperator::GreaterThan
|
||||
| BinaryOperator::GreaterEqualThan
|
||||
| BinaryOperator::ShiftRight
|
||||
| BinaryOperator::ShiftRightZeroFill
|
||||
);
|
||||
}
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn binary_like_needs_parens(
|
||||
binary_like: BinaryLikeExpression<'_, '_>,
|
||||
f: &JsFormatter<'_, '_>,
|
||||
|
||||
+8
@@ -2,6 +2,14 @@
|
||||
const a = (make<T>)!;
|
||||
(make<T>)!.b;
|
||||
(make<T>)!();
|
||||
(make<T>)<U>;
|
||||
(make<T>)<U>();
|
||||
new (make<T>)<U>();
|
||||
(make<T>)<U>``;
|
||||
x = (make<T>) + y;
|
||||
x = (make<T>) >> y;
|
||||
x = (a + make<T>) - y;
|
||||
x = (typeof make<T>) + y;
|
||||
export default (class {})<string>;
|
||||
export default (function () {})<string>;
|
||||
export default (class {})<string> as A;
|
||||
|
||||
+24
@@ -6,6 +6,14 @@ source: crates/oxc_formatter/tests/fixtures/mod.rs
|
||||
const a = (make<T>)!;
|
||||
(make<T>)!.b;
|
||||
(make<T>)!();
|
||||
(make<T>)<U>;
|
||||
(make<T>)<U>();
|
||||
new (make<T>)<U>();
|
||||
(make<T>)<U>``;
|
||||
x = (make<T>) + y;
|
||||
x = (make<T>) >> y;
|
||||
x = (a + make<T>) - y;
|
||||
x = (typeof make<T>) + y;
|
||||
export default (class {})<string>;
|
||||
export default (function () {})<string>;
|
||||
export default (class {})<string> as A;
|
||||
@@ -20,6 +28,14 @@ export default (class {})<string> as A;
|
||||
const a = (make<T>)!;
|
||||
(make<T>)!.b;
|
||||
(make<T>)!();
|
||||
(make<T>)<U>;
|
||||
(make<T>)<U>();
|
||||
new (make<T>)<U>();
|
||||
(make<T>)<U>``;
|
||||
x = (make<T>) + y;
|
||||
x = (make<T>) >> y;
|
||||
x = a + (make<T>) - y;
|
||||
x = typeof (make<T>) + y;
|
||||
export default (class {})<string>;
|
||||
export default (function () {})<string>;
|
||||
export default (class {})<string> as A;
|
||||
@@ -33,6 +49,14 @@ export default (class {})<string> as A;
|
||||
const a = (make<T>)!;
|
||||
(make<T>)!.b;
|
||||
(make<T>)!();
|
||||
(make<T>)<U>;
|
||||
(make<T>)<U>();
|
||||
new (make<T>)<U>();
|
||||
(make<T>)<U>``;
|
||||
x = (make<T>) + y;
|
||||
x = (make<T>) >> y;
|
||||
x = a + (make<T>) - y;
|
||||
x = typeof (make<T>) + y;
|
||||
export default (class {})<string>;
|
||||
export default (function () {})<string>;
|
||||
export default (class {})<string> as A;
|
||||
|
||||
Reference in new issue
Block a user