diff --git a/.github/.generated_ast_watch_list.yml b/.github/.generated_ast_watch_list.yml index 1b5622a939b8e..c7773930a04a6 100644 --- a/.github/.generated_ast_watch_list.yml +++ b/.github/.generated_ast_watch_list.yml @@ -29,7 +29,7 @@ src: - 'crates/oxc_regular_expression/src/generated/derive_get_address.rs' - 'crates/oxc_span/src/generated/derive_estree.rs' - 'crates/oxc_span/src/source_type/mod.rs' - - 'crates/oxc_span/src/span/types.rs' + - 'crates/oxc_span/src/span.rs' - 'crates/oxc_syntax/src/generated/derive_clone_in.rs' - 'crates/oxc_syntax/src/generated/derive_content_eq.rs' - 'crates/oxc_syntax/src/generated/derive_estree.rs' diff --git a/crates/oxc_span/src/generated/derive_estree.rs b/crates/oxc_span/src/generated/derive_estree.rs index a6ba2fe6808e4..a321e0ac20504 100644 --- a/crates/oxc_span/src/generated/derive_estree.rs +++ b/crates/oxc_span/src/generated/derive_estree.rs @@ -6,7 +6,7 @@ use serde::{ser::SerializeMap, Serialize, Serializer}; use crate::source_type::*; -use crate::span::types::*; +use crate::span::*; impl Serialize for Span { fn serialize(&self, serializer: S) -> Result { diff --git a/crates/oxc_span/src/span/mod.rs b/crates/oxc_span/src/span.rs similarity index 83% rename from crates/oxc_span/src/span/mod.rs rename to crates/oxc_span/src/span.rs index 73d9e38282e90..6e74ace6b2c7e 100644 --- a/crates/oxc_span/src/span/mod.rs +++ b/crates/oxc_span/src/span.rs @@ -6,23 +6,85 @@ use std::{ use miette::{LabeledSpan, SourceOffset, SourceSpan}; -pub mod types; use oxc_allocator::{Allocator, CloneIn}; -pub use types::Span; +use oxc_ast_macros::ast; +use oxc_estree::ESTree; -/// An Empty span useful for creating AST nodes. +/// An empty span. +/// +/// Should be used for newly created new AST nodes. pub const SPAN: Span = Span::new(0, 0); -/// Zero-sized type which has pointer alignment (8 on 64-bit, 4 on 32-bit). -#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -#[repr(transparent)] -struct PointerAlign([usize; 0]); - -impl PointerAlign { - #[inline] - const fn new() -> Self { - Self([]) - } +/// A range in text, represented by a zero-indexed start and end offset. +/// +/// It is a logical error for `end` to be less than `start`. +/// +/// ``` +/// # use oxc_span::Span; +/// let text = "foo bar baz"; +/// let span = Span::new(4, 7); +/// assert_eq!(&text[span], "bar"); +/// ``` +/// +/// Spans use `u32` for offsets, meaning only files up to 4GB are supported. +/// This is sufficient for "all" reasonable programs. This tradeof cuts the size +/// of `Span` in half, offering a sizeable performance improvement and memory +/// footprint reduction. +/// +/// ## Creating Spans +/// Span offers several constructors, each of which is more or less convenient +/// depending on the context. In general, [`Span::new`] is sufficient for most +/// cases. If you want to create a span starting at some point of a certain +/// length, you can use [`Span::sized`]. +/// +/// ``` +/// # use oxc_span::Span; +/// let a = Span::new(5, 10); // Start and end offsets +/// let b = Span::sized(5, 5); // Start offset and size +/// assert_eq!(a, b); +/// ``` +/// +/// ## Re-Sizing Spans +/// Span offsets can be mutated directly, but it is often more convenient to use +/// one of the [`expand`] or [`shrink`] methods. Each of these create a new span +/// without modifying the original. +/// +/// ``` +/// # use oxc_span::Span; +/// let s = Span::new(5, 10); +/// assert_eq!(s.shrink(2), Span::new(7, 8)); +/// assert_eq!(s.shrink(2), s.shrink_left(2).shrink_right(2)); +/// +/// assert_eq!(s.expand(5), Span::new(0, 15)); +/// assert_eq!(s.expand(5), s.expand_left(5).expand_right(5)); +/// ``` +/// +/// ## Comparison +/// [`Span`] has a normal implementation of [`PartialEq`]. If you want to compare two +/// AST nodes without considering their locations (e.g. to see if they have the +/// same content), use [`ContentEq`] instead. +/// +/// ## Implementation Notes +/// See the [`text-size`](https://docs.rs/text-size) crate for details. +/// Utility methods can be copied from the `text-size` crate if they are needed. +/// +/// [`expand`]: Span::expand +/// [`shrink`]: Span::shrink +/// [`ContentEq`]: crate::ContentEq +#[ast(visit)] +#[derive(Default, Clone, Copy, Eq, PartialOrd, Ord)] +#[generate_derive(ESTree)] +#[content_eq(skip)] +#[estree(no_type, flatten)] +pub struct Span { + /// The zero-based start offset of the span + pub start: u32, + /// The zero-based end offset of the span. This may be equal to [`start`](Span::start) if + /// the span is empty, but should not be less than it. + pub end: u32, + /// Align `Span` on 8 on 64-bit platforms + #[estree(skip)] + _align: PointerAlign, } impl Span { @@ -445,13 +507,13 @@ impl Debug for Span { } } -/// Get the span for an AST node +/// Get the span for an AST node. pub trait GetSpan { - /// Get the [`Span`] for an AST node + /// Get the [`Span`] for an AST node. fn span(&self) -> Span; } -/// Get mutable ref to span for an AST node +/// Get mutable ref to span for an AST node. pub trait GetSpanMut { /// Get a mutable reference to an AST node's [`Span`]. fn span_mut(&mut self) -> &mut Span; @@ -480,6 +542,18 @@ impl<'a> CloneIn<'a> for Span { } } +/// Zero-sized type which has pointer alignment (8 on 64-bit, 4 on 32-bit). +#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[repr(transparent)] +struct PointerAlign([usize; 0]); + +impl PointerAlign { + #[inline] + const fn new() -> Self { + Self([]) + } +} + #[cfg(test)] mod test { use super::Span; @@ -598,6 +672,33 @@ mod test { } } +#[cfg(test)] +mod doctests { + use super::Span; + + /// Tests from [`Span`] docs, since rustdoc test runner is disabled + #[test] + fn doctest() { + // 1 + let text = "foo bar baz"; + let span = Span::new(4, 7); + assert_eq!(&text[span], "bar"); + + // 2 + let a = Span::new(5, 10); // Start and end offsets + let b = Span::sized(5, 5); // Start offset and size + assert_eq!(a, b); + + // 3 + let s = Span::new(5, 10); + assert_eq!(s.shrink(2), Span::new(7, 8)); + assert_eq!(s.shrink(2), s.shrink_left(2).shrink_right(2)); + + assert_eq!(s.expand(5), Span::new(0, 15)); + assert_eq!(s.expand(5), s.expand_left(5).expand_right(5)); + } +} + #[cfg(test)] mod size_asserts { use std::mem::{align_of, size_of}; diff --git a/crates/oxc_span/src/span/types.rs b/crates/oxc_span/src/span/types.rs deleted file mode 100644 index e3a1d6918f960..0000000000000 --- a/crates/oxc_span/src/span/types.rs +++ /dev/null @@ -1,102 +0,0 @@ -use oxc_ast_macros::ast; -use oxc_estree::ESTree; - -use super::PointerAlign; - -/// A range in text, represented by a zero-indexed start and end offset. -/// -/// It is a logical error for `end` to be less than `start`. -/// -/// ``` -/// # use oxc_span::Span; -/// let text = "foo bar baz"; -/// let span = Span::new(4, 7); -/// assert_eq!(&text[span], "bar"); -/// ``` -/// -/// Spans use `u32` for offsets, meaning only files up to 4GB are supported. -/// This is sufficient for "all" reasonable programs. This tradeof cuts the size -/// of `Span` in half, offering a sizeable performance improvement and memory -/// footprint reduction. -/// -/// ## Creating Spans -/// Span offers several constructors, each of which is more or less convenient -/// depending on the context. In general, [`Span::new`] is sufficient for most -/// cases. If you want to create a span starting at some point of a certain -/// length, you can use [`Span::sized`]. -/// -/// ``` -/// # use oxc_span::Span; -/// let a = Span::new(5, 10); // Start and end offsets -/// let b = Span::sized(5, 5); // Start offset and size -/// assert_eq!(a, b); -/// ``` -/// -/// ## Re-Sizing Spans -/// Span offsets can be mutated directly, but it is often more convenient to use -/// one of the [`expand`] or [`shrink`] methods. Each of these create a new span -/// without modifying the original. -/// -/// ``` -/// # use oxc_span::Span; -/// let s = Span::new(5, 10); -/// assert_eq!(s.shrink(2), Span::new(7, 8)); -/// assert_eq!(s.shrink(2), s.shrink_left(2).shrink_right(2)); -/// -/// assert_eq!(s.expand(5), Span::new(0, 15)); -/// assert_eq!(s.expand(5), s.expand_left(5).expand_right(5)); -/// ``` -/// -/// ## Comparison -/// [`Span`] has a normal implementation of [`PartialEq`]. If you want to compare two -/// AST nodes without considering their locations (e.g. to see if they have the -/// same content), use [`ContentEq`](crate::ContentEq) instead. -/// -/// ## Implementation Notes -/// See the [`text-size`](https://docs.rs/text-size) crate for details. -/// Utility methods can be copied from the `text-size` crate if they are needed. -/// -/// [`expand`]: Span::expand -/// [`shrink`]: Span::shrink -#[ast(visit)] -#[derive(Default, Clone, Copy, Eq, PartialOrd, Ord)] -#[generate_derive(ESTree)] -#[content_eq(skip)] -#[estree(no_type, flatten)] -pub struct Span { - /// The zero-based start offset of the span - pub start: u32, - /// The zero-based end offset of the span. This may be equal to [`start`](Span::start) if - /// the span is empty, but should not be less than it. - pub end: u32, - /// Align `Span` on 8 on 64-bit platforms - #[estree(skip)] - pub(super) _align: PointerAlign, -} - -#[cfg(test)] -mod test { - use super::Span; - - /// Tests from [`Span`] docs, since rustdoc test runner is disabled - #[test] - fn doctest() { - // 1 - let text = "foo bar baz"; - let span = Span::new(4, 7); - assert_eq!(&text[span], "bar"); - - // 2 - let a = Span::new(5, 10); // Start and end offsets - let b = Span::sized(5, 5); // Start offset and size - assert_eq!(a, b); - - // 3 - let s = Span::new(5, 10); - assert_eq!(s.shrink(2), Span::new(7, 8)); - assert_eq!(s.shrink(2), s.shrink_left(2).shrink_right(2)); - - assert_eq!(s.expand(5), Span::new(0, 15)); - assert_eq!(s.expand(5), s.expand_left(5).expand_right(5)); - } -} diff --git a/tasks/ast_tools/src/main.rs b/tasks/ast_tools/src/main.rs index 275fd28959257..31d5acbaf954b 100644 --- a/tasks/ast_tools/src/main.rs +++ b/tasks/ast_tools/src/main.rs @@ -206,7 +206,7 @@ static SOURCE_PATHS: &[&str] = &[ "crates/oxc_syntax/src/scope.rs", "crates/oxc_syntax/src/symbol.rs", "crates/oxc_syntax/src/reference.rs", - "crates/oxc_span/src/span/types.rs", + "crates/oxc_span/src/span.rs", "crates/oxc_span/src/source_type/mod.rs", "crates/oxc_regular_expression/src/ast.rs", ];