Skip to content
Merged
Show file tree
Hide file tree
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
16 changes: 16 additions & 0 deletions crates/oxc_ast/src/ast/comment.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
#![warn(missing_docs)]
use oxc_allocator::CloneIn;
use oxc_ast_macros::ast;
use oxc_span::{cmp::ContentEq, hash::ContentHash, Span};

/// Indicates a line or block comment.
#[ast]
#[generate_derive(CloneIn, ContentEq, ContentHash)]
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
pub enum CommentKind {
/// Line comment
#[default]
Line = 0,
/// Block comment
Block = 1,
}

/// Information about a comment's position relative to a token.
#[ast]
#[generate_derive(CloneIn, ContentEq, ContentHash)]
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
Expand All @@ -33,6 +38,7 @@ pub enum CommentPosition {
Trailing = 1,
}

/// A comment in source code.
#[ast]
#[generate_derive(CloneIn, ContentEq, ContentHash)]
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
Expand Down Expand Up @@ -61,6 +67,7 @@ pub struct Comment {
}

impl Comment {
/// Create a line or block comment at a given location.
#[inline]
pub fn new(start: u32, end: u32, kind: CommentKind) -> Self {
let span = Span::new(start, end);
Expand All @@ -74,26 +81,32 @@ impl Comment {
}
}

/// Returns `true` if this is a line comment.
pub fn is_line(self) -> bool {
self.kind == CommentKind::Line
}

/// Returns `true` if this is a block comment.
pub fn is_block(self) -> bool {
self.kind == CommentKind::Block
}

/// Returns `true` if this comment is before a token.
pub fn is_leading(self) -> bool {
self.position == CommentPosition::Leading
}

/// Returns `true` if this comment is after a token.
pub fn is_trailing(self) -> bool {
self.position == CommentPosition::Trailing
}

#[allow(missing_docs)]
pub fn real_span(&self) -> Span {
Span::new(self.real_span_start(), self.real_span_end())
}

#[allow(missing_docs)]
pub fn real_span_end(&self) -> u32 {
match self.kind {
CommentKind::Line => self.span.end,
Expand All @@ -102,10 +115,13 @@ impl Comment {
}
}

#[allow(missing_docs)]
pub fn real_span_start(&self) -> u32 {
self.span.start - 2
}

/// Returns `true` if this comment is a JSDoc comment. Implies `is_leading`
/// and `is_block`.
pub fn is_jsdoc(&self, source_text: &str) -> bool {
self.is_leading() && self.is_block() && self.span.source_text(source_text).starts_with('*')
}
Expand Down
49 changes: 49 additions & 0 deletions crates/oxc_ast/src/ast/jsx.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! [JSX](https://facebook.github.io/jsx)
#![warn(missing_docs)]

// NB: `#[span]`, `#[scope(...)]`,`#[visit(...)]` and `#[generate_derive(...)]` do NOT do anything to the code.
// They are purely markers for codegen used in `tasks/ast_tools` and `crates/oxc_traverse/scripts`. See docs in those crates.
Expand Down Expand Up @@ -35,6 +36,7 @@ use super::{inherit_variants, js::*, literal::*, ts::*};
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXElement<'a> {
#[estree(flatten)]
/// Node location in source code
pub span: Span,
/// Opening tag of the element.
pub opening_element: Box<'a, JSXOpeningElement<'a>>,
Expand Down Expand Up @@ -63,6 +65,7 @@ pub struct JSXElement<'a> {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXOpeningElement<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// Is this tag self-closing?
Expand All @@ -73,6 +76,7 @@ pub struct JSXOpeningElement<'a> {
/// <Foo> // <- self_closing = false
/// ```
pub self_closing: bool,
/// The possibly-namespaced tag name, e.g. `Foo` in `<Foo />`.
pub name: JSXElementName<'a>,
/// List of JSX attributes. In React-like applications, these become props.
pub attributes: Vec<'a, JSXAttributeItem<'a>>,
Expand All @@ -95,8 +99,10 @@ pub struct JSXOpeningElement<'a> {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXClosingElement<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// The tag name, e.g. `Foo` in `</Foo>`.
pub name: JSXElementName<'a>,
}

Expand All @@ -112,6 +118,7 @@ pub struct JSXClosingElement<'a> {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXFragment<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// `<>`
Expand All @@ -127,6 +134,7 @@ pub struct JSXFragment<'a> {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXOpeningFragment {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
}
Expand All @@ -136,6 +144,7 @@ pub struct JSXOpeningFragment {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXClosingFragment {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
}
Expand Down Expand Up @@ -169,6 +178,7 @@ pub enum JSXElementName<'a> {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXNamespacedName<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// Namespace portion of the name, e.g. `Apple` in `<Apple:Orange />`
Expand Down Expand Up @@ -196,6 +206,7 @@ pub struct JSXNamespacedName<'a> {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXMemberExpression<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// The object being accessed. This is everything before the last `.`.
Expand All @@ -204,13 +215,32 @@ pub struct JSXMemberExpression<'a> {
pub property: JSXIdentifier<'a>,
}

/// JSX Member Expression Object
///
/// Part of a [`JSXMemberExpression`]. This is the object being accessed in
/// namespace-like JSX tag names.
///
/// ## Example
/// ```tsx
/// const x = <Apple.Orange />
/// // ^^^^^ IdentifierReference
///
/// const y = <Apple.Orange.Banana />
/// // ^^^^^^^^^^^^ MemberExpression
///
/// const z = <this.Orange />
/// // ^^^^ ThisExpression
/// ```
#[ast(visit)]
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash)]
#[estree(untagged)]
pub enum JSXMemberExpressionObject<'a> {
/// `<Apple.Orange />`
IdentifierReference(Box<'a, IdentifierReference<'a>>) = 0,
/// `<Apple.Orange.Banana />`
MemberExpression(Box<'a, JSXMemberExpression<'a>>) = 1,
/// `<this.Orange />`
ThisExpression(Box<'a, ThisExpression>) = 2,
}

Expand All @@ -231,6 +261,7 @@ pub enum JSXMemberExpressionObject<'a> {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXExpressionContainer<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// The expression inside the container.
Expand All @@ -249,6 +280,13 @@ inherit_variants! {
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
#[estree(untagged)]
pub enum JSXExpression<'a> {
/// An empty expression
///
/// ## Example
/// ```tsx
/// <Foo bar={} />
/// // ^^
/// ```
EmptyExpression(JSXEmptyExpression) = 64,
// `Expression` variants added here by `inherit_variants!` macro
@inherit Expression
Expand All @@ -260,6 +298,7 @@ pub enum JSXExpression<'a> {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXEmptyExpression {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
}
Expand Down Expand Up @@ -301,6 +340,7 @@ pub enum JSXAttributeItem<'a> {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXAttribute<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// The name of the attribute. This is a prop in React-like applications.
Expand All @@ -322,8 +362,10 @@ pub struct JSXAttribute<'a> {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXSpreadAttribute<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// The expression being spread.
pub argument: Expression<'a>,
}

Expand Down Expand Up @@ -376,9 +418,13 @@ pub enum JSXAttributeName<'a> {
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
#[estree(untagged)]
pub enum JSXAttributeValue<'a> {
/// `<Component foo="bar" />`
StringLiteral(Box<'a, StringLiteral<'a>>) = 0,
/// `<Component foo={someExpr} />`
ExpressionContainer(Box<'a, JSXExpressionContainer<'a>>) = 1,
/// `<Component foo=<Element /> />`
Element(Box<'a, JSXElement<'a>>) = 2,
/// `<Component foo=<></> />`
Fragment(Box<'a, JSXFragment<'a>>) = 3,
}

Expand All @@ -391,6 +437,7 @@ pub enum JSXAttributeValue<'a> {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXIdentifier<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// The name of the identifier.
Expand Down Expand Up @@ -426,6 +473,7 @@ pub enum JSXChild<'a> {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXSpreadChild<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// The expression being spread.
Expand All @@ -446,6 +494,7 @@ pub struct JSXSpreadChild<'a> {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct JSXText<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// The text content.
Expand Down
27 changes: 21 additions & 6 deletions crates/oxc_ast/src/ast/literal.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! Literals
#![warn(missing_docs)]

// NB: `#[span]`, `#[scope(...)]`,`#[visit(...)]` and `#[generate_derive(...)]` do NOT do anything to the code.
// They are purely markers for codegen used in `tasks/ast_tools` and `crates/oxc_traverse/scripts`. See docs in those crates.
Expand All @@ -21,8 +22,10 @@ use oxc_syntax::number::{BigintBase, NumberBase};
#[derive(Debug, Clone)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct BooleanLiteral {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// The boolean value itself
pub value: bool,
}

Expand All @@ -33,6 +36,7 @@ pub struct BooleanLiteral {
#[derive(Debug, Clone)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
pub struct NullLiteral {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
}
Expand All @@ -44,13 +48,14 @@ pub struct NullLiteral {
#[derive(Debug, Clone)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
pub struct NumericLiteral<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// The value of the number, converted into base 10
pub value: f64,
/// The number as it appears in the source code
/// The number as it appears in source code
pub raw: &'a str,
/// The base representation used by the literal in the source code
/// The base representation used by the literal in source code
#[estree(skip)]
pub base: NumberBase,
}
Expand All @@ -60,11 +65,12 @@ pub struct NumericLiteral<'a> {
#[derive(Debug, Clone)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct BigIntLiteral<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// The bigint as it appears in the source code
/// The bigint as it appears in source code
pub raw: Atom<'a>,
/// The base representation used by the literal in the source code
/// The base representation used by the literal in source code
#[estree(skip)]
pub base: BigintBase,
}
Expand All @@ -76,11 +82,17 @@ pub struct BigIntLiteral<'a> {
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct RegExpLiteral<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
// valid regex is printed as {}
// invalid regex is printed as null, which we can't implement yet
/// Placeholder for printing.
///
/// Valid regular expressions are printed as `{}`, while invalid ones are
/// printed as `null`. Note that invalid regular expressions are not yet
/// printed properly.
pub value: EmptyObject,
/// The parsed regular expression. See [`oxc_regular_expression`] for more
/// details.
pub regex: RegExp<'a>,
}

Expand Down Expand Up @@ -117,6 +129,7 @@ pub enum RegExpPattern<'a> {
Pattern(Box<'a, Pattern<'a>>) = 2,
}

/// An empty object literal (`{}`)
#[ast]
#[derive(Debug, Clone)]
#[generate_derive(CloneIn, ContentEq, ContentHash, ESTree)]
Expand All @@ -130,8 +143,10 @@ pub struct EmptyObject;
#[derive(Debug, Clone)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)]
pub struct StringLiteral<'a> {
/// Node location in source code
#[estree(flatten)]
pub span: Span,
/// The string as it appears in source code
pub value: Atom<'a>,
}

Expand Down
Loading