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