use proc_macro2::{Span, TokenStream, TokenTree};
use syn::{punctuated::Punctuated, Token};
pub trait Spanned {
fn span(&self) -> Span;
fn set_span(&mut self, span: Span);
}
impl Spanned for Span {
#[inline]
fn span(&self) -> Span {
*self
}
#[inline]
fn set_span(&mut self, span: Span) {
*self = span;
}
}
impl Spanned for TokenStream {
#[inline]
fn span(&self) -> Span {
syn::spanned::Spanned::span(self)
}
#[inline]
fn set_span(&mut self, span: Span) {
crate::utils::set_spans_clone(self, span);
}
}
impl Spanned for TokenTree {
#[inline]
fn span(&self) -> Span {
self.span()
}
#[inline]
fn set_span(&mut self, span: Span) {
self.set_span(span);
}
}
impl Spanned for syn::LitStr {
fn span(&self) -> Span {
self.span()
}
fn set_span(&mut self, span: Span) {
self.set_span(span);
}
}
impl<T: Spanned> Spanned for Option<T> {
#[inline]
fn span(&self) -> Span {
match self {
Some(t) => t.span(),
None => Span::call_site(),
}
}
#[inline]
fn set_span(&mut self, span: Span) {
if let Some(t) = self {
t.set_span(span);
}
}
}
impl<T: ?Sized + Spanned + Clone> Spanned for &T {
#[inline]
fn span(&self) -> Span {
(**self).span()
}
#[inline]
fn set_span(&mut self, _span: Span) {
unimplemented!(
"cannot set span of borrowed Spanned: {:?}",
std::any::type_name::<T>()
)
}
}
impl<T: Spanned + Clone, P> Spanned for Punctuated<T, P> {
fn span(&self) -> Span {
crate::utils::join_spans(self)
}
fn set_span(&mut self, span: Span) {
crate::utils::set_spans(self, span)
}
}
macro_rules! deref_impl {
($($(#[$attr:meta])* [$($gen:tt)*] $t:ty),+ $(,)?) => {$(
$(#[$attr])*
impl<$($gen)*> Spanned for $t {
#[inline]
fn span(&self) -> Span {
(**self).span()
}
#[inline]
fn set_span(&mut self, span: Span) {
(**self).set_span(span)
}
}
)+};
}
deref_impl! {
[T: ?Sized + Spanned] &mut T,
[T: ?Sized + Spanned] Box<T>,
[T: Spanned] Vec<T>,
}
impl<T: Spanned> Spanned for [T] {
#[inline]
fn span(&self) -> Span {
join_spans(self.iter().map(Spanned::span))
}
#[inline]
fn set_span(&mut self, span: Span) {
self.iter_mut().for_each(|item| item.set_span(span));
}
}
macro_rules! kw_impl {
($([$($t:tt)+])+) => { $(kw_impl!($($t)+);)+ };
(__more $t:tt) => {
impl Spanned for Token![$t] {
#[inline]
fn span(&self) -> Span {
join_spans(self.spans)
}
#[inline]
fn set_span(&mut self, span: Span) {
set_spans(&mut self.spans, span);
}
}
};
($t:tt) => {
impl Spanned for Token![$t] {
#[inline]
fn span(&self) -> Span {
self.span
}
#[inline]
fn set_span(&mut self, span: Span) {
self.span = span;
}
}
};
}
kw_impl! {
[abstract]
[as]
[async]
[auto]
[await]
[become]
[box]
[break]
[const]
[continue]
[crate]
[default]
[do]
[dyn]
[else]
[enum]
[extern]
[final]
[fn]
[for]
[if]
[impl]
[in]
[let]
[loop]
[macro]
[match]
[mod]
[move]
[mut]
[override]
[priv]
[pub]
[ref]
[return]
[Self]
[self]
[static]
[struct]
[super]
[trait]
[try]
[type]
[typeof]
[union]
[unsafe]
[unsized]
[use]
[virtual]
[where]
[while]
[yield]
[&]
[__more &&]
[__more &=]
[@]
[^]
[__more ^=]
[:]
[,]
[$]
[.]
[__more ..]
[__more ...]
[__more ..=]
[=]
[__more ==]
[__more =>]
[__more >=]
[>]
[__more <-]
[__more <=]
[<]
[-]
[__more -=]
[__more !=]
[!]
[|]
[__more |=]
[__more ||]
[__more ::]
[%]
[__more %=]
[+]
[__more +=]
[#]
[?]
[__more ->]
[;]
[__more <<]
[__more <<=]
[__more >>]
[__more >>=]
[/]
[__more /=]
[*]
[__more *=]
[~]
[_]
}
fn join_spans<I: IntoIterator<Item = Span>>(spans: I) -> Span {
let mut iter = spans.into_iter();
let Some(first) = iter.next() else {
return Span::call_site()
};
iter.last()
.and_then(|last| first.join(last))
.unwrap_or(first)
}
fn set_spans<'a, I: IntoIterator<Item = &'a mut Span>>(spans: I, set_to: Span) {
for span in spans {
*span = set_to;
}
}