Merge pull request #366 from dtolnay-contrib/delim

Add DelimSpan to hold the 3 different spans of a delimiter
This commit is contained in:
David Tolnay 2023-03-12 14:01:51 -07:00 committed by GitHub
commit 65699c4bcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 114 additions and 4 deletions

100
src/extra.rs Normal file
View File

@ -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)
}
}

View File

@ -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,

View File

@ -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.
///