Skip to content

Commit

Permalink
Merge pull request #366 from dtolnay-contrib/delim
Browse files Browse the repository at this point in the history
Add DelimSpan to hold the 3 different spans of a delimiter
  • Loading branch information
dtolnay committed Mar 12, 2023
2 parents 1e7fc7b + 0dc8736 commit 65699c4
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 4 deletions.
100 changes: 100 additions & 0 deletions 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)
}
}
8 changes: 4 additions & 4 deletions src/fallback.rs
Expand Up @@ -555,25 +555,25 @@ 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),
}
}

#[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,
Expand Down
10 changes: 10 additions & 0 deletions src/lib.rs
Expand Up @@ -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"]
Expand All @@ -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};
Expand Down Expand Up @@ -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.
///
Expand Down

0 comments on commit 65699c4

Please sign in to comment.