Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 38 additions & 20 deletions crates/oxc_ast/src/ast_impl/jsx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ impl fmt::Display for JSXNamespacedName<'_> {
}

impl<'a> JSXElementName<'a> {
/// Get this name's contained identifier reference, returning [`None`] if it
/// is some other variant. Note that [namespaced
/// identifiers](JSXElementName::NamespacedName) are not included.
/// Get this [`JSXElementName`]'s root identifier reference.
///
/// e.g. `Foo` in `<Foo>` or `<Foo.bar>` or `<Foo.bar.qux>`.
///
/// Returns [`None`] for any of:
/// * `<div>`
/// * `<this>`
/// * `<this.bar>`
/// * `<Foo:Bar>` - [namespaced identifiers](JSXElementName::NamespacedName)
pub fn get_identifier(&self) -> Option<&IdentifierReference<'a>> {
match self {
JSXElementName::Identifier(_)
Expand All @@ -34,7 +40,15 @@ impl<'a> JSXElementName<'a> {
}
}

#[expect(missing_docs)]
/// Get this [`JSXElementName`]'s identifier as an [`Atom`], if it is a plain identifier
/// or identifier reference.
///
/// e.g. `Foo` in `<Foo>`, or `div` in `<div>`.
///
/// Returns [`None`] for any of:
/// * `<this>`
/// * `<Foo.bar>`
/// * `<Foo:Bar>` - [namespaced identifiers](JSXElementName::NamespacedName)
pub fn get_identifier_name(&self) -> Option<Atom<'a>> {
match self {
Self::Identifier(id) => Some(id.as_ref().name),
Expand All @@ -45,17 +59,24 @@ impl<'a> JSXElementName<'a> {
}

impl<'a> JSXMemberExpression<'a> {
/// Get the identifier being referenced, if there is one. Will return
/// [`None`] for `this` expressions or if semantic analysis was skipped.
/// Get the identifier being referenced, if there is one.
///
/// e.g. `Foo` in `<Foo.bar>` or `<Foo.bar.qux>`.
///
/// Returns [`None`] if the root of the [`JSXMemberExpression`] is `this`
/// e.g. `<this.bar>` or `<this.bar.qux>`.
pub fn get_identifier(&self) -> Option<&IdentifierReference<'a>> {
self.object.get_identifier()
}
}

impl<'a> JSXMemberExpressionObject<'a> {
/// Get the identifier being referenced, if there is one. Will return
/// [`None`] for [`this`](JSXMemberExpressionObject::ThisExpression)
/// expressions or if semantic analysis was skipped.
/// Get the identifier being referenced, if there is one.
///
/// e.g. `Foo` in `<Foo.bar>` or `<Foo.bar.qux>`.
///
/// Returns [`None`] if the root of the [`JSXMemberExpressionObject`] is `this`
/// e.g. `<this.bar>` or `<this.bar.qux>`.
pub fn get_identifier(&self) -> Option<&IdentifierReference<'a>> {
let mut object = self;
loop {
Expand Down Expand Up @@ -99,7 +120,7 @@ impl fmt::Display for JSXElementName<'_> {
}

impl JSXExpression<'_> {
/// Determines whether the given expr is a `undefined` literal
/// Determines whether the given expr is a `undefined` literal.
pub fn is_undefined(&self) -> bool {
matches!(self, Self::Identifier(ident) if ident.name == "undefined")
}
Expand All @@ -114,8 +135,7 @@ impl JSXAttribute<'_> {
matches!(&self.name, JSXAttributeName::Identifier(ident) if ident.name == name)
}

/// Returns `true` if this attribute's name is the expected `name`, ignoring
/// casing.
/// Returns `true` if this attribute's name is the expected `name`, ignoring casing.
pub fn is_identifier_ignore_case(&self, name: &str) -> bool {
matches!(&self.name, JSXAttributeName::Identifier(ident) if ident.name.eq_ignore_ascii_case(name))
}
Expand All @@ -133,7 +153,8 @@ impl JSXAttribute<'_> {
}

impl<'a> JSXAttributeName<'a> {
/// Try to convert this attribute name into an [identifier](JSXIdentifier).
/// Try to convert this attribute name into an [`JSXIdentifier`].
///
/// Returns [`None`] for [namespaced names](JSXAttributeName::NamespacedName).
pub fn as_identifier(&self) -> Option<&JSXIdentifier<'a>> {
match self {
Expand All @@ -146,9 +167,8 @@ impl<'a> JSXAttributeName<'a> {
///
/// ## Example
/// ```tsx
/// <Foo /> // -> `Foo`
/// <Foo.Bar /> // -> `Bar`
/// <Foo.Bar.Baz /> // -> `Baz`
/// <Foo bar={123} /> // -> `bar`
/// <Foo bar:qux={123} /> // -> `qux`
/// ```
pub fn get_identifier(&self) -> &JSXIdentifier<'a> {
match self {
Expand All @@ -158,8 +178,7 @@ impl<'a> JSXAttributeName<'a> {
}
}
impl<'a> JSXAttributeValue<'a> {
/// Get the contained [`StringLiteral`], or [`None`] if this is some other
/// kind of value.
/// Get the contained [`StringLiteral`], or [`None`] if this is some other kind of value.
pub fn as_string_literal(&self) -> Option<&StringLiteral<'a>> {
match self {
Self::StringLiteral(lit) => Some(lit.as_ref()),
Expand All @@ -169,8 +188,7 @@ impl<'a> JSXAttributeValue<'a> {
}

impl<'a> JSXAttributeItem<'a> {
/// Get the contained [`JSXAttribute`] if it is an attribute item, otherwise
/// returns [`None`].
/// Get the contained [`JSXAttribute`] if it is an attribute item, otherwise returns [`None`].
///
/// This is the inverse of [`JSXAttributeItem::as_spread`].
pub fn as_attribute(&self) -> Option<&JSXAttribute<'a>> {
Expand Down
Loading