blob: 6d1e75a857f5580a023a52b33c0dc058d0b2b628 [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnaycfa5cc02017-11-13 01:05:11 -08009extern crate syntax;
10extern crate syntax_pos;
David Tolnayc7a5d3d2017-06-04 12:11:05 -070011
David Tolnaycfa5cc02017-11-13 01:05:11 -080012use self::syntax::ast::{Attribute, Expr, ExprKind, Field, FnDecl, FunctionRetTy, ImplItem,
David Tolnay51382052017-12-27 13:46:21 -050013 ImplItemKind, Item, ItemKind, Mac, MetaItem, MetaItemKind, MethodSig,
David Tolnaycfa5cc02017-11-13 01:05:11 -080014 NestedMetaItem, NestedMetaItemKind, TraitItem, TraitItemKind, TyParam,
David Tolnay51382052017-12-27 13:46:21 -050015 Visibility, WhereClause};
David Tolnaycfa5cc02017-11-13 01:05:11 -080016use self::syntax::codemap::{self, Spanned};
17use self::syntax::fold::{self, Folder};
18use self::syntax::parse::token::{Lit, Token};
19use self::syntax::ptr::P;
20use self::syntax::symbol::Symbol;
David Tolnaycfa5cc02017-11-13 01:05:11 -080021use self::syntax::util::move_map::MoveMap;
22use self::syntax::util::small_vector::SmallVector;
Michael Layzell53fc31a2017-06-07 09:21:53 -040023
David Tolnaycfa5cc02017-11-13 01:05:11 -080024use self::syntax_pos::{Span, DUMMY_SP};
25use self::syntax::ast;
Michael Layzell53fc31a2017-06-07 09:21:53 -040026
27struct Respanner;
28
29impl Respanner {
30 fn fold_spanned<T>(&mut self, spanned: Spanned<T>) -> Spanned<T> {
31 codemap::respan(self.new_span(spanned.span), spanned.node)
32 }
33
34 fn fold_lit(&mut self, l: Lit) -> Lit {
35 // Give up on comparing literals inside of macros because there are
36 // so many equivalent representations of the same literal; they are
37 // tested elsewhere
38 match l {
Alex Crichton605643b2017-07-05 18:35:14 -070039 Lit::Byte(_) => Lit::Byte(Symbol::intern("")),
40 Lit::Char(_) => Lit::Char(Symbol::intern("")),
41 Lit::Integer(_) => Lit::Integer(Symbol::intern("")),
42 Lit::Float(_) => Lit::Float(Symbol::intern("")),
43 Lit::Str_(_) => Lit::Str_(Symbol::intern("")),
44 Lit::ByteStr(_) => Lit::ByteStr(Symbol::intern("")),
Michael Layzell53fc31a2017-06-07 09:21:53 -040045 _ => l,
46 }
47 }
48}
49
50impl Folder for Respanner {
51 fn new_span(&mut self, _: Span) -> Span {
52 DUMMY_SP
53 }
54
Nika Layzella2a1a4a2017-11-19 11:33:17 -050055 fn fold_item(&mut self, i: P<Item>) -> SmallVector<P<Item>> {
56 let i = i.map(|mut i| {
57 i.tokens = None;
58 i
59 });
60 fold::noop_fold_item(i, self)
61 }
62
Michael Layzell53fc31a2017-06-07 09:21:53 -040063 fn fold_item_kind(&mut self, i: ItemKind) -> ItemKind {
64 match i {
65 ItemKind::Fn(decl, unsafety, constness, abi, generics, body) => {
66 let generics = self.fold_generics(generics);
67 let decl = self.fold_fn_decl(decl);
68 let body = self.fold_block(body);
69 // default fold_item_kind does not fold this span
70 let constness = self.fold_spanned(constness);
71 ItemKind::Fn(decl, unsafety, constness, abi, generics, body)
72 }
73 _ => fold::noop_fold_item_kind(i, self),
74 }
75 }
76
77 fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
78 e.map(|e| {
79 let folded = fold::noop_fold_expr(e, self);
80 Expr {
81 node: match folded.node {
82 ExprKind::Lit(l) => {
83 // default fold_expr does not fold lits
84 ExprKind::Lit(l.map(|l| self.fold_spanned(l)))
85 }
86 ExprKind::Binary(op, lhs, rhs) => {
87 // default fold_expr does not fold the op span
David Tolnay51382052017-12-27 13:46:21 -050088 ExprKind::Binary(
89 self.fold_spanned(op),
90 self.fold_expr(lhs),
91 self.fold_expr(rhs),
92 )
Michael Layzell53fc31a2017-06-07 09:21:53 -040093 }
94 ExprKind::AssignOp(op, lhs, rhs) => {
95 // default fold_expr does not fold the op span
David Tolnay51382052017-12-27 13:46:21 -050096 ExprKind::AssignOp(
97 self.fold_spanned(op),
98 self.fold_expr(lhs),
99 self.fold_expr(rhs),
100 )
Michael Layzell53fc31a2017-06-07 09:21:53 -0400101 }
102 other => other,
103 },
104 ..folded
105 }
106 })
107 }
108
109 fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
110 TyParam {
111 // default fold_ty_param does not fold the span
112 span: self.new_span(tp.span),
113 ..fold::noop_fold_ty_param(tp, self)
114 }
115 }
116
117 fn fold_fn_decl(&mut self, decl: P<FnDecl>) -> P<FnDecl> {
David Tolnay51382052017-12-27 13:46:21 -0500118 decl.map(
119 |FnDecl {
120 inputs,
121 output,
122 variadic,
123 }| {
124 FnDecl {
125 inputs: inputs.move_map(|x| self.fold_arg(x)),
126 output: match output {
127 FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(self.fold_ty(ty)),
128 // default fold_fn_decl does not fold this span
129 FunctionRetTy::Default(span) => FunctionRetTy::Default(self.new_span(span)),
130 },
David Tolnay54bdb4f2018-03-17 13:00:42 -0700131 variadic,
David Tolnay51382052017-12-27 13:46:21 -0500132 }
133 },
134 )
Michael Layzell53fc31a2017-06-07 09:21:53 -0400135 }
136
137 fn fold_field(&mut self, field: Field) -> Field {
138 Field {
David Tolnay51382052017-12-27 13:46:21 -0500139 ident: codemap::respan(
140 // default fold_field does not fold this span
141 self.new_span(field.ident.span),
142 self.fold_ident(field.ident.node),
143 ),
Michael Layzell53fc31a2017-06-07 09:21:53 -0400144 expr: self.fold_expr(field.expr),
145 span: self.new_span(field.span),
146 is_shorthand: field.is_shorthand,
147 attrs: ast::ThinVec::new(),
148 }
149 }
150
Nika Layzella2a1a4a2017-11-19 11:33:17 -0500151 fn fold_trait_item(&mut self, mut i: TraitItem) -> SmallVector<TraitItem> {
152 i.tokens = None;
Michael Layzell53fc31a2017-06-07 09:21:53 -0400153 let noop = fold::noop_fold_trait_item(i, self).expect_one("");
154 SmallVector::one(TraitItem {
Nika Layzella2a1a4a2017-11-19 11:33:17 -0500155 node: match noop.node {
David Tolnay51382052017-12-27 13:46:21 -0500156 TraitItemKind::Method(sig, body) => TraitItemKind::Method(
157 MethodSig {
Nika Layzella2a1a4a2017-11-19 11:33:17 -0500158 constness: self.fold_spanned(sig.constness),
159 ..sig
David Tolnay51382052017-12-27 13:46:21 -0500160 },
161 body,
162 ),
Nika Layzella2a1a4a2017-11-19 11:33:17 -0500163 node => node,
164 },
165 ..noop
166 })
Michael Layzell53fc31a2017-06-07 09:21:53 -0400167 }
168
Nika Layzella2a1a4a2017-11-19 11:33:17 -0500169 fn fold_impl_item(&mut self, mut i: ImplItem) -> SmallVector<ImplItem> {
170 i.tokens = None;
Michael Layzell53fc31a2017-06-07 09:21:53 -0400171 let noop = fold::noop_fold_impl_item(i, self).expect_one("");
172 SmallVector::one(ImplItem {
Nika Layzella2a1a4a2017-11-19 11:33:17 -0500173 node: match noop.node {
David Tolnay51382052017-12-27 13:46:21 -0500174 ImplItemKind::Method(sig, body) => ImplItemKind::Method(
175 MethodSig {
Nika Layzella2a1a4a2017-11-19 11:33:17 -0500176 constness: self.fold_spanned(sig.constness),
177 ..sig
David Tolnay51382052017-12-27 13:46:21 -0500178 },
179 body,
180 ),
Nika Layzella2a1a4a2017-11-19 11:33:17 -0500181 node => node,
182 },
183 ..noop
184 })
Michael Layzell53fc31a2017-06-07 09:21:53 -0400185 }
186
187 fn fold_attribute(&mut self, mut at: Attribute) -> Option<Attribute> {
188 at.id.0 = 0;
189 fold::noop_fold_attribute(at, self)
190 }
191
192 fn fold_meta_item(&mut self, meta_item: MetaItem) -> MetaItem {
193 let MetaItem { name, node, span } = meta_item;
194 MetaItem {
David Tolnay54bdb4f2018-03-17 13:00:42 -0700195 name,
Michael Layzell53fc31a2017-06-07 09:21:53 -0400196 node: match node {
Alex Crichton605643b2017-07-05 18:35:14 -0700197 MetaItemKind::Word => MetaItemKind::Word,
Michael Layzell53fc31a2017-06-07 09:21:53 -0400198 MetaItemKind::List(nested) => {
199 MetaItemKind::List(nested.move_map(|e| self.fold_meta_list_item(e)))
200 }
201 // default fold_meta_item does not fold the value span
202 MetaItemKind::NameValue(lit) => MetaItemKind::NameValue(self.fold_spanned(lit)),
203 },
204 span: self.new_span(span),
205 }
206 }
207
208 fn fold_meta_list_item(&mut self, list_item: NestedMetaItem) -> NestedMetaItem {
209 Spanned {
210 node: match list_item.node {
211 NestedMetaItemKind::MetaItem(mi) => {
212 NestedMetaItemKind::MetaItem(self.fold_meta_item(mi))
213 }
214 // default fold_meta_list_item does not fold the span
215 NestedMetaItemKind::Literal(lit) => {
216 NestedMetaItemKind::Literal(self.fold_spanned(lit))
217 }
218 },
219 span: self.new_span(list_item.span),
220 }
221 }
222
Nika Layzella2a1a4a2017-11-19 11:33:17 -0500223 // This folder is disabled by default.
Michael Layzell53fc31a2017-06-07 09:21:53 -0400224 fn fold_mac(&mut self, mac: Mac) -> Mac {
225 fold::noop_fold_mac(mac, self)
226 }
227
Michael Layzell53fc31a2017-06-07 09:21:53 -0400228 fn fold_token(&mut self, t: Token) -> Token {
David Tolnay51382052017-12-27 13:46:21 -0500229 fold::noop_fold_token(
230 match t {
231 // default fold_token does not fold literals
232 Token::Literal(lit, repr) => Token::Literal(self.fold_lit(lit), repr),
233 _ => t,
234 },
235 self,
236 )
Michael Layzell53fc31a2017-06-07 09:21:53 -0400237 }
238
239 fn fold_vis(&mut self, vis: Visibility) -> Visibility {
David Tolnay47551042018-02-25 23:52:47 -0800240 fold::noop_fold_vis(self.fold_spanned(vis), self)
Nika Layzella2a1a4a2017-11-19 11:33:17 -0500241 }
242
243 // noop_fold_where_clause doesn't modify the span.
244 fn fold_where_clause(&mut self, mut clause: WhereClause) -> WhereClause {
245 clause.span = self.new_span(clause.span);
246 fold::noop_fold_where_clause(clause, self)
Michael Layzell53fc31a2017-06-07 09:21:53 -0400247 }
248}
249
250#[allow(dead_code)]
251pub fn respan_crate(krate: ast::Crate) -> ast::Crate {
252 Respanner.fold_crate(krate)
253}
254
255#[allow(dead_code)]
256pub fn respan_expr(expr: P<ast::Expr>) -> P<ast::Expr> {
257 Respanner.fold_expr(expr)
258}