//! Do not use: This is not a public api and it can be changed without a version //! bump. use std::{mem::replace, ops::DerefMut}; use swc_atoms::js_word; use swc_common::DUMMY_SP; use swc_ecma_ast::*; use swc_ecma_utils::ExprExt; /// Do not use: This is not a public api and it can be changed without a version /// bump. /// /// Helper for migration from [Fold] to [VisitMut] #[doc(hidden)] pub trait MapWithMut: Sized { fn dummy() -> Self; fn take(&mut self) -> Self { replace(self, Self::dummy()) } #[inline] fn map_with_mut(&mut self, op: F) where F: FnOnce(Self) -> Self, { let dummy = Self::dummy(); let v = replace(self, dummy); let v = op(v); let _dummy = replace(self, v); } } impl MapWithMut for Program { #[inline] fn dummy() -> Self { Program::Module(Module::dummy()) } } impl MapWithMut for ModuleItem { #[inline] fn dummy() -> Self { ModuleItem::Stmt(Stmt::Empty(EmptyStmt { span: DUMMY_SP })) } } impl MapWithMut for Stmt { #[inline] fn dummy() -> Self { Stmt::Empty(EmptyStmt { span: DUMMY_SP }) } } impl MapWithMut for Expr { #[inline] fn dummy() -> Self { Expr::Invalid(Invalid { span: DUMMY_SP }) } } impl MapWithMut for Pat { #[inline] fn dummy() -> Self { Pat::Invalid(Invalid { span: DUMMY_SP }) } } impl MapWithMut for Option { #[inline] fn dummy() -> Self { None } } impl MapWithMut for Vec { #[inline] fn dummy() -> Self { Vec::new() } } impl MapWithMut for Box where T: MapWithMut, { #[inline] fn dummy() -> Self { Box::new(T::dummy()) } } impl MapWithMut for Ident { fn dummy() -> Self { Ident::new(js_word!(""), DUMMY_SP) } } impl MapWithMut for BindingIdent { fn dummy() -> Self { Ident::dummy().into() } } impl MapWithMut for ObjectPatProp { fn dummy() -> Self { ObjectPatProp::Assign(AssignPatProp { span: DUMMY_SP, key: Ident::dummy(), value: None, }) } } impl MapWithMut for PatOrExpr { fn dummy() -> Self { PatOrExpr::Pat(Box::new(Pat::Ident(BindingIdent::dummy()))) } } impl MapWithMut for Module { fn dummy() -> Self { Module { span: DUMMY_SP, body: vec![], shebang: None, } } } impl MapWithMut for JSXElement { fn dummy() -> Self { JSXElement { span: DUMMY_SP, opening: MapWithMut::dummy(), children: MapWithMut::dummy(), closing: MapWithMut::dummy(), } } } impl MapWithMut for ExprOrSuper { fn dummy() -> Self { ExprOrSuper::Super(Super { span: DUMMY_SP }) } } impl MapWithMut for CallExpr { fn dummy() -> Self { CallExpr { span: DUMMY_SP, callee: MapWithMut::dummy(), args: MapWithMut::dummy(), type_args: Default::default(), } } } impl MapWithMut for JSXOpeningElement { fn dummy() -> Self { JSXOpeningElement { span: DUMMY_SP, name: MapWithMut::dummy(), attrs: MapWithMut::dummy(), self_closing: false, type_args: MapWithMut::dummy(), } } } impl MapWithMut for NewExpr { fn dummy() -> Self { NewExpr { span: DUMMY_SP, callee: MapWithMut::dummy(), args: MapWithMut::dummy(), type_args: Default::default(), } } } impl MapWithMut for JSXClosingElement { fn dummy() -> Self { JSXClosingElement { span: DUMMY_SP, name: MapWithMut::dummy(), } } } impl MapWithMut for Decl { fn dummy() -> Self { Decl::Var(MapWithMut::dummy()) } } impl MapWithMut for VarDecl { fn dummy() -> Self { VarDecl { span: DUMMY_SP, kind: VarDeclKind::Var, declare: false, decls: vec![], } } } impl MapWithMut for JSXElementName { fn dummy() -> Self { JSXElementName::Ident(Ident::dummy()) } } impl MapWithMut for JSXFragment { fn dummy() -> Self { JSXFragment { span: DUMMY_SP, opening: MapWithMut::dummy(), children: MapWithMut::dummy(), closing: MapWithMut::dummy(), } } } impl MapWithMut for PropName { #[inline] fn dummy() -> Self { PropName::Ident(Ident::dummy()) } } impl MapWithMut for BlockStmtOrExpr { #[inline] fn dummy() -> Self { BlockStmtOrExpr::Expr(MapWithMut::dummy()) } } impl MapWithMut for VarDeclarator { #[inline] fn dummy() -> Self { VarDeclarator { span: DUMMY_SP, name: Pat::dummy(), init: None, definite: Default::default(), } } } impl MapWithMut for TplElement { #[inline] fn dummy() -> Self { TplElement { span: DUMMY_SP, tail: false, cooked: None, raw: Str { span: DUMMY_SP, value: "".into(), has_escape: false, kind: Default::default(), }, } } } impl MapWithMut for JSXOpeningFragment { fn dummy() -> Self { JSXOpeningFragment { span: DUMMY_SP } } } impl MapWithMut for JSXClosingFragment { fn dummy() -> Self { JSXClosingFragment { span: DUMMY_SP } } } /// Do not use: This is not a public api and it can be changed without a version /// bump. pub trait PatOrExprExt: AsOptExpr { fn as_ref(&self) -> &PatOrExpr; fn as_mut(&mut self) -> &mut PatOrExpr; fn as_ident(&self) -> Option<&Ident> { if let Some(expr) = self.as_expr() { match expr { Expr::Ident(i) => return Some(i), _ => {} } } match self.as_ref() { PatOrExpr::Expr(e) => match &**e { Expr::Ident(i) => Some(i), _ => None, }, PatOrExpr::Pat(p) => match &**p { Pat::Ident(i) => Some(&i.id), _ => None, }, } } fn as_ident_mut(&mut self) -> Option<&mut Ident> { match self.as_mut() { PatOrExpr::Pat(p) => match **p { Pat::Ident(ref mut i) => Some(&mut i.id), Pat::Expr(ref mut e) => match e.deref_mut() { Expr::Ident(i) => Some(i), _ => None, }, _ => None, }, PatOrExpr::Expr(ref mut e) => match e.deref_mut() { Expr::Ident(i) => Some(i), _ => None, }, } } fn normalize_expr(self) -> Self; fn normalize_ident(self) -> Self; } impl PatOrExprExt for PatOrExpr { fn as_ref(&self) -> &PatOrExpr { self } fn as_mut(&mut self) -> &mut PatOrExpr { self } fn normalize_expr(self) -> Self { match self { PatOrExpr::Pat(pat) => match *pat { Pat::Expr(expr) => PatOrExpr::Expr(expr), _ => return PatOrExpr::Pat(pat), }, _ => self, } } fn normalize_ident(self) -> Self { match self { PatOrExpr::Expr(expr) => match *expr { Expr::Ident(i) => PatOrExpr::Pat(Box::new(Pat::Ident(i.into()))), _ => PatOrExpr::Expr(expr), }, PatOrExpr::Pat(pat) => match *pat { Pat::Expr(expr) => match *expr { Expr::Ident(i) => PatOrExpr::Pat(Box::new(Pat::Ident(i.into()))), _ => PatOrExpr::Expr(expr), }, _ => PatOrExpr::Pat(pat), }, } } } pub trait ExprRefExt: ExprExt { fn as_ident(&self) -> Option<&Ident> { match self.as_expr() { Expr::Ident(ref i) => Some(i), _ => None, } } } impl ExprRefExt for T where T: ExprExt {} /// Do not use: This is not a public api and it can be changed without a version /// bump. pub trait AsOptExpr { fn as_expr(&self) -> Option<&Expr>; fn as_expr_mut(&mut self) -> Option<&mut Expr>; } impl AsOptExpr for PatOrExpr { fn as_expr(&self) -> Option<&Expr> { match self.as_ref() { PatOrExpr::Expr(e) => Some(e), PatOrExpr::Pat(p) => match &**p { Pat::Expr(e) => Some(e), _ => None, }, } } fn as_expr_mut(&mut self) -> Option<&mut Expr> { match self.as_mut() { PatOrExpr::Expr(e) => Some(e.deref_mut()), PatOrExpr::Pat(p) => match &mut **p { Pat::Expr(e) => Some(e.deref_mut()), _ => None, }, } } } impl AsOptExpr for ExprOrSuper { fn as_expr(&self) -> Option<&Expr> { match self { ExprOrSuper::Super(_) => None, ExprOrSuper::Expr(e) => Some(e), } } fn as_expr_mut(&mut self) -> Option<&mut Expr> { match self { ExprOrSuper::Super(_) => None, ExprOrSuper::Expr(e) => Some(e), } } } impl AsOptExpr for Option where N: AsOptExpr, { fn as_expr(&self) -> Option<&Expr> { match self { Some(n) => n.as_expr(), None => None, } } fn as_expr_mut(&mut self) -> Option<&mut Expr> { match self { None => None, Some(n) => n.as_expr_mut(), } } }