Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ast)!: add Program::comments #6445

Merged
merged 1 commit into from
Oct 11, 2024
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
1 change: 1 addition & 0 deletions .github/.generated_ast_watch_list.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ src:
- 'crates/oxc_ast/src/ast/js.rs'
- 'crates/oxc_ast/src/ast/ts.rs'
- 'crates/oxc_ast/src/ast/jsx.rs'
- 'crates/oxc_ast/src/ast/comment.rs'
- 'crates/oxc_syntax/src/number.rs'
- 'crates/oxc_syntax/src/operator.rs'
- 'crates/oxc_span/src/span/types.rs'
Expand Down
112 changes: 112 additions & 0 deletions crates/oxc_ast/src/ast/comment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use oxc_allocator::CloneIn;
use oxc_ast_macros::ast;
use oxc_span::{cmp::ContentEq, hash::ContentHash, Span};

#[ast]
#[generate_derive(CloneIn, ContentEq, ContentHash)]
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
pub enum CommentKind {
#[default]
Line = 0,
Block = 1,
}

#[ast]
#[generate_derive(CloneIn, ContentEq, ContentHash)]
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
pub enum CommentPosition {
/// Comments prior to a token until another token or trailing comment.
///
/// e.g.
///
/// ```
/// /* leading */ token;
/// /* leading */
/// // leading
/// token;
/// ```
#[default]
Leading = 0,

/// Comments tailing a token until a newline.
/// e.g. `token /* trailing */ // trailing`
Trailing = 1,
}

#[ast]
#[generate_derive(CloneIn, ContentEq, ContentHash)]
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
pub struct Comment {
/// The span of the comment text (without leading/trailing delimiters).
pub span: Span,

/// Line or block comment
pub kind: CommentKind,

/// Leading or trailing comment
pub position: CommentPosition,

/// Start of token this leading comment is attached to.
/// `/* Leading */ token`
/// ^ This start
/// NOTE: Trailing comment attachment is not computed yet.
pub attached_to: u32,

/// Whether this comment has a preceding newline.
/// Used to avoid becoming a trailing comment in codegen.
pub preceded_by_newline: bool,

/// Whether this comment has a tailing newline.
pub followed_by_newline: bool,
}

impl Comment {
#[inline]
pub fn new(start: u32, end: u32, kind: CommentKind) -> Self {
let span = Span::new(start, end);
Self {
span,
kind,
position: CommentPosition::Trailing,
attached_to: 0,
preceded_by_newline: false,
followed_by_newline: false,
}
}

pub fn is_line(self) -> bool {
self.kind == CommentKind::Line
}

pub fn is_block(self) -> bool {
self.kind == CommentKind::Block
}

pub fn is_leading(self) -> bool {
self.position == CommentPosition::Leading
}

pub fn is_trailing(self) -> bool {
self.position == CommentPosition::Trailing
}

pub fn real_span(&self) -> Span {
Span::new(self.real_span_start(), self.real_span_end())
}

pub fn real_span_end(&self) -> u32 {
match self.kind {
CommentKind::Line => self.span.end,
// length of `*/`
CommentKind::Block => self.span.end + 2,
}
}

pub fn real_span_start(&self) -> u32 {
self.span.start - 2
}

pub fn is_jsdoc(&self, source_text: &str) -> bool {
self.is_leading() && self.is_block() && self.span.source_text(source_text).starts_with('*')
}
}
3 changes: 3 additions & 0 deletions crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ pub struct Program<'a> {
pub source_type: SourceType,
#[serde(skip)]
pub source_text: &'a str,
/// Sorted comments
#[serde(skip)]
pub comments: Vec<'a, Comment>,
pub hashbang: Option<Hashbang<'a>>,
pub directives: Vec<'a, Directive<'a>>,
pub body: Vec<'a, Statement<'a>>,
Expand Down
3 changes: 2 additions & 1 deletion crates/oxc_ast/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@
//!
//! If you are seeing compile-time errors in `src/ast/macros.rs`, this will be the cause.

pub(crate) mod comment;
pub(crate) mod js;
pub(crate) mod jsx;
pub(crate) mod literal;
Expand All @@ -191,4 +192,4 @@ pub use oxc_syntax::{
},
};

pub use self::{js::*, jsx::*, literal::*, ts::*};
pub use self::{comment::*, js::*, jsx::*, literal::*, ts::*};
52 changes: 42 additions & 10 deletions crates/oxc_ast/src/generated/assert_layouts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,16 @@ const _: () = {
assert!(offset_of!(StringLiteral, span) == 0usize);
assert!(offset_of!(StringLiteral, value) == 8usize);

assert!(size_of::<Program>() == 128usize);
assert!(size_of::<Program>() == 160usize);
assert!(align_of::<Program>() == 8usize);
assert!(offset_of!(Program, span) == 0usize);
assert!(offset_of!(Program, source_type) == 8usize);
assert!(offset_of!(Program, source_text) == 16usize);
assert!(offset_of!(Program, hashbang) == 32usize);
assert!(offset_of!(Program, directives) == 56usize);
assert!(offset_of!(Program, body) == 88usize);
assert!(offset_of!(Program, scope_id) == 120usize);
assert!(offset_of!(Program, comments) == 32usize);
assert!(offset_of!(Program, hashbang) == 64usize);
assert!(offset_of!(Program, directives) == 88usize);
assert!(offset_of!(Program, body) == 120usize);
assert!(offset_of!(Program, scope_id) == 152usize);

assert!(size_of::<Expression>() == 16usize);
assert!(align_of::<Expression>() == 8usize);
Expand Down Expand Up @@ -1375,6 +1376,21 @@ const _: () = {
assert!(offset_of!(JSXText, span) == 0usize);
assert!(offset_of!(JSXText, value) == 8usize);

assert!(size_of::<CommentKind>() == 1usize);
assert!(align_of::<CommentKind>() == 1usize);

assert!(size_of::<CommentPosition>() == 1usize);
assert!(align_of::<CommentPosition>() == 1usize);

assert!(size_of::<Comment>() == 20usize);
assert!(align_of::<Comment>() == 4usize);
assert!(offset_of!(Comment, span) == 0usize);
assert!(offset_of!(Comment, kind) == 8usize);
assert!(offset_of!(Comment, position) == 9usize);
assert!(offset_of!(Comment, attached_to) == 12usize);
assert!(offset_of!(Comment, preceded_by_newline) == 16usize);
assert!(offset_of!(Comment, followed_by_newline) == 17usize);

assert!(size_of::<NumberBase>() == 1usize);
assert!(align_of::<NumberBase>() == 1usize);

Expand Down Expand Up @@ -1598,15 +1614,16 @@ const _: () = {
assert!(offset_of!(StringLiteral, span) == 0usize);
assert!(offset_of!(StringLiteral, value) == 8usize);

assert!(size_of::<Program>() == 72usize);
assert!(size_of::<Program>() == 88usize);
assert!(align_of::<Program>() == 4usize);
assert!(offset_of!(Program, span) == 0usize);
assert!(offset_of!(Program, source_type) == 8usize);
assert!(offset_of!(Program, source_text) == 12usize);
assert!(offset_of!(Program, hashbang) == 20usize);
assert!(offset_of!(Program, directives) == 36usize);
assert!(offset_of!(Program, body) == 52usize);
assert!(offset_of!(Program, scope_id) == 68usize);
assert!(offset_of!(Program, comments) == 20usize);
assert!(offset_of!(Program, hashbang) == 36usize);
assert!(offset_of!(Program, directives) == 52usize);
assert!(offset_of!(Program, body) == 68usize);
assert!(offset_of!(Program, scope_id) == 84usize);

assert!(size_of::<Expression>() == 8usize);
assert!(align_of::<Expression>() == 4usize);
Expand Down Expand Up @@ -2918,6 +2935,21 @@ const _: () = {
assert!(offset_of!(JSXText, span) == 0usize);
assert!(offset_of!(JSXText, value) == 8usize);

assert!(size_of::<CommentKind>() == 1usize);
assert!(align_of::<CommentKind>() == 1usize);

assert!(size_of::<CommentPosition>() == 1usize);
assert!(align_of::<CommentPosition>() == 1usize);

assert!(size_of::<Comment>() == 20usize);
assert!(align_of::<Comment>() == 4usize);
assert!(offset_of!(Comment, span) == 0usize);
assert!(offset_of!(Comment, kind) == 8usize);
assert!(offset_of!(Comment, position) == 9usize);
assert!(offset_of!(Comment, attached_to) == 12usize);
assert!(offset_of!(Comment, preceded_by_newline) == 16usize);
assert!(offset_of!(Comment, followed_by_newline) == 17usize);

assert!(size_of::<NumberBase>() == 1usize);
assert!(align_of::<NumberBase>() == 1usize);

Expand Down
7 changes: 6 additions & 1 deletion crates/oxc_ast/src/generated/ast_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ impl<'a> AstBuilder<'a> {
/// - span: The [`Span`] covering this node
/// - source_type
/// - source_text
/// - comments: Sorted comments
/// - hashbang
/// - directives
/// - body
Expand All @@ -231,6 +232,7 @@ impl<'a> AstBuilder<'a> {
span: Span,
source_type: SourceType,
source_text: S,
comments: Vec<'a, Comment>,
hashbang: Option<Hashbang<'a>>,
directives: Vec<'a, Directive<'a>>,
body: Vec<'a, Statement<'a>>,
Expand All @@ -242,6 +244,7 @@ impl<'a> AstBuilder<'a> {
span,
source_type,
source_text: source_text.into_in(self.allocator),
comments,
hashbang,
directives,
body,
Expand All @@ -257,6 +260,7 @@ impl<'a> AstBuilder<'a> {
/// - span: The [`Span`] covering this node
/// - source_type
/// - source_text
/// - comments: Sorted comments
/// - hashbang
/// - directives
/// - body
Expand All @@ -266,6 +270,7 @@ impl<'a> AstBuilder<'a> {
span: Span,
source_type: SourceType,
source_text: S,
comments: Vec<'a, Comment>,
hashbang: Option<Hashbang<'a>>,
directives: Vec<'a, Directive<'a>>,
body: Vec<'a, Statement<'a>>,
Expand All @@ -274,7 +279,7 @@ impl<'a> AstBuilder<'a> {
S: IntoIn<'a, &'a str>,
{
Box::new_in(
self.program(span, source_type, source_text, hashbang, directives, body),
self.program(span, source_type, source_text, comments, hashbang, directives, body),
self.allocator,
)
}
Expand Down
38 changes: 38 additions & 0 deletions crates/oxc_ast/src/generated/derive_clone_in.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

use oxc_allocator::{Allocator, CloneIn};

#[allow(clippy::wildcard_imports)]
use crate::ast::comment::*;

#[allow(clippy::wildcard_imports)]
use crate::ast::js::*;

Expand Down Expand Up @@ -113,6 +116,7 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for Program<'old_alloc> {
span: CloneIn::clone_in(&self.span, allocator),
source_type: CloneIn::clone_in(&self.source_type, allocator),
source_text: CloneIn::clone_in(&self.source_text, allocator),
comments: CloneIn::clone_in(&self.comments, allocator),
hashbang: CloneIn::clone_in(&self.hashbang, allocator),
directives: CloneIn::clone_in(&self.directives, allocator),
body: CloneIn::clone_in(&self.body, allocator),
Expand Down Expand Up @@ -4231,3 +4235,37 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for JSXText<'old_alloc> {
}
}
}

impl<'alloc> CloneIn<'alloc> for CommentKind {
type Cloned = CommentKind;
fn clone_in(&self, _: &'alloc Allocator) -> Self::Cloned {
match self {
Self::Line => CommentKind::Line,
Self::Block => CommentKind::Block,
}
}
}

impl<'alloc> CloneIn<'alloc> for CommentPosition {
type Cloned = CommentPosition;
fn clone_in(&self, _: &'alloc Allocator) -> Self::Cloned {
match self {
Self::Leading => CommentPosition::Leading,
Self::Trailing => CommentPosition::Trailing,
}
}
}

impl<'alloc> CloneIn<'alloc> for Comment {
type Cloned = Comment;
fn clone_in(&self, allocator: &'alloc Allocator) -> Self::Cloned {
Comment {
span: CloneIn::clone_in(&self.span, allocator),
kind: CloneIn::clone_in(&self.kind, allocator),
position: CloneIn::clone_in(&self.position, allocator),
attached_to: CloneIn::clone_in(&self.attached_to, allocator),
preceded_by_newline: CloneIn::clone_in(&self.preceded_by_newline, allocator),
followed_by_newline: CloneIn::clone_in(&self.followed_by_newline, allocator),
}
}
}
26 changes: 26 additions & 0 deletions crates/oxc_ast/src/generated/derive_content_eq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

use oxc_span::cmp::ContentEq;

#[allow(clippy::wildcard_imports)]
use crate::ast::comment::*;

#[allow(clippy::wildcard_imports)]
use crate::ast::js::*;

Expand Down Expand Up @@ -93,6 +96,7 @@ impl<'a> ContentEq for Program<'a> {
fn content_eq(&self, other: &Self) -> bool {
ContentEq::content_eq(&self.source_type, &other.source_type)
&& ContentEq::content_eq(&self.source_text, &other.source_text)
&& ContentEq::content_eq(&self.comments, &other.comments)
&& ContentEq::content_eq(&self.hashbang, &other.hashbang)
&& ContentEq::content_eq(&self.directives, &other.directives)
&& ContentEq::content_eq(&self.body, &other.body)
Expand Down Expand Up @@ -4212,3 +4216,25 @@ impl<'a> ContentEq for JSXText<'a> {
ContentEq::content_eq(&self.value, &other.value)
}
}

impl ContentEq for CommentKind {
fn content_eq(&self, other: &Self) -> bool {
self == other
}
}

impl ContentEq for CommentPosition {
fn content_eq(&self, other: &Self) -> bool {
self == other
}
}

impl ContentEq for Comment {
fn content_eq(&self, other: &Self) -> bool {
ContentEq::content_eq(&self.kind, &other.kind)
&& ContentEq::content_eq(&self.position, &other.position)
&& ContentEq::content_eq(&self.attached_to, &other.attached_to)
&& ContentEq::content_eq(&self.preceded_by_newline, &other.preceded_by_newline)
&& ContentEq::content_eq(&self.followed_by_newline, &other.followed_by_newline)
}
}
Loading