From 67b7cc0f510801d235692203bb5b19c5e18c12bf Mon Sep 17 00:00:00 2001 From: Dunqing Date: Wed, 13 Dec 2023 20:41:44 +0800 Subject: [PATCH] feat(ast): support visit more jsx ast in visit (#1662) --- crates/oxc_ast/src/ast_kind.rs | 15 ++++++++++ crates/oxc_ast/src/span.rs | 9 ++++++ crates/oxc_ast/src/visit.rs | 44 +++++++++++++++++++++++++++++ crates/oxc_ast/src/visit_mut.rs | 49 +++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+) diff --git a/crates/oxc_ast/src/ast_kind.rs b/crates/oxc_ast/src/ast_kind.rs index 3506b27cb6189..fb820d83ad852 100644 --- a/crates/oxc_ast/src/ast_kind.rs +++ b/crates/oxc_ast/src/ast_kind.rs @@ -115,11 +115,16 @@ pub enum AstKind<'a> { JSXElement(&'a JSXElement<'a>), JSXFragment(&'a JSXFragment<'a>), JSXOpeningElement(&'a JSXOpeningElement<'a>), + JSXClosingElement(&'a JSXClosingElement<'a>), JSXElementName(&'a JSXElementName<'a>), JSXExpressionContainer(&'a JSXExpressionContainer<'a>), JSXAttributeItem(&'a JSXAttributeItem<'a>), JSXSpreadAttribute(&'a JSXSpreadAttribute<'a>), JSXText(&'a JSXText), + JSXIdentifier(&'a JSXIdentifier), + JSXMemberExpression(&'a JSXMemberExpression<'a>), + JSXMemberExpressionObject(&'a JSXMemberExpressionObject<'a>), + JSXNamespacedName(&'a JSXNamespacedName), // TypeScript TSModuleBlock(&'a TSModuleBlock<'a>), @@ -414,6 +419,7 @@ impl<'a> GetSpan for AstKind<'a> { Self::ModuleDeclaration(x) => x.span(), Self::JSXOpeningElement(x) => x.span, + Self::JSXClosingElement(x) => x.span, Self::JSXElementName(x) => x.span(), Self::JSXElement(x) => x.span, Self::JSXFragment(x) => x.span, @@ -421,6 +427,10 @@ impl<'a> GetSpan for AstKind<'a> { Self::JSXSpreadAttribute(x) => x.span, Self::JSXText(x) => x.span, Self::JSXExpressionContainer(x) => x.span, + Self::JSXIdentifier(x) => x.span, + Self::JSXMemberExpression(x) => x.span, + Self::JSXMemberExpressionObject(x) => x.span(), + Self::JSXNamespacedName(x) => x.span, Self::TSModuleBlock(x) => x.span, @@ -585,6 +595,7 @@ impl<'a> AstKind<'a> { Self::ModuleDeclaration(_) => "ModuleDeclaration".into(), Self::JSXOpeningElement(_) => "JSXOpeningElement".into(), + Self::JSXClosingElement(_) => "JSXClosingElement".into(), Self::JSXElementName(_) => "JSXElementName".into(), Self::JSXElement(_) => "JSXElement".into(), Self::JSXFragment(_) => "JSXFragment".into(), @@ -592,6 +603,10 @@ impl<'a> AstKind<'a> { Self::JSXSpreadAttribute(_) => "JSXSpreadAttribute".into(), Self::JSXText(_) => "JSXText".into(), Self::JSXExpressionContainer(_) => "JSXExpressionContainer".into(), + Self::JSXIdentifier(_) => "JSXIdentifier".into(), + Self::JSXMemberExpression(_) => "JSXMemberExpression".into(), + Self::JSXMemberExpressionObject(_) => "JSXMemberExpressionObject".into(), + Self::JSXNamespacedName(_) => "JSXNamespacedName".into(), Self::TSModuleBlock(_) => "TSModuleBlock".into(), diff --git a/crates/oxc_ast/src/span.rs b/crates/oxc_ast/src/span.rs index 59693f06c7573..eafc15bf56d7e 100644 --- a/crates/oxc_ast/src/span.rs +++ b/crates/oxc_ast/src/span.rs @@ -416,3 +416,12 @@ impl<'a> GetSpan for JSXAttributeName<'a> { } } } + +impl<'a> GetSpan for JSXMemberExpressionObject<'a> { + fn span(&self) -> Span { + match &self { + JSXMemberExpressionObject::Identifier(ident) => ident.span, + JSXMemberExpressionObject::MemberExpression(expr) => expr.span, + } + } +} diff --git a/crates/oxc_ast/src/visit.rs b/crates/oxc_ast/src/visit.rs index 7ee13aa75fbda..5c97b6c3e21eb 100644 --- a/crates/oxc_ast/src/visit.rs +++ b/crates/oxc_ast/src/visit.rs @@ -1018,6 +1018,9 @@ pub trait Visit<'a>: Sized { for child in &elem.children { self.visit_jsx_child(child); } + if let Some(closing_elem) = &elem.closing_element { + self.visit_jsx_closing_element(closing_elem); + } self.leave_node(kind); } @@ -1031,12 +1034,53 @@ pub trait Visit<'a>: Sized { self.leave_node(kind); } + fn visit_jsx_closing_element(&mut self, elem: &JSXClosingElement<'a>) { + let kind = AstKind::JSXClosingElement(self.alloc(elem)); + self.enter_node(kind); + self.visit_jsx_element_name(&elem.name); + self.leave_node(kind); + } + fn visit_jsx_element_name(&mut self, name: &JSXElementName<'a>) { let kind = AstKind::JSXElementName(self.alloc(name)); self.enter_node(kind); self.leave_node(kind); } + fn visit_jsx_identifier(&mut self, ident: &JSXIdentifier) { + let kind = AstKind::JSXIdentifier(self.alloc(ident)); + self.enter_node(kind); + self.leave_node(kind); + } + + fn visit_jsx_member_expression(&mut self, expr: &JSXMemberExpression<'a>) { + let kind = AstKind::JSXMemberExpression(self.alloc(expr)); + self.enter_node(kind); + self.visit_jsx_member_expression_object(&expr.object); + self.visit_jsx_identifier(&expr.property); + self.leave_node(kind); + } + + fn visit_jsx_member_expression_object(&mut self, expr: &JSXMemberExpressionObject<'a>) { + let kind = AstKind::JSXMemberExpressionObject(self.alloc(expr)); + self.enter_node(kind); + match expr { + JSXMemberExpressionObject::Identifier(ident) => self.visit_jsx_identifier(ident), + JSXMemberExpressionObject::MemberExpression(expr) => { + self.visit_jsx_member_expression(expr); + } + } + self.leave_node(kind); + } + + fn visit_jsx_namespaced_name(&mut self, name: &JSXNamespacedName) { + let kind = AstKind::JSXNamespacedName(self.alloc(name)); + self.enter_node(kind); + self.visit_jsx_identifier(&name.namespace); + self.visit_jsx_identifier(&name.property); + self.leave_node(kind); + } + fn visit_jsx_attribute_item(&mut self, item: &JSXAttributeItem<'a>) { let kind = AstKind::JSXAttributeItem(self.alloc(item)); self.enter_node(kind); diff --git a/crates/oxc_ast/src/visit_mut.rs b/crates/oxc_ast/src/visit_mut.rs index c51e1a9fb00f8..f8484b465ea7c 100644 --- a/crates/oxc_ast/src/visit_mut.rs +++ b/crates/oxc_ast/src/visit_mut.rs @@ -1014,6 +1014,9 @@ pub trait VisitMut<'a>: Sized { for child in elem.children.iter_mut() { self.visit_jsx_child(child); } + if let Some(closing_elem) = &mut elem.closing_element { + self.visit_jsx_closing_element(closing_elem); + } self.leave_node(kind); } @@ -1028,9 +1031,55 @@ pub trait VisitMut<'a>: Sized { self.leave_node(kind); } + fn visit_jsx_closing_element(&mut self, elem: &mut JSXClosingElement<'a>) { + let kind = AstKind::JSXClosingElement(self.alloc(elem)); + self.enter_node(kind); + self.visit_jsx_element_name(&mut elem.name); + self.leave_node(kind); + } + fn visit_jsx_element_name(&mut self, name: &mut JSXElementName<'a>) { let kind = AstKind::JSXElementName(self.alloc(name)); self.enter_node(kind); + match name { + JSXElementName::Identifier(ident) => self.visit_jsx_identifier(ident), + JSXElementName::MemberExpression(expr) => self.visit_jsx_member_expression(expr), + JSXElementName::NamespacedName(name) => self.visit_jsx_namespaced_name(name), + } + self.leave_node(kind); + } + + fn visit_jsx_identifier(&mut self, ident: &mut JSXIdentifier) { + let kind = AstKind::JSXIdentifier(self.alloc(ident)); + self.enter_node(kind); + self.leave_node(kind); + } + + fn visit_jsx_member_expression(&mut self, expr: &mut JSXMemberExpression<'a>) { + let kind = AstKind::JSXMemberExpression(self.alloc(expr)); + self.enter_node(kind); + self.visit_jsx_member_expression_object(&mut expr.object); + self.visit_jsx_identifier(&mut expr.property); + self.leave_node(kind); + } + + fn visit_jsx_member_expression_object(&mut self, expr: &mut JSXMemberExpressionObject<'a>) { + let kind = AstKind::JSXMemberExpressionObject(self.alloc(expr)); + self.enter_node(kind); + match expr { + JSXMemberExpressionObject::Identifier(ident) => self.visit_jsx_identifier(ident), + JSXMemberExpressionObject::MemberExpression(expr) => { + self.visit_jsx_member_expression(expr); + } + } + self.leave_node(kind); + } + + fn visit_jsx_namespaced_name(&mut self, name: &mut JSXNamespacedName) { + let kind = AstKind::JSXNamespacedName(self.alloc(name)); + self.enter_node(kind); + self.visit_jsx_identifier(&mut name.namespace); + self.visit_jsx_identifier(&mut name.property); self.leave_node(kind); }