]> git.lizzy.rs Git - rust.git/blob - src/tools/rustfmt/src/spanned.rs
Add 'src/tools/rustfmt/' from commit '7872306edf2e11a69aaffb9434088fd66b46a863'
[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(self.pat.span.lo(), 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 = if let ast::GenericParamKind::Const {
117             ty: _,
118             kw_span,
119             default: _,
120         } = self.kind
121         {
122             kw_span.lo()
123         } else if self.attrs.is_empty() {
124             self.ident.span.lo()
125         } else {
126             self.attrs[0].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
146 impl Spanned for ast::FieldDef {
147     fn span(&self) -> Span {
148         span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi())
149     }
150 }
151
152 impl Spanned for ast::WherePredicate {
153     fn span(&self) -> Span {
154         match *self {
155             ast::WherePredicate::BoundPredicate(ref p) => p.span,
156             ast::WherePredicate::RegionPredicate(ref p) => p.span,
157             ast::WherePredicate::EqPredicate(ref p) => p.span,
158         }
159     }
160 }
161
162 impl Spanned for ast::FnRetTy {
163     fn span(&self) -> Span {
164         match *self {
165             ast::FnRetTy::Default(span) => span,
166             ast::FnRetTy::Ty(ref ty) => ty.span,
167         }
168     }
169 }
170
171 impl Spanned for ast::GenericArg {
172     fn span(&self) -> Span {
173         match *self {
174             ast::GenericArg::Lifetime(ref lt) => lt.ident.span,
175             ast::GenericArg::Type(ref ty) => ty.span(),
176             ast::GenericArg::Const(ref _const) => _const.value.span(),
177         }
178     }
179 }
180
181 impl Spanned for ast::GenericBound {
182     fn span(&self) -> Span {
183         match *self {
184             ast::GenericBound::Trait(ref ptr, _) => ptr.span,
185             ast::GenericBound::Outlives(ref l) => l.ident.span,
186         }
187     }
188 }
189
190 impl Spanned for MacroArg {
191     fn span(&self) -> Span {
192         match *self {
193             MacroArg::Expr(ref expr) => expr.span(),
194             MacroArg::Ty(ref ty) => ty.span(),
195             MacroArg::Pat(ref pat) => pat.span(),
196             MacroArg::Item(ref item) => item.span(),
197             MacroArg::Keyword(_, span) => span,
198         }
199     }
200 }
201
202 impl Spanned for ast::NestedMetaItem {
203     fn span(&self) -> Span {
204         self.span()
205     }
206 }