]>
Commit | Line | Data |
---|---|---|
1a4d82fc | 1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
223e47cc LB |
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 | ||
1a4d82fc JJ |
11 | pub use self::AnnNode::*; |
12 | ||
7453a54e | 13 | use abi::{self, Abi}; |
3157f602 XL |
14 | use ast::{self, BlockCheckMode, PatKind}; |
15 | use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; | |
92a42be0 | 16 | use ast::Attribute; |
92a42be0 | 17 | use util::parser::AssocOp; |
85aaf69f | 18 | use attr; |
3157f602 XL |
19 | use codemap::{self, CodeMap}; |
20 | use syntax_pos::{self, BytePos}; | |
9cc50fc6 | 21 | use errors; |
a7813a04 | 22 | use parse::token::{self, keywords, BinOpToken, Token, InternedString}; |
1a4d82fc | 23 | use parse::lexer::comments; |
223e47cc | 24 | use parse; |
1a4d82fc | 25 | use print::pp::{self, break_offset, word, space, zerobreak, hardbreak}; |
85aaf69f SL |
26 | use print::pp::{Breaks, eof}; |
27 | use print::pp::Breaks::{Consistent, Inconsistent}; | |
1a4d82fc | 28 | use ptr::P; |
85aaf69f | 29 | use std_inject; |
3157f602 | 30 | use tokenstream::{self, TokenTree}; |
1a4d82fc | 31 | |
d9579d0f | 32 | use std::ascii; |
c34b1796 | 33 | use std::io::{self, Write, Read}; |
1a4d82fc JJ |
34 | use std::iter; |
35 | ||
36 | pub enum AnnNode<'a> { | |
37 | NodeIdent(&'a ast::Ident), | |
38 | NodeName(&'a ast::Name), | |
39 | NodeBlock(&'a ast::Block), | |
40 | NodeItem(&'a ast::Item), | |
c34b1796 | 41 | NodeSubItem(ast::NodeId), |
1a4d82fc JJ |
42 | NodeExpr(&'a ast::Expr), |
43 | NodePat(&'a ast::Pat), | |
223e47cc LB |
44 | } |
45 | ||
1a4d82fc | 46 | pub trait PpAnn { |
c34b1796 AL |
47 | fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) } |
48 | fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) } | |
223e47cc LB |
49 | } |
50 | ||
c34b1796 | 51 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
52 | pub struct NoAnn; |
53 | ||
54 | impl PpAnn for NoAnn {} | |
55 | ||
c34b1796 | 56 | #[derive(Copy, Clone)] |
223e47cc | 57 | pub struct CurrentCommentAndLiteral { |
b039eaaf SL |
58 | pub cur_cmnt: usize, |
59 | pub cur_lit: usize, | |
223e47cc LB |
60 | } |
61 | ||
1a4d82fc | 62 | pub struct State<'a> { |
c34b1796 | 63 | pub s: pp::Printer<'a>, |
1a4d82fc JJ |
64 | cm: Option<&'a CodeMap>, |
65 | comments: Option<Vec<comments::Comment> >, | |
66 | literals: Option<Vec<comments::Literal> >, | |
67 | cur_cmnt_and_lit: CurrentCommentAndLiteral, | |
68 | boxes: Vec<pp::Breaks>, | |
69 | ann: &'a (PpAnn+'a), | |
223e47cc LB |
70 | } |
71 | ||
c34b1796 | 72 | pub fn rust_printer<'a>(writer: Box<Write+'a>) -> State<'a> { |
1a4d82fc JJ |
73 | static NO_ANN: NoAnn = NoAnn; |
74 | rust_printer_annotated(writer, &NO_ANN) | |
223e47cc LB |
75 | } |
76 | ||
c34b1796 | 77 | pub fn rust_printer_annotated<'a>(writer: Box<Write+'a>, |
1a4d82fc JJ |
78 | ann: &'a PpAnn) -> State<'a> { |
79 | State { | |
92a42be0 | 80 | s: pp::mk_printer(writer, DEFAULT_COLUMNS), |
1a4d82fc JJ |
81 | cm: None, |
82 | comments: None, | |
83 | literals: None, | |
84 | cur_cmnt_and_lit: CurrentCommentAndLiteral { | |
223e47cc LB |
85 | cur_cmnt: 0, |
86 | cur_lit: 0 | |
87 | }, | |
1a4d82fc JJ |
88 | boxes: Vec::new(), |
89 | ann: ann, | |
1a4d82fc JJ |
90 | } |
91 | } | |
92 | ||
92a42be0 | 93 | pub const INDENT_UNIT: usize = 4; |
1a4d82fc | 94 | |
92a42be0 | 95 | pub const DEFAULT_COLUMNS: usize = 78; |
1a4d82fc JJ |
96 | |
97 | /// Requires you to pass an input filename and reader so that | |
98 | /// it can scan the input text for comments and literals to | |
99 | /// copy forward. | |
100 | pub fn print_crate<'a>(cm: &'a CodeMap, | |
9cc50fc6 | 101 | span_diagnostic: &errors::Handler, |
1a4d82fc JJ |
102 | krate: &ast::Crate, |
103 | filename: String, | |
c34b1796 AL |
104 | input: &mut Read, |
105 | out: Box<Write+'a>, | |
1a4d82fc | 106 | ann: &'a PpAnn, |
c34b1796 | 107 | is_expanded: bool) -> io::Result<()> { |
1a4d82fc JJ |
108 | let mut s = State::new_from_input(cm, |
109 | span_diagnostic, | |
110 | filename, | |
111 | input, | |
112 | out, | |
113 | ann, | |
114 | is_expanded); | |
c30ab7b3 | 115 | if is_expanded && !std_inject::injected_crate_name(krate).is_none() { |
85aaf69f SL |
116 | // We need to print `#![no_std]` (and its feature gate) so that |
117 | // compiling pretty-printed source won't inject libstd again. | |
118 | // However we don't want these attributes in the AST because | |
119 | // of the feature gate, so we fake them up here. | |
120 | ||
92a42be0 | 121 | // #![feature(prelude_import)] |
9e0c209e | 122 | let prelude_import_meta = attr::mk_list_word_item(InternedString::new("prelude_import")); |
92a42be0 SL |
123 | let list = attr::mk_list_item(InternedString::new("feature"), |
124 | vec![prelude_import_meta]); | |
125 | let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), list); | |
3157f602 | 126 | try!(s.print_attribute(&fake_attr)); |
85aaf69f SL |
127 | |
128 | // #![no_std] | |
92a42be0 | 129 | let no_std_meta = attr::mk_word_item(InternedString::new("no_std")); |
85aaf69f | 130 | let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), no_std_meta); |
3157f602 | 131 | try!(s.print_attribute(&fake_attr)); |
85aaf69f SL |
132 | } |
133 | ||
3157f602 XL |
134 | try!(s.print_mod(&krate.module, &krate.attrs)); |
135 | try!(s.print_remaining_comments()); | |
1a4d82fc JJ |
136 | eof(&mut s.s) |
137 | } | |
138 | ||
139 | impl<'a> State<'a> { | |
140 | pub fn new_from_input(cm: &'a CodeMap, | |
9cc50fc6 | 141 | span_diagnostic: &errors::Handler, |
1a4d82fc | 142 | filename: String, |
c34b1796 AL |
143 | input: &mut Read, |
144 | out: Box<Write+'a>, | |
1a4d82fc JJ |
145 | ann: &'a PpAnn, |
146 | is_expanded: bool) -> State<'a> { | |
147 | let (cmnts, lits) = comments::gather_comments_and_literals( | |
148 | span_diagnostic, | |
149 | filename, | |
150 | input); | |
151 | ||
152 | State::new( | |
153 | cm, | |
154 | out, | |
155 | ann, | |
156 | Some(cmnts), | |
157 | // If the code is post expansion, don't use the table of | |
158 | // literals, since it doesn't correspond with the literals | |
159 | // in the AST anymore. | |
160 | if is_expanded { None } else { Some(lits) }) | |
161 | } | |
162 | ||
163 | pub fn new(cm: &'a CodeMap, | |
c34b1796 | 164 | out: Box<Write+'a>, |
1a4d82fc JJ |
165 | ann: &'a PpAnn, |
166 | comments: Option<Vec<comments::Comment>>, | |
167 | literals: Option<Vec<comments::Literal>>) -> State<'a> { | |
168 | State { | |
92a42be0 | 169 | s: pp::mk_printer(out, DEFAULT_COLUMNS), |
1a4d82fc JJ |
170 | cm: Some(cm), |
171 | comments: comments, | |
172 | literals: literals, | |
173 | cur_cmnt_and_lit: CurrentCommentAndLiteral { | |
174 | cur_cmnt: 0, | |
175 | cur_lit: 0 | |
176 | }, | |
177 | boxes: Vec::new(), | |
178 | ann: ann, | |
1a4d82fc JJ |
179 | } |
180 | } | |
181 | } | |
182 | ||
183 | pub fn to_string<F>(f: F) -> String where | |
c34b1796 | 184 | F: FnOnce(&mut State) -> io::Result<()>, |
1a4d82fc | 185 | { |
d9579d0f AL |
186 | let mut wr = Vec::new(); |
187 | { | |
188 | let mut printer = rust_printer(Box::new(&mut wr)); | |
189 | f(&mut printer).unwrap(); | |
190 | eof(&mut printer.s).unwrap(); | |
191 | } | |
192 | String::from_utf8(wr).unwrap() | |
1a4d82fc JJ |
193 | } |
194 | ||
195 | pub fn binop_to_string(op: BinOpToken) -> &'static str { | |
196 | match op { | |
197 | token::Plus => "+", | |
198 | token::Minus => "-", | |
199 | token::Star => "*", | |
200 | token::Slash => "/", | |
201 | token::Percent => "%", | |
202 | token::Caret => "^", | |
203 | token::And => "&", | |
204 | token::Or => "|", | |
205 | token::Shl => "<<", | |
206 | token::Shr => ">>", | |
207 | } | |
208 | } | |
209 | ||
210 | pub fn token_to_string(tok: &Token) -> String { | |
211 | match *tok { | |
212 | token::Eq => "=".to_string(), | |
213 | token::Lt => "<".to_string(), | |
214 | token::Le => "<=".to_string(), | |
215 | token::EqEq => "==".to_string(), | |
216 | token::Ne => "!=".to_string(), | |
217 | token::Ge => ">=".to_string(), | |
218 | token::Gt => ">".to_string(), | |
219 | token::Not => "!".to_string(), | |
220 | token::Tilde => "~".to_string(), | |
221 | token::OrOr => "||".to_string(), | |
222 | token::AndAnd => "&&".to_string(), | |
223 | token::BinOp(op) => binop_to_string(op).to_string(), | |
224 | token::BinOpEq(op) => format!("{}=", binop_to_string(op)), | |
225 | ||
226 | /* Structural symbols */ | |
227 | token::At => "@".to_string(), | |
228 | token::Dot => ".".to_string(), | |
229 | token::DotDot => "..".to_string(), | |
230 | token::DotDotDot => "...".to_string(), | |
231 | token::Comma => ",".to_string(), | |
232 | token::Semi => ";".to_string(), | |
233 | token::Colon => ":".to_string(), | |
234 | token::ModSep => "::".to_string(), | |
235 | token::RArrow => "->".to_string(), | |
236 | token::LArrow => "<-".to_string(), | |
237 | token::FatArrow => "=>".to_string(), | |
238 | token::OpenDelim(token::Paren) => "(".to_string(), | |
239 | token::CloseDelim(token::Paren) => ")".to_string(), | |
240 | token::OpenDelim(token::Bracket) => "[".to_string(), | |
241 | token::CloseDelim(token::Bracket) => "]".to_string(), | |
242 | token::OpenDelim(token::Brace) => "{".to_string(), | |
243 | token::CloseDelim(token::Brace) => "}".to_string(), | |
5bcae85e SL |
244 | token::OpenDelim(token::NoDelim) => " ".to_string(), |
245 | token::CloseDelim(token::NoDelim) => " ".to_string(), | |
1a4d82fc JJ |
246 | token::Pound => "#".to_string(), |
247 | token::Dollar => "$".to_string(), | |
248 | token::Question => "?".to_string(), | |
249 | ||
250 | /* Literals */ | |
251 | token::Literal(lit, suf) => { | |
252 | let mut out = match lit { | |
c1a9b12d SL |
253 | token::Byte(b) => format!("b'{}'", b), |
254 | token::Char(c) => format!("'{}'", c), | |
255 | token::Float(c) => c.to_string(), | |
256 | token::Integer(c) => c.to_string(), | |
257 | token::Str_(s) => format!("\"{}\"", s), | |
1a4d82fc JJ |
258 | token::StrRaw(s, n) => format!("r{delim}\"{string}\"{delim}", |
259 | delim=repeat("#", n), | |
c1a9b12d | 260 | string=s), |
e9174d1e SL |
261 | token::ByteStr(v) => format!("b\"{}\"", v), |
262 | token::ByteStrRaw(s, n) => format!("br{delim}\"{string}\"{delim}", | |
1a4d82fc | 263 | delim=repeat("#", n), |
c1a9b12d | 264 | string=s), |
1a4d82fc | 265 | }; |
223e47cc | 266 | |
1a4d82fc | 267 | if let Some(s) = suf { |
c1a9b12d | 268 | out.push_str(&s.as_str()) |
1a4d82fc | 269 | } |
223e47cc | 270 | |
1a4d82fc JJ |
271 | out |
272 | } | |
223e47cc | 273 | |
1a4d82fc | 274 | /* Name components */ |
a7813a04 | 275 | token::Ident(s) => s.to_string(), |
c1a9b12d | 276 | token::Lifetime(s) => s.to_string(), |
1a4d82fc | 277 | token::Underscore => "_".to_string(), |
223e47cc | 278 | |
1a4d82fc | 279 | /* Other */ |
c1a9b12d | 280 | token::DocComment(s) => s.to_string(), |
a7813a04 XL |
281 | token::SubstNt(s) => format!("${}", s), |
282 | token::MatchNt(s, t) => format!("${}:{}", s, t), | |
1a4d82fc JJ |
283 | token::Eof => "<eof>".to_string(), |
284 | token::Whitespace => " ".to_string(), | |
285 | token::Comment => "/* */".to_string(), | |
c1a9b12d | 286 | token::Shebang(s) => format!("/* shebang: {}*/", s), |
223e47cc | 287 | |
c30ab7b3 | 288 | token::Interpolated(ref nt) => match **nt { |
7453a54e SL |
289 | token::NtExpr(ref e) => expr_to_string(&e), |
290 | token::NtMeta(ref e) => meta_item_to_string(&e), | |
291 | token::NtTy(ref e) => ty_to_string(&e), | |
292 | token::NtPath(ref e) => path_to_string(&e), | |
293 | token::NtItem(ref e) => item_to_string(&e), | |
294 | token::NtBlock(ref e) => block_to_string(&e), | |
295 | token::NtStmt(ref e) => stmt_to_string(&e), | |
296 | token::NtPat(ref e) => pat_to_string(&e), | |
a7813a04 | 297 | token::NtIdent(ref e) => ident_to_string(e.node), |
7453a54e SL |
298 | token::NtTT(ref e) => tt_to_string(&e), |
299 | token::NtArm(ref e) => arm_to_string(&e), | |
300 | token::NtImplItem(ref e) => impl_item_to_string(&e), | |
301 | token::NtTraitItem(ref e) => trait_item_to_string(&e), | |
302 | token::NtGenerics(ref e) => generics_to_string(&e), | |
303 | token::NtWhereClause(ref e) => where_clause_to_string(&e), | |
304 | token::NtArg(ref e) => arg_to_string(&e), | |
1a4d82fc JJ |
305 | } |
306 | } | |
223e47cc LB |
307 | } |
308 | ||
1a4d82fc | 309 | pub fn ty_to_string(ty: &ast::Ty) -> String { |
d9579d0f | 310 | to_string(|s| s.print_type(ty)) |
223e47cc LB |
311 | } |
312 | ||
1a4d82fc | 313 | pub fn bounds_to_string(bounds: &[ast::TyParamBound]) -> String { |
d9579d0f | 314 | to_string(|s| s.print_bounds("", bounds)) |
223e47cc LB |
315 | } |
316 | ||
1a4d82fc | 317 | pub fn pat_to_string(pat: &ast::Pat) -> String { |
d9579d0f | 318 | to_string(|s| s.print_pat(pat)) |
223e47cc LB |
319 | } |
320 | ||
1a4d82fc | 321 | pub fn arm_to_string(arm: &ast::Arm) -> String { |
d9579d0f | 322 | to_string(|s| s.print_arm(arm)) |
223e47cc LB |
323 | } |
324 | ||
1a4d82fc | 325 | pub fn expr_to_string(e: &ast::Expr) -> String { |
d9579d0f | 326 | to_string(|s| s.print_expr(e)) |
223e47cc LB |
327 | } |
328 | ||
1a4d82fc | 329 | pub fn lifetime_to_string(e: &ast::Lifetime) -> String { |
d9579d0f | 330 | to_string(|s| s.print_lifetime(e)) |
223e47cc LB |
331 | } |
332 | ||
3157f602 | 333 | pub fn tt_to_string(tt: &tokenstream::TokenTree) -> String { |
d9579d0f | 334 | to_string(|s| s.print_tt(tt)) |
223e47cc LB |
335 | } |
336 | ||
3157f602 | 337 | pub fn tts_to_string(tts: &[tokenstream::TokenTree]) -> String { |
d9579d0f | 338 | to_string(|s| s.print_tts(tts)) |
223e47cc LB |
339 | } |
340 | ||
1a4d82fc | 341 | pub fn stmt_to_string(stmt: &ast::Stmt) -> String { |
d9579d0f | 342 | to_string(|s| s.print_stmt(stmt)) |
223e47cc LB |
343 | } |
344 | ||
9346a6ac | 345 | pub fn attr_to_string(attr: &ast::Attribute) -> String { |
d9579d0f | 346 | to_string(|s| s.print_attribute(attr)) |
9346a6ac AL |
347 | } |
348 | ||
1a4d82fc | 349 | pub fn item_to_string(i: &ast::Item) -> String { |
d9579d0f | 350 | to_string(|s| s.print_item(i)) |
223e47cc LB |
351 | } |
352 | ||
c34b1796 | 353 | pub fn impl_item_to_string(i: &ast::ImplItem) -> String { |
d9579d0f | 354 | to_string(|s| s.print_impl_item(i)) |
c34b1796 AL |
355 | } |
356 | ||
357 | pub fn trait_item_to_string(i: &ast::TraitItem) -> String { | |
d9579d0f | 358 | to_string(|s| s.print_trait_item(i)) |
223e47cc LB |
359 | } |
360 | ||
c34b1796 | 361 | pub fn generics_to_string(generics: &ast::Generics) -> String { |
d9579d0f | 362 | to_string(|s| s.print_generics(generics)) |
223e47cc LB |
363 | } |
364 | ||
c34b1796 | 365 | pub fn where_clause_to_string(i: &ast::WhereClause) -> String { |
d9579d0f | 366 | to_string(|s| s.print_where_clause(i)) |
223e47cc | 367 | } |
223e47cc | 368 | |
1a4d82fc | 369 | pub fn fn_block_to_string(p: &ast::FnDecl) -> String { |
d9579d0f | 370 | to_string(|s| s.print_fn_block_args(p)) |
223e47cc LB |
371 | } |
372 | ||
1a4d82fc | 373 | pub fn path_to_string(p: &ast::Path) -> String { |
d9579d0f | 374 | to_string(|s| s.print_path(p, false, 0)) |
223e47cc LB |
375 | } |
376 | ||
b039eaaf SL |
377 | pub fn ident_to_string(id: ast::Ident) -> String { |
378 | to_string(|s| s.print_ident(id)) | |
223e47cc LB |
379 | } |
380 | ||
62682a34 SL |
381 | pub fn fun_to_string(decl: &ast::FnDecl, |
382 | unsafety: ast::Unsafety, | |
383 | constness: ast::Constness, | |
384 | name: ast::Ident, | |
62682a34 SL |
385 | generics: &ast::Generics) |
386 | -> String { | |
d9579d0f | 387 | to_string(|s| { |
3157f602 XL |
388 | try!(s.head("")); |
389 | try!(s.print_fn(decl, unsafety, constness, Abi::Rust, Some(name), | |
390 | generics, &ast::Visibility::Inherited)); | |
391 | try!(s.end()); // Close the head box | |
1a4d82fc JJ |
392 | s.end() // Close the outer box |
393 | }) | |
223e47cc LB |
394 | } |
395 | ||
1a4d82fc | 396 | pub fn block_to_string(blk: &ast::Block) -> String { |
d9579d0f | 397 | to_string(|s| { |
1a4d82fc | 398 | // containing cbox, will be closed by print-block at } |
3157f602 | 399 | try!(s.cbox(INDENT_UNIT)); |
1a4d82fc | 400 | // head-ibox, will be closed by print-block after { |
3157f602 | 401 | try!(s.ibox(0)); |
1a4d82fc JJ |
402 | s.print_block(blk) |
403 | }) | |
223e47cc LB |
404 | } |
405 | ||
9e0c209e SL |
406 | pub fn meta_list_item_to_string(li: &ast::NestedMetaItem) -> String { |
407 | to_string(|s| s.print_meta_list_item(li)) | |
408 | } | |
409 | ||
1a4d82fc | 410 | pub fn meta_item_to_string(mi: &ast::MetaItem) -> String { |
d9579d0f | 411 | to_string(|s| s.print_meta_item(mi)) |
223e47cc LB |
412 | } |
413 | ||
1a4d82fc | 414 | pub fn attribute_to_string(attr: &ast::Attribute) -> String { |
d9579d0f | 415 | to_string(|s| s.print_attribute(attr)) |
223e47cc LB |
416 | } |
417 | ||
1a4d82fc | 418 | pub fn lit_to_string(l: &ast::Lit) -> String { |
d9579d0f | 419 | to_string(|s| s.print_literal(l)) |
223e47cc LB |
420 | } |
421 | ||
1a4d82fc | 422 | pub fn variant_to_string(var: &ast::Variant) -> String { |
d9579d0f | 423 | to_string(|s| s.print_variant(var)) |
223e47cc LB |
424 | } |
425 | ||
1a4d82fc | 426 | pub fn arg_to_string(arg: &ast::Arg) -> String { |
7453a54e | 427 | to_string(|s| s.print_arg(arg, false)) |
223e47cc LB |
428 | } |
429 | ||
1a4d82fc | 430 | pub fn mac_to_string(arg: &ast::Mac) -> String { |
d9579d0f | 431 | to_string(|s| s.print_mac(arg, ::parse::token::Paren)) |
970d7e83 LB |
432 | } |
433 | ||
54a0048b SL |
434 | pub fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String { |
435 | match *vis { | |
7453a54e | 436 | ast::Visibility::Public => format!("pub {}", s), |
a7813a04 | 437 | ast::Visibility::Crate(_) => format!("pub(crate) {}", s), |
54a0048b | 438 | ast::Visibility::Restricted { ref path, .. } => format!("pub({}) {}", path, s), |
7453a54e | 439 | ast::Visibility::Inherited => s.to_string() |
1a4d82fc | 440 | } |
223e47cc LB |
441 | } |
442 | ||
1a4d82fc JJ |
443 | fn needs_parentheses(expr: &ast::Expr) -> bool { |
444 | match expr.node { | |
7453a54e SL |
445 | ast::ExprKind::Assign(..) | ast::ExprKind::Binary(..) | |
446 | ast::ExprKind::Closure(..) | | |
447 | ast::ExprKind::AssignOp(..) | ast::ExprKind::Cast(..) | | |
448 | ast::ExprKind::InPlace(..) | ast::ExprKind::Type(..) => true, | |
1a4d82fc JJ |
449 | _ => false, |
450 | } | |
223e47cc LB |
451 | } |
452 | ||
b039eaaf SL |
453 | pub trait PrintState<'a> { |
454 | fn writer(&mut self) -> &mut pp::Printer<'a>; | |
455 | fn boxes(&mut self) -> &mut Vec<pp::Breaks>; | |
456 | fn comments(&mut self) -> &mut Option<Vec<comments::Comment>>; | |
457 | fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral; | |
458 | fn literals(&self) -> &Option<Vec<comments::Literal>>; | |
459 | ||
460 | fn word_space(&mut self, w: &str) -> io::Result<()> { | |
3157f602 | 461 | try!(word(self.writer(), w)); |
b039eaaf | 462 | space(self.writer()) |
223e47cc | 463 | } |
223e47cc | 464 | |
b039eaaf SL |
465 | fn popen(&mut self) -> io::Result<()> { word(self.writer(), "(") } |
466 | ||
467 | fn pclose(&mut self) -> io::Result<()> { word(self.writer(), ")") } | |
468 | ||
469 | fn is_begin(&mut self) -> bool { | |
470 | match self.writer().last_token() { | |
471 | pp::Token::Begin(_) => true, | |
472 | _ => false, | |
473 | } | |
223e47cc | 474 | } |
223e47cc | 475 | |
b039eaaf SL |
476 | fn is_end(&mut self) -> bool { |
477 | match self.writer().last_token() { | |
478 | pp::Token::End => true, | |
479 | _ => false, | |
480 | } | |
481 | } | |
482 | ||
483 | // is this the beginning of a line? | |
484 | fn is_bol(&mut self) -> bool { | |
485 | self.writer().last_token().is_eof() || self.writer().last_token().is_hardbreak_tok() | |
486 | } | |
487 | ||
488 | fn hardbreak_if_not_bol(&mut self) -> io::Result<()> { | |
489 | if !self.is_bol() { | |
3157f602 | 490 | try!(hardbreak(self.writer())) |
b039eaaf SL |
491 | } |
492 | Ok(()) | |
223e47cc | 493 | } |
223e47cc | 494 | |
1a4d82fc | 495 | // "raw box" |
b039eaaf SL |
496 | fn rbox(&mut self, u: usize, b: pp::Breaks) -> io::Result<()> { |
497 | self.boxes().push(b); | |
498 | pp::rbox(self.writer(), u, b) | |
1a4d82fc | 499 | } |
223e47cc | 500 | |
b039eaaf SL |
501 | fn ibox(&mut self, u: usize) -> io::Result<()> { |
502 | self.boxes().push(pp::Breaks::Inconsistent); | |
503 | pp::ibox(self.writer(), u) | |
504 | } | |
223e47cc | 505 | |
b039eaaf SL |
506 | fn end(&mut self) -> io::Result<()> { |
507 | self.boxes().pop().unwrap(); | |
508 | pp::end(self.writer()) | |
223e47cc | 509 | } |
223e47cc | 510 | |
b039eaaf SL |
511 | fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()> |
512 | where F: FnMut(&mut Self, &T) -> io::Result<()>, | |
513 | { | |
3157f602 | 514 | try!(self.rbox(0, b)); |
b039eaaf SL |
515 | let mut first = true; |
516 | for elt in elts { | |
3157f602 XL |
517 | if first { first = false; } else { try!(self.word_space(",")); } |
518 | try!(op(self, elt)); | |
b039eaaf SL |
519 | } |
520 | self.end() | |
521 | } | |
522 | ||
523 | fn next_lit(&mut self, pos: BytePos) -> Option<comments::Literal> { | |
524 | let mut cur_lit = self.cur_cmnt_and_lit().cur_lit; | |
525 | ||
526 | let mut result = None; | |
527 | ||
528 | if let &Some(ref lits) = self.literals() | |
529 | { | |
530 | while cur_lit < lits.len() { | |
531 | let ltrl = (*lits)[cur_lit].clone(); | |
532 | if ltrl.pos > pos { break; } | |
533 | cur_lit += 1; | |
534 | if ltrl.pos == pos { | |
535 | result = Some(ltrl); | |
536 | break; | |
537 | } | |
538 | } | |
539 | } | |
540 | ||
541 | self.cur_cmnt_and_lit().cur_lit = cur_lit; | |
542 | result | |
543 | } | |
544 | ||
545 | fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> { | |
c30ab7b3 SL |
546 | while let Some(ref cmnt) = self.next_comment() { |
547 | if cmnt.pos < pos { | |
548 | try!(self.print_comment(cmnt)); | |
549 | self.cur_cmnt_and_lit().cur_cmnt += 1; | |
550 | } else { | |
551 | break | |
b039eaaf SL |
552 | } |
553 | } | |
554 | Ok(()) | |
555 | } | |
556 | ||
557 | fn print_comment(&mut self, | |
558 | cmnt: &comments::Comment) -> io::Result<()> { | |
559 | match cmnt.style { | |
560 | comments::Mixed => { | |
561 | assert_eq!(cmnt.lines.len(), 1); | |
3157f602 XL |
562 | try!(zerobreak(self.writer())); |
563 | try!(word(self.writer(), &cmnt.lines[0])); | |
b039eaaf SL |
564 | zerobreak(self.writer()) |
565 | } | |
566 | comments::Isolated => { | |
3157f602 | 567 | try!(self.hardbreak_if_not_bol()); |
b039eaaf SL |
568 | for line in &cmnt.lines { |
569 | // Don't print empty lines because they will end up as trailing | |
570 | // whitespace | |
571 | if !line.is_empty() { | |
3157f602 | 572 | try!(word(self.writer(), &line[..])); |
b039eaaf | 573 | } |
3157f602 | 574 | try!(hardbreak(self.writer())); |
b039eaaf SL |
575 | } |
576 | Ok(()) | |
577 | } | |
578 | comments::Trailing => { | |
c30ab7b3 SL |
579 | if !self.is_bol() { |
580 | try!(word(self.writer(), " ")); | |
581 | } | |
b039eaaf | 582 | if cmnt.lines.len() == 1 { |
3157f602 | 583 | try!(word(self.writer(), &cmnt.lines[0])); |
b039eaaf SL |
584 | hardbreak(self.writer()) |
585 | } else { | |
3157f602 | 586 | try!(self.ibox(0)); |
b039eaaf SL |
587 | for line in &cmnt.lines { |
588 | if !line.is_empty() { | |
3157f602 | 589 | try!(word(self.writer(), &line[..])); |
b039eaaf | 590 | } |
3157f602 | 591 | try!(hardbreak(self.writer())); |
b039eaaf SL |
592 | } |
593 | self.end() | |
594 | } | |
595 | } | |
596 | comments::BlankLine => { | |
597 | // We need to do at least one, possibly two hardbreaks. | |
598 | let is_semi = match self.writer().last_token() { | |
599 | pp::Token::String(s, _) => ";" == s, | |
600 | _ => false | |
601 | }; | |
602 | if is_semi || self.is_begin() || self.is_end() { | |
3157f602 | 603 | try!(hardbreak(self.writer())); |
b039eaaf SL |
604 | } |
605 | hardbreak(self.writer()) | |
606 | } | |
607 | } | |
608 | } | |
609 | ||
610 | fn next_comment(&mut self) -> Option<comments::Comment> { | |
611 | let cur_cmnt = self.cur_cmnt_and_lit().cur_cmnt; | |
612 | match *self.comments() { | |
613 | Some(ref cmnts) => { | |
614 | if cur_cmnt < cmnts.len() { | |
615 | Some(cmnts[cur_cmnt].clone()) | |
616 | } else { | |
617 | None | |
618 | } | |
619 | } | |
620 | _ => None | |
621 | } | |
622 | } | |
623 | ||
624 | fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> { | |
3157f602 | 625 | try!(self.maybe_print_comment(lit.span.lo)); |
b039eaaf SL |
626 | match self.next_lit(lit.span.lo) { |
627 | Some(ref ltrl) => { | |
628 | return word(self.writer(), &(*ltrl).lit); | |
629 | } | |
630 | _ => () | |
631 | } | |
632 | match lit.node { | |
7453a54e SL |
633 | ast::LitKind::Str(ref st, style) => self.print_string(&st, style), |
634 | ast::LitKind::Byte(byte) => { | |
b039eaaf SL |
635 | let mut res = String::from("b'"); |
636 | res.extend(ascii::escape_default(byte).map(|c| c as char)); | |
637 | res.push('\''); | |
638 | word(self.writer(), &res[..]) | |
639 | } | |
7453a54e | 640 | ast::LitKind::Char(ch) => { |
b039eaaf SL |
641 | let mut res = String::from("'"); |
642 | res.extend(ch.escape_default()); | |
643 | res.push('\''); | |
644 | word(self.writer(), &res[..]) | |
645 | } | |
7453a54e | 646 | ast::LitKind::Int(i, t) => { |
b039eaaf | 647 | match t { |
7453a54e | 648 | ast::LitIntType::Signed(st) => { |
b039eaaf | 649 | word(self.writer(), |
9cc50fc6 | 650 | &st.val_to_string(i as i64)) |
b039eaaf | 651 | } |
7453a54e | 652 | ast::LitIntType::Unsigned(ut) => { |
9cc50fc6 | 653 | word(self.writer(), &ut.val_to_string(i)) |
b039eaaf | 654 | } |
7453a54e | 655 | ast::LitIntType::Unsuffixed => { |
b039eaaf SL |
656 | word(self.writer(), &format!("{}", i)) |
657 | } | |
b039eaaf SL |
658 | } |
659 | } | |
7453a54e | 660 | ast::LitKind::Float(ref f, t) => { |
b039eaaf SL |
661 | word(self.writer(), |
662 | &format!( | |
663 | "{}{}", | |
664 | &f, | |
9cc50fc6 | 665 | t.ty_to_string())) |
b039eaaf | 666 | } |
7453a54e SL |
667 | ast::LitKind::FloatUnsuffixed(ref f) => word(self.writer(), &f[..]), |
668 | ast::LitKind::Bool(val) => { | |
b039eaaf SL |
669 | if val { word(self.writer(), "true") } else { word(self.writer(), "false") } |
670 | } | |
7453a54e | 671 | ast::LitKind::ByteStr(ref v) => { |
b039eaaf SL |
672 | let mut escaped: String = String::new(); |
673 | for &ch in v.iter() { | |
674 | escaped.extend(ascii::escape_default(ch) | |
675 | .map(|c| c as char)); | |
676 | } | |
677 | word(self.writer(), &format!("b\"{}\"", escaped)) | |
678 | } | |
679 | } | |
680 | } | |
681 | ||
682 | fn print_string(&mut self, st: &str, | |
683 | style: ast::StrStyle) -> io::Result<()> { | |
684 | let st = match style { | |
7453a54e | 685 | ast::StrStyle::Cooked => { |
b039eaaf SL |
686 | (format!("\"{}\"", st.escape_default())) |
687 | } | |
7453a54e | 688 | ast::StrStyle::Raw(n) => { |
b039eaaf SL |
689 | (format!("r{delim}\"{string}\"{delim}", |
690 | delim=repeat("#", n), | |
691 | string=st)) | |
692 | } | |
693 | }; | |
694 | word(self.writer(), &st[..]) | |
695 | } | |
696 | ||
697 | fn print_inner_attributes(&mut self, | |
92a42be0 SL |
698 | attrs: &[ast::Attribute]) -> io::Result<()> { |
699 | self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true) | |
700 | } | |
701 | ||
702 | fn print_inner_attributes_no_trailing_hardbreak(&mut self, | |
703 | attrs: &[ast::Attribute]) | |
704 | -> io::Result<()> { | |
705 | self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false) | |
b039eaaf SL |
706 | } |
707 | ||
708 | fn print_outer_attributes(&mut self, | |
709 | attrs: &[ast::Attribute]) -> io::Result<()> { | |
92a42be0 SL |
710 | self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true) |
711 | } | |
712 | ||
713 | fn print_inner_attributes_inline(&mut self, | |
714 | attrs: &[ast::Attribute]) -> io::Result<()> { | |
715 | self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true) | |
716 | } | |
717 | ||
718 | fn print_outer_attributes_inline(&mut self, | |
719 | attrs: &[ast::Attribute]) -> io::Result<()> { | |
720 | self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true) | |
721 | } | |
722 | ||
723 | fn print_either_attributes(&mut self, | |
724 | attrs: &[ast::Attribute], | |
725 | kind: ast::AttrStyle, | |
726 | is_inline: bool, | |
727 | trailing_hardbreak: bool) -> io::Result<()> { | |
b039eaaf SL |
728 | let mut count = 0; |
729 | for attr in attrs { | |
92a42be0 | 730 | if attr.node.style == kind { |
3157f602 XL |
731 | try!(self.print_attribute_inline(attr, is_inline)); |
732 | if is_inline { | |
733 | try!(self.nbsp()); | |
734 | } | |
735 | count += 1; | |
b039eaaf SL |
736 | } |
737 | } | |
92a42be0 | 738 | if count > 0 && trailing_hardbreak && !is_inline { |
3157f602 | 739 | try!(self.hardbreak_if_not_bol()); |
b039eaaf SL |
740 | } |
741 | Ok(()) | |
223e47cc | 742 | } |
223e47cc | 743 | |
b039eaaf | 744 | fn print_attribute(&mut self, attr: &ast::Attribute) -> io::Result<()> { |
92a42be0 SL |
745 | self.print_attribute_inline(attr, false) |
746 | } | |
747 | ||
748 | fn print_attribute_inline(&mut self, attr: &ast::Attribute, | |
749 | is_inline: bool) -> io::Result<()> { | |
750 | if !is_inline { | |
3157f602 | 751 | try!(self.hardbreak_if_not_bol()); |
92a42be0 | 752 | } |
3157f602 | 753 | try!(self.maybe_print_comment(attr.span.lo)); |
b039eaaf | 754 | if attr.node.is_sugared_doc { |
3157f602 | 755 | try!(word(self.writer(), &attr.value_str().unwrap())); |
54a0048b | 756 | hardbreak(self.writer()) |
b039eaaf SL |
757 | } else { |
758 | match attr.node.style { | |
3157f602 XL |
759 | ast::AttrStyle::Inner => try!(word(self.writer(), "#![")), |
760 | ast::AttrStyle::Outer => try!(word(self.writer(), "#[")), | |
b039eaaf | 761 | } |
3157f602 | 762 | try!(self.print_meta_item(&attr.meta())); |
b039eaaf SL |
763 | word(self.writer(), "]") |
764 | } | |
765 | } | |
1a4d82fc | 766 | |
9e0c209e SL |
767 | fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) -> io::Result<()> { |
768 | match item.node { | |
769 | ast::NestedMetaItemKind::MetaItem(ref mi) => { | |
770 | self.print_meta_item(mi) | |
771 | }, | |
772 | ast::NestedMetaItemKind::Literal(ref lit) => { | |
773 | self.print_literal(lit) | |
774 | } | |
775 | } | |
776 | } | |
777 | ||
b039eaaf | 778 | fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> { |
3157f602 | 779 | try!(self.ibox(INDENT_UNIT)); |
b039eaaf | 780 | match item.node { |
7453a54e | 781 | ast::MetaItemKind::Word(ref name) => { |
3157f602 | 782 | try!(word(self.writer(), &name)); |
b039eaaf | 783 | } |
7453a54e | 784 | ast::MetaItemKind::NameValue(ref name, ref value) => { |
3157f602 XL |
785 | try!(self.word_space(&name[..])); |
786 | try!(self.word_space("=")); | |
787 | try!(self.print_literal(value)); | |
b039eaaf | 788 | } |
7453a54e | 789 | ast::MetaItemKind::List(ref name, ref items) => { |
3157f602 XL |
790 | try!(word(self.writer(), &name)); |
791 | try!(self.popen()); | |
792 | try!(self.commasep(Consistent, | |
54a0048b | 793 | &items[..], |
9e0c209e | 794 | |s, i| s.print_meta_list_item(&i))); |
3157f602 | 795 | try!(self.pclose()); |
b039eaaf SL |
796 | } |
797 | } | |
798 | self.end() | |
799 | } | |
92a42be0 SL |
800 | |
801 | fn space_if_not_bol(&mut self) -> io::Result<()> { | |
3157f602 | 802 | if !self.is_bol() { try!(space(self.writer())); } |
92a42be0 SL |
803 | Ok(()) |
804 | } | |
805 | ||
806 | fn nbsp(&mut self) -> io::Result<()> { word(self.writer(), " ") } | |
b039eaaf SL |
807 | } |
808 | ||
809 | impl<'a> PrintState<'a> for State<'a> { | |
810 | fn writer(&mut self) -> &mut pp::Printer<'a> { | |
811 | &mut self.s | |
812 | } | |
813 | ||
814 | fn boxes(&mut self) -> &mut Vec<pp::Breaks> { | |
815 | &mut self.boxes | |
816 | } | |
817 | ||
818 | fn comments(&mut self) -> &mut Option<Vec<comments::Comment>> { | |
819 | &mut self.comments | |
820 | } | |
821 | ||
822 | fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral { | |
823 | &mut self.cur_cmnt_and_lit | |
824 | } | |
825 | ||
826 | fn literals(&self) -> &Option<Vec<comments::Literal>> { | |
827 | &self.literals | |
828 | } | |
829 | } | |
830 | ||
831 | impl<'a> State<'a> { | |
832 | pub fn cbox(&mut self, u: usize) -> io::Result<()> { | |
833 | self.boxes.push(pp::Breaks::Consistent); | |
834 | pp::cbox(&mut self.s, u) | |
835 | } | |
836 | ||
b039eaaf | 837 | pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> { |
3157f602 | 838 | try!(word(&mut self.s, w)); |
b039eaaf SL |
839 | self.nbsp() |
840 | } | |
1a4d82fc | 841 | |
c34b1796 | 842 | pub fn head(&mut self, w: &str) -> io::Result<()> { |
1a4d82fc | 843 | // outer-box is consistent |
3157f602 | 844 | try!(self.cbox(INDENT_UNIT)); |
1a4d82fc | 845 | // head-box is inconsistent |
3157f602 | 846 | try!(self.ibox(w.len() + 1)); |
1a4d82fc JJ |
847 | // keyword that starts the head |
848 | if !w.is_empty() { | |
3157f602 | 849 | try!(self.word_nbsp(w)); |
223e47cc | 850 | } |
1a4d82fc | 851 | Ok(()) |
223e47cc | 852 | } |
223e47cc | 853 | |
c34b1796 | 854 | pub fn bopen(&mut self) -> io::Result<()> { |
3157f602 | 855 | try!(word(&mut self.s, "{")); |
1a4d82fc JJ |
856 | self.end() // close the head-box |
857 | } | |
858 | ||
3157f602 | 859 | pub fn bclose_(&mut self, span: syntax_pos::Span, |
c34b1796 | 860 | indented: usize) -> io::Result<()> { |
1a4d82fc JJ |
861 | self.bclose_maybe_open(span, indented, true) |
862 | } | |
3157f602 | 863 | pub fn bclose_maybe_open(&mut self, span: syntax_pos::Span, |
9cc50fc6 | 864 | indented: usize, close_box: bool) -> io::Result<()> { |
3157f602 XL |
865 | try!(self.maybe_print_comment(span.hi)); |
866 | try!(self.break_offset_if_not_bol(1, -(indented as isize))); | |
867 | try!(word(&mut self.s, "}")); | |
1a4d82fc | 868 | if close_box { |
3157f602 | 869 | try!(self.end()); // close the outer-box |
223e47cc | 870 | } |
1a4d82fc | 871 | Ok(()) |
223e47cc | 872 | } |
3157f602 | 873 | pub fn bclose(&mut self, span: syntax_pos::Span) -> io::Result<()> { |
92a42be0 | 874 | self.bclose_(span, INDENT_UNIT) |
223e47cc | 875 | } |
223e47cc | 876 | |
1a4d82fc JJ |
877 | pub fn in_cbox(&self) -> bool { |
878 | match self.boxes.last() { | |
85aaf69f | 879 | Some(&last_box) => last_box == pp::Breaks::Consistent, |
1a4d82fc | 880 | None => false |
223e47cc LB |
881 | } |
882 | } | |
223e47cc | 883 | |
85aaf69f | 884 | pub fn break_offset_if_not_bol(&mut self, n: usize, |
c34b1796 | 885 | off: isize) -> io::Result<()> { |
1a4d82fc JJ |
886 | if !self.is_bol() { |
887 | break_offset(&mut self.s, n, off) | |
888 | } else { | |
889 | if off != 0 && self.s.last_token().is_hardbreak_tok() { | |
890 | // We do something pretty sketchy here: tuck the nonzero | |
891 | // offset-adjustment we were going to deposit along with the | |
892 | // break into the previous hardbreak. | |
893 | self.s.replace_last_token(pp::hardbreak_tok_offset(off)); | |
223e47cc | 894 | } |
1a4d82fc | 895 | Ok(()) |
223e47cc LB |
896 | } |
897 | } | |
223e47cc | 898 | |
1a4d82fc JJ |
899 | // Synthesizes a comment that was not textually present in the original source |
900 | // file. | |
c34b1796 | 901 | pub fn synth_comment(&mut self, text: String) -> io::Result<()> { |
3157f602 XL |
902 | try!(word(&mut self.s, "/*")); |
903 | try!(space(&mut self.s)); | |
904 | try!(word(&mut self.s, &text[..])); | |
905 | try!(space(&mut self.s)); | |
1a4d82fc | 906 | word(&mut self.s, "*/") |
223e47cc | 907 | } |
223e47cc | 908 | |
1a4d82fc JJ |
909 | |
910 | ||
911 | pub fn commasep_cmnt<T, F, G>(&mut self, | |
912 | b: Breaks, | |
913 | elts: &[T], | |
914 | mut op: F, | |
c34b1796 AL |
915 | mut get_span: G) -> io::Result<()> where |
916 | F: FnMut(&mut State, &T) -> io::Result<()>, | |
3157f602 | 917 | G: FnMut(&T) -> syntax_pos::Span, |
1a4d82fc | 918 | { |
3157f602 | 919 | try!(self.rbox(0, b)); |
1a4d82fc | 920 | let len = elts.len(); |
85aaf69f SL |
921 | let mut i = 0; |
922 | for elt in elts { | |
3157f602 XL |
923 | try!(self.maybe_print_comment(get_span(elt).hi)); |
924 | try!(op(self, elt)); | |
85aaf69f | 925 | i += 1; |
1a4d82fc | 926 | if i < len { |
3157f602 XL |
927 | try!(word(&mut self.s, ",")); |
928 | try!(self.maybe_print_trailing_comment(get_span(elt), | |
929 | Some(get_span(&elts[i]).hi))); | |
930 | try!(self.space_if_not_bol()); | |
1a4d82fc JJ |
931 | } |
932 | } | |
933 | self.end() | |
934 | } | |
223e47cc | 935 | |
1a4d82fc | 936 | pub fn commasep_exprs(&mut self, b: Breaks, |
c34b1796 | 937 | exprs: &[P<ast::Expr>]) -> io::Result<()> { |
7453a54e | 938 | self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span) |
1a4d82fc | 939 | } |
223e47cc | 940 | |
1a4d82fc | 941 | pub fn print_mod(&mut self, _mod: &ast::Mod, |
c34b1796 | 942 | attrs: &[ast::Attribute]) -> io::Result<()> { |
3157f602 | 943 | try!(self.print_inner_attributes(attrs)); |
85aaf69f | 944 | for item in &_mod.items { |
3157f602 | 945 | try!(self.print_item(&item)); |
1a4d82fc JJ |
946 | } |
947 | Ok(()) | |
223e47cc | 948 | } |
223e47cc | 949 | |
1a4d82fc | 950 | pub fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, |
c34b1796 | 951 | attrs: &[ast::Attribute]) -> io::Result<()> { |
3157f602 | 952 | try!(self.print_inner_attributes(attrs)); |
85aaf69f | 953 | for item in &nmod.items { |
3157f602 | 954 | try!(self.print_foreign_item(item)); |
1a4d82fc JJ |
955 | } |
956 | Ok(()) | |
223e47cc | 957 | } |
223e47cc | 958 | |
1a4d82fc | 959 | pub fn print_opt_lifetime(&mut self, |
c34b1796 | 960 | lifetime: &Option<ast::Lifetime>) -> io::Result<()> { |
85aaf69f | 961 | if let Some(l) = *lifetime { |
3157f602 XL |
962 | try!(self.print_lifetime(&l)); |
963 | try!(self.nbsp()); | |
1a4d82fc JJ |
964 | } |
965 | Ok(()) | |
223e47cc | 966 | } |
223e47cc | 967 | |
c34b1796 | 968 | pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> { |
3157f602 XL |
969 | try!(self.maybe_print_comment(ty.span.lo)); |
970 | try!(self.ibox(0)); | |
1a4d82fc | 971 | match ty.node { |
c30ab7b3 | 972 | ast::TyKind::Slice(ref ty) => { |
3157f602 XL |
973 | try!(word(&mut self.s, "[")); |
974 | try!(self.print_type(&ty)); | |
975 | try!(word(&mut self.s, "]")); | |
1a4d82fc | 976 | } |
7453a54e | 977 | ast::TyKind::Ptr(ref mt) => { |
3157f602 | 978 | try!(word(&mut self.s, "*")); |
1a4d82fc | 979 | match mt.mutbl { |
3157f602 XL |
980 | ast::Mutability::Mutable => try!(self.word_nbsp("mut")), |
981 | ast::Mutability::Immutable => try!(self.word_nbsp("const")), | |
1a4d82fc | 982 | } |
3157f602 | 983 | try!(self.print_type(&mt.ty)); |
1a4d82fc | 984 | } |
7453a54e | 985 | ast::TyKind::Rptr(ref lifetime, ref mt) => { |
3157f602 XL |
986 | try!(word(&mut self.s, "&")); |
987 | try!(self.print_opt_lifetime(lifetime)); | |
988 | try!(self.print_mt(mt)); | |
1a4d82fc | 989 | } |
5bcae85e SL |
990 | ast::TyKind::Never => { |
991 | try!(word(&mut self.s, "!")); | |
992 | }, | |
7453a54e | 993 | ast::TyKind::Tup(ref elts) => { |
3157f602 XL |
994 | try!(self.popen()); |
995 | try!(self.commasep(Inconsistent, &elts[..], | |
996 | |s, ty| s.print_type(&ty))); | |
1a4d82fc | 997 | if elts.len() == 1 { |
3157f602 | 998 | try!(word(&mut self.s, ",")); |
1a4d82fc | 999 | } |
3157f602 | 1000 | try!(self.pclose()); |
1a4d82fc | 1001 | } |
7453a54e | 1002 | ast::TyKind::Paren(ref typ) => { |
3157f602 XL |
1003 | try!(self.popen()); |
1004 | try!(self.print_type(&typ)); | |
1005 | try!(self.pclose()); | |
1a4d82fc | 1006 | } |
7453a54e | 1007 | ast::TyKind::BareFn(ref f) => { |
1a4d82fc JJ |
1008 | let generics = ast::Generics { |
1009 | lifetimes: f.lifetimes.clone(), | |
a7813a04 | 1010 | ty_params: P::new(), |
1a4d82fc JJ |
1011 | where_clause: ast::WhereClause { |
1012 | id: ast::DUMMY_NODE_ID, | |
1013 | predicates: Vec::new(), | |
1014 | }, | |
9e0c209e | 1015 | span: syntax_pos::DUMMY_SP, |
1a4d82fc | 1016 | }; |
3157f602 | 1017 | try!(self.print_ty_fn(f.abi, |
54a0048b SL |
1018 | f.unsafety, |
1019 | &f.decl, | |
1020 | None, | |
3157f602 | 1021 | &generics)); |
1a4d82fc | 1022 | } |
7453a54e | 1023 | ast::TyKind::Path(None, ref path) => { |
3157f602 | 1024 | try!(self.print_path(path, false, 0)); |
c34b1796 | 1025 | } |
7453a54e | 1026 | ast::TyKind::Path(Some(ref qself), ref path) => { |
3157f602 | 1027 | try!(self.print_qpath(path, qself, false)) |
1a4d82fc | 1028 | } |
7453a54e | 1029 | ast::TyKind::ObjectSum(ref ty, ref bounds) => { |
3157f602 XL |
1030 | try!(self.print_type(&ty)); |
1031 | try!(self.print_bounds("+", &bounds[..])); | |
1a4d82fc | 1032 | } |
7453a54e | 1033 | ast::TyKind::PolyTraitRef(ref bounds) => { |
3157f602 | 1034 | try!(self.print_bounds("", &bounds[..])); |
1a4d82fc | 1035 | } |
5bcae85e SL |
1036 | ast::TyKind::ImplTrait(ref bounds) => { |
1037 | try!(self.print_bounds("impl ", &bounds[..])); | |
1038 | } | |
c30ab7b3 | 1039 | ast::TyKind::Array(ref ty, ref v) => { |
3157f602 XL |
1040 | try!(word(&mut self.s, "[")); |
1041 | try!(self.print_type(&ty)); | |
1042 | try!(word(&mut self.s, "; ")); | |
1043 | try!(self.print_expr(&v)); | |
1044 | try!(word(&mut self.s, "]")); | |
1a4d82fc | 1045 | } |
7453a54e | 1046 | ast::TyKind::Typeof(ref e) => { |
3157f602 XL |
1047 | try!(word(&mut self.s, "typeof(")); |
1048 | try!(self.print_expr(&e)); | |
1049 | try!(word(&mut self.s, ")")); | |
1a4d82fc | 1050 | } |
7453a54e | 1051 | ast::TyKind::Infer => { |
3157f602 XL |
1052 | try!(word(&mut self.s, "_")); |
1053 | } | |
1054 | ast::TyKind::ImplicitSelf => { | |
1055 | try!(word(&mut self.s, "Self")); | |
1a4d82fc | 1056 | } |
7453a54e | 1057 | ast::TyKind::Mac(ref m) => { |
3157f602 | 1058 | try!(self.print_mac(m, token::Paren)); |
e9174d1e | 1059 | } |
223e47cc | 1060 | } |
1a4d82fc JJ |
1061 | self.end() |
1062 | } | |
1063 | ||
1064 | pub fn print_foreign_item(&mut self, | |
c34b1796 | 1065 | item: &ast::ForeignItem) -> io::Result<()> { |
3157f602 XL |
1066 | try!(self.hardbreak_if_not_bol()); |
1067 | try!(self.maybe_print_comment(item.span.lo)); | |
1068 | try!(self.print_outer_attributes(&item.attrs)); | |
1a4d82fc | 1069 | match item.node { |
7453a54e | 1070 | ast::ForeignItemKind::Fn(ref decl, ref generics) => { |
3157f602 XL |
1071 | try!(self.head("")); |
1072 | try!(self.print_fn(decl, ast::Unsafety::Normal, | |
54a0048b SL |
1073 | ast::Constness::NotConst, |
1074 | Abi::Rust, Some(item.ident), | |
3157f602 XL |
1075 | generics, &item.vis)); |
1076 | try!(self.end()); // end head-ibox | |
1077 | try!(word(&mut self.s, ";")); | |
1a4d82fc JJ |
1078 | self.end() // end the outer fn box |
1079 | } | |
7453a54e | 1080 | ast::ForeignItemKind::Static(ref t, m) => { |
3157f602 | 1081 | try!(self.head(&visibility_qualified(&item.vis, "static"))); |
1a4d82fc | 1082 | if m { |
3157f602 | 1083 | try!(self.word_space("mut")); |
1a4d82fc | 1084 | } |
3157f602 XL |
1085 | try!(self.print_ident(item.ident)); |
1086 | try!(self.word_space(":")); | |
1087 | try!(self.print_type(&t)); | |
1088 | try!(word(&mut self.s, ";")); | |
1089 | try!(self.end()); // end the head-ibox | |
1a4d82fc JJ |
1090 | self.end() // end the outer cbox |
1091 | } | |
223e47cc | 1092 | } |
223e47cc | 1093 | } |
223e47cc | 1094 | |
d9579d0f AL |
1095 | fn print_associated_const(&mut self, |
1096 | ident: ast::Ident, | |
1097 | ty: &ast::Ty, | |
1098 | default: Option<&ast::Expr>, | |
54a0048b | 1099 | vis: &ast::Visibility) |
d9579d0f AL |
1100 | -> io::Result<()> |
1101 | { | |
3157f602 XL |
1102 | try!(word(&mut self.s, &visibility_qualified(vis, ""))); |
1103 | try!(self.word_space("const")); | |
1104 | try!(self.print_ident(ident)); | |
1105 | try!(self.word_space(":")); | |
1106 | try!(self.print_type(ty)); | |
d9579d0f | 1107 | if let Some(expr) = default { |
3157f602 XL |
1108 | try!(space(&mut self.s)); |
1109 | try!(self.word_space("=")); | |
1110 | try!(self.print_expr(expr)); | |
d9579d0f AL |
1111 | } |
1112 | word(&mut self.s, ";") | |
1113 | } | |
1114 | ||
c34b1796 AL |
1115 | fn print_associated_type(&mut self, |
1116 | ident: ast::Ident, | |
1117 | bounds: Option<&ast::TyParamBounds>, | |
1118 | ty: Option<&ast::Ty>) | |
1119 | -> io::Result<()> { | |
3157f602 XL |
1120 | try!(self.word_space("type")); |
1121 | try!(self.print_ident(ident)); | |
c34b1796 | 1122 | if let Some(bounds) = bounds { |
3157f602 | 1123 | try!(self.print_bounds(":", bounds)); |
c34b1796 AL |
1124 | } |
1125 | if let Some(ty) = ty { | |
3157f602 XL |
1126 | try!(space(&mut self.s)); |
1127 | try!(self.word_space("=")); | |
1128 | try!(self.print_type(ty)); | |
c34b1796 | 1129 | } |
1a4d82fc JJ |
1130 | word(&mut self.s, ";") |
1131 | } | |
1132 | ||
1a4d82fc | 1133 | /// Pretty-print an item |
c34b1796 | 1134 | pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> { |
3157f602 XL |
1135 | try!(self.hardbreak_if_not_bol()); |
1136 | try!(self.maybe_print_comment(item.span.lo)); | |
1137 | try!(self.print_outer_attributes(&item.attrs)); | |
1138 | try!(self.ann.pre(self, NodeItem(item))); | |
1a4d82fc | 1139 | match item.node { |
7453a54e | 1140 | ast::ItemKind::ExternCrate(ref optional_path) => { |
3157f602 | 1141 | try!(self.head(&visibility_qualified(&item.vis, "extern crate"))); |
c34b1796 | 1142 | if let Some(p) = *optional_path { |
c1a9b12d | 1143 | let val = p.as_str(); |
c34b1796 | 1144 | if val.contains("-") { |
3157f602 | 1145 | try!(self.print_string(&val, ast::StrStyle::Cooked)); |
c34b1796 | 1146 | } else { |
3157f602 | 1147 | try!(self.print_name(p)); |
c34b1796 | 1148 | } |
3157f602 XL |
1149 | try!(space(&mut self.s)); |
1150 | try!(word(&mut self.s, "as")); | |
1151 | try!(space(&mut self.s)); | |
85aaf69f | 1152 | } |
3157f602 XL |
1153 | try!(self.print_ident(item.ident)); |
1154 | try!(word(&mut self.s, ";")); | |
1155 | try!(self.end()); // end inner head-block | |
1156 | try!(self.end()); // end outer head-block | |
85aaf69f | 1157 | } |
7453a54e | 1158 | ast::ItemKind::Use(ref vp) => { |
3157f602 XL |
1159 | try!(self.head(&visibility_qualified(&item.vis, "use"))); |
1160 | try!(self.print_view_path(&vp)); | |
1161 | try!(word(&mut self.s, ";")); | |
1162 | try!(self.end()); // end inner head-block | |
1163 | try!(self.end()); // end outer head-block | |
85aaf69f | 1164 | } |
7453a54e | 1165 | ast::ItemKind::Static(ref ty, m, ref expr) => { |
3157f602 | 1166 | try!(self.head(&visibility_qualified(&item.vis, "static"))); |
7453a54e | 1167 | if m == ast::Mutability::Mutable { |
3157f602 | 1168 | try!(self.word_space("mut")); |
1a4d82fc | 1169 | } |
3157f602 XL |
1170 | try!(self.print_ident(item.ident)); |
1171 | try!(self.word_space(":")); | |
1172 | try!(self.print_type(&ty)); | |
1173 | try!(space(&mut self.s)); | |
1174 | try!(self.end()); // end the head-ibox | |
1a4d82fc | 1175 | |
3157f602 XL |
1176 | try!(self.word_space("=")); |
1177 | try!(self.print_expr(&expr)); | |
1178 | try!(word(&mut self.s, ";")); | |
1179 | try!(self.end()); // end the outer cbox | |
1a4d82fc | 1180 | } |
7453a54e | 1181 | ast::ItemKind::Const(ref ty, ref expr) => { |
3157f602 XL |
1182 | try!(self.head(&visibility_qualified(&item.vis, "const"))); |
1183 | try!(self.print_ident(item.ident)); | |
1184 | try!(self.word_space(":")); | |
1185 | try!(self.print_type(&ty)); | |
1186 | try!(space(&mut self.s)); | |
1187 | try!(self.end()); // end the head-ibox | |
1188 | ||
1189 | try!(self.word_space("=")); | |
1190 | try!(self.print_expr(&expr)); | |
1191 | try!(word(&mut self.s, ";")); | |
1192 | try!(self.end()); // end the outer cbox | |
1a4d82fc | 1193 | } |
7453a54e | 1194 | ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref typarams, ref body) => { |
3157f602 XL |
1195 | try!(self.head("")); |
1196 | try!(self.print_fn( | |
c34b1796 AL |
1197 | decl, |
1198 | unsafety, | |
9e0c209e | 1199 | constness.node, |
1a4d82fc | 1200 | abi, |
c34b1796 | 1201 | Some(item.ident), |
1a4d82fc | 1202 | typarams, |
54a0048b | 1203 | &item.vis |
3157f602 XL |
1204 | )); |
1205 | try!(word(&mut self.s, " ")); | |
1206 | try!(self.print_block_with_attrs(&body, &item.attrs)); | |
1a4d82fc | 1207 | } |
7453a54e | 1208 | ast::ItemKind::Mod(ref _mod) => { |
3157f602 XL |
1209 | try!(self.head(&visibility_qualified(&item.vis, "mod"))); |
1210 | try!(self.print_ident(item.ident)); | |
1211 | try!(self.nbsp()); | |
1212 | try!(self.bopen()); | |
1213 | try!(self.print_mod(_mod, &item.attrs)); | |
1214 | try!(self.bclose(item.span)); | |
1a4d82fc | 1215 | } |
7453a54e | 1216 | ast::ItemKind::ForeignMod(ref nmod) => { |
3157f602 XL |
1217 | try!(self.head("extern")); |
1218 | try!(self.word_nbsp(&nmod.abi.to_string())); | |
1219 | try!(self.bopen()); | |
1220 | try!(self.print_foreign_mod(nmod, &item.attrs)); | |
1221 | try!(self.bclose(item.span)); | |
1a4d82fc | 1222 | } |
7453a54e | 1223 | ast::ItemKind::Ty(ref ty, ref params) => { |
3157f602 XL |
1224 | try!(self.ibox(INDENT_UNIT)); |
1225 | try!(self.ibox(0)); | |
1226 | try!(self.word_nbsp(&visibility_qualified(&item.vis, "type"))); | |
1227 | try!(self.print_ident(item.ident)); | |
1228 | try!(self.print_generics(params)); | |
1229 | try!(self.end()); // end the inner ibox | |
1230 | ||
1231 | try!(self.print_where_clause(¶ms.where_clause)); | |
1232 | try!(space(&mut self.s)); | |
1233 | try!(self.word_space("=")); | |
1234 | try!(self.print_type(&ty)); | |
1235 | try!(word(&mut self.s, ";")); | |
1236 | try!(self.end()); // end the outer ibox | |
1a4d82fc | 1237 | } |
7453a54e | 1238 | ast::ItemKind::Enum(ref enum_definition, ref params) => { |
3157f602 | 1239 | try!(self.print_enum_def( |
1a4d82fc JJ |
1240 | enum_definition, |
1241 | params, | |
1242 | item.ident, | |
1243 | item.span, | |
54a0048b | 1244 | &item.vis |
3157f602 | 1245 | )); |
1a4d82fc | 1246 | } |
7453a54e | 1247 | ast::ItemKind::Struct(ref struct_def, ref generics) => { |
3157f602 XL |
1248 | try!(self.head(&visibility_qualified(&item.vis, "struct"))); |
1249 | try!(self.print_struct(&struct_def, generics, item.ident, item.span, true)); | |
1a4d82fc | 1250 | } |
9e0c209e SL |
1251 | ast::ItemKind::Union(ref struct_def, ref generics) => { |
1252 | try!(self.head(&visibility_qualified(&item.vis, "union"))); | |
1253 | try!(self.print_struct(&struct_def, generics, item.ident, item.span, true)); | |
1254 | } | |
7453a54e | 1255 | ast::ItemKind::DefaultImpl(unsafety, ref trait_ref) => { |
3157f602 XL |
1256 | try!(self.head("")); |
1257 | try!(self.print_visibility(&item.vis)); | |
1258 | try!(self.print_unsafety(unsafety)); | |
1259 | try!(self.word_nbsp("impl")); | |
1260 | try!(self.print_trait_ref(trait_ref)); | |
1261 | try!(space(&mut self.s)); | |
1262 | try!(self.word_space("for")); | |
1263 | try!(self.word_space("..")); | |
1264 | try!(self.bopen()); | |
1265 | try!(self.bclose(item.span)); | |
c34b1796 | 1266 | } |
7453a54e | 1267 | ast::ItemKind::Impl(unsafety, |
1a4d82fc JJ |
1268 | polarity, |
1269 | ref generics, | |
1270 | ref opt_trait, | |
1271 | ref ty, | |
1272 | ref impl_items) => { | |
3157f602 XL |
1273 | try!(self.head("")); |
1274 | try!(self.print_visibility(&item.vis)); | |
1275 | try!(self.print_unsafety(unsafety)); | |
1276 | try!(self.word_nbsp("impl")); | |
1a4d82fc JJ |
1277 | |
1278 | if generics.is_parameterized() { | |
3157f602 XL |
1279 | try!(self.print_generics(generics)); |
1280 | try!(space(&mut self.s)); | |
1a4d82fc JJ |
1281 | } |
1282 | ||
1283 | match polarity { | |
1284 | ast::ImplPolarity::Negative => { | |
3157f602 | 1285 | try!(word(&mut self.s, "!")); |
1a4d82fc JJ |
1286 | }, |
1287 | _ => {} | |
1288 | } | |
1289 | ||
3157f602 XL |
1290 | if let Some(ref t) = *opt_trait { |
1291 | try!(self.print_trait_ref(t)); | |
1292 | try!(space(&mut self.s)); | |
1293 | try!(self.word_space("for")); | |
1a4d82fc JJ |
1294 | } |
1295 | ||
3157f602 XL |
1296 | try!(self.print_type(&ty)); |
1297 | try!(self.print_where_clause(&generics.where_clause)); | |
1a4d82fc | 1298 | |
3157f602 XL |
1299 | try!(space(&mut self.s)); |
1300 | try!(self.bopen()); | |
1301 | try!(self.print_inner_attributes(&item.attrs)); | |
85aaf69f | 1302 | for impl_item in impl_items { |
3157f602 | 1303 | try!(self.print_impl_item(impl_item)); |
1a4d82fc | 1304 | } |
3157f602 | 1305 | try!(self.bclose(item.span)); |
1a4d82fc | 1306 | } |
7453a54e | 1307 | ast::ItemKind::Trait(unsafety, ref generics, ref bounds, ref trait_items) => { |
3157f602 XL |
1308 | try!(self.head("")); |
1309 | try!(self.print_visibility(&item.vis)); | |
1310 | try!(self.print_unsafety(unsafety)); | |
1311 | try!(self.word_nbsp("trait")); | |
1312 | try!(self.print_ident(item.ident)); | |
1313 | try!(self.print_generics(generics)); | |
1a4d82fc | 1314 | let mut real_bounds = Vec::with_capacity(bounds.len()); |
85aaf69f SL |
1315 | for b in bounds.iter() { |
1316 | if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b { | |
3157f602 XL |
1317 | try!(space(&mut self.s)); |
1318 | try!(self.word_space("for ?")); | |
1319 | try!(self.print_trait_ref(&ptr.trait_ref)); | |
1a4d82fc | 1320 | } else { |
85aaf69f | 1321 | real_bounds.push(b.clone()); |
1a4d82fc JJ |
1322 | } |
1323 | } | |
3157f602 XL |
1324 | try!(self.print_bounds(":", &real_bounds[..])); |
1325 | try!(self.print_where_clause(&generics.where_clause)); | |
1326 | try!(word(&mut self.s, " ")); | |
1327 | try!(self.bopen()); | |
c34b1796 | 1328 | for trait_item in trait_items { |
3157f602 | 1329 | try!(self.print_trait_item(trait_item)); |
1a4d82fc | 1330 | } |
3157f602 | 1331 | try!(self.bclose(item.span)); |
1a4d82fc | 1332 | } |
7453a54e | 1333 | ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => { |
3157f602 XL |
1334 | try!(self.print_visibility(&item.vis)); |
1335 | try!(self.print_path(&node.path, false, 0)); | |
1336 | try!(word(&mut self.s, "! ")); | |
1337 | try!(self.print_ident(item.ident)); | |
1338 | try!(self.cbox(INDENT_UNIT)); | |
1339 | try!(self.popen()); | |
1340 | try!(self.print_tts(&node.tts[..])); | |
1341 | try!(self.pclose()); | |
1342 | try!(word(&mut self.s, ";")); | |
1343 | try!(self.end()); | |
1a4d82fc | 1344 | } |
223e47cc | 1345 | } |
1a4d82fc | 1346 | self.ann.post(self, NodeItem(item)) |
223e47cc | 1347 | } |
223e47cc | 1348 | |
c34b1796 AL |
1349 | fn print_trait_ref(&mut self, t: &ast::TraitRef) -> io::Result<()> { |
1350 | self.print_path(&t.path, false, 0) | |
223e47cc | 1351 | } |
223e47cc | 1352 | |
c34b1796 | 1353 | fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> io::Result<()> { |
85aaf69f | 1354 | if !lifetimes.is_empty() { |
3157f602 | 1355 | try!(word(&mut self.s, "for<")); |
1a4d82fc | 1356 | let mut comma = false; |
85aaf69f | 1357 | for lifetime_def in lifetimes { |
1a4d82fc | 1358 | if comma { |
3157f602 | 1359 | try!(self.word_space(",")) |
1a4d82fc | 1360 | } |
c30ab7b3 | 1361 | try!(self.print_outer_attributes_inline(&lifetime_def.attrs)); |
3157f602 | 1362 | try!(self.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds)); |
1a4d82fc JJ |
1363 | comma = true; |
1364 | } | |
3157f602 | 1365 | try!(word(&mut self.s, ">")); |
1a4d82fc | 1366 | } |
85aaf69f SL |
1367 | Ok(()) |
1368 | } | |
1a4d82fc | 1369 | |
c34b1796 | 1370 | fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) -> io::Result<()> { |
3157f602 | 1371 | try!(self.print_formal_lifetime_list(&t.bound_lifetimes)); |
1a4d82fc JJ |
1372 | self.print_trait_ref(&t.trait_ref) |
1373 | } | |
1374 | ||
1375 | pub fn print_enum_def(&mut self, enum_definition: &ast::EnumDef, | |
1376 | generics: &ast::Generics, ident: ast::Ident, | |
3157f602 | 1377 | span: syntax_pos::Span, |
54a0048b | 1378 | visibility: &ast::Visibility) -> io::Result<()> { |
3157f602 XL |
1379 | try!(self.head(&visibility_qualified(visibility, "enum"))); |
1380 | try!(self.print_ident(ident)); | |
1381 | try!(self.print_generics(generics)); | |
1382 | try!(self.print_where_clause(&generics.where_clause)); | |
1383 | try!(space(&mut self.s)); | |
85aaf69f | 1384 | self.print_variants(&enum_definition.variants, span) |
1a4d82fc JJ |
1385 | } |
1386 | ||
1387 | pub fn print_variants(&mut self, | |
7453a54e | 1388 | variants: &[ast::Variant], |
3157f602 XL |
1389 | span: syntax_pos::Span) -> io::Result<()> { |
1390 | try!(self.bopen()); | |
85aaf69f | 1391 | for v in variants { |
3157f602 XL |
1392 | try!(self.space_if_not_bol()); |
1393 | try!(self.maybe_print_comment(v.span.lo)); | |
1394 | try!(self.print_outer_attributes(&v.node.attrs)); | |
1395 | try!(self.ibox(INDENT_UNIT)); | |
1396 | try!(self.print_variant(v)); | |
1397 | try!(word(&mut self.s, ",")); | |
1398 | try!(self.end()); | |
1399 | try!(self.maybe_print_trailing_comment(v.span, None)); | |
1a4d82fc JJ |
1400 | } |
1401 | self.bclose(span) | |
1402 | } | |
1403 | ||
54a0048b SL |
1404 | pub fn print_visibility(&mut self, vis: &ast::Visibility) -> io::Result<()> { |
1405 | match *vis { | |
7453a54e | 1406 | ast::Visibility::Public => self.word_nbsp("pub"), |
a7813a04 | 1407 | ast::Visibility::Crate(_) => self.word_nbsp("pub(crate)"), |
54a0048b SL |
1408 | ast::Visibility::Restricted { ref path, .. } => |
1409 | self.word_nbsp(&format!("pub({})", path)), | |
7453a54e | 1410 | ast::Visibility::Inherited => Ok(()) |
1a4d82fc JJ |
1411 | } |
1412 | } | |
1413 | ||
1414 | pub fn print_struct(&mut self, | |
b039eaaf | 1415 | struct_def: &ast::VariantData, |
1a4d82fc JJ |
1416 | generics: &ast::Generics, |
1417 | ident: ast::Ident, | |
3157f602 | 1418 | span: syntax_pos::Span, |
b039eaaf | 1419 | print_finalizer: bool) -> io::Result<()> { |
3157f602 XL |
1420 | try!(self.print_ident(ident)); |
1421 | try!(self.print_generics(generics)); | |
b039eaaf SL |
1422 | if !struct_def.is_struct() { |
1423 | if struct_def.is_tuple() { | |
3157f602 XL |
1424 | try!(self.popen()); |
1425 | try!(self.commasep( | |
b039eaaf | 1426 | Inconsistent, struct_def.fields(), |
1a4d82fc | 1427 | |s, field| { |
3157f602 XL |
1428 | try!(s.maybe_print_comment(field.span.lo)); |
1429 | try!(s.print_outer_attributes(&field.attrs)); | |
1430 | try!(s.print_visibility(&field.vis)); | |
54a0048b | 1431 | s.print_type(&field.ty) |
223e47cc | 1432 | } |
3157f602 XL |
1433 | )); |
1434 | try!(self.pclose()); | |
223e47cc | 1435 | } |
3157f602 | 1436 | try!(self.print_where_clause(&generics.where_clause)); |
b039eaaf | 1437 | if print_finalizer { |
3157f602 | 1438 | try!(word(&mut self.s, ";")); |
b039eaaf | 1439 | } |
3157f602 | 1440 | try!(self.end()); |
1a4d82fc | 1441 | self.end() // close the outer-box |
223e47cc | 1442 | } else { |
3157f602 XL |
1443 | try!(self.print_where_clause(&generics.where_clause)); |
1444 | try!(self.nbsp()); | |
1445 | try!(self.bopen()); | |
1446 | try!(self.hardbreak_if_not_bol()); | |
223e47cc | 1447 | |
b039eaaf | 1448 | for field in struct_def.fields() { |
3157f602 XL |
1449 | try!(self.hardbreak_if_not_bol()); |
1450 | try!(self.maybe_print_comment(field.span.lo)); | |
1451 | try!(self.print_outer_attributes(&field.attrs)); | |
1452 | try!(self.print_visibility(&field.vis)); | |
1453 | try!(self.print_ident(field.ident.unwrap())); | |
1454 | try!(self.word_nbsp(":")); | |
1455 | try!(self.print_type(&field.ty)); | |
1456 | try!(word(&mut self.s, ",")); | |
1a4d82fc | 1457 | } |
223e47cc | 1458 | |
1a4d82fc | 1459 | self.bclose(span) |
223e47cc | 1460 | } |
1a4d82fc | 1461 | } |
223e47cc | 1462 | |
1a4d82fc JJ |
1463 | /// This doesn't deserve to be called "pretty" printing, but it should be |
1464 | /// meaning-preserving. A quick hack that might help would be to look at the | |
1465 | /// spans embedded in the TTs to decide where to put spaces and newlines. | |
1466 | /// But it'd be better to parse these according to the grammar of the | |
1467 | /// appropriate macro, transcribe back into the grammar we just parsed from, | |
1468 | /// and then pretty-print the resulting AST nodes (so, e.g., we print | |
1469 | /// expression arguments as expressions). It can be done! I think. | |
3157f602 | 1470 | pub fn print_tt(&mut self, tt: &tokenstream::TokenTree) -> io::Result<()> { |
1a4d82fc | 1471 | match *tt { |
92a42be0 | 1472 | TokenTree::Token(_, ref tk) => { |
3157f602 | 1473 | try!(word(&mut self.s, &token_to_string(tk))); |
1a4d82fc JJ |
1474 | match *tk { |
1475 | parse::token::DocComment(..) => { | |
1476 | hardbreak(&mut self.s) | |
1477 | } | |
1478 | _ => Ok(()) | |
1479 | } | |
1480 | } | |
92a42be0 | 1481 | TokenTree::Delimited(_, ref delimed) => { |
3157f602 XL |
1482 | try!(word(&mut self.s, &token_to_string(&delimed.open_token()))); |
1483 | try!(space(&mut self.s)); | |
1484 | try!(self.print_tts(&delimed.tts)); | |
1485 | try!(space(&mut self.s)); | |
85aaf69f | 1486 | word(&mut self.s, &token_to_string(&delimed.close_token())) |
1a4d82fc | 1487 | }, |
92a42be0 | 1488 | TokenTree::Sequence(_, ref seq) => { |
3157f602 | 1489 | try!(word(&mut self.s, "$(")); |
85aaf69f | 1490 | for tt_elt in &seq.tts { |
3157f602 | 1491 | try!(self.print_tt(tt_elt)); |
1a4d82fc | 1492 | } |
3157f602 XL |
1493 | try!(word(&mut self.s, ")")); |
1494 | if let Some(ref tk) = seq.separator { | |
1495 | try!(word(&mut self.s, &token_to_string(tk))); | |
1a4d82fc JJ |
1496 | } |
1497 | match seq.op { | |
3157f602 XL |
1498 | tokenstream::KleeneOp::ZeroOrMore => word(&mut self.s, "*"), |
1499 | tokenstream::KleeneOp::OneOrMore => word(&mut self.s, "+"), | |
1a4d82fc | 1500 | } |
223e47cc LB |
1501 | } |
1502 | } | |
1a4d82fc | 1503 | } |
970d7e83 | 1504 | |
3157f602 XL |
1505 | pub fn print_tts(&mut self, tts: &[tokenstream::TokenTree]) -> io::Result<()> { |
1506 | try!(self.ibox(0)); | |
1a4d82fc | 1507 | for (i, tt) in tts.iter().enumerate() { |
a7813a04 | 1508 | if i != 0 { |
3157f602 | 1509 | try!(space(&mut self.s)); |
1a4d82fc | 1510 | } |
3157f602 | 1511 | try!(self.print_tt(tt)); |
1a4d82fc JJ |
1512 | } |
1513 | self.end() | |
1514 | } | |
1515 | ||
c34b1796 | 1516 | pub fn print_variant(&mut self, v: &ast::Variant) -> io::Result<()> { |
3157f602 | 1517 | try!(self.head("")); |
9cc50fc6 | 1518 | let generics = ast::Generics::default(); |
3157f602 | 1519 | try!(self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)); |
1a4d82fc JJ |
1520 | match v.node.disr_expr { |
1521 | Some(ref d) => { | |
3157f602 XL |
1522 | try!(space(&mut self.s)); |
1523 | try!(self.word_space("=")); | |
7453a54e | 1524 | self.print_expr(&d) |
1a4d82fc JJ |
1525 | } |
1526 | _ => Ok(()) | |
1527 | } | |
1528 | } | |
1529 | ||
c34b1796 AL |
1530 | pub fn print_method_sig(&mut self, |
1531 | ident: ast::Ident, | |
1532 | m: &ast::MethodSig, | |
54a0048b | 1533 | vis: &ast::Visibility) |
c34b1796 AL |
1534 | -> io::Result<()> { |
1535 | self.print_fn(&m.decl, | |
1536 | m.unsafety, | |
9e0c209e | 1537 | m.constness.node, |
c34b1796 AL |
1538 | m.abi, |
1539 | Some(ident), | |
1540 | &m.generics, | |
c34b1796 | 1541 | vis) |
1a4d82fc JJ |
1542 | } |
1543 | ||
c34b1796 AL |
1544 | pub fn print_trait_item(&mut self, ti: &ast::TraitItem) |
1545 | -> io::Result<()> { | |
3157f602 XL |
1546 | try!(self.ann.pre(self, NodeSubItem(ti.id))); |
1547 | try!(self.hardbreak_if_not_bol()); | |
1548 | try!(self.maybe_print_comment(ti.span.lo)); | |
1549 | try!(self.print_outer_attributes(&ti.attrs)); | |
c34b1796 | 1550 | match ti.node { |
7453a54e | 1551 | ast::TraitItemKind::Const(ref ty, ref default) => { |
3157f602 | 1552 | try!(self.print_associated_const(ti.ident, &ty, |
54a0048b | 1553 | default.as_ref().map(|expr| &**expr), |
3157f602 | 1554 | &ast::Visibility::Inherited)); |
d9579d0f | 1555 | } |
7453a54e | 1556 | ast::TraitItemKind::Method(ref sig, ref body) => { |
c34b1796 | 1557 | if body.is_some() { |
3157f602 | 1558 | try!(self.head("")); |
c34b1796 | 1559 | } |
3157f602 | 1560 | try!(self.print_method_sig(ti.ident, sig, &ast::Visibility::Inherited)); |
c34b1796 | 1561 | if let Some(ref body) = *body { |
3157f602 XL |
1562 | try!(self.nbsp()); |
1563 | try!(self.print_block_with_attrs(body, &ti.attrs)); | |
c34b1796 | 1564 | } else { |
3157f602 | 1565 | try!(word(&mut self.s, ";")); |
c34b1796 AL |
1566 | } |
1567 | } | |
7453a54e | 1568 | ast::TraitItemKind::Type(ref bounds, ref default) => { |
3157f602 XL |
1569 | try!(self.print_associated_type(ti.ident, Some(bounds), |
1570 | default.as_ref().map(|ty| &**ty))); | |
1571 | } | |
1572 | ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => { | |
1573 | // code copied from ItemKind::Mac: | |
1574 | self.print_path(&node.path, false, 0)?; | |
1575 | word(&mut self.s, "! ")?; | |
1576 | self.cbox(INDENT_UNIT)?; | |
1577 | self.popen()?; | |
1578 | self.print_tts(&node.tts[..])?; | |
1579 | self.pclose()?; | |
1580 | word(&mut self.s, ";")?; | |
1581 | self.end()? | |
c34b1796 | 1582 | } |
1a4d82fc | 1583 | } |
c34b1796 | 1584 | self.ann.post(self, NodeSubItem(ti.id)) |
1a4d82fc JJ |
1585 | } |
1586 | ||
c34b1796 | 1587 | pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> { |
3157f602 XL |
1588 | try!(self.ann.pre(self, NodeSubItem(ii.id))); |
1589 | try!(self.hardbreak_if_not_bol()); | |
1590 | try!(self.maybe_print_comment(ii.span.lo)); | |
1591 | try!(self.print_outer_attributes(&ii.attrs)); | |
54a0048b | 1592 | if let ast::Defaultness::Default = ii.defaultness { |
3157f602 | 1593 | try!(self.word_nbsp("default")); |
54a0048b | 1594 | } |
c34b1796 | 1595 | match ii.node { |
92a42be0 | 1596 | ast::ImplItemKind::Const(ref ty, ref expr) => { |
3157f602 | 1597 | try!(self.print_associated_const(ii.ident, &ty, Some(&expr), &ii.vis)); |
d9579d0f | 1598 | } |
92a42be0 | 1599 | ast::ImplItemKind::Method(ref sig, ref body) => { |
3157f602 XL |
1600 | try!(self.head("")); |
1601 | try!(self.print_method_sig(ii.ident, sig, &ii.vis)); | |
1602 | try!(self.nbsp()); | |
1603 | try!(self.print_block_with_attrs(body, &ii.attrs)); | |
c34b1796 | 1604 | } |
92a42be0 | 1605 | ast::ImplItemKind::Type(ref ty) => { |
3157f602 | 1606 | try!(self.print_associated_type(ii.ident, None, Some(ty))); |
c34b1796 | 1607 | } |
92a42be0 | 1608 | ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => { |
7453a54e | 1609 | // code copied from ItemKind::Mac: |
3157f602 XL |
1610 | try!(self.print_path(&node.path, false, 0)); |
1611 | try!(word(&mut self.s, "! ")); | |
1612 | try!(self.cbox(INDENT_UNIT)); | |
1613 | try!(self.popen()); | |
1614 | try!(self.print_tts(&node.tts[..])); | |
1615 | try!(self.pclose()); | |
1616 | try!(word(&mut self.s, ";")); | |
1617 | try!(self.end()) | |
1a4d82fc JJ |
1618 | } |
1619 | } | |
c34b1796 | 1620 | self.ann.post(self, NodeSubItem(ii.id)) |
223e47cc | 1621 | } |
223e47cc | 1622 | |
c34b1796 | 1623 | pub fn print_stmt(&mut self, st: &ast::Stmt) -> io::Result<()> { |
3157f602 | 1624 | try!(self.maybe_print_comment(st.span.lo)); |
1a4d82fc | 1625 | match st.node { |
3157f602 XL |
1626 | ast::StmtKind::Local(ref loc) => { |
1627 | try!(self.print_outer_attributes(&loc.attrs)); | |
1628 | try!(self.space_if_not_bol()); | |
1629 | try!(self.ibox(INDENT_UNIT)); | |
1630 | try!(self.word_nbsp("let")); | |
1631 | ||
1632 | try!(self.ibox(INDENT_UNIT)); | |
1633 | try!(self.print_local_decl(&loc)); | |
1634 | try!(self.end()); | |
1635 | if let Some(ref init) = loc.init { | |
1636 | try!(self.nbsp()); | |
1637 | try!(self.word_space("=")); | |
1638 | try!(self.print_expr(&init)); | |
1639 | } | |
1640 | try!(word(&mut self.s, ";")); | |
1641 | self.end()?; | |
1a4d82fc | 1642 | } |
3157f602 XL |
1643 | ast::StmtKind::Item(ref item) => self.print_item(&item)?, |
1644 | ast::StmtKind::Expr(ref expr) => { | |
1645 | try!(self.space_if_not_bol()); | |
1646 | try!(self.print_expr_outer_attr_style(&expr, false)); | |
1647 | if parse::classify::expr_requires_semi_to_be_stmt(expr) { | |
1648 | try!(word(&mut self.s, ";")); | |
1649 | } | |
1a4d82fc | 1650 | } |
3157f602 XL |
1651 | ast::StmtKind::Semi(ref expr) => { |
1652 | try!(self.space_if_not_bol()); | |
1653 | try!(self.print_expr_outer_attr_style(&expr, false)); | |
1654 | try!(word(&mut self.s, ";")); | |
1a4d82fc | 1655 | } |
3157f602 XL |
1656 | ast::StmtKind::Mac(ref mac) => { |
1657 | let (ref mac, style, ref attrs) = **mac; | |
1658 | try!(self.space_if_not_bol()); | |
1659 | try!(self.print_outer_attributes(&attrs)); | |
1a4d82fc | 1660 | let delim = match style { |
7453a54e | 1661 | ast::MacStmtStyle::Braces => token::Brace, |
1a4d82fc JJ |
1662 | _ => token::Paren |
1663 | }; | |
3157f602 | 1664 | try!(self.print_mac(&mac, delim)); |
5bcae85e SL |
1665 | if style == ast::MacStmtStyle::Semicolon { |
1666 | try!(word(&mut self.s, ";")); | |
223e47cc LB |
1667 | } |
1668 | } | |
223e47cc | 1669 | } |
1a4d82fc | 1670 | self.maybe_print_trailing_comment(st.span, None) |
223e47cc | 1671 | } |
223e47cc | 1672 | |
c34b1796 | 1673 | pub fn print_block(&mut self, blk: &ast::Block) -> io::Result<()> { |
1a4d82fc JJ |
1674 | self.print_block_with_attrs(blk, &[]) |
1675 | } | |
970d7e83 | 1676 | |
c34b1796 | 1677 | pub fn print_block_unclosed(&mut self, blk: &ast::Block) -> io::Result<()> { |
92a42be0 SL |
1678 | self.print_block_unclosed_indent(blk, INDENT_UNIT) |
1679 | } | |
1680 | ||
1681 | pub fn print_block_unclosed_with_attrs(&mut self, blk: &ast::Block, | |
1682 | attrs: &[ast::Attribute]) | |
1683 | -> io::Result<()> { | |
1684 | self.print_block_maybe_unclosed(blk, INDENT_UNIT, attrs, false) | |
1a4d82fc | 1685 | } |
970d7e83 | 1686 | |
1a4d82fc | 1687 | pub fn print_block_unclosed_indent(&mut self, blk: &ast::Block, |
c34b1796 | 1688 | indented: usize) -> io::Result<()> { |
1a4d82fc JJ |
1689 | self.print_block_maybe_unclosed(blk, indented, &[], false) |
1690 | } | |
223e47cc | 1691 | |
1a4d82fc JJ |
1692 | pub fn print_block_with_attrs(&mut self, |
1693 | blk: &ast::Block, | |
c34b1796 | 1694 | attrs: &[ast::Attribute]) -> io::Result<()> { |
92a42be0 | 1695 | self.print_block_maybe_unclosed(blk, INDENT_UNIT, attrs, true) |
1a4d82fc | 1696 | } |
223e47cc | 1697 | |
1a4d82fc JJ |
1698 | pub fn print_block_maybe_unclosed(&mut self, |
1699 | blk: &ast::Block, | |
85aaf69f | 1700 | indented: usize, |
1a4d82fc | 1701 | attrs: &[ast::Attribute], |
c34b1796 | 1702 | close_box: bool) -> io::Result<()> { |
1a4d82fc | 1703 | match blk.rules { |
3157f602 | 1704 | BlockCheckMode::Unsafe(..) => try!(self.word_space("unsafe")), |
7453a54e | 1705 | BlockCheckMode::Default => () |
1a4d82fc | 1706 | } |
3157f602 XL |
1707 | try!(self.maybe_print_comment(blk.span.lo)); |
1708 | try!(self.ann.pre(self, NodeBlock(blk))); | |
1709 | try!(self.bopen()); | |
223e47cc | 1710 | |
3157f602 | 1711 | try!(self.print_inner_attributes(attrs)); |
970d7e83 | 1712 | |
3157f602 XL |
1713 | for (i, st) in blk.stmts.iter().enumerate() { |
1714 | match st.node { | |
1715 | ast::StmtKind::Expr(ref expr) if i == blk.stmts.len() - 1 => { | |
c30ab7b3 | 1716 | try!(self.maybe_print_comment(st.span.lo)); |
3157f602 XL |
1717 | try!(self.space_if_not_bol()); |
1718 | try!(self.print_expr_outer_attr_style(&expr, false)); | |
1719 | try!(self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi))); | |
1720 | } | |
1721 | _ => try!(self.print_stmt(st)), | |
1a4d82fc | 1722 | } |
1a4d82fc | 1723 | } |
3157f602 XL |
1724 | |
1725 | try!(self.bclose_maybe_open(blk.span, indented, close_box)); | |
1a4d82fc JJ |
1726 | self.ann.post(self, NodeBlock(blk)) |
1727 | } | |
1728 | ||
c34b1796 | 1729 | fn print_else(&mut self, els: Option<&ast::Expr>) -> io::Result<()> { |
1a4d82fc JJ |
1730 | match els { |
1731 | Some(_else) => { | |
1732 | match _else.node { | |
1733 | // "another else-if" | |
7453a54e | 1734 | ast::ExprKind::If(ref i, ref then, ref e) => { |
3157f602 XL |
1735 | try!(self.cbox(INDENT_UNIT - 1)); |
1736 | try!(self.ibox(0)); | |
1737 | try!(word(&mut self.s, " else if ")); | |
1738 | try!(self.print_expr(&i)); | |
1739 | try!(space(&mut self.s)); | |
1740 | try!(self.print_block(&then)); | |
1a4d82fc JJ |
1741 | self.print_else(e.as_ref().map(|e| &**e)) |
1742 | } | |
1743 | // "another else-if-let" | |
7453a54e | 1744 | ast::ExprKind::IfLet(ref pat, ref expr, ref then, ref e) => { |
3157f602 XL |
1745 | try!(self.cbox(INDENT_UNIT - 1)); |
1746 | try!(self.ibox(0)); | |
1747 | try!(word(&mut self.s, " else if let ")); | |
1748 | try!(self.print_pat(&pat)); | |
1749 | try!(space(&mut self.s)); | |
1750 | try!(self.word_space("=")); | |
1751 | try!(self.print_expr(&expr)); | |
1752 | try!(space(&mut self.s)); | |
1753 | try!(self.print_block(&then)); | |
1a4d82fc JJ |
1754 | self.print_else(e.as_ref().map(|e| &**e)) |
1755 | } | |
1756 | // "final else" | |
7453a54e | 1757 | ast::ExprKind::Block(ref b) => { |
3157f602 XL |
1758 | try!(self.cbox(INDENT_UNIT - 1)); |
1759 | try!(self.ibox(0)); | |
1760 | try!(word(&mut self.s, " else ")); | |
7453a54e | 1761 | self.print_block(&b) |
1a4d82fc JJ |
1762 | } |
1763 | // BLEAH, constraints would be great here | |
1764 | _ => { | |
1765 | panic!("print_if saw if with weird alternative"); | |
1766 | } | |
1767 | } | |
1768 | } | |
1769 | _ => Ok(()) | |
1770 | } | |
1771 | } | |
1772 | ||
1773 | pub fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block, | |
c34b1796 | 1774 | elseopt: Option<&ast::Expr>) -> io::Result<()> { |
3157f602 XL |
1775 | try!(self.head("if")); |
1776 | try!(self.print_expr(test)); | |
1777 | try!(space(&mut self.s)); | |
1778 | try!(self.print_block(blk)); | |
1a4d82fc JJ |
1779 | self.print_else(elseopt) |
1780 | } | |
1781 | ||
1782 | pub fn print_if_let(&mut self, pat: &ast::Pat, expr: &ast::Expr, blk: &ast::Block, | |
c34b1796 | 1783 | elseopt: Option<&ast::Expr>) -> io::Result<()> { |
3157f602 XL |
1784 | try!(self.head("if let")); |
1785 | try!(self.print_pat(pat)); | |
1786 | try!(space(&mut self.s)); | |
1787 | try!(self.word_space("=")); | |
1788 | try!(self.print_expr(expr)); | |
1789 | try!(space(&mut self.s)); | |
1790 | try!(self.print_block(blk)); | |
1a4d82fc JJ |
1791 | self.print_else(elseopt) |
1792 | } | |
1793 | ||
1794 | pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken) | |
c34b1796 | 1795 | -> io::Result<()> { |
3157f602 XL |
1796 | try!(self.print_path(&m.node.path, false, 0)); |
1797 | try!(word(&mut self.s, "!")); | |
b039eaaf | 1798 | match delim { |
3157f602 XL |
1799 | token::Paren => try!(self.popen()), |
1800 | token::Bracket => try!(word(&mut self.s, "[")), | |
92a42be0 | 1801 | token::Brace => { |
3157f602 XL |
1802 | try!(self.head("")); |
1803 | try!(self.bopen()); | |
92a42be0 | 1804 | } |
5bcae85e | 1805 | token::NoDelim => {} |
b039eaaf | 1806 | } |
3157f602 | 1807 | try!(self.print_tts(&m.node.tts)); |
b039eaaf SL |
1808 | match delim { |
1809 | token::Paren => self.pclose(), | |
1810 | token::Bracket => word(&mut self.s, "]"), | |
1811 | token::Brace => self.bclose(m.span), | |
5bcae85e | 1812 | token::NoDelim => Ok(()), |
223e47cc LB |
1813 | } |
1814 | } | |
223e47cc | 1815 | |
223e47cc | 1816 | |
c34b1796 | 1817 | fn print_call_post(&mut self, args: &[P<ast::Expr>]) -> io::Result<()> { |
3157f602 XL |
1818 | try!(self.popen()); |
1819 | try!(self.commasep_exprs(Inconsistent, args)); | |
1a4d82fc | 1820 | self.pclose() |
223e47cc LB |
1821 | } |
1822 | ||
e9174d1e SL |
1823 | pub fn check_expr_bin_needs_paren(&mut self, sub_expr: &ast::Expr, |
1824 | binop: ast::BinOp) -> bool { | |
1825 | match sub_expr.node { | |
7453a54e | 1826 | ast::ExprKind::Binary(ref sub_op, _, _) => { |
92a42be0 SL |
1827 | if AssocOp::from_ast_binop(sub_op.node).precedence() < |
1828 | AssocOp::from_ast_binop(binop.node).precedence() { | |
e9174d1e SL |
1829 | true |
1830 | } else { | |
1831 | false | |
1832 | } | |
1833 | } | |
1834 | _ => true | |
1835 | } | |
1836 | } | |
1837 | ||
c34b1796 | 1838 | pub fn print_expr_maybe_paren(&mut self, expr: &ast::Expr) -> io::Result<()> { |
1a4d82fc JJ |
1839 | let needs_par = needs_parentheses(expr); |
1840 | if needs_par { | |
3157f602 | 1841 | try!(self.popen()); |
1a4d82fc | 1842 | } |
3157f602 | 1843 | try!(self.print_expr(expr)); |
1a4d82fc | 1844 | if needs_par { |
3157f602 | 1845 | try!(self.pclose()); |
1a4d82fc JJ |
1846 | } |
1847 | Ok(()) | |
223e47cc LB |
1848 | } |
1849 | ||
b039eaaf SL |
1850 | fn print_expr_in_place(&mut self, |
1851 | place: &ast::Expr, | |
1852 | expr: &ast::Expr) -> io::Result<()> { | |
3157f602 XL |
1853 | try!(self.print_expr_maybe_paren(place)); |
1854 | try!(space(&mut self.s)); | |
1855 | try!(self.word_space("<-")); | |
92a42be0 | 1856 | self.print_expr_maybe_paren(expr) |
85aaf69f SL |
1857 | } |
1858 | ||
92a42be0 SL |
1859 | fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>], |
1860 | attrs: &[Attribute]) -> io::Result<()> { | |
3157f602 XL |
1861 | try!(self.ibox(INDENT_UNIT)); |
1862 | try!(word(&mut self.s, "[")); | |
1863 | try!(self.print_inner_attributes_inline(attrs)); | |
1864 | try!(self.commasep_exprs(Inconsistent, &exprs[..])); | |
1865 | try!(word(&mut self.s, "]")); | |
85aaf69f SL |
1866 | self.end() |
1867 | } | |
1868 | ||
1869 | fn print_expr_repeat(&mut self, | |
1870 | element: &ast::Expr, | |
92a42be0 SL |
1871 | count: &ast::Expr, |
1872 | attrs: &[Attribute]) -> io::Result<()> { | |
3157f602 XL |
1873 | try!(self.ibox(INDENT_UNIT)); |
1874 | try!(word(&mut self.s, "[")); | |
1875 | try!(self.print_inner_attributes_inline(attrs)); | |
1876 | try!(self.print_expr(element)); | |
1877 | try!(self.word_space(";")); | |
1878 | try!(self.print_expr(count)); | |
1879 | try!(word(&mut self.s, "]")); | |
85aaf69f SL |
1880 | self.end() |
1881 | } | |
1882 | ||
1883 | fn print_expr_struct(&mut self, | |
1884 | path: &ast::Path, | |
1885 | fields: &[ast::Field], | |
92a42be0 SL |
1886 | wth: &Option<P<ast::Expr>>, |
1887 | attrs: &[Attribute]) -> io::Result<()> { | |
3157f602 XL |
1888 | try!(self.print_path(path, true, 0)); |
1889 | try!(word(&mut self.s, "{")); | |
1890 | try!(self.print_inner_attributes_inline(attrs)); | |
1891 | try!(self.commasep_cmnt( | |
b039eaaf SL |
1892 | Consistent, |
1893 | &fields[..], | |
1894 | |s, field| { | |
3157f602 | 1895 | try!(s.ibox(INDENT_UNIT)); |
c30ab7b3 SL |
1896 | if !field.is_shorthand { |
1897 | try!(s.print_ident(field.ident.node)); | |
1898 | try!(s.word_space(":")); | |
1899 | } | |
3157f602 | 1900 | try!(s.print_expr(&field.expr)); |
b039eaaf SL |
1901 | s.end() |
1902 | }, | |
3157f602 | 1903 | |f| f.span)); |
b039eaaf SL |
1904 | match *wth { |
1905 | Some(ref expr) => { | |
3157f602 | 1906 | try!(self.ibox(INDENT_UNIT)); |
b039eaaf | 1907 | if !fields.is_empty() { |
3157f602 XL |
1908 | try!(word(&mut self.s, ",")); |
1909 | try!(space(&mut self.s)); | |
85aaf69f | 1910 | } |
3157f602 XL |
1911 | try!(word(&mut self.s, "..")); |
1912 | try!(self.print_expr(&expr)); | |
1913 | try!(self.end()); | |
b039eaaf SL |
1914 | } |
1915 | _ => if !fields.is_empty() { | |
3157f602 | 1916 | try!(word(&mut self.s, ",")) |
85aaf69f | 1917 | } |
85aaf69f | 1918 | } |
3157f602 | 1919 | try!(word(&mut self.s, "}")); |
85aaf69f SL |
1920 | Ok(()) |
1921 | } | |
1922 | ||
92a42be0 SL |
1923 | fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>], |
1924 | attrs: &[Attribute]) -> io::Result<()> { | |
3157f602 XL |
1925 | try!(self.popen()); |
1926 | try!(self.print_inner_attributes_inline(attrs)); | |
1927 | try!(self.commasep_exprs(Inconsistent, &exprs[..])); | |
85aaf69f | 1928 | if exprs.len() == 1 { |
3157f602 | 1929 | try!(word(&mut self.s, ",")); |
85aaf69f SL |
1930 | } |
1931 | self.pclose() | |
1932 | } | |
1933 | ||
1934 | fn print_expr_call(&mut self, | |
1935 | func: &ast::Expr, | |
c34b1796 | 1936 | args: &[P<ast::Expr>]) -> io::Result<()> { |
3157f602 | 1937 | try!(self.print_expr_maybe_paren(func)); |
85aaf69f SL |
1938 | self.print_call_post(args) |
1939 | } | |
1940 | ||
1941 | fn print_expr_method_call(&mut self, | |
1942 | ident: ast::SpannedIdent, | |
1943 | tys: &[P<ast::Ty>], | |
c34b1796 | 1944 | args: &[P<ast::Expr>]) -> io::Result<()> { |
85aaf69f | 1945 | let base_args = &args[1..]; |
3157f602 XL |
1946 | try!(self.print_expr(&args[0])); |
1947 | try!(word(&mut self.s, ".")); | |
1948 | try!(self.print_ident(ident.node)); | |
9346a6ac | 1949 | if !tys.is_empty() { |
3157f602 XL |
1950 | try!(word(&mut self.s, "::<")); |
1951 | try!(self.commasep(Inconsistent, tys, | |
1952 | |s, ty| s.print_type(&ty))); | |
1953 | try!(word(&mut self.s, ">")); | |
85aaf69f SL |
1954 | } |
1955 | self.print_call_post(base_args) | |
1956 | } | |
1957 | ||
1958 | fn print_expr_binary(&mut self, | |
1959 | op: ast::BinOp, | |
1960 | lhs: &ast::Expr, | |
c34b1796 | 1961 | rhs: &ast::Expr) -> io::Result<()> { |
e9174d1e | 1962 | if self.check_expr_bin_needs_paren(lhs, op) { |
3157f602 | 1963 | try!(self.print_expr_maybe_paren(lhs)); |
e9174d1e | 1964 | } else { |
3157f602 | 1965 | try!(self.print_expr(lhs)); |
e9174d1e | 1966 | } |
3157f602 XL |
1967 | try!(space(&mut self.s)); |
1968 | try!(self.word_space(op.node.to_string())); | |
e9174d1e SL |
1969 | if self.check_expr_bin_needs_paren(rhs, op) { |
1970 | self.print_expr_maybe_paren(rhs) | |
1971 | } else { | |
1972 | self.print_expr(rhs) | |
1973 | } | |
85aaf69f SL |
1974 | } |
1975 | ||
1976 | fn print_expr_unary(&mut self, | |
1977 | op: ast::UnOp, | |
c34b1796 | 1978 | expr: &ast::Expr) -> io::Result<()> { |
3157f602 | 1979 | try!(word(&mut self.s, ast::UnOp::to_string(op))); |
85aaf69f SL |
1980 | self.print_expr_maybe_paren(expr) |
1981 | } | |
1982 | ||
1983 | fn print_expr_addr_of(&mut self, | |
1984 | mutability: ast::Mutability, | |
c34b1796 | 1985 | expr: &ast::Expr) -> io::Result<()> { |
3157f602 XL |
1986 | try!(word(&mut self.s, "&")); |
1987 | try!(self.print_mutability(mutability)); | |
85aaf69f SL |
1988 | self.print_expr_maybe_paren(expr) |
1989 | } | |
1990 | ||
c34b1796 | 1991 | pub fn print_expr(&mut self, expr: &ast::Expr) -> io::Result<()> { |
92a42be0 SL |
1992 | self.print_expr_outer_attr_style(expr, true) |
1993 | } | |
1994 | ||
1995 | fn print_expr_outer_attr_style(&mut self, | |
1996 | expr: &ast::Expr, | |
1997 | is_inline: bool) -> io::Result<()> { | |
3157f602 | 1998 | try!(self.maybe_print_comment(expr.span.lo)); |
92a42be0 | 1999 | |
3157f602 | 2000 | let attrs = &expr.attrs; |
92a42be0 | 2001 | if is_inline { |
3157f602 | 2002 | try!(self.print_outer_attributes_inline(attrs)); |
92a42be0 | 2003 | } else { |
3157f602 | 2004 | try!(self.print_outer_attributes(attrs)); |
92a42be0 SL |
2005 | } |
2006 | ||
3157f602 XL |
2007 | try!(self.ibox(INDENT_UNIT)); |
2008 | try!(self.ann.pre(self, NodeExpr(expr))); | |
1a4d82fc | 2009 | match expr.node { |
7453a54e | 2010 | ast::ExprKind::Box(ref expr) => { |
3157f602 XL |
2011 | try!(self.word_space("box")); |
2012 | try!(self.print_expr(expr)); | |
b039eaaf | 2013 | } |
7453a54e | 2014 | ast::ExprKind::InPlace(ref place, ref expr) => { |
3157f602 | 2015 | try!(self.print_expr_in_place(place, expr)); |
1a4d82fc | 2016 | } |
7453a54e | 2017 | ast::ExprKind::Vec(ref exprs) => { |
3157f602 | 2018 | try!(self.print_expr_vec(&exprs[..], attrs)); |
1a4d82fc | 2019 | } |
7453a54e | 2020 | ast::ExprKind::Repeat(ref element, ref count) => { |
3157f602 | 2021 | try!(self.print_expr_repeat(&element, &count, attrs)); |
1a4d82fc | 2022 | } |
7453a54e | 2023 | ast::ExprKind::Struct(ref path, ref fields, ref wth) => { |
3157f602 | 2024 | try!(self.print_expr_struct(path, &fields[..], wth, attrs)); |
1a4d82fc | 2025 | } |
7453a54e | 2026 | ast::ExprKind::Tup(ref exprs) => { |
3157f602 | 2027 | try!(self.print_expr_tup(&exprs[..], attrs)); |
1a4d82fc | 2028 | } |
7453a54e | 2029 | ast::ExprKind::Call(ref func, ref args) => { |
3157f602 | 2030 | try!(self.print_expr_call(&func, &args[..])); |
1a4d82fc | 2031 | } |
7453a54e | 2032 | ast::ExprKind::MethodCall(ident, ref tys, ref args) => { |
3157f602 | 2033 | try!(self.print_expr_method_call(ident, &tys[..], &args[..])); |
1a4d82fc | 2034 | } |
7453a54e | 2035 | ast::ExprKind::Binary(op, ref lhs, ref rhs) => { |
3157f602 | 2036 | try!(self.print_expr_binary(op, &lhs, &rhs)); |
1a4d82fc | 2037 | } |
7453a54e | 2038 | ast::ExprKind::Unary(op, ref expr) => { |
3157f602 | 2039 | try!(self.print_expr_unary(op, &expr)); |
1a4d82fc | 2040 | } |
7453a54e | 2041 | ast::ExprKind::AddrOf(m, ref expr) => { |
3157f602 | 2042 | try!(self.print_expr_addr_of(m, &expr)); |
85aaf69f | 2043 | } |
7453a54e | 2044 | ast::ExprKind::Lit(ref lit) => { |
3157f602 | 2045 | try!(self.print_literal(&lit)); |
1a4d82fc | 2046 | } |
7453a54e SL |
2047 | ast::ExprKind::Cast(ref expr, ref ty) => { |
2048 | if let ast::ExprKind::Cast(..) = expr.node { | |
3157f602 | 2049 | try!(self.print_expr(&expr)); |
e9174d1e | 2050 | } else { |
3157f602 | 2051 | try!(self.print_expr_maybe_paren(&expr)); |
e9174d1e | 2052 | } |
3157f602 XL |
2053 | try!(space(&mut self.s)); |
2054 | try!(self.word_space("as")); | |
2055 | try!(self.print_type(&ty)); | |
1a4d82fc | 2056 | } |
7453a54e | 2057 | ast::ExprKind::Type(ref expr, ref ty) => { |
3157f602 XL |
2058 | try!(self.print_expr(&expr)); |
2059 | try!(self.word_space(":")); | |
2060 | try!(self.print_type(&ty)); | |
9cc50fc6 | 2061 | } |
7453a54e | 2062 | ast::ExprKind::If(ref test, ref blk, ref elseopt) => { |
3157f602 | 2063 | try!(self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))); |
1a4d82fc | 2064 | } |
7453a54e | 2065 | ast::ExprKind::IfLet(ref pat, ref expr, ref blk, ref elseopt) => { |
3157f602 | 2066 | try!(self.print_if_let(&pat, &expr, &blk, elseopt.as_ref().map(|e| &**e))); |
1a4d82fc | 2067 | } |
7453a54e | 2068 | ast::ExprKind::While(ref test, ref blk, opt_ident) => { |
85aaf69f | 2069 | if let Some(ident) = opt_ident { |
3157f602 XL |
2070 | try!(self.print_ident(ident.node)); |
2071 | try!(self.word_space(":")); | |
1a4d82fc | 2072 | } |
3157f602 XL |
2073 | try!(self.head("while")); |
2074 | try!(self.print_expr(&test)); | |
2075 | try!(space(&mut self.s)); | |
2076 | try!(self.print_block_with_attrs(&blk, attrs)); | |
1a4d82fc | 2077 | } |
7453a54e | 2078 | ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_ident) => { |
85aaf69f | 2079 | if let Some(ident) = opt_ident { |
3157f602 XL |
2080 | try!(self.print_ident(ident.node)); |
2081 | try!(self.word_space(":")); | |
1a4d82fc | 2082 | } |
3157f602 XL |
2083 | try!(self.head("while let")); |
2084 | try!(self.print_pat(&pat)); | |
2085 | try!(space(&mut self.s)); | |
2086 | try!(self.word_space("=")); | |
2087 | try!(self.print_expr(&expr)); | |
2088 | try!(space(&mut self.s)); | |
2089 | try!(self.print_block_with_attrs(&blk, attrs)); | |
1a4d82fc | 2090 | } |
7453a54e | 2091 | ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_ident) => { |
85aaf69f | 2092 | if let Some(ident) = opt_ident { |
3157f602 XL |
2093 | try!(self.print_ident(ident.node)); |
2094 | try!(self.word_space(":")); | |
1a4d82fc | 2095 | } |
3157f602 XL |
2096 | try!(self.head("for")); |
2097 | try!(self.print_pat(&pat)); | |
2098 | try!(space(&mut self.s)); | |
2099 | try!(self.word_space("in")); | |
2100 | try!(self.print_expr(&iter)); | |
2101 | try!(space(&mut self.s)); | |
2102 | try!(self.print_block_with_attrs(&blk, attrs)); | |
1a4d82fc | 2103 | } |
7453a54e | 2104 | ast::ExprKind::Loop(ref blk, opt_ident) => { |
85aaf69f | 2105 | if let Some(ident) = opt_ident { |
3157f602 XL |
2106 | try!(self.print_ident(ident.node)); |
2107 | try!(self.word_space(":")); | |
1a4d82fc | 2108 | } |
3157f602 XL |
2109 | try!(self.head("loop")); |
2110 | try!(space(&mut self.s)); | |
2111 | try!(self.print_block_with_attrs(&blk, attrs)); | |
1a4d82fc | 2112 | } |
7453a54e | 2113 | ast::ExprKind::Match(ref expr, ref arms) => { |
3157f602 XL |
2114 | try!(self.cbox(INDENT_UNIT)); |
2115 | try!(self.ibox(4)); | |
2116 | try!(self.word_nbsp("match")); | |
2117 | try!(self.print_expr(&expr)); | |
2118 | try!(space(&mut self.s)); | |
2119 | try!(self.bopen()); | |
2120 | try!(self.print_inner_attributes_no_trailing_hardbreak(attrs)); | |
85aaf69f | 2121 | for arm in arms { |
3157f602 | 2122 | try!(self.print_arm(arm)); |
1a4d82fc | 2123 | } |
3157f602 | 2124 | try!(self.bclose_(expr.span, INDENT_UNIT)); |
1a4d82fc | 2125 | } |
a7813a04 | 2126 | ast::ExprKind::Closure(capture_clause, ref decl, ref body, _) => { |
3157f602 | 2127 | try!(self.print_capture_clause(capture_clause)); |
1a4d82fc | 2128 | |
3157f602 XL |
2129 | try!(self.print_fn_block_args(&decl)); |
2130 | try!(space(&mut self.s)); | |
1a4d82fc | 2131 | |
c34b1796 | 2132 | let default_return = match decl.output { |
7453a54e | 2133 | ast::FunctionRetTy::Default(..) => true, |
c34b1796 AL |
2134 | _ => false |
2135 | }; | |
2136 | ||
3157f602 XL |
2137 | match body.stmts.last().map(|stmt| &stmt.node) { |
2138 | Some(&ast::StmtKind::Expr(ref i_expr)) if default_return && | |
2139 | body.stmts.len() == 1 => { | |
2140 | // we extract the block, so as not to create another set of boxes | |
2141 | if let ast::ExprKind::Block(ref blk) = i_expr.node { | |
2142 | try!(self.print_block_unclosed_with_attrs(&blk, &i_expr.attrs)); | |
2143 | } else { | |
1a4d82fc | 2144 | // this is a bare expression |
3157f602 XL |
2145 | try!(self.print_expr(&i_expr)); |
2146 | try!(self.end()); // need to close a box | |
1a4d82fc JJ |
2147 | } |
2148 | } | |
3157f602 | 2149 | _ => try!(self.print_block_unclosed(&body)), |
1a4d82fc | 2150 | } |
3157f602 | 2151 | |
1a4d82fc JJ |
2152 | // a box will be closed by print_expr, but we didn't want an overall |
2153 | // wrapper so we closed the corresponding opening. so create an | |
2154 | // empty box to satisfy the close. | |
3157f602 | 2155 | try!(self.ibox(0)); |
1a4d82fc | 2156 | } |
7453a54e | 2157 | ast::ExprKind::Block(ref blk) => { |
1a4d82fc | 2158 | // containing cbox, will be closed by print-block at } |
3157f602 | 2159 | try!(self.cbox(INDENT_UNIT)); |
1a4d82fc | 2160 | // head-box, will be closed by print-block after { |
3157f602 XL |
2161 | try!(self.ibox(0)); |
2162 | try!(self.print_block_with_attrs(&blk, attrs)); | |
1a4d82fc | 2163 | } |
7453a54e | 2164 | ast::ExprKind::Assign(ref lhs, ref rhs) => { |
3157f602 XL |
2165 | try!(self.print_expr(&lhs)); |
2166 | try!(space(&mut self.s)); | |
2167 | try!(self.word_space("=")); | |
2168 | try!(self.print_expr(&rhs)); | |
1a4d82fc | 2169 | } |
7453a54e | 2170 | ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => { |
3157f602 XL |
2171 | try!(self.print_expr(&lhs)); |
2172 | try!(space(&mut self.s)); | |
2173 | try!(word(&mut self.s, op.node.to_string())); | |
2174 | try!(self.word_space("=")); | |
2175 | try!(self.print_expr(&rhs)); | |
1a4d82fc | 2176 | } |
7453a54e | 2177 | ast::ExprKind::Field(ref expr, id) => { |
3157f602 XL |
2178 | try!(self.print_expr(&expr)); |
2179 | try!(word(&mut self.s, ".")); | |
2180 | try!(self.print_ident(id.node)); | |
1a4d82fc | 2181 | } |
7453a54e | 2182 | ast::ExprKind::TupField(ref expr, id) => { |
3157f602 XL |
2183 | try!(self.print_expr(&expr)); |
2184 | try!(word(&mut self.s, ".")); | |
2185 | try!(self.print_usize(id.node)); | |
1a4d82fc | 2186 | } |
7453a54e | 2187 | ast::ExprKind::Index(ref expr, ref index) => { |
3157f602 XL |
2188 | try!(self.print_expr(&expr)); |
2189 | try!(word(&mut self.s, "[")); | |
2190 | try!(self.print_expr(&index)); | |
2191 | try!(word(&mut self.s, "]")); | |
1a4d82fc | 2192 | } |
54a0048b | 2193 | ast::ExprKind::Range(ref start, ref end, limits) => { |
1a4d82fc | 2194 | if let &Some(ref e) = start { |
3157f602 | 2195 | try!(self.print_expr(&e)); |
54a0048b SL |
2196 | } |
2197 | if limits == ast::RangeLimits::HalfOpen { | |
3157f602 | 2198 | try!(word(&mut self.s, "..")); |
54a0048b | 2199 | } else { |
3157f602 | 2200 | try!(word(&mut self.s, "...")); |
1a4d82fc | 2201 | } |
1a4d82fc | 2202 | if let &Some(ref e) = end { |
3157f602 | 2203 | try!(self.print_expr(&e)); |
1a4d82fc JJ |
2204 | } |
2205 | } | |
7453a54e | 2206 | ast::ExprKind::Path(None, ref path) => { |
3157f602 | 2207 | try!(self.print_path(path, true, 0)) |
c34b1796 | 2208 | } |
7453a54e | 2209 | ast::ExprKind::Path(Some(ref qself), ref path) => { |
3157f602 | 2210 | try!(self.print_qpath(path, qself, true)) |
c34b1796 | 2211 | } |
7453a54e | 2212 | ast::ExprKind::Break(opt_ident) => { |
3157f602 XL |
2213 | try!(word(&mut self.s, "break")); |
2214 | try!(space(&mut self.s)); | |
85aaf69f | 2215 | if let Some(ident) = opt_ident { |
3157f602 XL |
2216 | try!(self.print_ident(ident.node)); |
2217 | try!(space(&mut self.s)); | |
1a4d82fc JJ |
2218 | } |
2219 | } | |
3157f602 XL |
2220 | ast::ExprKind::Continue(opt_ident) => { |
2221 | try!(word(&mut self.s, "continue")); | |
2222 | try!(space(&mut self.s)); | |
85aaf69f | 2223 | if let Some(ident) = opt_ident { |
3157f602 XL |
2224 | try!(self.print_ident(ident.node)); |
2225 | try!(space(&mut self.s)) | |
1a4d82fc JJ |
2226 | } |
2227 | } | |
7453a54e | 2228 | ast::ExprKind::Ret(ref result) => { |
3157f602 | 2229 | try!(word(&mut self.s, "return")); |
1a4d82fc JJ |
2230 | match *result { |
2231 | Some(ref expr) => { | |
3157f602 XL |
2232 | try!(word(&mut self.s, " ")); |
2233 | try!(self.print_expr(&expr)); | |
1a4d82fc JJ |
2234 | } |
2235 | _ => () | |
2236 | } | |
2237 | } | |
7453a54e | 2238 | ast::ExprKind::InlineAsm(ref a) => { |
3157f602 XL |
2239 | try!(word(&mut self.s, "asm!")); |
2240 | try!(self.popen()); | |
2241 | try!(self.print_string(&a.asm, a.asm_str_style)); | |
2242 | try!(self.word_space(":")); | |
1a4d82fc | 2243 | |
3157f602 | 2244 | try!(self.commasep(Inconsistent, &a.outputs, |
9cc50fc6 | 2245 | |s, out| { |
54a0048b SL |
2246 | let mut ch = out.constraint.chars(); |
2247 | match ch.next() { | |
2248 | Some('=') if out.is_rw => { | |
3157f602 XL |
2249 | try!(s.print_string(&format!("+{}", ch.as_str()), |
2250 | ast::StrStyle::Cooked)) | |
1a4d82fc | 2251 | } |
3157f602 XL |
2252 | _ => try!(s.print_string(&out.constraint, |
2253 | ast::StrStyle::Cooked)) | |
1a4d82fc | 2254 | } |
3157f602 XL |
2255 | try!(s.popen()); |
2256 | try!(s.print_expr(&out.expr)); | |
2257 | try!(s.pclose()); | |
1a4d82fc | 2258 | Ok(()) |
3157f602 XL |
2259 | })); |
2260 | try!(space(&mut self.s)); | |
2261 | try!(self.word_space(":")); | |
1a4d82fc | 2262 | |
3157f602 | 2263 | try!(self.commasep(Inconsistent, &a.inputs, |
1a4d82fc | 2264 | |s, &(ref co, ref o)| { |
3157f602 XL |
2265 | try!(s.print_string(&co, ast::StrStyle::Cooked)); |
2266 | try!(s.popen()); | |
2267 | try!(s.print_expr(&o)); | |
2268 | try!(s.pclose()); | |
1a4d82fc | 2269 | Ok(()) |
3157f602 XL |
2270 | })); |
2271 | try!(space(&mut self.s)); | |
2272 | try!(self.word_space(":")); | |
1a4d82fc | 2273 | |
3157f602 | 2274 | try!(self.commasep(Inconsistent, &a.clobbers, |
1a4d82fc | 2275 | |s, co| { |
3157f602 | 2276 | try!(s.print_string(&co, ast::StrStyle::Cooked)); |
1a4d82fc | 2277 | Ok(()) |
3157f602 | 2278 | })); |
1a4d82fc | 2279 | |
c30ab7b3 | 2280 | let mut options = vec![]; |
1a4d82fc JJ |
2281 | if a.volatile { |
2282 | options.push("volatile"); | |
2283 | } | |
2284 | if a.alignstack { | |
2285 | options.push("alignstack"); | |
2286 | } | |
b039eaaf | 2287 | if a.dialect == ast::AsmDialect::Intel { |
1a4d82fc JJ |
2288 | options.push("intel"); |
2289 | } | |
223e47cc | 2290 | |
9346a6ac | 2291 | if !options.is_empty() { |
3157f602 XL |
2292 | try!(space(&mut self.s)); |
2293 | try!(self.word_space(":")); | |
2294 | try!(self.commasep(Inconsistent, &options, | |
54a0048b | 2295 | |s, &co| { |
3157f602 | 2296 | try!(s.print_string(co, ast::StrStyle::Cooked)); |
54a0048b | 2297 | Ok(()) |
3157f602 | 2298 | })); |
1a4d82fc | 2299 | } |
223e47cc | 2300 | |
3157f602 | 2301 | try!(self.pclose()); |
1a4d82fc | 2302 | } |
3157f602 | 2303 | ast::ExprKind::Mac(ref m) => try!(self.print_mac(m, token::Paren)), |
7453a54e | 2304 | ast::ExprKind::Paren(ref e) => { |
3157f602 XL |
2305 | try!(self.popen()); |
2306 | try!(self.print_inner_attributes_inline(attrs)); | |
2307 | try!(self.print_expr(&e)); | |
2308 | try!(self.pclose()); | |
54a0048b SL |
2309 | }, |
2310 | ast::ExprKind::Try(ref e) => { | |
3157f602 XL |
2311 | try!(self.print_expr(e)); |
2312 | try!(word(&mut self.s, "?")) | |
1a4d82fc | 2313 | } |
223e47cc | 2314 | } |
3157f602 | 2315 | try!(self.ann.post(self, NodeExpr(expr))); |
1a4d82fc JJ |
2316 | self.end() |
2317 | } | |
2318 | ||
c34b1796 | 2319 | pub fn print_local_decl(&mut self, loc: &ast::Local) -> io::Result<()> { |
3157f602 | 2320 | try!(self.print_pat(&loc.pat)); |
1a4d82fc | 2321 | if let Some(ref ty) = loc.ty { |
3157f602 XL |
2322 | try!(self.word_space(":")); |
2323 | try!(self.print_type(&ty)); | |
1a4d82fc JJ |
2324 | } |
2325 | Ok(()) | |
223e47cc | 2326 | } |
223e47cc | 2327 | |
c34b1796 | 2328 | pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> { |
3157f602 | 2329 | try!(word(&mut self.s, &ident.name.as_str())); |
1a4d82fc JJ |
2330 | self.ann.post(self, NodeIdent(&ident)) |
2331 | } | |
2332 | ||
c34b1796 | 2333 | pub fn print_usize(&mut self, i: usize) -> io::Result<()> { |
85aaf69f | 2334 | word(&mut self.s, &i.to_string()) |
1a4d82fc JJ |
2335 | } |
2336 | ||
c34b1796 | 2337 | pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { |
3157f602 | 2338 | try!(word(&mut self.s, &name.as_str())); |
1a4d82fc JJ |
2339 | self.ann.post(self, NodeName(&name)) |
2340 | } | |
2341 | ||
2342 | pub fn print_for_decl(&mut self, loc: &ast::Local, | |
c34b1796 | 2343 | coll: &ast::Expr) -> io::Result<()> { |
3157f602 XL |
2344 | try!(self.print_local_decl(loc)); |
2345 | try!(space(&mut self.s)); | |
2346 | try!(self.word_space("in")); | |
1a4d82fc JJ |
2347 | self.print_expr(coll) |
2348 | } | |
2349 | ||
2350 | fn print_path(&mut self, | |
2351 | path: &ast::Path, | |
c34b1796 AL |
2352 | colons_before_params: bool, |
2353 | depth: usize) | |
2354 | -> io::Result<()> | |
1a4d82fc | 2355 | { |
3157f602 | 2356 | try!(self.maybe_print_comment(path.span.lo)); |
223e47cc | 2357 | |
c34b1796 AL |
2358 | let mut first = !path.global; |
2359 | for segment in &path.segments[..path.segments.len()-depth] { | |
223e47cc | 2360 | if first { |
1a4d82fc | 2361 | first = false |
223e47cc | 2362 | } else { |
3157f602 | 2363 | try!(word(&mut self.s, "::")) |
1a4d82fc JJ |
2364 | } |
2365 | ||
3157f602 | 2366 | try!(self.print_ident(segment.identifier)); |
1a4d82fc | 2367 | |
3157f602 | 2368 | try!(self.print_path_parameters(&segment.parameters, colons_before_params)); |
1a4d82fc JJ |
2369 | } |
2370 | ||
2371 | Ok(()) | |
2372 | } | |
2373 | ||
85aaf69f | 2374 | fn print_qpath(&mut self, |
c34b1796 AL |
2375 | path: &ast::Path, |
2376 | qself: &ast::QSelf, | |
85aaf69f | 2377 | colons_before_params: bool) |
c34b1796 | 2378 | -> io::Result<()> |
85aaf69f | 2379 | { |
3157f602 XL |
2380 | try!(word(&mut self.s, "<")); |
2381 | try!(self.print_type(&qself.ty)); | |
c34b1796 | 2382 | if qself.position > 0 { |
3157f602 XL |
2383 | try!(space(&mut self.s)); |
2384 | try!(self.word_space("as")); | |
c34b1796 | 2385 | let depth = path.segments.len() - qself.position; |
3157f602 | 2386 | try!(self.print_path(&path, false, depth)); |
c34b1796 | 2387 | } |
3157f602 XL |
2388 | try!(word(&mut self.s, ">")); |
2389 | try!(word(&mut self.s, "::")); | |
c34b1796 | 2390 | let item_segment = path.segments.last().unwrap(); |
3157f602 | 2391 | try!(self.print_ident(item_segment.identifier)); |
c34b1796 | 2392 | self.print_path_parameters(&item_segment.parameters, colons_before_params) |
85aaf69f SL |
2393 | } |
2394 | ||
1a4d82fc JJ |
2395 | fn print_path_parameters(&mut self, |
2396 | parameters: &ast::PathParameters, | |
2397 | colons_before_params: bool) | |
c34b1796 | 2398 | -> io::Result<()> |
1a4d82fc JJ |
2399 | { |
2400 | if parameters.is_empty() { | |
2401 | return Ok(()); | |
2402 | } | |
2403 | ||
2404 | if colons_before_params { | |
3157f602 | 2405 | try!(word(&mut self.s, "::")) |
1a4d82fc JJ |
2406 | } |
2407 | ||
2408 | match *parameters { | |
9cc50fc6 | 2409 | ast::PathParameters::AngleBracketed(ref data) => { |
3157f602 | 2410 | try!(word(&mut self.s, "<")); |
1a4d82fc JJ |
2411 | |
2412 | let mut comma = false; | |
85aaf69f | 2413 | for lifetime in &data.lifetimes { |
1a4d82fc | 2414 | if comma { |
3157f602 | 2415 | try!(self.word_space(",")) |
1a4d82fc | 2416 | } |
3157f602 | 2417 | try!(self.print_lifetime(lifetime)); |
1a4d82fc JJ |
2418 | comma = true; |
2419 | } | |
2420 | ||
2421 | if !data.types.is_empty() { | |
2422 | if comma { | |
3157f602 | 2423 | try!(self.word_space(",")) |
1a4d82fc | 2424 | } |
3157f602 | 2425 | try!(self.commasep( |
1a4d82fc | 2426 | Inconsistent, |
85aaf69f | 2427 | &data.types, |
3157f602 | 2428 | |s, ty| s.print_type(&ty))); |
1a4d82fc JJ |
2429 | comma = true; |
2430 | } | |
2431 | ||
62682a34 | 2432 | for binding in data.bindings.iter() { |
1a4d82fc | 2433 | if comma { |
3157f602 | 2434 | try!(self.word_space(",")) |
1a4d82fc | 2435 | } |
3157f602 XL |
2436 | try!(self.print_ident(binding.ident)); |
2437 | try!(space(&mut self.s)); | |
2438 | try!(self.word_space("=")); | |
2439 | try!(self.print_type(&binding.ty)); | |
1a4d82fc JJ |
2440 | comma = true; |
2441 | } | |
2442 | ||
3157f602 | 2443 | try!(word(&mut self.s, ">")) |
223e47cc LB |
2444 | } |
2445 | ||
9cc50fc6 | 2446 | ast::PathParameters::Parenthesized(ref data) => { |
3157f602 XL |
2447 | try!(word(&mut self.s, "(")); |
2448 | try!(self.commasep( | |
1a4d82fc | 2449 | Inconsistent, |
85aaf69f | 2450 | &data.inputs, |
3157f602 XL |
2451 | |s, ty| s.print_type(&ty))); |
2452 | try!(word(&mut self.s, ")")); | |
1a4d82fc | 2453 | |
c30ab7b3 SL |
2454 | if let Some(ref ty) = data.output { |
2455 | try!(self.space_if_not_bol()); | |
2456 | try!(self.word_space("->")); | |
2457 | try!(self.print_type(&ty)); | |
1a4d82fc | 2458 | } |
223e47cc LB |
2459 | } |
2460 | } | |
1a4d82fc JJ |
2461 | |
2462 | Ok(()) | |
223e47cc | 2463 | } |
223e47cc | 2464 | |
c34b1796 | 2465 | pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> { |
3157f602 XL |
2466 | try!(self.maybe_print_comment(pat.span.lo)); |
2467 | try!(self.ann.pre(self, NodePat(pat))); | |
1a4d82fc JJ |
2468 | /* Pat isn't normalized, but the beauty of it |
2469 | is that it doesn't matter */ | |
2470 | match pat.node { | |
3157f602 | 2471 | PatKind::Wild => try!(word(&mut self.s, "_")), |
7453a54e | 2472 | PatKind::Ident(binding_mode, ref path1, ref sub) => { |
1a4d82fc | 2473 | match binding_mode { |
9cc50fc6 | 2474 | ast::BindingMode::ByRef(mutbl) => { |
3157f602 XL |
2475 | try!(self.word_nbsp("ref")); |
2476 | try!(self.print_mutability(mutbl)); | |
1a4d82fc | 2477 | } |
7453a54e SL |
2478 | ast::BindingMode::ByValue(ast::Mutability::Immutable) => {} |
2479 | ast::BindingMode::ByValue(ast::Mutability::Mutable) => { | |
3157f602 | 2480 | try!(self.word_nbsp("mut")); |
1a4d82fc JJ |
2481 | } |
2482 | } | |
3157f602 XL |
2483 | try!(self.print_ident(path1.node)); |
2484 | if let Some(ref p) = *sub { | |
2485 | try!(word(&mut self.s, "@")); | |
2486 | try!(self.print_pat(&p)); | |
2487 | } | |
2488 | } | |
2489 | PatKind::TupleStruct(ref path, ref elts, ddpos) => { | |
2490 | try!(self.print_path(path, true, 0)); | |
2491 | try!(self.popen()); | |
2492 | if let Some(ddpos) = ddpos { | |
2493 | try!(self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))); | |
2494 | if ddpos != 0 { | |
2495 | try!(self.word_space(",")); | |
1a4d82fc | 2496 | } |
3157f602 XL |
2497 | try!(word(&mut self.s, "..")); |
2498 | if ddpos != elts.len() { | |
2499 | try!(word(&mut self.s, ",")); | |
2500 | try!(self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))); | |
1a4d82fc | 2501 | } |
3157f602 XL |
2502 | } else { |
2503 | try!(self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))); | |
1a4d82fc | 2504 | } |
3157f602 | 2505 | try!(self.pclose()); |
1a4d82fc | 2506 | } |
3157f602 XL |
2507 | PatKind::Path(None, ref path) => { |
2508 | try!(self.print_path(path, true, 0)); | |
7453a54e | 2509 | } |
3157f602 XL |
2510 | PatKind::Path(Some(ref qself), ref path) => { |
2511 | try!(self.print_qpath(path, qself, false)); | |
d9579d0f | 2512 | } |
7453a54e | 2513 | PatKind::Struct(ref path, ref fields, etc) => { |
3157f602 XL |
2514 | try!(self.print_path(path, true, 0)); |
2515 | try!(self.nbsp()); | |
2516 | try!(self.word_space("{")); | |
2517 | try!(self.commasep_cmnt( | |
85aaf69f | 2518 | Consistent, &fields[..], |
1a4d82fc | 2519 | |s, f| { |
3157f602 | 2520 | try!(s.cbox(INDENT_UNIT)); |
1a4d82fc | 2521 | if !f.node.is_shorthand { |
3157f602 XL |
2522 | try!(s.print_ident(f.node.ident)); |
2523 | try!(s.word_nbsp(":")); | |
1a4d82fc | 2524 | } |
3157f602 | 2525 | try!(s.print_pat(&f.node.pat)); |
1a4d82fc JJ |
2526 | s.end() |
2527 | }, | |
3157f602 | 2528 | |f| f.node.pat.span)); |
1a4d82fc | 2529 | if etc { |
3157f602 XL |
2530 | if !fields.is_empty() { try!(self.word_space(",")); } |
2531 | try!(word(&mut self.s, "..")); | |
2532 | } | |
2533 | try!(space(&mut self.s)); | |
2534 | try!(word(&mut self.s, "}")); | |
2535 | } | |
2536 | PatKind::Tuple(ref elts, ddpos) => { | |
2537 | try!(self.popen()); | |
2538 | if let Some(ddpos) = ddpos { | |
2539 | try!(self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))); | |
2540 | if ddpos != 0 { | |
2541 | try!(self.word_space(",")); | |
2542 | } | |
2543 | try!(word(&mut self.s, "..")); | |
2544 | if ddpos != elts.len() { | |
2545 | try!(word(&mut self.s, ",")); | |
2546 | try!(self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))); | |
2547 | } | |
2548 | } else { | |
2549 | try!(self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))); | |
2550 | if elts.len() == 1 { | |
2551 | try!(word(&mut self.s, ",")); | |
2552 | } | |
1a4d82fc | 2553 | } |
3157f602 | 2554 | try!(self.pclose()); |
1a4d82fc | 2555 | } |
7453a54e | 2556 | PatKind::Box(ref inner) => { |
3157f602 XL |
2557 | try!(word(&mut self.s, "box ")); |
2558 | try!(self.print_pat(&inner)); | |
1a4d82fc | 2559 | } |
7453a54e | 2560 | PatKind::Ref(ref inner, mutbl) => { |
3157f602 | 2561 | try!(word(&mut self.s, "&")); |
7453a54e | 2562 | if mutbl == ast::Mutability::Mutable { |
3157f602 | 2563 | try!(word(&mut self.s, "mut ")); |
1a4d82fc | 2564 | } |
3157f602 | 2565 | try!(self.print_pat(&inner)); |
1a4d82fc | 2566 | } |
3157f602 | 2567 | PatKind::Lit(ref e) => try!(self.print_expr(&**e)), |
7453a54e | 2568 | PatKind::Range(ref begin, ref end) => { |
3157f602 XL |
2569 | try!(self.print_expr(&begin)); |
2570 | try!(space(&mut self.s)); | |
2571 | try!(word(&mut self.s, "...")); | |
2572 | try!(self.print_expr(&end)); | |
1a4d82fc | 2573 | } |
c30ab7b3 | 2574 | PatKind::Slice(ref before, ref slice, ref after) => { |
3157f602 XL |
2575 | try!(word(&mut self.s, "[")); |
2576 | try!(self.commasep(Inconsistent, | |
85aaf69f | 2577 | &before[..], |
3157f602 | 2578 | |s, p| s.print_pat(&p))); |
85aaf69f | 2579 | if let Some(ref p) = *slice { |
3157f602 | 2580 | if !before.is_empty() { try!(self.word_space(",")); } |
7453a54e | 2581 | if p.node != PatKind::Wild { |
3157f602 | 2582 | try!(self.print_pat(&p)); |
1a4d82fc | 2583 | } |
3157f602 XL |
2584 | try!(word(&mut self.s, "..")); |
2585 | if !after.is_empty() { try!(self.word_space(",")); } | |
1a4d82fc | 2586 | } |
3157f602 | 2587 | try!(self.commasep(Inconsistent, |
85aaf69f | 2588 | &after[..], |
3157f602 XL |
2589 | |s, p| s.print_pat(&p))); |
2590 | try!(word(&mut self.s, "]")); | |
1a4d82fc | 2591 | } |
3157f602 | 2592 | PatKind::Mac(ref m) => try!(self.print_mac(m, token::Paren)), |
1a4d82fc JJ |
2593 | } |
2594 | self.ann.post(self, NodePat(pat)) | |
2595 | } | |
223e47cc | 2596 | |
c34b1796 | 2597 | fn print_arm(&mut self, arm: &ast::Arm) -> io::Result<()> { |
1a4d82fc JJ |
2598 | // I have no idea why this check is necessary, but here it |
2599 | // is :( | |
2600 | if arm.attrs.is_empty() { | |
3157f602 | 2601 | try!(space(&mut self.s)); |
1a4d82fc | 2602 | } |
3157f602 XL |
2603 | try!(self.cbox(INDENT_UNIT)); |
2604 | try!(self.ibox(0)); | |
c30ab7b3 | 2605 | try!(self.maybe_print_comment(arm.pats[0].span.lo)); |
3157f602 | 2606 | try!(self.print_outer_attributes(&arm.attrs)); |
1a4d82fc | 2607 | let mut first = true; |
85aaf69f | 2608 | for p in &arm.pats { |
1a4d82fc JJ |
2609 | if first { |
2610 | first = false; | |
223e47cc | 2611 | } else { |
3157f602 XL |
2612 | try!(space(&mut self.s)); |
2613 | try!(self.word_space("|")); | |
223e47cc | 2614 | } |
3157f602 | 2615 | try!(self.print_pat(&p)); |
1a4d82fc | 2616 | } |
3157f602 | 2617 | try!(space(&mut self.s)); |
1a4d82fc | 2618 | if let Some(ref e) = arm.guard { |
3157f602 XL |
2619 | try!(self.word_space("if")); |
2620 | try!(self.print_expr(&e)); | |
2621 | try!(space(&mut self.s)); | |
223e47cc | 2622 | } |
3157f602 | 2623 | try!(self.word_space("=>")); |
223e47cc | 2624 | |
1a4d82fc | 2625 | match arm.body.node { |
7453a54e | 2626 | ast::ExprKind::Block(ref blk) => { |
1a4d82fc | 2627 | // the block will close the pattern's ibox |
3157f602 | 2628 | try!(self.print_block_unclosed_indent(&blk, INDENT_UNIT)); |
1a4d82fc JJ |
2629 | |
2630 | // If it is a user-provided unsafe block, print a comma after it | |
7453a54e | 2631 | if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules { |
3157f602 | 2632 | try!(word(&mut self.s, ",")); |
1a4d82fc JJ |
2633 | } |
2634 | } | |
2635 | _ => { | |
3157f602 XL |
2636 | try!(self.end()); // close the ibox for the pattern |
2637 | try!(self.print_expr(&arm.body)); | |
2638 | try!(word(&mut self.s, ",")); | |
1a4d82fc | 2639 | } |
223e47cc | 2640 | } |
1a4d82fc JJ |
2641 | self.end() // close enclosing cbox |
2642 | } | |
223e47cc | 2643 | |
3157f602 XL |
2644 | fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) -> io::Result<()> { |
2645 | match explicit_self.node { | |
2646 | SelfKind::Value(m) => { | |
2647 | try!(self.print_mutability(m)); | |
2648 | word(&mut self.s, "self") | |
1a4d82fc | 2649 | } |
3157f602 XL |
2650 | SelfKind::Region(ref lt, m) => { |
2651 | try!(word(&mut self.s, "&")); | |
2652 | try!(self.print_opt_lifetime(lt)); | |
2653 | try!(self.print_mutability(m)); | |
2654 | word(&mut self.s, "self") | |
1a4d82fc | 2655 | } |
3157f602 XL |
2656 | SelfKind::Explicit(ref typ, m) => { |
2657 | try!(self.print_mutability(m)); | |
2658 | try!(word(&mut self.s, "self")); | |
2659 | try!(self.word_space(":")); | |
2660 | self.print_type(&typ) | |
1a4d82fc JJ |
2661 | } |
2662 | } | |
223e47cc | 2663 | } |
223e47cc | 2664 | |
1a4d82fc JJ |
2665 | pub fn print_fn(&mut self, |
2666 | decl: &ast::FnDecl, | |
c34b1796 | 2667 | unsafety: ast::Unsafety, |
62682a34 | 2668 | constness: ast::Constness, |
1a4d82fc | 2669 | abi: abi::Abi, |
c34b1796 | 2670 | name: Option<ast::Ident>, |
1a4d82fc | 2671 | generics: &ast::Generics, |
54a0048b | 2672 | vis: &ast::Visibility) -> io::Result<()> { |
3157f602 | 2673 | try!(self.print_fn_header_info(unsafety, constness, abi, vis)); |
c34b1796 AL |
2674 | |
2675 | if let Some(name) = name { | |
3157f602 XL |
2676 | try!(self.nbsp()); |
2677 | try!(self.print_ident(name)); | |
c34b1796 | 2678 | } |
3157f602 XL |
2679 | try!(self.print_generics(generics)); |
2680 | try!(self.print_fn_args_and_ret(decl)); | |
c34b1796 | 2681 | self.print_where_clause(&generics.where_clause) |
1a4d82fc JJ |
2682 | } |
2683 | ||
3157f602 | 2684 | pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl) |
c34b1796 | 2685 | -> io::Result<()> { |
3157f602 XL |
2686 | try!(self.popen()); |
2687 | try!(self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))); | |
1a4d82fc | 2688 | if decl.variadic { |
3157f602 | 2689 | try!(word(&mut self.s, ", ...")); |
223e47cc | 2690 | } |
3157f602 | 2691 | try!(self.pclose()); |
1a4d82fc JJ |
2692 | |
2693 | self.print_fn_output(decl) | |
223e47cc | 2694 | } |
223e47cc | 2695 | |
1a4d82fc JJ |
2696 | pub fn print_fn_block_args( |
2697 | &mut self, | |
85aaf69f | 2698 | decl: &ast::FnDecl) |
c34b1796 | 2699 | -> io::Result<()> { |
3157f602 XL |
2700 | try!(word(&mut self.s, "|")); |
2701 | try!(self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true))); | |
2702 | try!(word(&mut self.s, "|")); | |
223e47cc | 2703 | |
7453a54e | 2704 | if let ast::FunctionRetTy::Default(..) = decl.output { |
85aaf69f | 2705 | return Ok(()); |
223e47cc LB |
2706 | } |
2707 | ||
3157f602 XL |
2708 | try!(self.space_if_not_bol()); |
2709 | try!(self.word_space("->")); | |
1a4d82fc | 2710 | match decl.output { |
7453a54e | 2711 | ast::FunctionRetTy::Ty(ref ty) => { |
3157f602 | 2712 | try!(self.print_type(&ty)); |
1a4d82fc JJ |
2713 | self.maybe_print_comment(ty.span.lo) |
2714 | } | |
7453a54e | 2715 | ast::FunctionRetTy::Default(..) => unreachable!(), |
223e47cc LB |
2716 | } |
2717 | } | |
223e47cc | 2718 | |
7453a54e | 2719 | pub fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy) |
c34b1796 | 2720 | -> io::Result<()> { |
1a4d82fc | 2721 | match capture_clause { |
7453a54e SL |
2722 | ast::CaptureBy::Value => self.word_space("move"), |
2723 | ast::CaptureBy::Ref => Ok(()), | |
1a4d82fc | 2724 | } |
223e47cc | 2725 | } |
223e47cc | 2726 | |
1a4d82fc JJ |
2727 | pub fn print_bounds(&mut self, |
2728 | prefix: &str, | |
2729 | bounds: &[ast::TyParamBound]) | |
c34b1796 | 2730 | -> io::Result<()> { |
1a4d82fc | 2731 | if !bounds.is_empty() { |
3157f602 | 2732 | try!(word(&mut self.s, prefix)); |
1a4d82fc | 2733 | let mut first = true; |
85aaf69f | 2734 | for bound in bounds { |
3157f602 | 2735 | try!(self.nbsp()); |
1a4d82fc JJ |
2736 | if first { |
2737 | first = false; | |
2738 | } else { | |
3157f602 | 2739 | try!(self.word_space("+")); |
1a4d82fc JJ |
2740 | } |
2741 | ||
3157f602 | 2742 | try!(match *bound { |
1a4d82fc JJ |
2743 | TraitTyParamBound(ref tref, TraitBoundModifier::None) => { |
2744 | self.print_poly_trait_ref(tref) | |
2745 | } | |
2746 | TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => { | |
3157f602 | 2747 | try!(word(&mut self.s, "?")); |
1a4d82fc JJ |
2748 | self.print_poly_trait_ref(tref) |
2749 | } | |
2750 | RegionTyParamBound(ref lt) => { | |
2751 | self.print_lifetime(lt) | |
2752 | } | |
3157f602 | 2753 | }) |
1a4d82fc JJ |
2754 | } |
2755 | Ok(()) | |
2756 | } else { | |
2757 | Ok(()) | |
2758 | } | |
2759 | } | |
223e47cc | 2760 | |
1a4d82fc JJ |
2761 | pub fn print_lifetime(&mut self, |
2762 | lifetime: &ast::Lifetime) | |
c34b1796 | 2763 | -> io::Result<()> |
1a4d82fc JJ |
2764 | { |
2765 | self.print_name(lifetime.name) | |
223e47cc | 2766 | } |
223e47cc | 2767 | |
3157f602 XL |
2768 | pub fn print_lifetime_bounds(&mut self, |
2769 | lifetime: &ast::Lifetime, | |
2770 | bounds: &[ast::Lifetime]) | |
2771 | -> io::Result<()> | |
1a4d82fc | 2772 | { |
3157f602 XL |
2773 | try!(self.print_lifetime(lifetime)); |
2774 | if !bounds.is_empty() { | |
2775 | try!(word(&mut self.s, ": ")); | |
2776 | for (i, bound) in bounds.iter().enumerate() { | |
2777 | if i != 0 { | |
2778 | try!(word(&mut self.s, " + ")); | |
2779 | } | |
2780 | try!(self.print_lifetime(bound)); | |
2781 | } | |
223e47cc | 2782 | } |
1a4d82fc | 2783 | Ok(()) |
223e47cc | 2784 | } |
223e47cc | 2785 | |
1a4d82fc JJ |
2786 | pub fn print_generics(&mut self, |
2787 | generics: &ast::Generics) | |
c34b1796 | 2788 | -> io::Result<()> |
1a4d82fc JJ |
2789 | { |
2790 | let total = generics.lifetimes.len() + generics.ty_params.len(); | |
2791 | if total == 0 { | |
2792 | return Ok(()); | |
2793 | } | |
2794 | ||
3157f602 | 2795 | try!(word(&mut self.s, "<")); |
1a4d82fc JJ |
2796 | |
2797 | let mut ints = Vec::new(); | |
85aaf69f | 2798 | for i in 0..total { |
1a4d82fc JJ |
2799 | ints.push(i); |
2800 | } | |
2801 | ||
3157f602 | 2802 | try!(self.commasep(Inconsistent, &ints[..], |s, &idx| { |
1a4d82fc | 2803 | if idx < generics.lifetimes.len() { |
3157f602 | 2804 | let lifetime_def = &generics.lifetimes[idx]; |
c30ab7b3 | 2805 | try!(s.print_outer_attributes_inline(&lifetime_def.attrs)); |
3157f602 | 2806 | s.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds) |
1a4d82fc JJ |
2807 | } else { |
2808 | let idx = idx - generics.lifetimes.len(); | |
2809 | let param = &generics.ty_params[idx]; | |
2810 | s.print_ty_param(param) | |
2811 | } | |
3157f602 | 2812 | })); |
1a4d82fc | 2813 | |
3157f602 | 2814 | try!(word(&mut self.s, ">")); |
1a4d82fc | 2815 | Ok(()) |
223e47cc | 2816 | } |
223e47cc | 2817 | |
c34b1796 | 2818 | pub fn print_ty_param(&mut self, param: &ast::TyParam) -> io::Result<()> { |
c30ab7b3 | 2819 | try!(self.print_outer_attributes_inline(¶m.attrs)); |
3157f602 XL |
2820 | try!(self.print_ident(param.ident)); |
2821 | try!(self.print_bounds(":", ¶m.bounds)); | |
1a4d82fc JJ |
2822 | match param.default { |
2823 | Some(ref default) => { | |
3157f602 XL |
2824 | try!(space(&mut self.s)); |
2825 | try!(self.word_space("=")); | |
7453a54e | 2826 | self.print_type(&default) |
1a4d82fc JJ |
2827 | } |
2828 | _ => Ok(()) | |
2829 | } | |
2830 | } | |
2831 | ||
c34b1796 AL |
2832 | pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause) |
2833 | -> io::Result<()> { | |
9346a6ac | 2834 | if where_clause.predicates.is_empty() { |
1a4d82fc JJ |
2835 | return Ok(()) |
2836 | } | |
2837 | ||
3157f602 XL |
2838 | try!(space(&mut self.s)); |
2839 | try!(self.word_space("where")); | |
1a4d82fc | 2840 | |
c34b1796 | 2841 | for (i, predicate) in where_clause.predicates.iter().enumerate() { |
1a4d82fc | 2842 | if i != 0 { |
3157f602 | 2843 | try!(self.word_space(",")); |
1a4d82fc JJ |
2844 | } |
2845 | ||
92a42be0 SL |
2846 | match *predicate { |
2847 | ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes, | |
2848 | ref bounded_ty, | |
2849 | ref bounds, | |
2850 | ..}) => { | |
3157f602 XL |
2851 | try!(self.print_formal_lifetime_list(bound_lifetimes)); |
2852 | try!(self.print_type(&bounded_ty)); | |
2853 | try!(self.print_bounds(":", bounds)); | |
1a4d82fc | 2854 | } |
92a42be0 SL |
2855 | ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, |
2856 | ref bounds, | |
2857 | ..}) => { | |
3157f602 | 2858 | try!(self.print_lifetime_bounds(lifetime, bounds)); |
1a4d82fc | 2859 | } |
92a42be0 | 2860 | ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { |
3157f602 XL |
2861 | try!(self.print_path(path, false, 0)); |
2862 | try!(space(&mut self.s)); | |
2863 | try!(self.word_space("=")); | |
2864 | try!(self.print_type(&ty)); | |
1a4d82fc JJ |
2865 | } |
2866 | } | |
223e47cc | 2867 | } |
1a4d82fc JJ |
2868 | |
2869 | Ok(()) | |
223e47cc | 2870 | } |
223e47cc | 2871 | |
c34b1796 | 2872 | pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> io::Result<()> { |
1a4d82fc | 2873 | match vp.node { |
85aaf69f | 2874 | ast::ViewPathSimple(ident, ref path) => { |
3157f602 | 2875 | try!(self.print_path(path, false, 0)); |
1a4d82fc | 2876 | |
1a4d82fc JJ |
2877 | if path.segments.last().unwrap().identifier.name != |
2878 | ident.name { | |
3157f602 XL |
2879 | try!(space(&mut self.s)); |
2880 | try!(self.word_space("as")); | |
2881 | try!(self.print_ident(ident)); | |
1a4d82fc JJ |
2882 | } |
2883 | ||
2884 | Ok(()) | |
2885 | } | |
2886 | ||
85aaf69f | 2887 | ast::ViewPathGlob(ref path) => { |
3157f602 | 2888 | try!(self.print_path(path, false, 0)); |
1a4d82fc JJ |
2889 | word(&mut self.s, "::*") |
2890 | } | |
2891 | ||
85aaf69f | 2892 | ast::ViewPathList(ref path, ref idents) => { |
1a4d82fc | 2893 | if path.segments.is_empty() { |
3157f602 | 2894 | try!(word(&mut self.s, "{")); |
1a4d82fc | 2895 | } else { |
3157f602 XL |
2896 | try!(self.print_path(path, false, 0)); |
2897 | try!(word(&mut self.s, "::{")); | |
1a4d82fc | 2898 | } |
3157f602 | 2899 | try!(self.commasep(Inconsistent, &idents[..], |s, w| { |
9e0c209e SL |
2900 | try!(s.print_ident(w.node.name)); |
2901 | if let Some(ident) = w.node.rename { | |
2902 | try!(space(&mut s.s)); | |
2903 | try!(s.word_space("as")); | |
2904 | try!(s.print_ident(ident)); | |
1a4d82fc | 2905 | } |
9e0c209e | 2906 | Ok(()) |
3157f602 | 2907 | })); |
1a4d82fc JJ |
2908 | word(&mut self.s, "}") |
2909 | } | |
2910 | } | |
223e47cc | 2911 | } |
223e47cc | 2912 | |
1a4d82fc | 2913 | pub fn print_mutability(&mut self, |
c34b1796 | 2914 | mutbl: ast::Mutability) -> io::Result<()> { |
1a4d82fc | 2915 | match mutbl { |
7453a54e SL |
2916 | ast::Mutability::Mutable => self.word_nbsp("mut"), |
2917 | ast::Mutability::Immutable => Ok(()), | |
1a4d82fc JJ |
2918 | } |
2919 | } | |
2920 | ||
c34b1796 | 2921 | pub fn print_mt(&mut self, mt: &ast::MutTy) -> io::Result<()> { |
3157f602 | 2922 | try!(self.print_mutability(mt.mutbl)); |
7453a54e | 2923 | self.print_type(&mt.ty) |
223e47cc | 2924 | } |
223e47cc | 2925 | |
7453a54e | 2926 | pub fn print_arg(&mut self, input: &ast::Arg, is_closure: bool) -> io::Result<()> { |
3157f602 | 2927 | try!(self.ibox(INDENT_UNIT)); |
1a4d82fc | 2928 | match input.ty.node { |
3157f602 | 2929 | ast::TyKind::Infer if is_closure => try!(self.print_pat(&input.pat)), |
1a4d82fc | 2930 | _ => { |
a7813a04 | 2931 | if let Some(eself) = input.to_self() { |
3157f602 | 2932 | try!(self.print_explicit_self(&eself)); |
a7813a04 | 2933 | } else { |
3157f602 XL |
2934 | let invalid = if let PatKind::Ident(_, ident, _) = input.pat.node { |
2935 | ident.node.name == keywords::Invalid.name() | |
2936 | } else { | |
2937 | false | |
2938 | }; | |
a7813a04 | 2939 | if !invalid { |
3157f602 XL |
2940 | try!(self.print_pat(&input.pat)); |
2941 | try!(word(&mut self.s, ":")); | |
2942 | try!(space(&mut self.s)); | |
1a4d82fc | 2943 | } |
3157f602 | 2944 | try!(self.print_type(&input.ty)); |
1a4d82fc | 2945 | } |
1a4d82fc | 2946 | } |
223e47cc | 2947 | } |
1a4d82fc | 2948 | self.end() |
223e47cc | 2949 | } |
223e47cc | 2950 | |
c34b1796 | 2951 | pub fn print_fn_output(&mut self, decl: &ast::FnDecl) -> io::Result<()> { |
7453a54e | 2952 | if let ast::FunctionRetTy::Default(..) = decl.output { |
85aaf69f | 2953 | return Ok(()); |
223e47cc | 2954 | } |
223e47cc | 2955 | |
3157f602 XL |
2956 | try!(self.space_if_not_bol()); |
2957 | try!(self.ibox(INDENT_UNIT)); | |
2958 | try!(self.word_space("->")); | |
1a4d82fc | 2959 | match decl.output { |
7453a54e SL |
2960 | ast::FunctionRetTy::Default(..) => unreachable!(), |
2961 | ast::FunctionRetTy::Ty(ref ty) => | |
3157f602 | 2962 | try!(self.print_type(&ty)) |
1a4d82fc | 2963 | } |
3157f602 | 2964 | try!(self.end()); |
1a4d82fc JJ |
2965 | |
2966 | match decl.output { | |
7453a54e | 2967 | ast::FunctionRetTy::Ty(ref output) => self.maybe_print_comment(output.span.lo), |
1a4d82fc JJ |
2968 | _ => Ok(()) |
2969 | } | |
2970 | } | |
2971 | ||
2972 | pub fn print_ty_fn(&mut self, | |
85aaf69f | 2973 | abi: abi::Abi, |
1a4d82fc | 2974 | unsafety: ast::Unsafety, |
1a4d82fc | 2975 | decl: &ast::FnDecl, |
c34b1796 | 2976 | name: Option<ast::Ident>, |
3157f602 | 2977 | generics: &ast::Generics) |
c34b1796 | 2978 | -> io::Result<()> { |
3157f602 | 2979 | try!(self.ibox(INDENT_UNIT)); |
9346a6ac | 2980 | if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { |
3157f602 XL |
2981 | try!(word(&mut self.s, "for")); |
2982 | try!(self.print_generics(generics)); | |
c34b1796 AL |
2983 | } |
2984 | let generics = ast::Generics { | |
2985 | lifetimes: Vec::new(), | |
a7813a04 | 2986 | ty_params: P::new(), |
c34b1796 AL |
2987 | where_clause: ast::WhereClause { |
2988 | id: ast::DUMMY_NODE_ID, | |
2989 | predicates: Vec::new(), | |
2990 | }, | |
9e0c209e | 2991 | span: syntax_pos::DUMMY_SP, |
c34b1796 | 2992 | }; |
3157f602 | 2993 | try!(self.print_fn(decl, |
54a0048b SL |
2994 | unsafety, |
2995 | ast::Constness::NotConst, | |
2996 | abi, | |
2997 | name, | |
2998 | &generics, | |
3157f602 | 2999 | &ast::Visibility::Inherited)); |
1a4d82fc | 3000 | self.end() |
223e47cc LB |
3001 | } |
3002 | ||
3157f602 | 3003 | pub fn maybe_print_trailing_comment(&mut self, span: syntax_pos::Span, |
1a4d82fc | 3004 | next_pos: Option<BytePos>) |
c34b1796 | 3005 | -> io::Result<()> { |
1a4d82fc JJ |
3006 | let cm = match self.cm { |
3007 | Some(cm) => cm, | |
3008 | _ => return Ok(()) | |
3009 | }; | |
3157f602 | 3010 | if let Some(ref cmnt) = self.next_comment() { |
c30ab7b3 | 3011 | if cmnt.style != comments::Trailing { return Ok(()) } |
3157f602 | 3012 | let span_line = cm.lookup_char_pos(span.hi); |
c30ab7b3 SL |
3013 | let comment_line = cm.lookup_char_pos(cmnt.pos); |
3014 | let next = next_pos.unwrap_or(cmnt.pos + BytePos(1)); | |
3015 | if span.hi < cmnt.pos && cmnt.pos < next && span_line.line == comment_line.line { | |
3157f602 XL |
3016 | self.print_comment(cmnt)?; |
3017 | self.cur_cmnt_and_lit.cur_cmnt += 1; | |
1a4d82fc | 3018 | } |
1a4d82fc JJ |
3019 | } |
3020 | Ok(()) | |
3021 | } | |
223e47cc | 3022 | |
c34b1796 | 3023 | pub fn print_remaining_comments(&mut self) -> io::Result<()> { |
1a4d82fc JJ |
3024 | // If there aren't any remaining comments, then we need to manually |
3025 | // make sure there is a line break at the end. | |
3026 | if self.next_comment().is_none() { | |
3157f602 | 3027 | try!(hardbreak(&mut self.s)); |
1a4d82fc JJ |
3028 | } |
3029 | loop { | |
3030 | match self.next_comment() { | |
3031 | Some(ref cmnt) => { | |
3157f602 | 3032 | try!(self.print_comment(cmnt)); |
85aaf69f | 3033 | self.cur_cmnt_and_lit.cur_cmnt += 1; |
1a4d82fc JJ |
3034 | } |
3035 | _ => break | |
3036 | } | |
3037 | } | |
3038 | Ok(()) | |
223e47cc | 3039 | } |
223e47cc | 3040 | |
1a4d82fc | 3041 | pub fn print_opt_abi_and_extern_if_nondefault(&mut self, |
7453a54e | 3042 | opt_abi: Option<Abi>) |
c34b1796 | 3043 | -> io::Result<()> { |
1a4d82fc | 3044 | match opt_abi { |
7453a54e | 3045 | Some(Abi::Rust) => Ok(()), |
1a4d82fc | 3046 | Some(abi) => { |
3157f602 | 3047 | try!(self.word_nbsp("extern")); |
85aaf69f | 3048 | self.word_nbsp(&abi.to_string()) |
1a4d82fc JJ |
3049 | } |
3050 | None => Ok(()) | |
3051 | } | |
3052 | } | |
3053 | ||
3054 | pub fn print_extern_opt_abi(&mut self, | |
7453a54e | 3055 | opt_abi: Option<Abi>) -> io::Result<()> { |
1a4d82fc JJ |
3056 | match opt_abi { |
3057 | Some(abi) => { | |
3157f602 | 3058 | try!(self.word_nbsp("extern")); |
85aaf69f | 3059 | self.word_nbsp(&abi.to_string()) |
1a4d82fc JJ |
3060 | } |
3061 | None => Ok(()) | |
3062 | } | |
3063 | } | |
3064 | ||
3065 | pub fn print_fn_header_info(&mut self, | |
c34b1796 | 3066 | unsafety: ast::Unsafety, |
62682a34 | 3067 | constness: ast::Constness, |
7453a54e | 3068 | abi: Abi, |
54a0048b | 3069 | vis: &ast::Visibility) -> io::Result<()> { |
3157f602 | 3070 | try!(word(&mut self.s, &visibility_qualified(vis, ""))); |
1a4d82fc | 3071 | |
62682a34 SL |
3072 | match constness { |
3073 | ast::Constness::NotConst => {} | |
3157f602 | 3074 | ast::Constness::Const => try!(self.word_nbsp("const")) |
62682a34 SL |
3075 | } |
3076 | ||
3157f602 | 3077 | try!(self.print_unsafety(unsafety)); |
b039eaaf | 3078 | |
7453a54e | 3079 | if abi != Abi::Rust { |
3157f602 XL |
3080 | try!(self.word_nbsp("extern")); |
3081 | try!(self.word_nbsp(&abi.to_string())); | |
1a4d82fc JJ |
3082 | } |
3083 | ||
3084 | word(&mut self.s, "fn") | |
3085 | } | |
3086 | ||
c34b1796 | 3087 | pub fn print_unsafety(&mut self, s: ast::Unsafety) -> io::Result<()> { |
1a4d82fc JJ |
3088 | match s { |
3089 | ast::Unsafety::Normal => Ok(()), | |
3090 | ast::Unsafety::Unsafe => self.word_nbsp("unsafe"), | |
3091 | } | |
223e47cc LB |
3092 | } |
3093 | } | |
3094 | ||
85aaf69f | 3095 | fn repeat(s: &str, n: usize) -> String { iter::repeat(s).take(n).collect() } |
1a4d82fc | 3096 | |
223e47cc | 3097 | #[cfg(test)] |
d9579d0f | 3098 | mod tests { |
223e47cc LB |
3099 | use super::*; |
3100 | ||
3101 | use ast; | |
223e47cc | 3102 | use codemap; |
970d7e83 | 3103 | use parse::token; |
3157f602 | 3104 | use syntax_pos; |
223e47cc LB |
3105 | |
3106 | #[test] | |
1a4d82fc | 3107 | fn test_fun_to_string() { |
970d7e83 | 3108 | let abba_ident = token::str_to_ident("abba"); |
223e47cc | 3109 | |
1a4d82fc JJ |
3110 | let decl = ast::FnDecl { |
3111 | inputs: Vec::new(), | |
3157f602 | 3112 | output: ast::FunctionRetTy::Default(syntax_pos::DUMMY_SP), |
1a4d82fc | 3113 | variadic: false |
223e47cc | 3114 | }; |
9cc50fc6 | 3115 | let generics = ast::Generics::default(); |
62682a34 SL |
3116 | assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal, |
3117 | ast::Constness::NotConst, | |
3157f602 | 3118 | abba_ident, &generics), |
1a4d82fc | 3119 | "fn abba()"); |
223e47cc LB |
3120 | } |
3121 | ||
3122 | #[test] | |
1a4d82fc | 3123 | fn test_variant_to_string() { |
970d7e83 | 3124 | let ident = token::str_to_ident("principal_skinner"); |
223e47cc | 3125 | |
3157f602 | 3126 | let var = codemap::respan(syntax_pos::DUMMY_SP, ast::Variant_ { |
223e47cc | 3127 | name: ident, |
1a4d82fc | 3128 | attrs: Vec::new(), |
223e47cc | 3129 | // making this up as I go.... ? |
b039eaaf | 3130 | data: ast::VariantData::Unit(ast::DUMMY_NODE_ID), |
223e47cc | 3131 | disr_expr: None, |
223e47cc LB |
3132 | }); |
3133 | ||
1a4d82fc | 3134 | let varstr = variant_to_string(&var); |
b039eaaf | 3135 | assert_eq!(varstr, "principal_skinner"); |
1a4d82fc | 3136 | } |
223e47cc | 3137 | } |