]> git.lizzy.rs Git - rust.git/blob - src/tools/rustfmt/src/spanned.rs
Rollup merge of #100804 - GuillaumeGomez:search-results-color-ayu, r=notriddle
[rust.git] / src / tools / rustfmt / src / spanned.rs
1 use std::cmp::max;
2
3 use rustc_ast::{ast, ptr};
4 use rustc_span::{source_map, Span};
5
6 use crate::macros::MacroArg;
7 use crate::utils::{mk_sp, outer_attributes};
8
9 /// Spanned returns a span including attributes, if available.
10 pub(crate) trait Spanned {
11     fn span(&self) -> Span;
12 }
13
14 impl<T: Spanned> Spanned for ptr::P<T> {
15     fn span(&self) -> Span {
16         (**self).span()
17     }
18 }
19
20 impl<T> Spanned for source_map::Spanned<T> {
21     fn span(&self) -> Span {
22         self.span
23     }
24 }
25
26 macro_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
37 macro_rules! span_with_attrs {
38     ($this:ident) => {
39         span_with_attrs_lo_hi!($this, $this.span.lo(), $this.span.hi())
40     };
41 }
42
43 macro_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.
54 implement_spanned!(ast::AssocItem);
55 implement_spanned!(ast::Expr);
56 implement_spanned!(ast::ExprField);
57 implement_spanned!(ast::ForeignItem);
58 implement_spanned!(ast::Item);
59 implement_spanned!(ast::Local);
60
61 impl Spanned for ast::Stmt {
62     fn span(&self) -> Span {
63         match self.kind {
64             ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()),
65             ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()),
66             ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => {
67                 mk_sp(expr.span().lo(), self.span.hi())
68             }
69             ast::StmtKind::MacCall(ref mac_stmt) => {
70                 if mac_stmt.attrs.is_empty() {
71                     self.span
72                 } else {
73                     mk_sp(mac_stmt.attrs[0].span.lo(), self.span.hi())
74                 }
75             }
76             ast::StmtKind::Empty => self.span,
77         }
78     }
79 }
80
81 impl Spanned for ast::Pat {
82     fn span(&self) -> Span {
83         self.span
84     }
85 }
86
87 impl Spanned for ast::Ty {
88     fn span(&self) -> Span {
89         self.span
90     }
91 }
92
93 impl Spanned for ast::Arm {
94     fn span(&self) -> Span {
95         let lo = if self.attrs.is_empty() {
96             self.pat.span.lo()
97         } else {
98             self.attrs[0].span.lo()
99         };
100         span_with_attrs_lo_hi!(self, lo, self.body.span.hi())
101     }
102 }
103
104 impl Spanned for ast::Param {
105     fn span(&self) -> Span {
106         if crate::items::is_named_param(self) {
107             mk_sp(crate::items::span_lo_for_param(self), self.ty.span.hi())
108         } else {
109             self.ty.span
110         }
111     }
112 }
113
114 impl Spanned for ast::GenericParam {
115     fn span(&self) -> Span {
116         let lo = match self.kind {
117             _ if !self.attrs.is_empty() => self.attrs[0].span.lo(),
118             ast::GenericParamKind::Const { kw_span, .. } => kw_span.lo(),
119             _ => self.ident.span.lo(),
120         };
121         let hi = if self.bounds.is_empty() {
122             self.ident.span.hi()
123         } else {
124             self.bounds.last().unwrap().span().hi()
125         };
126         let ty_hi = if let ast::GenericParamKind::Type {
127             default: Some(ref ty),
128         }
129         | ast::GenericParamKind::Const { ref ty, .. } = self.kind
130         {
131             ty.span().hi()
132         } else {
133             hi
134         };
135         mk_sp(lo, max(hi, ty_hi))
136     }
137 }
138
139 impl Spanned for ast::FieldDef {
140     fn span(&self) -> Span {
141         span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi())
142     }
143 }
144
145 impl Spanned for ast::WherePredicate {
146     fn span(&self) -> Span {
147         match *self {
148             ast::WherePredicate::BoundPredicate(ref p) => p.span,
149             ast::WherePredicate::RegionPredicate(ref p) => p.span,
150             ast::WherePredicate::EqPredicate(ref p) => p.span,
151         }
152     }
153 }
154
155 impl Spanned for ast::FnRetTy {
156     fn span(&self) -> Span {
157         match *self {
158             ast::FnRetTy::Default(span) => span,
159             ast::FnRetTy::Ty(ref ty) => ty.span,
160         }
161     }
162 }
163
164 impl Spanned for ast::GenericArg {
165     fn span(&self) -> Span {
166         match *self {
167             ast::GenericArg::Lifetime(ref lt) => lt.ident.span,
168             ast::GenericArg::Type(ref ty) => ty.span(),
169             ast::GenericArg::Const(ref _const) => _const.value.span(),
170         }
171     }
172 }
173
174 impl Spanned for ast::GenericBound {
175     fn span(&self) -> Span {
176         match *self {
177             ast::GenericBound::Trait(ref ptr, _) => ptr.span,
178             ast::GenericBound::Outlives(ref l) => l.ident.span,
179         }
180     }
181 }
182
183 impl Spanned for MacroArg {
184     fn span(&self) -> Span {
185         match *self {
186             MacroArg::Expr(ref expr) => expr.span(),
187             MacroArg::Ty(ref ty) => ty.span(),
188             MacroArg::Pat(ref pat) => pat.span(),
189             MacroArg::Item(ref item) => item.span(),
190             MacroArg::Keyword(_, span) => span,
191         }
192     }
193 }
194
195 impl Spanned for ast::NestedMetaItem {
196     fn span(&self) -> Span {
197         self.span()
198     }
199 }