docs(span): add doc comments to oxc_span::Span (#3543)

This commit is contained in:
Don Isaac 2024-06-05 13:05:34 -04:00 committed by GitHub
parent dd42f279f7
commit 1d3c0d7879
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -18,6 +18,23 @@ pub const SPAN: Span = Span::new(0, 0);
/// 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.
/// NOTE: `u32` is sufficient for "all" reasonable programs. Larger than u32 is a 4GB JS file.
///
/// ## Hashing
/// [`Span`]'s implementation of [`Hash`] is a no-op so that AST nodes can be
/// compared by hash. This makes them unsuitable for use as keys in a hash map.
///
/// ```
/// use std::hash::{Hash, Hasher, DefaultHasher};
/// use oxc_span::Span;
///
/// let mut first = DefaultHasher::new();
/// let mut second = DefaultHasher::new();
///
/// Span::new(0, 5).hash(&mut first);
/// Span::new(10, 20).hash(&mut second);
///
/// assert_eq!(first.finish(), second.finish());
/// ```
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[non_exhaustive] // disallow struct expression constructor `Span {}`
@ -27,21 +44,75 @@ pub struct Span {
}
impl Span {
/// Create a new [`Span`] from a start and end position.
///
/// # Invariants
/// The `start` position must be less than or equal to `end`. Note that this
/// invariant is only checked in debug builds to avoid a performance
/// penalty.
///
#[inline]
pub const fn new(start: u32, end: u32) -> Self {
Self { start, end }
}
/// Get the number of characters covered by the [`Span`].
///
/// # Example
/// ```
/// use oxc_span::Span;
///
/// assert_eq!(Span::new(1, 1).size(), 0);
/// assert_eq!(Span::new(0, 5).size(), 5);
/// assert_eq!(Span::new(5, 10).size(), 5);
/// ```
pub fn size(&self) -> u32 {
debug_assert!(self.start <= self.end);
self.end - self.start
}
/// Returns `true` if `self` covers a range of zero length.
///
/// # Example
/// ```
/// use oxc_span::Span;
///
/// assert!(Span::new(0, 0).is_empty());
/// assert!(Span::new(5, 5).is_empty());
/// assert!(!Span::new(0, 5).is_empty());
/// ```
pub fn is_empty(&self) -> bool {
debug_assert!(self.start <= self.end);
self.start == self.end
}
/// Create a [`Span`] covering the maximum range of two [`Span`]s.
///
/// # Example
/// ```
/// use oxc_span::Span;
///
/// let span1 = Span::new(0, 5);
/// let span2 = Span::new(3, 8);
/// let merged_span = span1.merge(&span2);
/// assert_eq!(merged_span, Span::new(0, 8));
/// ```
#[must_use]
pub fn merge(&self, other: &Self) -> Self {
Self::new(self.start.min(other.start), self.end.max(other.end))
}
/// Get a snippet of text from a source string that the [`Span`] covers.
///
/// # Example
/// ```
/// use oxc_span::Span;
///
/// let source = "function add (a, b) { return a + b; }";
/// let name_span = Span::new(9, 12);
/// let name = name_span.source_text(source);
/// assert_eq!(name_span.size(), name.len() as u32);
/// ```
pub fn source_text<'a>(&self, source_text: &'a str) -> &'a str {
&source_text[self.start as usize..self.end as usize]
}
@ -49,7 +120,7 @@ impl Span {
impl Hash for Span {
fn hash<H: Hasher>(&self, _state: &mut H) {
// hash to nothing so all ast spans can be comparible with hash
// hash to nothing so all ast spans can be comparable with hash
}
}
@ -69,3 +140,36 @@ impl From<Span> for LabeledSpan {
pub trait GetSpan {
fn span(&self) -> Span;
}
#[cfg(test)]
mod test {
use super::Span;
#[test]
fn test_hash() {
use std::hash::{DefaultHasher, Hash, Hasher};
let mut first = DefaultHasher::new();
let mut second = DefaultHasher::new();
Span::new(0, 5).hash(&mut first);
Span::new(10, 20).hash(&mut second);
assert_eq!(first.finish(), second.finish());
}
#[test]
fn test_eq() {
assert_eq!(Span::new(0, 0), Span::new(0, 0));
assert_eq!(Span::new(0, 1), Span::new(0, 1));
assert_ne!(Span::new(0, 0), Span::new(0, 1));
}
#[test]
fn test_ordering_less() {
assert!(Span::new(0, 0) < Span::new(0, 1));
assert!(Span::new(0, 3) < Span::new(2, 5));
}
#[test]
fn test_ordering_greater() {
assert!(Span::new(0, 1) > Span::new(0, 0));
assert!(Span::new(2, 5) > Span::new(0, 3));
}
}