1use std::fmt::{self, Display};
4
5use oxc_span::Atom;
6
7use crate::ast::*;
8
9impl Display for JSXIdentifier<'_> {
12 #[inline]
13 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14 self.name.fmt(f)
15 }
16}
17
18impl Display for JSXNamespacedName<'_> {
19 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20 write!(f, "{}:{}", self.namespace.name, self.name.name)
21 }
22}
23
24impl<'a> JSXElementName<'a> {
25 pub fn get_identifier(&self) -> Option<&IdentifierReference<'a>> {
35 match self {
36 JSXElementName::Identifier(_)
37 | JSXElementName::NamespacedName(_)
38 | JSXElementName::ThisExpression(_) => None,
39 JSXElementName::IdentifierReference(ident) => Some(ident),
40 JSXElementName::MemberExpression(member_expr) => member_expr.get_identifier(),
41 }
42 }
43
44 pub fn get_identifier_name(&self) -> Option<Atom<'a>> {
54 match self {
55 Self::Identifier(id) => Some(id.as_ref().name),
56 Self::IdentifierReference(id) => Some(id.as_ref().name),
57 _ => None,
58 }
59 }
60}
61
62impl<'a> JSXMemberExpression<'a> {
63 pub fn get_identifier(&self) -> Option<&IdentifierReference<'a>> {
70 self.object.get_identifier()
71 }
72}
73
74impl<'a> JSXMemberExpressionObject<'a> {
75 pub fn get_identifier(&self) -> Option<&IdentifierReference<'a>> {
82 let mut object = self;
83 loop {
84 match object {
85 JSXMemberExpressionObject::IdentifierReference(ident) => return Some(ident),
86 JSXMemberExpressionObject::MemberExpression(member_expr) => {
87 object = &member_expr.object;
88 }
89 JSXMemberExpressionObject::ThisExpression(_) => return None,
90 }
91 }
92 }
93}
94
95impl Display for JSXMemberExpression<'_> {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 write!(f, "{}.{}", self.object, self.property)
98 }
99}
100
101impl Display for JSXMemberExpressionObject<'_> {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 match self {
104 Self::IdentifierReference(id) => id.fmt(f),
105 Self::MemberExpression(expr) => expr.fmt(f),
106 Self::ThisExpression(_) => "this".fmt(f),
107 }
108 }
109}
110
111impl Display for JSXElementName<'_> {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 match self {
114 Self::Identifier(ident) => ident.fmt(f),
115 Self::IdentifierReference(ident) => ident.fmt(f),
116 Self::NamespacedName(namespaced) => namespaced.fmt(f),
117 Self::MemberExpression(member_expr) => member_expr.fmt(f),
118 Self::ThisExpression(_) => "this".fmt(f),
119 }
120 }
121}
122
123impl JSXExpression<'_> {
124 pub fn is_undefined(&self) -> bool {
126 matches!(self, Self::Identifier(ident) if ident.name == "undefined")
127 }
128}
129
130impl JSXAttribute<'_> {
131 pub fn is_identifier(&self, name: &str) -> bool {
136 matches!(&self.name, JSXAttributeName::Identifier(ident) if ident.name == name)
137 }
138
139 pub fn is_identifier_ignore_case(&self, name: &str) -> bool {
141 matches!(&self.name, JSXAttributeName::Identifier(ident) if ident.name.eq_ignore_ascii_case(name))
142 }
143
144 pub fn is_key(&self) -> bool {
152 self.is_identifier("key")
153 }
154}
155
156impl<'a> JSXAttributeName<'a> {
157 pub fn as_identifier(&self) -> Option<&JSXIdentifier<'a>> {
161 match self {
162 Self::Identifier(ident) => Some(ident.as_ref()),
163 Self::NamespacedName(_) => None,
164 }
165 }
166
167 pub fn get_identifier(&self) -> &JSXIdentifier<'a> {
175 match self {
176 Self::Identifier(ident) => ident.as_ref(),
177 Self::NamespacedName(namespaced) => &namespaced.name,
178 }
179 }
180}
181impl<'a> JSXAttributeValue<'a> {
182 pub fn as_string_literal(&self) -> Option<&StringLiteral<'a>> {
184 match self {
185 Self::StringLiteral(lit) => Some(lit.as_ref()),
186 _ => None,
187 }
188 }
189}
190
191impl<'a> JSXAttributeItem<'a> {
192 pub fn as_attribute(&self) -> Option<&JSXAttribute<'a>> {
196 match self {
197 Self::Attribute(attr) => Some(attr),
198 Self::SpreadAttribute(_) => None,
199 }
200 }
201
202 pub fn as_spread(&self) -> Option<&JSXSpreadAttribute<'a>> {
207 match self {
208 Self::Attribute(_) => None,
209 Self::SpreadAttribute(spread) => Some(spread),
210 }
211 }
212}
213
214impl JSXChild<'_> {
215 pub const fn is_expression_container(&self) -> bool {
217 matches!(self, Self::ExpressionContainer(_))
218 }
219}