]> git.lizzy.rs Git - rust.git/blob - src/spanned.rs
Work around removal of beginning_vert field from ast::Arm
[rust.git] / src / spanned.rs
1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use syntax::ast;
12 use syntax::codemap::Span;
13
14 use macros::MacroArg;
15 use utils::{mk_sp, outer_attributes};
16
17 /// Spanned returns a span including attributes, if available.
18 pub trait Spanned {
19     fn span(&self) -> Span;
20 }
21
22 macro_rules! span_with_attrs_lo_hi {
23     ($this: ident, $lo: expr, $hi: expr) => {{
24         let attrs = outer_attributes(&$this.attrs);
25         if attrs.is_empty() {
26             mk_sp($lo, $hi)
27         } else {
28             mk_sp(attrs[0].span.lo(), $hi)
29         }
30     }};
31 }
32
33 macro_rules! span_with_attrs {
34     ($this: ident) => {
35         span_with_attrs_lo_hi!($this, $this.span.lo(), $this.span.hi())
36     };
37 }
38
39 macro_rules! implement_spanned {
40     ($this: ty) => {
41         impl Spanned for $this {
42             fn span(&self) -> Span {
43                 span_with_attrs!(self)
44             }
45         }
46     };
47 }
48
49 // Implement `Spanned` for structs with `attrs` field.
50 implement_spanned!(ast::Expr);
51 implement_spanned!(ast::Field);
52 implement_spanned!(ast::ForeignItem);
53 implement_spanned!(ast::Item);
54 implement_spanned!(ast::Local);
55 implement_spanned!(ast::TraitItem);
56 implement_spanned!(ast::ImplItem);
57
58 impl Spanned for ast::Stmt {
59     fn span(&self) -> Span {
60         match self.node {
61             ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()),
62             ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()),
63             ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => {
64                 mk_sp(expr.span().lo(), self.span.hi())
65             }
66             ast::StmtKind::Mac(ref mac) => {
67                 let (_, _, ref attrs) = **mac;
68                 if attrs.is_empty() {
69                     self.span
70                 } else {
71                     mk_sp(attrs[0].span.lo(), self.span.hi())
72                 }
73             }
74         }
75     }
76 }
77
78 impl Spanned for ast::Pat {
79     fn span(&self) -> Span {
80         self.span
81     }
82 }
83
84 impl Spanned for ast::Ty {
85     fn span(&self) -> Span {
86         self.span
87     }
88 }
89
90 impl Spanned for ast::Arm {
91     fn span(&self) -> Span {
92         let lo = if self.attrs.is_empty() {
93             self.pats[0].span.lo()
94         } else {
95             self.attrs[0].span.lo()
96         };
97         span_with_attrs_lo_hi!(self, lo, self.body.span.hi())
98     }
99 }
100
101 impl Spanned for ast::Arg {
102     fn span(&self) -> Span {
103         if ::items::is_named_arg(self) {
104             mk_sp(self.pat.span.lo(), self.ty.span.hi())
105         } else {
106             self.ty.span
107         }
108     }
109 }
110
111 impl Spanned for ast::GenericParam {
112     fn span(&self) -> Span {
113         match *self {
114             ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.span(),
115             ast::GenericParam::Type(ref ty) => ty.span(),
116         }
117     }
118 }
119
120 impl Spanned for ast::StructField {
121     fn span(&self) -> Span {
122         span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi())
123     }
124 }
125
126 impl Spanned for ast::WherePredicate {
127     fn span(&self) -> Span {
128         match *self {
129             ast::WherePredicate::BoundPredicate(ref p) => p.span,
130             ast::WherePredicate::RegionPredicate(ref p) => p.span,
131             ast::WherePredicate::EqPredicate(ref p) => p.span,
132         }
133     }
134 }
135
136 impl Spanned for ast::FunctionRetTy {
137     fn span(&self) -> Span {
138         match *self {
139             ast::FunctionRetTy::Default(span) => span,
140             ast::FunctionRetTy::Ty(ref ty) => ty.span,
141         }
142     }
143 }
144
145 impl Spanned for ast::TyParam {
146     fn span(&self) -> Span {
147         // Note that ty.span is the span for ty.ident, not the whole item.
148         let lo = if self.attrs.is_empty() {
149             self.span.lo()
150         } else {
151             self.attrs[0].span.lo()
152         };
153         if let Some(ref def) = self.default {
154             return mk_sp(lo, def.span.hi());
155         }
156         if self.bounds.is_empty() {
157             return mk_sp(lo, self.span.hi());
158         }
159         let hi = self.bounds[self.bounds.len() - 1].span().hi();
160         mk_sp(lo, hi)
161     }
162 }
163
164 impl Spanned for ast::TyParamBound {
165     fn span(&self) -> Span {
166         match *self {
167             ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span,
168             ast::TyParamBound::RegionTyParamBound(ref l) => l.span,
169         }
170     }
171 }
172
173 impl Spanned for ast::LifetimeDef {
174     fn span(&self) -> Span {
175         let hi = if self.bounds.is_empty() {
176             self.lifetime.span.hi()
177         } else {
178             self.bounds[self.bounds.len() - 1].span.hi()
179         };
180         mk_sp(self.lifetime.span.lo(), hi)
181     }
182 }
183
184 impl Spanned for MacroArg {
185     fn span(&self) -> Span {
186         match *self {
187             MacroArg::Expr(ref expr) => expr.span(),
188             MacroArg::Ty(ref ty) => ty.span(),
189             MacroArg::Pat(ref pat) => pat.span(),
190         }
191     }
192 }