From 6cff132c80c59acfd8c8a49e23b10b06cce27ba8 Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Wed, 19 Nov 2025 14:03:06 +0000 Subject: [PATCH] feat(span): add `Span::merge_within` method (#15869) Add `Span::merge_within` method that creates a connected Span that is covered by both Spans if they are within a specified Span. The bug described in the OP of #15778 is caused by trying to create a Span assuming that the Spans are adjacent. This method would avoid that kind of issue. --- crates/oxc_span/src/span.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/crates/oxc_span/src/span.rs b/crates/oxc_span/src/span.rs index b8b7e7e9ed7d6..fadec4453fe04 100644 --- a/crates/oxc_span/src/span.rs +++ b/crates/oxc_span/src/span.rs @@ -226,6 +226,28 @@ impl Span { Self::new(self.start.min(other.start), self.end.max(other.end)) } + /// Create a [`Span`] covering the maximum range of two [`Span`]s if that range is within the specified `within` [`Span`]. + /// + /// # Example + /// ``` + /// use oxc_span::Span; + /// + /// let span1 = Span::new(0, 3); + /// let span2 = Span::new(3, 8); + /// let merged_span = span1.merge_within(span2, Span::new(0, 12)); + /// assert_eq!(merged_span, Some(Span::new(0, 8))); + /// + /// let span1 = Span::new(0, 1); + /// let span2 = Span::new(5, 8); + /// let merged_span = span1.merge_within(span2, Span::new(0, 4)); + /// assert_eq!(merged_span, None); + /// ``` + #[must_use] + pub fn merge_within(self, other: Self, within: Self) -> Option { + let merged = self.merge(other); + if within.contains_inclusive(merged) { Some(merged) } else { None } + } + /// Create a [`Span`] that is grown by `offset` on either side. /// /// This is equivalent to `span.expand_left(offset).expand_right(offset)`.