diff --git a/crates/oxc_ast/src/ast_impl/js.rs b/crates/oxc_ast/src/ast_impl/js.rs index 8dd17b38b88e73..2ddd39a2208eb4 100644 --- a/crates/oxc_ast/src/ast_impl/js.rs +++ b/crates/oxc_ast/src/ast_impl/js.rs @@ -293,6 +293,13 @@ impl<'a> IdentifierName<'a> { } } +impl<'a> fmt::Display for IdentifierName<'a> { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.name.fmt(f) + } +} + impl<'a> Hash for IdentifierReference<'a> { fn hash(&self, state: &mut H) { self.name.hash(state); @@ -319,6 +326,12 @@ impl<'a> IdentifierReference<'a> { } } +impl<'a> fmt::Display for IdentifierReference<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.name.fmt(f) + } +} + impl<'a> Hash for BindingIdentifier<'a> { fn hash(&self, state: &mut H) { self.name.hash(state); @@ -331,6 +344,13 @@ impl<'a> BindingIdentifier<'a> { } } +impl<'a> fmt::Display for BindingIdentifier<'a> { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.name.fmt(f) + } +} + impl<'a> ArrayExpressionElement<'a> { pub fn is_elision(&self) -> bool { matches!(self, Self::Elision(_)) diff --git a/crates/oxc_ast/src/ast_impl/jsx.rs b/crates/oxc_ast/src/ast_impl/jsx.rs index 42624cb0a90066..8d41211334f491 100644 --- a/crates/oxc_ast/src/ast_impl/jsx.rs +++ b/crates/oxc_ast/src/ast_impl/jsx.rs @@ -1,12 +1,25 @@ //! [JSX](https://facebook.github.io/jsx) +use std::fmt; use crate::ast::*; use oxc_span::{Atom, Span}; // 1.2 JSX Elements -impl<'a> std::fmt::Display for JSXNamespacedName<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl<'a> JSXIdentifier<'a> { + pub fn new(span: Span, name: Atom<'a>) -> Self { + Self { span, name } + } +} +impl<'a> fmt::Display for JSXIdentifier<'a> { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.name.fmt(f) + } +} + +impl<'a> fmt::Display for JSXNamespacedName<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}:{}", self.namespace.name, self.property.name) } } @@ -41,6 +54,31 @@ impl<'a> JSXMemberExpression<'a> { } } +impl<'a> fmt::Display for JSXMemberExpression<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}.{}", self.object, self.property) + } +} + +impl<'a> fmt::Display for JSXMemberExpressionObject<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Identifier(id) => id.fmt(f), + Self::MemberExpression(expr) => expr.fmt(f), + } + } +} + +impl<'a> fmt::Display for JSXElementName<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Identifier(ident) => ident.fmt(f), + Self::NamespacedName(namespaced) => namespaced.fmt(f), + Self::MemberExpression(member_expr) => member_expr.fmt(f), + } + } +} + impl<'a> JSXExpression<'a> { /// Determines whether the given expr is a `undefined` literal pub fn is_undefined(&self) -> bool { @@ -57,9 +95,3 @@ impl<'a> JSXAttribute<'a> { self.is_identifier("key") } } - -impl<'a> JSXIdentifier<'a> { - pub fn new(span: Span, name: Atom<'a>) -> Self { - Self { span, name } - } -} diff --git a/crates/oxc_ast/src/ast_impl/ts.rs b/crates/oxc_ast/src/ast_impl/ts.rs index 1ec47a58be3a06..f7dcf2efba71f9 100644 --- a/crates/oxc_ast/src/ast_impl/ts.rs +++ b/crates/oxc_ast/src/ast_impl/ts.rs @@ -3,7 +3,7 @@ //! [AST Spec](https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/ast-spec) //! [Archived TypeScript spec](https://github.com/microsoft/TypeScript/blob/3c99d50da5a579d9fa92d02664b1b66d4ff55944/doc/spec-ARCHIVED.md) -use std::{cell::Cell, hash::Hash}; +use std::{cell::Cell, fmt, hash::Hash}; use oxc_allocator::Vec; use oxc_span::{Atom, Span}; @@ -100,6 +100,21 @@ impl<'a> TSTypeName<'a> { } } +impl<'a> fmt::Display for TSTypeName<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + TSTypeName::IdentifierReference(ident) => ident.fmt(f), + TSTypeName::QualifiedName(qualified) => qualified.fmt(f), + } + } +} + +impl<'a> fmt::Display for TSQualifiedName<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}.{}", self.left, self.right) + } +} + impl<'a> TSType<'a> { /// Remove nested parentheses from this type. pub fn without_parenthesized(&self) -> &Self { @@ -154,6 +169,15 @@ impl<'a> TSModuleDeclarationName<'a> { } } +impl<'a> fmt::Display for TSModuleDeclarationName<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Identifier(id) => id.fmt(f), + Self::StringLiteral(lit) => lit.fmt(f), + } + } +} + impl<'a> TSModuleDeclarationBody<'a> { pub fn is_strict(&self) -> bool { matches!(self, Self::TSModuleBlock(block) if block.is_strict()) diff --git a/crates/oxc_ast/src/ast_kind_impl.rs b/crates/oxc_ast/src/ast_kind_impl.rs index 53387a051259e2..5d14464d8d0a56 100644 --- a/crates/oxc_ast/src/ast_kind_impl.rs +++ b/crates/oxc_ast/src/ast_kind_impl.rs @@ -178,6 +178,18 @@ impl<'a> AstKind<'a> { /// Note that this method does not exist in release builds. Do not include /// usage of this method within your code. pub fn debug_name(&self) -> std::borrow::Cow { + use std::borrow::Cow; + + const COMPUTED: Cow<'static, str> = Cow::Borrowed(""); + const UNKNOWN: Cow<'static, str> = Cow::Borrowed(""); + const ANONYMOUS: Cow<'static, str> = Cow::Borrowed(""); + const DESTRUCTURE: Cow<'static, str> = Cow::Borrowed(""); + + #[inline] + fn or_anonymous<'a>(id: Option<&BindingIdentifier<'a>>) -> Cow<'a, str> { + id.map_or_else(|| ANONYMOUS.as_ref(), |id| id.name.as_str()).into() + } + match self { Self::Program(_) => "Program".into(), Self::Directive(d) => d.directive.as_ref().into(), @@ -195,7 +207,7 @@ impl<'a> AstKind<'a> { Self::ForStatement(_) => "ForStatement".into(), Self::ForStatementInit(_) => "ForStatementInit".into(), Self::IfStatement(_) => "IfStatement".into(), - Self::LabeledStatement(_) => "LabeledStatement".into(), + Self::LabeledStatement(l) => format!("LabeledStatement({})", l.label.name).into(), Self::ReturnStatement(_) => "ReturnStatement".into(), Self::SwitchStatement(_) => "SwitchStatement".into(), Self::ThrowStatement(_) => "ThrowStatement".into(), @@ -208,7 +220,11 @@ impl<'a> AstKind<'a> { Self::FinallyClause(_) => "FinallyClause".into(), Self::VariableDeclaration(_) => "VariableDeclaration".into(), - Self::VariableDeclarator(_) => "VariableDeclarator".into(), + Self::VariableDeclarator(v) => format!( + "VariableDeclarator({})", + v.id.get_identifier().unwrap_or(Atom::from(DESTRUCTURE.as_ref())) + ) + .into(), Self::UsingDeclaration(_) => "UsingDeclaration".into(), @@ -237,13 +253,26 @@ impl<'a> AstKind<'a> { Self::ArrowFunctionExpression(_) => "ArrowFunctionExpression".into(), Self::AssignmentExpression(_) => "AssignmentExpression".into(), Self::AwaitExpression(_) => "AwaitExpression".into(), - Self::BinaryExpression(b) => format!("BinaryExpression{}", b.operator.as_str()).into(), - Self::CallExpression(_) => "CallExpression".into(), + Self::BinaryExpression(b) => { + format!("BinaryExpression({})", b.operator.as_str()).into() + } + Self::CallExpression(c) => { + format!("CallExpression({})", c.callee_name().unwrap_or(&COMPUTED)).into() + } Self::ChainExpression(_) => "ChainExpression".into(), Self::ConditionalExpression(_) => "ConditionalExpression".into(), Self::LogicalExpression(_) => "LogicalExpression".into(), Self::MemberExpression(_) => "MemberExpression".into(), - Self::NewExpression(_) => "NewExpression".into(), + Self::NewExpression(n) => { + let callee = match &n.callee { + Expression::Identifier(id) => Some(id.name.as_str()), + match_member_expression!(Expression) => { + n.callee.to_member_expression().static_property_name() + } + _ => None, + }; + format!("NewExpression({})", callee.unwrap_or(&COMPUTED)).into() + } Self::ObjectExpression(_) => "ObjectExpression".into(), Self::ParenthesizedExpression(_) => "ParenthesizedExpression".into(), Self::SequenceExpression(_) => "SequenceExpression".into(), @@ -255,12 +284,16 @@ impl<'a> AstKind<'a> { Self::ImportExpression(_) => "ImportExpression".into(), Self::PrivateInExpression(_) => "PrivateInExpression".into(), - Self::ObjectProperty(_) => "ObjectProperty".into(), - Self::PropertyKey(_) => "PropertyKey".into(), + Self::ObjectProperty(p) => { + format!("ObjectProperty({})", p.key.name().unwrap_or(COMPUTED)).into() + } + Self::PropertyKey(p) => format!("PropertyKey({})", p.name().unwrap_or(COMPUTED)).into(), Self::Argument(_) => "Argument".into(), Self::ArrayExpressionElement(_) => "ArrayExpressionElement".into(), Self::AssignmentTarget(_) => "AssignmentTarget".into(), - Self::SimpleAssignmentTarget(_) => "SimpleAssignmentTarget".into(), + Self::SimpleAssignmentTarget(a) => { + format!("SimpleAssignmentTarget({})", a.get_identifier().unwrap_or(&UNKNOWN)).into() + } Self::AssignmentTargetPattern(_) => "AssignmentTargetPattern".into(), Self::ArrayAssignmentTarget(_) => "ArrayAssignmentTarget".into(), Self::ObjectAssignmentTarget(_) => "ObjectAssignmentTarget".into(), @@ -270,21 +303,17 @@ impl<'a> AstKind<'a> { Self::ExpressionArrayElement(_) => "ExpressionArrayElement".into(), Self::BindingRestElement(_) => "BindingRestElement".into(), - Self::Function(x) => format!( - "Function({})", - x.id.as_ref().map_or_else(|| "", |id| id.name.as_str()) - ) - .into(), + Self::Function(x) => format!("Function({})", or_anonymous(x.id.as_ref())).into(), Self::FunctionBody(_) => "FunctionBody".into(), Self::FormalParameters(_) => "FormalParameters".into(), - Self::FormalParameter(_) => "FormalParameter".into(), - Self::CatchParameter(_) => "CatchParameter".into(), - - Self::Class(c) => format!( - "Class({})", - c.id.as_ref().map_or_else(|| "", |id| id.name.as_str()) + Self::FormalParameter(p) => format!( + "FormalParameter({})", + p.pattern.get_identifier().unwrap_or(Atom::from(DESTRUCTURE.as_ref())) ) .into(), + Self::CatchParameter(_) => "CatchParameter".into(), + + Self::Class(c) => format!("Class({})", or_anonymous(c.id.as_ref())).into(), Self::TSClassImplements(_) => "TSClassImplements".into(), Self::ClassBody(_) => "ClassBody".into(), Self::ClassHeritage(_) => "ClassHeritage".into(), @@ -300,8 +329,8 @@ impl<'a> AstKind<'a> { Self::ModuleDeclaration(_) => "ModuleDeclaration".into(), Self::ImportDeclaration(_) => "ImportDeclaration".into(), - Self::ImportSpecifier(_) => "ImportSpecifier".into(), - Self::ExportSpecifier(_) => "ExportSpecifier".into(), + Self::ImportSpecifier(i) => format!("ImportSpecifier({})", i.local.name).into(), + Self::ExportSpecifier(e) => format!("ExportSpecifier({})", e.local.name()).into(), Self::ImportDefaultSpecifier(_) => "ImportDefaultSpecifier".into(), Self::ImportNamespaceSpecifier(_) => "ImportNamespaceSpecifier".into(), Self::ExportDefaultDeclaration(_) => "ExportDefaultDeclaration".into(), @@ -309,14 +338,14 @@ impl<'a> AstKind<'a> { Self::ExportAllDeclaration(_) => "ExportAllDeclaration".into(), Self::JSXOpeningElement(_) => "JSXOpeningElement".into(), Self::JSXClosingElement(_) => "JSXClosingElement".into(), - Self::JSXElementName(_) => "JSXElementName".into(), + Self::JSXElementName(n) => format!("JSXElementName({n})").into(), Self::JSXElement(_) => "JSXElement".into(), Self::JSXFragment(_) => "JSXFragment".into(), Self::JSXAttributeItem(_) => "JSXAttributeItem".into(), Self::JSXSpreadAttribute(_) => "JSXSpreadAttribute".into(), Self::JSXText(_) => "JSXText".into(), Self::JSXExpressionContainer(_) => "JSXExpressionContainer".into(), - Self::JSXIdentifier(_) => "JSXIdentifier".into(), + Self::JSXIdentifier(id) => format!("JSXIdentifier({id})").into(), Self::JSXMemberExpression(_) => "JSXMemberExpression".into(), Self::JSXMemberExpressionObject(_) => "JSXMemberExpressionObject".into(), Self::JSXNamespacedName(_) => "JSXNamespacedName".into(), @@ -329,7 +358,7 @@ impl<'a> AstKind<'a> { Self::TSMethodSignature(_) => "TSMethodSignature".into(), Self::TSNullKeyword(_) => "TSNullKeyword".into(), Self::TSTypeLiteral(_) => "TSTypeLiteral".into(), - Self::TSTypeReference(_) => "TSTypeReference".into(), + Self::TSTypeReference(t) => format!("TSTypeReference({})", t.type_name).into(), Self::TSUnionType(_) => "TSUnionType".into(), Self::TSParenthesizedType(_) => "TSParenthesizedType".into(), Self::TSVoidKeyword(_) => "TSVoidKeyword".into(), @@ -359,18 +388,18 @@ impl<'a> AstKind<'a> { Self::TSEnumMember(_) => "TSEnumMember".into(), Self::TSImportEqualsDeclaration(_) => "TSImportEqualsDeclaration".into(), - Self::TSTypeName(_) => "TSTypeName".into(), + Self::TSTypeName(n) => format!("TSTypeName({n})").into(), Self::TSExternalModuleReference(_) => "TSExternalModuleReference".into(), - Self::TSQualifiedName(_) => "TSQualifiedName".into(), + Self::TSQualifiedName(n) => format!("TSQualifiedName({n})").into(), Self::TSInterfaceDeclaration(_) => "TSInterfaceDeclaration".into(), Self::TSInterfaceHeritage(_) => "TSInterfaceHeritage".into(), - Self::TSModuleDeclaration(_) => "TSModuleDeclaration".into(), + Self::TSModuleDeclaration(m) => format!("TSModuleDeclaration({})", m.id).into(), Self::TSTypeAliasDeclaration(_) => "TSTypeAliasDeclaration".into(), Self::TSTypeAnnotation(_) => "TSTypeAnnotation".into(), Self::TSTypeQuery(_) => "TSTypeQuery".into(), Self::TSTypeAssertion(_) => "TSTypeAssertion".into(), Self::TSThisParameter(_) => "TSThisParameter".into(), - Self::TSTypeParameter(_) => "TSTypeParameter".into(), + Self::TSTypeParameter(t) => format!("TSTypeParameter({})", t.name).into(), Self::TSTypeParameterDeclaration(_) => "TSTypeParameterDeclaration".into(), Self::TSTypeParameterInstantiation(_) => "TSTypeParameterInstantiation".into(), Self::TSImportType(_) => "TSImportType".into(),