From 72679d9a97b77a6569310f38ab63edcd04cc3c3a Mon Sep 17 00:00:00 2001 From: YunfeiHe Date: Tue, 13 Dec 2022 20:43:35 +0800 Subject: [PATCH] fix(es/transform_base): should add correct parens for optioanl chaining expression --- .../fixture/issues-6xxx/6459/1/input/.swcrc | 10 +++++ .../fixture/issues-6xxx/6459/1/input/index.ts | 1 + .../issues-6xxx/6459/1/output/index.ts | 1 + .../fixture/issues-6xxx/6459/2/input/.swcrc | 10 +++++ .../fixture/issues-6xxx/6459/2/input/index.ts | 1 + .../issues-6xxx/6459/2/output/index.ts | 1 + .../fixture/issues-6xxx/6459/3/input/.swcrc | 10 +++++ .../fixture/issues-6xxx/6459/3/input/index.ts | 1 + .../issues-6xxx/6459/3/output/index.ts | 1 + crates/swc_ecma_transforms_base/src/fixer.rs | 39 ++++++++++++++++++- 10 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 crates/swc/tests/fixture/issues-6xxx/6459/1/input/.swcrc create mode 100644 crates/swc/tests/fixture/issues-6xxx/6459/1/input/index.ts create mode 100644 crates/swc/tests/fixture/issues-6xxx/6459/1/output/index.ts create mode 100644 crates/swc/tests/fixture/issues-6xxx/6459/2/input/.swcrc create mode 100644 crates/swc/tests/fixture/issues-6xxx/6459/2/input/index.ts create mode 100644 crates/swc/tests/fixture/issues-6xxx/6459/2/output/index.ts create mode 100644 crates/swc/tests/fixture/issues-6xxx/6459/3/input/.swcrc create mode 100644 crates/swc/tests/fixture/issues-6xxx/6459/3/input/index.ts create mode 100644 crates/swc/tests/fixture/issues-6xxx/6459/3/output/index.ts diff --git a/crates/swc/tests/fixture/issues-6xxx/6459/1/input/.swcrc b/crates/swc/tests/fixture/issues-6xxx/6459/1/input/.swcrc new file mode 100644 index 000000000000..596439d43450 --- /dev/null +++ b/crates/swc/tests/fixture/issues-6xxx/6459/1/input/.swcrc @@ -0,0 +1,10 @@ +{ + "jsc": { + "parser": { + "syntax": "typescript" + }, + "target": "es2020", + "loose": false + }, + "isModule": true +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-6xxx/6459/1/input/index.ts b/crates/swc/tests/fixture/issues-6xxx/6459/1/input/index.ts new file mode 100644 index 000000000000..7f2a677887ca --- /dev/null +++ b/crates/swc/tests/fixture/issues-6xxx/6459/1/input/index.ts @@ -0,0 +1 @@ +(myValue.children?.children[0] as ChildType).value = 'My Value'; diff --git a/crates/swc/tests/fixture/issues-6xxx/6459/1/output/index.ts b/crates/swc/tests/fixture/issues-6xxx/6459/1/output/index.ts new file mode 100644 index 000000000000..ec4e5fe19132 --- /dev/null +++ b/crates/swc/tests/fixture/issues-6xxx/6459/1/output/index.ts @@ -0,0 +1 @@ +(myValue.children?.children)[0].value = 'My Value'; diff --git a/crates/swc/tests/fixture/issues-6xxx/6459/2/input/.swcrc b/crates/swc/tests/fixture/issues-6xxx/6459/2/input/.swcrc new file mode 100644 index 000000000000..596439d43450 --- /dev/null +++ b/crates/swc/tests/fixture/issues-6xxx/6459/2/input/.swcrc @@ -0,0 +1,10 @@ +{ + "jsc": { + "parser": { + "syntax": "typescript" + }, + "target": "es2020", + "loose": false + }, + "isModule": true +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-6xxx/6459/2/input/index.ts b/crates/swc/tests/fixture/issues-6xxx/6459/2/input/index.ts new file mode 100644 index 000000000000..284eab42846a --- /dev/null +++ b/crates/swc/tests/fixture/issues-6xxx/6459/2/input/index.ts @@ -0,0 +1 @@ +(foo?.bar.baz?.bax).faz = 1 \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-6xxx/6459/2/output/index.ts b/crates/swc/tests/fixture/issues-6xxx/6459/2/output/index.ts new file mode 100644 index 000000000000..245477e7e86e --- /dev/null +++ b/crates/swc/tests/fixture/issues-6xxx/6459/2/output/index.ts @@ -0,0 +1 @@ +(foo?.bar.baz?.bax).faz = 1; diff --git a/crates/swc/tests/fixture/issues-6xxx/6459/3/input/.swcrc b/crates/swc/tests/fixture/issues-6xxx/6459/3/input/.swcrc new file mode 100644 index 000000000000..596439d43450 --- /dev/null +++ b/crates/swc/tests/fixture/issues-6xxx/6459/3/input/.swcrc @@ -0,0 +1,10 @@ +{ + "jsc": { + "parser": { + "syntax": "typescript" + }, + "target": "es2020", + "loose": false + }, + "isModule": true +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-6xxx/6459/3/input/index.ts b/crates/swc/tests/fixture/issues-6xxx/6459/3/input/index.ts new file mode 100644 index 000000000000..3e8a5b57548c --- /dev/null +++ b/crates/swc/tests/fixture/issues-6xxx/6459/3/input/index.ts @@ -0,0 +1 @@ +(foo?.bar.bar.bar?.baz.baz.baz).foo.baz = 1 \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-6xxx/6459/3/output/index.ts b/crates/swc/tests/fixture/issues-6xxx/6459/3/output/index.ts new file mode 100644 index 000000000000..b464686388f2 --- /dev/null +++ b/crates/swc/tests/fixture/issues-6xxx/6459/3/output/index.ts @@ -0,0 +1 @@ +(foo?.bar.bar.bar?.baz).baz.baz.foo.baz = 1; diff --git a/crates/swc_ecma_transforms_base/src/fixer.rs b/crates/swc_ecma_transforms_base/src/fixer.rs index f06daf330301..98781f67ac66 100644 --- a/crates/swc_ecma_transforms_base/src/fixer.rs +++ b/crates/swc_ecma_transforms_base/src/fixer.rs @@ -16,6 +16,7 @@ pub fn fixer(comments: Option<&dyn Comments>) -> impl '_ + Fold + VisitMut { ctx: Default::default(), span_map: Default::default(), in_for_stmt_head: Default::default(), + in_assign_lhs: Default::default(), remove_only: false, }) } @@ -26,6 +27,7 @@ pub fn paren_remover(comments: Option<&dyn Comments>) -> impl '_ + Fold + VisitM ctx: Default::default(), span_map: Default::default(), in_for_stmt_head: Default::default(), + in_assign_lhs: Default::default(), remove_only: true, }) } @@ -40,6 +42,7 @@ struct Fixer<'a> { span_map: FxHashMap, in_for_stmt_head: bool, + in_assign_lhs: bool, remove_only: bool, } @@ -152,12 +155,18 @@ impl VisitMut for Fixer<'_> { } fn visit_mut_assign_expr(&mut self, expr: &mut AssignExpr) { + let old = self.in_assign_lhs; + + self.in_assign_lhs = true; expr.left.visit_mut_with(self); let ctx = self.ctx; self.ctx = Context::FreeExpr; + self.in_assign_lhs = false; expr.right.visit_mut_with(self); + self.ctx = ctx; + self.in_assign_lhs = old; fn rhs_need_paren(e: &Expr) -> bool { match e { @@ -170,6 +179,34 @@ impl VisitMut for Fixer<'_> { if rhs_need_paren(&expr.right) { self.wrap(&mut expr.right); } + + fn find_nearest_opt_chain_as_obj(e: &mut Expr) -> Option<&mut Expr> { + match e { + Expr::Member(MemberExpr { obj, .. }) => { + if obj.is_opt_chain() { + Some(obj) + } else { + find_nearest_opt_chain_as_obj(obj) + } + } + _ => None, + } + } + + let lhs_expr = match &mut expr.left { + PatOrExpr::Expr(e) => Some(e), + PatOrExpr::Pat(pat) => { + if let Pat::Expr(e) = pat.as_mut() { + Some(e) + } else { + None + } + } + }; + + if let Some(e) = lhs_expr.and_then(|e| find_nearest_opt_chain_as_obj(e)) { + self.wrap(e) + }; } fn visit_mut_assign_pat(&mut self, node: &mut AssignPat) { @@ -440,7 +477,7 @@ impl VisitMut for Fixer<'_> { e.visit_mut_children_with(self); self.ctx = ctx; - self.wrap_with_paren_if_required(e) + self.wrap_with_paren_if_required(e); } fn visit_mut_expr_or_spread(&mut self, e: &mut ExprOrSpread) {