Skip to content

Commit

Permalink
refactor(span): combine Span type and impls in 1 file
Browse files Browse the repository at this point in the history
  • Loading branch information
overlookmotel committed Feb 4, 2025
1 parent 80264d4 commit 4de0f57
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 121 deletions.
2 changes: 1 addition & 1 deletion .github/.generated_ast_watch_list.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_span/src/generated/derive_estree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
Expand Down
133 changes: 117 additions & 16 deletions crates/oxc_span/src/span/mod.rs → crates/oxc_span/src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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};
Expand Down
102 changes: 0 additions & 102 deletions crates/oxc_span/src/span/types.rs

This file was deleted.

2 changes: 1 addition & 1 deletion tasks/ast_tools/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
];
Expand Down

0 comments on commit 4de0f57

Please sign in to comment.