syn_solidity/
spanned.rs

1//! Helper [trait](Spanned) and methods to manipulate syntax tree nodes' spans.
2
3#![deny(unconditional_recursion)]
4
5use proc_macro2::{Span, TokenStream};
6use syn::{
7    punctuated::{Pair, Punctuated},
8    Token,
9};
10
11/// A trait that can provide the `Span` of the complete contents of a syntax
12/// tree node.
13///
14/// The main difference between this trait and [`syn::spanned::Spanned`] is that
15/// this trait does not depend on a [`quote::ToTokens`] implementation to
16/// retrieve a span, as it is usually stored inside of the syntax tree node
17/// itself.
18pub trait Spanned {
19    /// Returns a `Span` covering the complete contents of this syntax tree
20    /// node, or [`Span::call_site()`] if this node is empty.
21    ///
22    /// [`Span::call_site()`]: proc_macro2::Span::call_site
23    fn span(&self) -> Span;
24
25    /// Sets the span of this syntax tree node if it is not empty.
26    fn set_span(&mut self, span: Span);
27
28    /// Sets the span of this owned syntax tree node if it is not empty.
29    #[inline]
30    fn with_span(mut self, span: Span) -> Self
31    where
32        Self: Sized,
33    {
34        self.set_span(span);
35        self
36    }
37}
38
39fn _object_safe(_: &dyn Spanned) {}
40
41impl Spanned for Span {
42    #[inline]
43    fn span(&self) -> Span {
44        *self
45    }
46
47    #[inline]
48    fn set_span(&mut self, span: Span) {
49        *self = span;
50    }
51}
52
53impl Spanned for TokenStream {
54    #[inline]
55    fn span(&self) -> Span {
56        syn::spanned::Spanned::span(self)
57    }
58
59    #[inline]
60    fn set_span(&mut self, span: Span) {
61        *self = self.clone().with_span(span);
62    }
63
64    fn with_span(self, span: Span) -> Self {
65        self.into_iter()
66            .map(|mut tt| {
67                tt.set_span(span);
68                tt
69            })
70            .collect()
71    }
72}
73
74impl<T: Spanned> Spanned for Option<T> {
75    #[inline]
76    fn span(&self) -> Span {
77        match self {
78            Some(t) => t.span(),
79            None => Span::call_site(),
80        }
81    }
82
83    #[inline]
84    fn set_span(&mut self, span: Span) {
85        if let Some(t) = self {
86            t.set_span(span);
87        }
88    }
89}
90
91impl<T: ?Sized + Spanned> Spanned for &T {
92    #[inline]
93    fn span(&self) -> Span {
94        (**self).span()
95    }
96
97    #[inline]
98    #[track_caller]
99    fn set_span(&mut self, _span: Span) {
100        unimplemented!("cannot set span of borrowed Spanned: {:?}", std::any::type_name::<&T>())
101    }
102}
103
104impl<T: Spanned> Spanned for [T] {
105    #[inline]
106    fn span(&self) -> Span {
107        join_spans(self)
108    }
109
110    #[inline]
111    fn set_span(&mut self, span: Span) {
112        set_spans(self, span);
113    }
114}
115
116impl<T: Spanned, P: Spanned> Spanned for Punctuated<T, P> {
117    fn span(&self) -> Span {
118        join_spans(self.pairs())
119    }
120
121    fn set_span(&mut self, span: Span) {
122        set_spans(self.pairs_mut(), span);
123    }
124}
125
126impl<T: Spanned, P: Spanned> Spanned for Pair<T, P> {
127    fn span(&self) -> Span {
128        let span = self.value().span();
129        self.punct().and_then(|punct| span.join(punct.span())).unwrap_or(span)
130    }
131
132    fn set_span(&mut self, span: Span) {
133        self.value_mut().set_span(span);
134        self.punct_mut().set_span(span);
135    }
136}
137
138macro_rules! deref_impls {
139    ($($(#[$attr:meta])* [$($gen:tt)*] $t:ty),+ $(,)?) => {$(
140        $(#[$attr])*
141        impl<$($gen)*> Spanned for $t {
142            #[inline]
143            fn span(&self) -> Span {
144                (**self).span()
145            }
146
147            #[inline]
148            fn set_span(&mut self, span: Span) {
149                (**self).set_span(span)
150            }
151        }
152    )+};
153}
154
155deref_impls! {
156    [T: ?Sized + Spanned] &mut T,
157    [T: ?Sized + Spanned] Box<T>,
158    [T: Spanned] Vec<T>,
159}
160
161macro_rules! inherent_impl {
162    ($($t:ty),* $(,)?) => {$(
163        impl Spanned for $t {
164            #[inline]
165            fn span(&self) -> Span {
166                self.span()
167            }
168
169            #[inline]
170            fn set_span(&mut self, span: Span) {
171                self.set_span(span);
172            }
173        }
174    )*};
175}
176
177inherent_impl!(
178    proc_macro2::TokenTree,
179    proc_macro2::Group,
180    proc_macro2::Punct,
181    proc_macro2::Ident,
182    proc_macro2::Literal,
183    syn::Lifetime,
184    syn::Lit,
185    syn::LitStr,
186    syn::LitByteStr,
187    syn::LitByte,
188    syn::LitChar,
189    syn::LitInt,
190    syn::LitFloat,
191    syn::LitBool,
192);
193
194/// Implements `Spanned` for `syn::Token!`s.
195///
196/// Prefix with `__more` when the underlying token has more than one span.
197macro_rules! kw_impl {
198    ($([$($t:tt)+])+) => { $(kw_impl!($($t)+);)+ };
199
200    (__more $t:tt) => {
201        impl Spanned for Token![$t] {
202            #[inline]
203            fn span(&self) -> Span {
204                self.spans.span()
205            }
206
207            #[inline]
208            fn set_span(&mut self, span: Span) {
209                self.spans.set_span(span);
210            }
211        }
212    };
213
214    ($t:tt) => {
215        impl Spanned for Token![$t] {
216            #[inline]
217            fn span(&self) -> Span {
218                self.span
219            }
220
221            #[inline]
222            fn set_span(&mut self, span: Span) {
223                self.span = span;
224            }
225        }
226    };
227}
228
229kw_impl! {
230    [abstract]
231    [as]
232    [async]
233    [auto]
234    [await]
235    [become]
236    [box]
237    [break]
238    [const]
239    [continue]
240    [crate]
241    [default]
242    [do]
243    [dyn]
244    [else]
245    [enum]
246    [extern]
247    [final]
248    [fn]
249    [for]
250    [if]
251    [impl]
252    [in]
253    [let]
254    [loop]
255    [macro]
256    [match]
257    [mod]
258    [move]
259    [mut]
260    [override]
261    [priv]
262    [pub]
263    [ref]
264    [return]
265    [Self]
266    [self]
267    [static]
268    [struct]
269    [super]
270    [trait]
271    [try]
272    [type]
273    [typeof]
274    [union]
275    [unsafe]
276    [unsized]
277    [use]
278    [virtual]
279    [where]
280    [while]
281    [yield]
282    [&]
283    [__more &&]
284    [__more &=]
285    [@]
286    [^]
287    [__more ^=]
288    [:]
289    [,]
290    [$]
291    [.]
292    [__more ..]
293    [__more ...]
294    [__more ..=]
295    [=]
296    [__more ==]
297    [__more =>]
298    [__more >=]
299    [>]
300    [__more <-]
301    [__more <=]
302    [<]
303    [-]
304    [__more -=]
305    [__more !=]
306    [!]
307    [|]
308    [__more |=]
309    [__more ||]
310    [__more ::]
311    [%]
312    [__more %=]
313    [+]
314    [__more +=]
315    [#]
316    [?]
317    [__more ->]
318    [;]
319    [__more <<]
320    [__more <<=]
321    [__more >>]
322    [__more >>=]
323    [/]
324    [__more /=]
325    [*]
326    [__more *=]
327    [~]
328    [_]
329}
330
331macro_rules! delim_impl {
332    ($($t:path),* $(,)?) => {$(
333        impl Spanned for $t {
334            #[inline]
335            fn span(&self) -> Span {
336                self.span.join()
337            }
338
339            #[inline]
340            fn set_span(&mut self, span: Span) {
341                *self = $t(span);
342            }
343
344            #[inline]
345            fn with_span(self, span: Span) -> Self {
346                $t(span)
347            }
348        }
349    )*};
350}
351
352delim_impl!(syn::token::Brace, syn::token::Bracket, syn::token::Paren);
353
354/// Joins the spans of each item in the given iterator.
355pub fn join_spans<T: Spanned, I: IntoIterator<Item = T>>(items: I) -> Span {
356    items
357        .into_iter()
358        .map(|t| t.span())
359        .reduce(|span, other| span.join(other).unwrap_or(span))
360        .unwrap_or_else(Span::call_site)
361}
362
363/// Sets the span of each item in the given iterator.
364pub fn set_spans<T: Spanned, I: IntoIterator<Item = T>>(items: I, span: Span) {
365    for mut item in items {
366        item.set_span(span);
367    }
368}