Skip to content

Commit

Permalink
docs(ast): enforce doc comments on JSX nodes, literal nodes, and comm…
Browse files Browse the repository at this point in the history
…ents
  • Loading branch information
DonIsaac committed Oct 21, 2024
1 parent 374b972 commit 99c74fc
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 129 deletions.
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

0 comments on commit 99c74fc

Please sign in to comment.