]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
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); | |
cdc7bbd5 | 56 | implement_spanned!(ast::ExprField); |
f20569fa XL |
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) { | |
3c0e092e | 107 | mk_sp(crate::items::span_lo_for_param(self), self.ty.span.hi()) |
f20569fa XL |
108 | } else { |
109 | self.ty.span | |
110 | } | |
111 | } | |
112 | } | |
113 | ||
114 | impl Spanned for ast::GenericParam { | |
115 | fn span(&self) -> Span { | |
5e7ed085 FG |
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(), | |
f20569fa XL |
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 | ||
cdc7bbd5 | 139 | impl Spanned for ast::FieldDef { |
f20569fa XL |
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 | } |