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);
61implement_spanned!(ast::WherePredicate);
62
63impl Spanned for ast::Stmt {
64    fn span(&self) -> Span {
65        match self.kind {
66            ast::StmtKind::Let(ref local) => mk_sp(local.span().lo(), self.span.hi()),
67            ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()),
68            ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => {
69                mk_sp(expr.span().lo(), self.span.hi())
70            }
71            ast::StmtKind::MacCall(ref mac_stmt) => {
72                if mac_stmt.attrs.is_empty() {
73                    self.span
74                } else {
75                    mk_sp(mac_stmt.attrs[0].span.lo(), self.span.hi())
76                }
77            }
78            ast::StmtKind::Empty => self.span,
79        }
80    }
81}
82
83impl Spanned for ast::Pat {
84    fn span(&self) -> Span {
85        self.span
86    }
87}
88
89impl Spanned for ast::Ty {
90    fn span(&self) -> Span {
91        self.span
92    }
93}
94
95impl Spanned for ast::Arm {
96    fn span(&self) -> Span {
97        let lo = if self.attrs.is_empty() {
98            self.pat.span.lo()
99        } else {
100            self.attrs[0].span.lo()
101        };
102        let hi = if let Some(body) = &self.body {
103            body.span.hi()
104        } else {
105            self.pat.span.hi()
106        };
107        span_with_attrs_lo_hi!(self, lo, hi)
108    }
109}
110
111impl Spanned for ast::Param {
112    fn span(&self) -> Span {
113        if crate::items::is_named_param(self) {
114            mk_sp(crate::items::span_lo_for_param(self), self.ty.span.hi())
115        } else {
116            self.ty.span
117        }
118    }
119}
120
121impl Spanned for ast::GenericParam {
122    fn span(&self) -> Span {
123        let lo = match self.kind {
124            _ if !self.attrs.is_empty() => self.attrs[0].span.lo(),
125            ast::GenericParamKind::Const { kw_span, .. } => kw_span.lo(),
126            _ => self.ident.span.lo(),
127        };
128        let hi = if self.bounds.is_empty() {
129            self.ident.span.hi()
130        } else {
131            self.bounds.last().unwrap().span().hi()
132        };
133        let ty_hi = if let ast::GenericParamKind::Type {
134            default: Some(ref ty),
135        }
136        | ast::GenericParamKind::Const { ref ty, .. } = self.kind
137        {
138            ty.span().hi()
139        } else {
140            hi
141        };
142        mk_sp(lo, max(hi, ty_hi))
143    }
144}
145
146impl Spanned for ast::FieldDef {
147    fn span(&self) -> Span {
148        // FIXME(default_field_values): This needs to be adjusted.
149        span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi())
150    }
151}
152
153impl Spanned for ast::FnRetTy {
154    fn span(&self) -> Span {
155        match *self {
156            ast::FnRetTy::Default(span) => span,
157            ast::FnRetTy::Ty(ref ty) => ty.span,
158        }
159    }
160}
161
162impl Spanned for ast::GenericArg {
163    fn span(&self) -> Span {
164        match *self {
165            ast::GenericArg::Lifetime(ref lt) => lt.ident.span,
166            ast::GenericArg::Type(ref ty) => ty.span(),
167            ast::GenericArg::Const(ref _const) => _const.value.span(),
168        }
169    }
170}
171
172impl Spanned for ast::GenericBound {
173    fn span(&self) -> Span {
174        match *self {
175            ast::GenericBound::Trait(ref ptr) => ptr.span,
176            ast::GenericBound::Outlives(ref l) => l.ident.span,
177            ast::GenericBound::Use(_, span) => span,
178        }
179    }
180}
181
182impl Spanned for MacroArg {
183    fn span(&self) -> Span {
184        match *self {
185            MacroArg::Expr(ref expr) => expr.span(),
186            MacroArg::Ty(ref ty) => ty.span(),
187            MacroArg::Pat(ref pat) => pat.span(),
188            MacroArg::Item(ref item) => item.span(),
189            MacroArg::Keyword(_, span) => span,
190        }
191    }
192}
193
194impl Spanned for ast::MetaItemInner {
195    fn span(&self) -> Span {
196        self.span()
197    }
198}
199
200impl Spanned for ast::PreciseCapturingArg {
201    fn span(&self) -> Span {
202        match self {
203            ast::PreciseCapturingArg::Lifetime(lt) => lt.ident.span,
204            ast::PreciseCapturingArg::Arg(path, _) => path.span,
205        }
206    }
207}
208
209impl<'a, T> Spanned for RangeOperand<'a, T> {
210    fn span(&self) -> Span {
211        self.span
212    }
213}