blob: d96ba40a0feef96a375897528b7cd1530a9e7eca [file] [log] [blame]
Michael Layzell53fc31a2017-06-07 09:21:53 -04001use std::rc::Rc;
2use syntex_syntax::ast::{Attribute, Expr, ExprKind, Field, FnDecl, FunctionRetTy, ImplItem,
3 ImplItemKind, ItemKind, Mac, MetaItem, MetaItemKind, MethodSig,
4 NestedMetaItem, NestedMetaItemKind, TraitItem, TraitItemKind, TyParam,
5 Visibility};
6use syntex_syntax::codemap::{self, Spanned};
7use syntex_syntax::fold::{self, Folder};
8use syntex_syntax::parse::token::{Lit, Token};
9use syntex_syntax::ptr::P;
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -070010use syntex_syntax::symbol::Term;
Michael Layzell53fc31a2017-06-07 09:21:53 -040011use syntex_syntax::tokenstream::{Delimited, TokenTree};
12use syntex_syntax::util::move_map::MoveMap;
13use syntex_syntax::util::small_vector::SmallVector;
14
15use syntex_pos::{Span, DUMMY_SP};
16use syntex_syntax::ast;
17
18struct Respanner;
19
20impl Respanner {
21 fn fold_spanned<T>(&mut self, spanned: Spanned<T>) -> Spanned<T> {
22 codemap::respan(self.new_span(spanned.span), spanned.node)
23 }
24
25 fn fold_lit(&mut self, l: Lit) -> Lit {
26 // Give up on comparing literals inside of macros because there are
27 // so many equivalent representations of the same literal; they are
28 // tested elsewhere
29 match l {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -070030 Lit::Byte(_) => Lit::Byte(Term::intern("")),
31 Lit::Char(_) => Lit::Char(Term::intern("")),
32 Lit::Integer(_) => Lit::Integer(Term::intern("")),
33 Lit::Float(_) => Lit::Float(Term::intern("")),
34 Lit::Str_(_) => Lit::Str_(Term::intern("")),
35 Lit::ByteStr(_) => Lit::ByteStr(Term::intern("")),
Michael Layzell53fc31a2017-06-07 09:21:53 -040036 _ => l,
37 }
38 }
39}
40
41impl Folder for Respanner {
42 fn new_span(&mut self, _: Span) -> Span {
43 DUMMY_SP
44 }
45
46 fn fold_item_kind(&mut self, i: ItemKind) -> ItemKind {
47 match i {
48 ItemKind::Fn(decl, unsafety, constness, abi, generics, body) => {
49 let generics = self.fold_generics(generics);
50 let decl = self.fold_fn_decl(decl);
51 let body = self.fold_block(body);
52 // default fold_item_kind does not fold this span
53 let constness = self.fold_spanned(constness);
54 ItemKind::Fn(decl, unsafety, constness, abi, generics, body)
55 }
56 _ => fold::noop_fold_item_kind(i, self),
57 }
58 }
59
60 fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
61 e.map(|e| {
62 let folded = fold::noop_fold_expr(e, self);
63 Expr {
64 node: match folded.node {
65 ExprKind::Lit(l) => {
66 // default fold_expr does not fold lits
67 ExprKind::Lit(l.map(|l| self.fold_spanned(l)))
68 }
69 ExprKind::Binary(op, lhs, rhs) => {
70 // default fold_expr does not fold the op span
71 ExprKind::Binary(self.fold_spanned(op),
72 self.fold_expr(lhs),
73 self.fold_expr(rhs))
74 }
75 ExprKind::AssignOp(op, lhs, rhs) => {
76 // default fold_expr does not fold the op span
77 ExprKind::AssignOp(self.fold_spanned(op),
78 self.fold_expr(lhs),
79 self.fold_expr(rhs))
80 }
81 other => other,
82 },
83 ..folded
84 }
85 })
86 }
87
88 fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
89 TyParam {
90 // default fold_ty_param does not fold the span
91 span: self.new_span(tp.span),
92 ..fold::noop_fold_ty_param(tp, self)
93 }
94 }
95
96 fn fold_fn_decl(&mut self, decl: P<FnDecl>) -> P<FnDecl> {
97 decl.map(|FnDecl { inputs, output, variadic }| {
98 FnDecl {
99 inputs: inputs.move_map(|x| self.fold_arg(x)),
100 output: match output {
101 FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(self.fold_ty(ty)),
102 // default fold_fn_decl does not fold this span
103 FunctionRetTy::Default(span) => FunctionRetTy::Default(self.new_span(span)),
104 },
105 variadic: variadic,
106 }
107 })
108 }
109
110 fn fold_field(&mut self, field: Field) -> Field {
111 Field {
112 ident: codemap::respan(// default fold_field does not fold this span
113 self.new_span(field.ident.span),
114 self.fold_ident(field.ident.node)),
115 expr: self.fold_expr(field.expr),
116 span: self.new_span(field.span),
117 is_shorthand: field.is_shorthand,
118 attrs: ast::ThinVec::new(),
119 }
120 }
121
122 fn fold_trait_item(&mut self, i: TraitItem) -> SmallVector<TraitItem> {
123 let noop = fold::noop_fold_trait_item(i, self).expect_one("");
124 SmallVector::one(TraitItem {
125 node: match noop.node {
126 TraitItemKind::Method(sig, body) => {
127 TraitItemKind::Method(MethodSig {
128 constness: self.fold_spanned(sig.constness),
129 ..sig
130 },
131 body)
132 }
133 node => node,
134 },
135 ..noop
136 })
137 }
138
139 fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector<ImplItem> {
140 let noop = fold::noop_fold_impl_item(i, self).expect_one("");
141 SmallVector::one(ImplItem {
142 node: match noop.node {
143 ImplItemKind::Method(sig, body) => {
144 ImplItemKind::Method(MethodSig {
145 constness: self.fold_spanned(sig.constness),
146 ..sig
147 },
148 body)
149 }
150 node => node,
151 },
152 ..noop
153 })
154 }
155
156 fn fold_attribute(&mut self, mut at: Attribute) -> Option<Attribute> {
157 at.id.0 = 0;
158 fold::noop_fold_attribute(at, self)
159 }
160
161 fn fold_meta_item(&mut self, meta_item: MetaItem) -> MetaItem {
162 let MetaItem { name, node, span } = meta_item;
163 MetaItem {
164 name: name,
165 node: match node {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700166 MetaItemKind::Term => MetaItemKind::Term,
Michael Layzell53fc31a2017-06-07 09:21:53 -0400167 MetaItemKind::List(nested) => {
168 MetaItemKind::List(nested.move_map(|e| self.fold_meta_list_item(e)))
169 }
170 // default fold_meta_item does not fold the value span
171 MetaItemKind::NameValue(lit) => MetaItemKind::NameValue(self.fold_spanned(lit)),
172 },
173 span: self.new_span(span),
174 }
175 }
176
177 fn fold_meta_list_item(&mut self, list_item: NestedMetaItem) -> NestedMetaItem {
178 Spanned {
179 node: match list_item.node {
180 NestedMetaItemKind::MetaItem(mi) => {
181 NestedMetaItemKind::MetaItem(self.fold_meta_item(mi))
182 }
183 // default fold_meta_list_item does not fold the span
184 NestedMetaItemKind::Literal(lit) => {
185 NestedMetaItemKind::Literal(self.fold_spanned(lit))
186 }
187 },
188 span: self.new_span(list_item.span),
189 }
190 }
191
192 fn fold_mac(&mut self, mac: Mac) -> Mac {
193 fold::noop_fold_mac(mac, self)
194 }
195
196 fn fold_tt(&mut self, tt: TokenTree) -> TokenTree {
197 match tt {
198 TokenTree::Token(span, ref tok) => {
199 TokenTree::Token(self.new_span(span), self.fold_token(tok.clone()))
200 }
201 TokenTree::Delimited(span, ref delimed) => {
202 TokenTree::Delimited(self.new_span(span),
203 Delimited {
204 delim: delimed.delim,
205 tts: self.fold_tts(delimed.tts.clone().into()).into(),
206 })
207 }
208 }
209 }
210
211 fn fold_token(&mut self, t: Token) -> Token {
212 match t {
213 // default fold_token does not fold literals
214 Token::Literal(lit, repr) => Token::Literal(self.fold_lit(lit), repr),
215 Token::Ident(id) => Token::Ident(self.fold_ident(id)),
216 Token::Lifetime(id) => Token::Lifetime(self.fold_ident(id)),
217 Token::Interpolated(nt) => {
218 let nt = match Rc::try_unwrap(nt) {
219 Ok(nt) => nt,
220 Err(nt) => (*nt).clone(),
221 };
222 Token::Interpolated(Rc::new(self.fold_interpolated(nt)))
223 }
224 Token::SubstNt(ident) => Token::SubstNt(self.fold_ident(ident)),
225 _ => t,
226 }
227 }
228
229 fn fold_vis(&mut self, vis: Visibility) -> Visibility {
230 match vis {
231 Visibility::Crate(span) => Visibility::Crate(self.new_span(span)),
232 _ => fold::noop_fold_vis(vis, self),
233 }
234 }
235}
236
237#[allow(dead_code)]
238pub fn respan_crate(krate: ast::Crate) -> ast::Crate {
239 Respanner.fold_crate(krate)
240}
241
242#[allow(dead_code)]
243pub fn respan_expr(expr: P<ast::Expr>) -> P<ast::Expr> {
244 Respanner.fold_expr(expr)
245}