From 0dc873698b57d082bd167b229e5d1cdb81d025af Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 11 Mar 2023 19:54:42 -0800 Subject: [PATCH] Add DelimSpan to hold the 3 different spans of a delimiter --- src/extra.rs | 100 ++++++++++++++++++++++++++++++++++++++++++++++++ src/fallback.rs | 8 ++-- src/lib.rs | 10 +++++ 3 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 src/extra.rs diff --git a/src/extra.rs b/src/extra.rs new file mode 100644 index 0000000..daf4ba1 --- /dev/null +++ b/src/extra.rs @@ -0,0 +1,100 @@ +//! Items which do not have a correspondence to any API in the proc_macro crate, +//! but are necessary to include in proc-macro2. + +use crate::fallback; +use crate::imp; +use crate::marker::Marker; +use crate::Span; +use core::fmt::{self, Debug}; + +/// An object that holds a [`Group`]'s `span_open()` and `span_close()` together +/// (in a more compact representation than holding those 2 spans individually. +/// +/// [`Group`]: crate::Group +#[derive(Copy, Clone)] +pub struct DelimSpan { + inner: DelimSpanEnum, + _marker: Marker, +} + +#[derive(Copy, Clone)] +enum DelimSpanEnum { + #[cfg(wrap_proc_macro)] + Compiler { + join: proc_macro::Span, + #[cfg(not(no_group_open_close))] + open: proc_macro::Span, + #[cfg(not(no_group_open_close))] + close: proc_macro::Span, + }, + Fallback(fallback::Span), +} + +impl DelimSpan { + pub(crate) fn new(group: &imp::Group) -> Self { + #[cfg(wrap_proc_macro)] + let inner = match group { + imp::Group::Compiler(group) => DelimSpanEnum::Compiler { + join: group.span(), + #[cfg(not(no_group_open_close))] + open: group.span_open(), + #[cfg(not(no_group_open_close))] + close: group.span_close(), + }, + imp::Group::Fallback(group) => DelimSpanEnum::Fallback(group.span()), + }; + + #[cfg(not(wrap_proc_macro))] + let inner = DelimSpanEnum::Fallback(group.span()); + + DelimSpan { + inner, + _marker: Marker, + } + } + + /// Returns a span covering the entire delimited group. + pub fn join(&self) -> Span { + match &self.inner { + #[cfg(wrap_proc_macro)] + DelimSpanEnum::Compiler { join, .. } => Span::_new(imp::Span::Compiler(*join)), + DelimSpanEnum::Fallback(span) => Span::_new_stable(*span), + } + } + + /// Returns a span for the opening punctuation of the group only. + pub fn open(&self) -> Span { + match &self.inner { + #[cfg(wrap_proc_macro)] + DelimSpanEnum::Compiler { + #[cfg(not(no_group_open_close))] + open, + #[cfg(no_group_open_close)] + join: open, + .. + } => Span::_new(imp::Span::Compiler(*open)), + DelimSpanEnum::Fallback(span) => Span::_new_stable(span.first_byte()), + } + } + + /// Returns a span for the closing punctuation of the group only. + pub fn close(&self) -> Span { + match &self.inner { + #[cfg(wrap_proc_macro)] + DelimSpanEnum::Compiler { + #[cfg(not(no_group_open_close))] + close, + #[cfg(no_group_open_close)] + join: close, + .. + } => Span::_new(imp::Span::Compiler(*close)), + DelimSpanEnum::Fallback(span) => Span::_new_stable(span.last_byte()), + } + } +} + +impl Debug for DelimSpan { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(&self.join(), f) + } +} diff --git a/src/fallback.rs b/src/fallback.rs index 587395d..52bdcf7 100644 --- a/src/fallback.rs +++ b/src/fallback.rs @@ -555,12 +555,12 @@ impl Span { } #[cfg(not(span_locations))] - fn first_byte(self) -> Self { + pub(crate) fn first_byte(self) -> Self { self } #[cfg(span_locations)] - fn first_byte(self) -> Self { + pub(crate) fn first_byte(self) -> Self { Span { lo: self.lo, hi: cmp::min(self.lo.saturating_add(1), self.hi), @@ -568,12 +568,12 @@ impl Span { } #[cfg(not(span_locations))] - fn last_byte(self) -> Self { + pub(crate) fn last_byte(self) -> Self { self } #[cfg(span_locations)] - fn last_byte(self) -> Self { + pub(crate) fn last_byte(self) -> Self { Span { lo: cmp::max(self.hi.saturating_sub(1), self.lo), hi: self.hi, diff --git a/src/lib.rs b/src/lib.rs index 90a5803..9e0f7fd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -134,6 +134,8 @@ mod detection; #[doc(hidden)] pub mod fallback; +pub mod extra; + #[cfg(not(wrap_proc_macro))] use crate::fallback as imp; #[path = "wrapper.rs"] @@ -143,6 +145,7 @@ mod imp; #[cfg(span_locations)] mod location; +use crate::extra::DelimSpan; use crate::marker::Marker; use core::cmp::Ordering; use core::fmt::{self, Debug, Display}; @@ -727,6 +730,13 @@ impl Group { Span::_new(self.inner.span_close()) } + /// Returns an object that holds this group's `span_open()` and + /// `span_close()` together (in a more compact representation than holding + /// those 2 spans individually). + pub fn delim_span(&self) -> DelimSpan { + DelimSpan::new(&self.inner) + } + /// Configures the span for this `Group`'s delimiters, but not its internal /// tokens. ///