docs(span): enhance Span documentation (#6707)

Part of https://github.com/oxc-project/backlog/issues/130
This commit is contained in:
DonIsaac 2024-10-21 14:32:55 +00:00
parent 5b41eeaa9d
commit 85d52201b4

View file

@ -1,16 +1,61 @@
use oxc_ast_macros::ast; use oxc_ast_macros::ast;
use oxc_estree::ESTree; use oxc_estree::ESTree;
/// Newtype for working with text ranges /// A range in text, represented by a zero-indexed start and end offset.
/// ///
/// See the [`text-size`](https://docs.rs/text-size) crate for details. /// It is a logical error for `end` to be less than `start`.
/// Utility methods can be copied from the `text-size` crate if they are needed. ///
/// NOTE: `u32` is sufficient for "all" reasonable programs. Larger than u32 is a 4GB JS file. /// ```
/// # 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));
/// ```
/// ///
/// ## Hashing /// ## Hashing
/// [`Span`] has a normal implementation of [`Hash`]. If you want to compare two /// [`Span`] has a normal implementation of [`Hash`]. If you want to compare two
/// AST nodes without considering their locations (e.g. to see if they have the /// AST nodes without considering their locations (e.g. to see if they have the
/// same content), use [`ContentHash`](crate::hash::ContentHash) instead. /// same content), use [`ContentHash`](crate::hash::ContentHash) 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] #[ast]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[generate_derive(ESTree)] #[generate_derive(ESTree)]
@ -23,3 +68,30 @@ pub struct Span {
/// the span is empty, but should not be less than it. /// the span is empty, but should not be less than it.
pub end: u32, pub end: u32,
} }
#[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));
}
}