Skip to main content

rune/ast/
spanned.rs

1use crate::alloc;
2use crate::ast::Span;
3use crate::parse::NonZeroId;
4
5/// Helper derive to implement [`OptionSpanned`].
6pub use rune_macros::OptionSpanned;
7
8/// Helper derive to implement [`Spanned`].
9pub use rune_macros::Spanned;
10
11/// Types for which we can get a span.
12pub trait Spanned {
13    /// Get the span of the type.
14    fn span(&self) -> Span;
15}
16
17impl Spanned for syntree::Span<u32> {
18    fn span(&self) -> Span {
19        Span::new(self.start, self.end)
20    }
21}
22
23impl<A, B> Spanned for (A, B)
24where
25    A: Spanned,
26    B: OptionSpanned,
27{
28    fn span(&self) -> Span {
29        if let Some(end) = self.1.option_span() {
30            self.0.span().join(end)
31        } else {
32            self.0.span()
33        }
34    }
35}
36
37impl Spanned for Span {
38    fn span(&self) -> Span {
39        *self
40    }
41}
42
43impl<T> Spanned for alloc::Box<T>
44where
45    T: Spanned,
46{
47    #[inline]
48    fn span(&self) -> Span {
49        Spanned::span(&**self)
50    }
51}
52
53impl<T> Spanned for &T
54where
55    T: ?Sized + Spanned,
56{
57    fn span(&self) -> Span {
58        Spanned::span(*self)
59    }
60}
61
62impl<T> Spanned for &mut T
63where
64    T: ?Sized + Spanned,
65{
66    fn span(&self) -> Span {
67        Spanned::span(*self)
68    }
69}
70
71impl<S> Spanned for (S, NonZeroId)
72where
73    S: Spanned,
74{
75    fn span(&self) -> Span {
76        self.0.span()
77    }
78}
79
80/// Types for which we can optionally get a span.
81pub trait OptionSpanned {
82    /// Get the optional span of the type.
83    fn option_span(&self) -> Option<Span>;
84}
85
86/// Take the span of a vector of spanned.
87/// Provides the span between the first and the last element.
88impl<T> OptionSpanned for [T]
89where
90    T: Spanned,
91{
92    fn option_span(&self) -> Option<Span> {
93        let span = self.first()?.span();
94
95        if let Some(last) = self.last() {
96            Some(span.join(last.span()))
97        } else {
98            Some(span)
99        }
100    }
101}
102
103impl<T> OptionSpanned for Option<T>
104where
105    T: Spanned,
106{
107    #[inline]
108    fn option_span(&self) -> Option<Span> {
109        Some(self.as_ref()?.span())
110    }
111}
112
113impl<T> OptionSpanned for alloc::Box<T>
114where
115    T: OptionSpanned,
116{
117    #[inline]
118    fn option_span(&self) -> Option<Span> {
119        OptionSpanned::option_span(&**self)
120    }
121}