Skip to main content

rustfmt_nightly/
spanned.rs

1use std::cmp::max;
2
3use rustc_ast::ast;
4use rustc_span::Span;
5
6use crate::macros::MacroArg;
7use crate::utils::{mk_sp, outer_attributes};
8
9/// Spanned returns a span including attributes, if available.
10pub(crate) trait Spanned {
11    fn span(&self) -> Span;
12}
13
14impl<T: Spanned> Spanned for Box<T> {
15    fn span(&self) -> Span {
16        (**self).span()
17    }
18}
19
20impl<T> Spanned for rustc_span::Spanned<T> {
21    fn span(&self) -> Span {
22        self.span
23    }
24}
25
26macro_rules! span_with_attrs_lo_hi {
27    ($this:ident, $lo:expr, $hi:expr) => {{
28        let attrs = outer_attributes(&$this.attrs);
29        if attrs.is_empty() {
30            mk_sp($lo, $hi)
31        } else {
32            mk_sp(attrs[0].span.lo(), $hi)
33        }
34    }};
35}
36
37macro_rules! span_with_attrs {
38    ($this:ident) => {
39        span_with_attrs_lo_hi!($this, $this.span.lo(), $this.span.hi())
40    };
41}
42
43macro_rules! implement_spanned {
44    ($this:ty) => {
45        impl Spanned for $this {
46            fn span(&self) -> Span {
47                span_with_attrs!(self)
48            }
49        }
50    };
51}
52
53// Implement `Spanned` for structs with `attrs` field.
54implement_spanned!(ast::AssocItem);
55implement_spanned!(ast::Expr);
56implement_spanned!(ast::ExprField);
57implement_spanned!(ast::ForeignItem);
58implement_spanned!(ast::Item);
59implement_spanned!(ast::Local);
60implement_spanned!(ast::WherePredicate);
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 { span, .. } => 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::FnRetTy {
153    fn span(&self) -> Span {
154        match *self {
155            ast::FnRetTy::Default(span) => span,
156            ast::FnRetTy::Ty(ref ty) => ty.span,
157        }
158    }
159}
160
161impl Spanned for ast::GenericArg {
162    fn span(&self) -> Span {
163        match *self {
164            ast::GenericArg::Lifetime(ref lt) => lt.ident.span,
165            ast::GenericArg::Type(ref ty) => ty.span(),
166            ast::GenericArg::Const(ref _const) => _const.value.span(),
167        }
168    }
169}
170
171impl Spanned for ast::GenericBound {
172    fn span(&self) -> Span {
173        match *self {
174            ast::GenericBound::Trait(ref ptr) => ptr.span,
175            ast::GenericBound::Outlives(ref l) => l.ident.span,
176            ast::GenericBound::Use(_, span) => span,
177        }
178    }
179}
180
181impl Spanned for MacroArg {
182    fn span(&self) -> Span {
183        match *self {
184            MacroArg::Expr(ref expr) => expr.span(),
185            MacroArg::Ty(ref ty) => ty.span(),
186            MacroArg::Pat(ref pat) => pat.span(),
187            MacroArg::Item(ref item) => item.span(),
188            MacroArg::Keyword(_, span) => span,
189        }
190    }
191}
192
193impl Spanned for ast::MetaItemInner {
194    fn span(&self) -> Span {
195        self.span()
196    }
197}
198
199impl Spanned for ast::PreciseCapturingArg {
200    fn span(&self) -> Span {
201        match self {
202            ast::PreciseCapturingArg::Lifetime(lt) => lt.ident.span,
203            ast::PreciseCapturingArg::Arg(path, _) => path.span,
204        }
205    }
206}