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

refactor(span): combine Span type and impls in 1 file #8900

Merged
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
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
Loading