rustfmt_nightly/
spanned.rs

1use std::cmp::max;
2
3use rustc_ast::{ast, ptr};
4use rustc_span::{Span, source_map};
5
6use crate::macros::MacroArg;
7use crate::patterns::RangeOperand;
8use crate::utils::{mk_sp, outer_attributes};
9
10/// Spanned returns a span including attributes, if available.
11pub(crate) trait Spanned {
12    fn span(&self) -> Span;
13}
14
15impl<T: Spanned> Spanned for ptr::P<T> {
16    fn span(&self) -> Span {
17        (**self).span()
18    }
19}
20
21impl<T> Spanned for source_map::Spanned<T> {
22    fn span(&self) -> Span {
23        self.span
24    }
25}
26
27macro_rules! span_with_attrs_lo_hi {
28    ($this:ident, $lo:expr, $hi:expr) => {{
29        let attrs = outer_attributes(&$this.attrs);
30        if attrs.is_empty() {
31            mk_sp($lo, $hi)
32        } else {
33            mk_sp(attrs[0].span.lo(), $hi)
34        }
35    }};
36}
37
38macro_rules! span_with_attrs {
39    ($this:ident) => {
40        span_with_attrs_lo_hi!($this, $this.span.lo(), $this.span.hi())
41    };
42}
43
44macro_rules! implement_spanned {
45    ($this:ty) => {
46        impl Spanned for $this {
47            fn span(&self) -> Span {
48                span_with_attrs!(self)
49            }
50        }
51    };
52}
53
54// Implement `Spanned` for structs with `attrs` field.
55implement_spanned!(ast::AssocItem);
56implement_spanned!(ast::Expr);
57implement_spanned!(ast::ExprField);
58implement_spanned!(ast::ForeignItem);
59implement_spanned!(ast::Item);
60implement_spanned!(ast::Local);
61
62impl Spanned for ast::Stmt {
63    fn span(&self) -> Span {
64        match self.kind {
65            ast::StmtKind::Let(ref local) => mk_sp(local.span().lo(), self.span.hi()),
66            ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()),
67            ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => {
68                mk_sp(expr.span().lo(), self.span.hi())
69            }
70            ast::StmtKind::MacCall(ref mac_stmt) => {
71                if mac_stmt.attrs.is_empty() {
72                    self.span
73                } else {
74                    mk_sp(mac_stmt.attrs[0].span.lo(), self.span.hi())
75                }
76            }
77            ast::StmtKind::Empty => self.span,
78        }
79    }
80}
81
82impl Spanned for ast::Pat {
83    fn span(&self) -> Span {
84        self.span
85    }
86}
87
88impl Spanned for ast::Ty {
89    fn span(&self) -> Span {
90        self.span
91    }
92}
93
94impl Spanned for ast::Arm {
95    fn span(&self) -> Span {
96        let lo = if self.attrs.is_empty() {
97            self.pat.span.lo()
98        } else {
99            self.attrs[0].span.lo()
100        };
101        let hi = if let Some(body) = &self.body {
102            body.span.hi()
103        } else {
104            self.pat.span.hi()
105        };
106        span_with_attrs_lo_hi!(self, lo, hi)
107    }
108}
109
110impl Spanned for ast::Param {
111    fn span(&self) -> Span {
112        if crate::items::is_named_param(self) {
113            mk_sp(crate::items::span_lo_for_param(self), self.ty.span.hi())
114        } else {
115            self.ty.span
116        }
117    }
118}
119
120impl Spanned for ast::GenericParam {
121    fn span(&self) -> Span {
122        let lo = match self.kind {
123            _ if !self.attrs.is_empty() => self.attrs[0].span.lo(),
124            ast::GenericParamKind::Const { kw_span, .. } => kw_span.lo(),
125            _ => self.ident.span.lo(),
126        };
127        let hi = if self.bounds.is_empty() {
128            self.ident.span.hi()
129        } else {
130            self.bounds.last().unwrap().span().hi()
131        };
132        let ty_hi = if let ast::GenericParamKind::Type {
133            default: Some(ref ty),
134        }
135        | ast::GenericParamKind::Const { ref ty, .. } = self.kind
136        {
137            ty.span().hi()
138        } else {
139            hi
140        };
141        mk_sp(lo, max(hi, ty_hi))
142    }
143}
144
145impl Spanned for ast::FieldDef {
146    fn span(&self) -> Span {
147        // FIXME(default_field_values): This needs to be adjusted.
148        span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi())
149    }
150}
151
152impl Spanned for ast::WherePredicate {
153    fn span(&self) -> Span {
154        self.span
155    }
156}
157
158impl Spanned for ast::FnRetTy {
159    fn span(&self) -> Span {
160        match *self {
161            ast::FnRetTy::Default(span) => span,
162            ast::FnRetTy::Ty(ref ty) => ty.span,
163        }
164    }
165}
166
167impl Spanned for ast::GenericArg {
168    fn span(&self) -> Span {
169        match *self {
170            ast::GenericArg::Lifetime(ref lt) => lt.ident.span,
171            ast::GenericArg::Type(ref ty) => ty.span(),
172            ast::GenericArg::Const(ref _const) => _const.value.span(),
173        }
174    }
175}
176
177impl Spanned for ast::GenericBound {
178    fn span(&self) -> Span {
179        match *self {
180            ast::GenericBound::Trait(ref ptr) => ptr.span,
181            ast::GenericBound::Outlives(ref l) => l.ident.span,
182            ast::GenericBound::Use(_, span) => span,
183        }
184    }
185}
186
187impl Spanned for MacroArg {
188    fn span(&self) -> Span {
189        match *self {
190            MacroArg::Expr(ref expr) => expr.span(),
191            MacroArg::Ty(ref ty) => ty.span(),
192            MacroArg::Pat(ref pat) => pat.span(),
193            MacroArg::Item(ref item) => item.span(),
194            MacroArg::Keyword(_, span) => span,
195        }
196    }
197}
198
199impl Spanned for ast::MetaItemInner {
200    fn span(&self) -> Span {
201        self.span()
202    }
203}
204
205impl Spanned for ast::PreciseCapturingArg {
206    fn span(&self) -> Span {
207        match self {
208            ast::PreciseCapturingArg::Lifetime(lt) => lt.ident.span,
209            ast::PreciseCapturingArg::Arg(path, _) => path.span,
210        }
211    }
212}
213
214impl<'a, T> Spanned for RangeOperand<'a, T> {
215    fn span(&self) -> Span {
216        self.span
217    }
218}