]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | pub use self::AnnNode::*; | |
12 | ||
7453a54e | 13 | use syntax::abi::Abi; |
e9174d1e | 14 | use syntax::ast; |
b039eaaf | 15 | use syntax::codemap::{self, CodeMap, BytePos, Spanned}; |
9cc50fc6 | 16 | use syntax::errors; |
e9174d1e SL |
17 | use syntax::parse::token::{self, BinOpToken}; |
18 | use syntax::parse::lexer::comments; | |
19 | use syntax::parse; | |
b039eaaf | 20 | use syntax::print::pp::{self, break_offset, word, space, hardbreak}; |
e9174d1e SL |
21 | use syntax::print::pp::{Breaks, eof}; |
22 | use syntax::print::pp::Breaks::{Consistent, Inconsistent}; | |
b039eaaf | 23 | use syntax::print::pprust::{self as ast_pp, PrintState}; |
e9174d1e SL |
24 | use syntax::ptr::P; |
25 | ||
26 | use hir; | |
7453a54e | 27 | use hir::{Crate, PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; |
e9174d1e | 28 | |
e9174d1e | 29 | use std::io::{self, Write, Read}; |
e9174d1e SL |
30 | |
31 | pub enum AnnNode<'a> { | |
e9174d1e SL |
32 | NodeName(&'a ast::Name), |
33 | NodeBlock(&'a hir::Block), | |
34 | NodeItem(&'a hir::Item), | |
35 | NodeSubItem(ast::NodeId), | |
36 | NodeExpr(&'a hir::Expr), | |
37 | NodePat(&'a hir::Pat), | |
38 | } | |
39 | ||
40 | pub trait PpAnn { | |
b039eaaf SL |
41 | fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { |
42 | Ok(()) | |
43 | } | |
44 | fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { | |
45 | Ok(()) | |
46 | } | |
e9174d1e SL |
47 | } |
48 | ||
49 | #[derive(Copy, Clone)] | |
50 | pub struct NoAnn; | |
51 | ||
52 | impl PpAnn for NoAnn {} | |
53 | ||
e9174d1e SL |
54 | |
55 | pub struct State<'a> { | |
92a42be0 | 56 | krate: Option<&'a Crate>, |
e9174d1e SL |
57 | pub s: pp::Printer<'a>, |
58 | cm: Option<&'a CodeMap>, | |
b039eaaf SL |
59 | comments: Option<Vec<comments::Comment>>, |
60 | literals: Option<Vec<comments::Literal>>, | |
61 | cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral, | |
e9174d1e | 62 | boxes: Vec<pp::Breaks>, |
b039eaaf | 63 | ann: &'a (PpAnn + 'a), |
e9174d1e SL |
64 | } |
65 | ||
b039eaaf SL |
66 | impl<'a> PrintState<'a> for State<'a> { |
67 | fn writer(&mut self) -> &mut pp::Printer<'a> { | |
68 | &mut self.s | |
69 | } | |
70 | ||
71 | fn boxes(&mut self) -> &mut Vec<pp::Breaks> { | |
72 | &mut self.boxes | |
73 | } | |
74 | ||
75 | fn comments(&mut self) -> &mut Option<Vec<comments::Comment>> { | |
76 | &mut self.comments | |
77 | } | |
78 | ||
79 | fn cur_cmnt_and_lit(&mut self) -> &mut ast_pp::CurrentCommentAndLiteral { | |
80 | &mut self.cur_cmnt_and_lit | |
81 | } | |
82 | ||
83 | fn literals(&self) -> &Option<Vec<comments::Literal>> { | |
84 | &self.literals | |
85 | } | |
86 | } | |
87 | ||
92a42be0 | 88 | pub fn rust_printer<'a>(writer: Box<Write + 'a>, krate: Option<&'a Crate>) -> State<'a> { |
e9174d1e | 89 | static NO_ANN: NoAnn = NoAnn; |
92a42be0 | 90 | rust_printer_annotated(writer, &NO_ANN, krate) |
e9174d1e SL |
91 | } |
92 | ||
92a42be0 SL |
93 | pub fn rust_printer_annotated<'a>(writer: Box<Write + 'a>, |
94 | ann: &'a PpAnn, | |
95 | krate: Option<&'a Crate>) | |
96 | -> State<'a> { | |
e9174d1e | 97 | State { |
92a42be0 | 98 | krate: krate, |
e9174d1e SL |
99 | s: pp::mk_printer(writer, default_columns), |
100 | cm: None, | |
101 | comments: None, | |
102 | literals: None, | |
b039eaaf | 103 | cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral { |
e9174d1e | 104 | cur_cmnt: 0, |
b039eaaf | 105 | cur_lit: 0, |
e9174d1e SL |
106 | }, |
107 | boxes: Vec::new(), | |
108 | ann: ann, | |
109 | } | |
110 | } | |
111 | ||
112 | #[allow(non_upper_case_globals)] | |
113 | pub const indent_unit: usize = 4; | |
114 | ||
115 | #[allow(non_upper_case_globals)] | |
116 | pub const default_columns: usize = 78; | |
117 | ||
118 | ||
119 | /// Requires you to pass an input filename and reader so that | |
120 | /// it can scan the input text for comments and literals to | |
121 | /// copy forward. | |
122 | pub fn print_crate<'a>(cm: &'a CodeMap, | |
9cc50fc6 | 123 | span_diagnostic: &errors::Handler, |
e9174d1e SL |
124 | krate: &hir::Crate, |
125 | filename: String, | |
126 | input: &mut Read, | |
b039eaaf | 127 | out: Box<Write + 'a>, |
e9174d1e | 128 | ann: &'a PpAnn, |
b039eaaf SL |
129 | is_expanded: bool) |
130 | -> io::Result<()> { | |
92a42be0 SL |
131 | let mut s = State::new_from_input(cm, span_diagnostic, filename, input, |
132 | out, ann, is_expanded, Some(krate)); | |
e9174d1e SL |
133 | |
134 | // When printing the AST, we sometimes need to inject `#[no_std]` here. | |
135 | // Since you can't compile the HIR, it's not necessary. | |
136 | ||
137 | try!(s.print_mod(&krate.module, &krate.attrs)); | |
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, | |
9cc50fc6 | 144 | span_diagnostic: &errors::Handler, |
e9174d1e SL |
145 | filename: String, |
146 | input: &mut Read, | |
b039eaaf | 147 | out: Box<Write + 'a>, |
e9174d1e | 148 | ann: &'a PpAnn, |
92a42be0 SL |
149 | is_expanded: bool, |
150 | krate: Option<&'a Crate>) | |
b039eaaf SL |
151 | -> State<'a> { |
152 | let (cmnts, lits) = comments::gather_comments_and_literals(span_diagnostic, | |
153 | filename, | |
154 | input); | |
155 | ||
156 | State::new(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 { | |
164 | None | |
165 | } else { | |
166 | Some(lits) | |
92a42be0 SL |
167 | }, |
168 | krate) | |
e9174d1e SL |
169 | } |
170 | ||
171 | pub fn new(cm: &'a CodeMap, | |
b039eaaf | 172 | out: Box<Write + 'a>, |
e9174d1e SL |
173 | ann: &'a PpAnn, |
174 | comments: Option<Vec<comments::Comment>>, | |
92a42be0 SL |
175 | literals: Option<Vec<comments::Literal>>, |
176 | krate: Option<&'a Crate>) | |
b039eaaf | 177 | -> State<'a> { |
e9174d1e | 178 | State { |
92a42be0 | 179 | krate: krate, |
e9174d1e SL |
180 | s: pp::mk_printer(out, default_columns), |
181 | cm: Some(cm), | |
b039eaaf SL |
182 | comments: comments.clone(), |
183 | literals: literals.clone(), | |
184 | cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral { | |
e9174d1e | 185 | cur_cmnt: 0, |
b039eaaf | 186 | cur_lit: 0, |
e9174d1e SL |
187 | }, |
188 | boxes: Vec::new(), | |
189 | ann: ann, | |
190 | } | |
191 | } | |
192 | } | |
193 | ||
b039eaaf SL |
194 | pub fn to_string<F>(f: F) -> String |
195 | where F: FnOnce(&mut State) -> io::Result<()> | |
e9174d1e SL |
196 | { |
197 | let mut wr = Vec::new(); | |
198 | { | |
92a42be0 | 199 | let mut printer = rust_printer(Box::new(&mut wr), None); |
e9174d1e SL |
200 | f(&mut printer).unwrap(); |
201 | eof(&mut printer.s).unwrap(); | |
202 | } | |
203 | String::from_utf8(wr).unwrap() | |
204 | } | |
205 | ||
206 | pub fn binop_to_string(op: BinOpToken) -> &'static str { | |
207 | match op { | |
b039eaaf SL |
208 | token::Plus => "+", |
209 | token::Minus => "-", | |
210 | token::Star => "*", | |
211 | token::Slash => "/", | |
212 | token::Percent => "%", | |
213 | token::Caret => "^", | |
214 | token::And => "&", | |
215 | token::Or => "|", | |
216 | token::Shl => "<<", | |
217 | token::Shr => ">>", | |
e9174d1e SL |
218 | } |
219 | } | |
220 | ||
221 | pub fn ty_to_string(ty: &hir::Ty) -> String { | |
222 | to_string(|s| s.print_type(ty)) | |
223 | } | |
224 | ||
225 | pub fn bounds_to_string(bounds: &[hir::TyParamBound]) -> String { | |
226 | to_string(|s| s.print_bounds("", bounds)) | |
227 | } | |
228 | ||
229 | pub fn pat_to_string(pat: &hir::Pat) -> String { | |
230 | to_string(|s| s.print_pat(pat)) | |
231 | } | |
232 | ||
233 | pub fn arm_to_string(arm: &hir::Arm) -> String { | |
234 | to_string(|s| s.print_arm(arm)) | |
235 | } | |
236 | ||
237 | pub fn expr_to_string(e: &hir::Expr) -> String { | |
238 | to_string(|s| s.print_expr(e)) | |
239 | } | |
240 | ||
241 | pub fn lifetime_to_string(e: &hir::Lifetime) -> String { | |
242 | to_string(|s| s.print_lifetime(e)) | |
243 | } | |
244 | ||
245 | pub fn stmt_to_string(stmt: &hir::Stmt) -> String { | |
246 | to_string(|s| s.print_stmt(stmt)) | |
247 | } | |
248 | ||
e9174d1e SL |
249 | pub fn item_to_string(i: &hir::Item) -> String { |
250 | to_string(|s| s.print_item(i)) | |
251 | } | |
252 | ||
253 | pub fn impl_item_to_string(i: &hir::ImplItem) -> String { | |
254 | to_string(|s| s.print_impl_item(i)) | |
255 | } | |
256 | ||
257 | pub fn trait_item_to_string(i: &hir::TraitItem) -> String { | |
258 | to_string(|s| s.print_trait_item(i)) | |
259 | } | |
260 | ||
261 | pub fn generics_to_string(generics: &hir::Generics) -> String { | |
262 | to_string(|s| s.print_generics(generics)) | |
263 | } | |
264 | ||
265 | pub fn where_clause_to_string(i: &hir::WhereClause) -> String { | |
266 | to_string(|s| s.print_where_clause(i)) | |
267 | } | |
268 | ||
269 | pub fn fn_block_to_string(p: &hir::FnDecl) -> String { | |
270 | to_string(|s| s.print_fn_block_args(p)) | |
271 | } | |
272 | ||
273 | pub fn path_to_string(p: &hir::Path) -> String { | |
274 | to_string(|s| s.print_path(p, false, 0)) | |
275 | } | |
276 | ||
b039eaaf SL |
277 | pub fn name_to_string(name: ast::Name) -> String { |
278 | to_string(|s| s.print_name(name)) | |
e9174d1e SL |
279 | } |
280 | ||
281 | pub fn fun_to_string(decl: &hir::FnDecl, | |
282 | unsafety: hir::Unsafety, | |
283 | constness: hir::Constness, | |
b039eaaf | 284 | name: ast::Name, |
e9174d1e SL |
285 | opt_explicit_self: Option<&hir::ExplicitSelf_>, |
286 | generics: &hir::Generics) | |
287 | -> String { | |
288 | to_string(|s| { | |
289 | try!(s.head("")); | |
b039eaaf SL |
290 | try!(s.print_fn(decl, |
291 | unsafety, | |
292 | constness, | |
7453a54e | 293 | Abi::Rust, |
b039eaaf SL |
294 | Some(name), |
295 | generics, | |
296 | opt_explicit_self, | |
297 | hir::Inherited)); | |
e9174d1e SL |
298 | try!(s.end()); // Close the head box |
299 | s.end() // Close the outer box | |
300 | }) | |
301 | } | |
302 | ||
303 | pub fn block_to_string(blk: &hir::Block) -> String { | |
304 | to_string(|s| { | |
305 | // containing cbox, will be closed by print-block at } | |
306 | try!(s.cbox(indent_unit)); | |
307 | // head-ibox, will be closed by print-block after { | |
308 | try!(s.ibox(0)); | |
309 | s.print_block(blk) | |
310 | }) | |
311 | } | |
312 | ||
e9174d1e SL |
313 | pub fn explicit_self_to_string(explicit_self: &hir::ExplicitSelf_) -> String { |
314 | to_string(|s| s.print_explicit_self(explicit_self, hir::MutImmutable).map(|_| {})) | |
315 | } | |
316 | ||
317 | pub fn variant_to_string(var: &hir::Variant) -> String { | |
318 | to_string(|s| s.print_variant(var)) | |
319 | } | |
320 | ||
321 | pub fn arg_to_string(arg: &hir::Arg) -> String { | |
7453a54e | 322 | to_string(|s| s.print_arg(arg, false)) |
e9174d1e SL |
323 | } |
324 | ||
325 | pub fn visibility_qualified(vis: hir::Visibility, s: &str) -> String { | |
326 | match vis { | |
327 | hir::Public => format!("pub {}", s), | |
b039eaaf | 328 | hir::Inherited => s.to_string(), |
e9174d1e SL |
329 | } |
330 | } | |
331 | ||
332 | fn needs_parentheses(expr: &hir::Expr) -> bool { | |
333 | match expr.node { | |
b039eaaf SL |
334 | hir::ExprAssign(..) | |
335 | hir::ExprBinary(..) | | |
e9174d1e | 336 | hir::ExprClosure(..) | |
b039eaaf | 337 | hir::ExprAssignOp(..) | |
9cc50fc6 SL |
338 | hir::ExprCast(..) | |
339 | hir::ExprType(..) => true, | |
e9174d1e SL |
340 | _ => false, |
341 | } | |
342 | } | |
343 | ||
344 | impl<'a> State<'a> { | |
e9174d1e SL |
345 | pub fn cbox(&mut self, u: usize) -> io::Result<()> { |
346 | self.boxes.push(pp::Breaks::Consistent); | |
347 | pp::cbox(&mut self.s, u) | |
348 | } | |
349 | ||
b039eaaf SL |
350 | pub fn nbsp(&mut self) -> io::Result<()> { |
351 | word(&mut self.s, " ") | |
e9174d1e SL |
352 | } |
353 | ||
e9174d1e SL |
354 | pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> { |
355 | try!(word(&mut self.s, w)); | |
356 | self.nbsp() | |
357 | } | |
358 | ||
e9174d1e SL |
359 | pub fn head(&mut self, w: &str) -> io::Result<()> { |
360 | // outer-box is consistent | |
361 | try!(self.cbox(indent_unit)); | |
362 | // head-box is inconsistent | |
363 | try!(self.ibox(w.len() + 1)); | |
364 | // keyword that starts the head | |
365 | if !w.is_empty() { | |
366 | try!(self.word_nbsp(w)); | |
367 | } | |
368 | Ok(()) | |
369 | } | |
370 | ||
371 | pub fn bopen(&mut self) -> io::Result<()> { | |
372 | try!(word(&mut self.s, "{")); | |
373 | self.end() // close the head-box | |
374 | } | |
375 | ||
b039eaaf | 376 | pub fn bclose_(&mut self, span: codemap::Span, indented: usize) -> io::Result<()> { |
e9174d1e SL |
377 | self.bclose_maybe_open(span, indented, true) |
378 | } | |
b039eaaf SL |
379 | pub fn bclose_maybe_open(&mut self, |
380 | span: codemap::Span, | |
381 | indented: usize, | |
382 | close_box: bool) | |
383 | -> io::Result<()> { | |
e9174d1e SL |
384 | try!(self.maybe_print_comment(span.hi)); |
385 | try!(self.break_offset_if_not_bol(1, -(indented as isize))); | |
386 | try!(word(&mut self.s, "}")); | |
387 | if close_box { | |
388 | try!(self.end()); // close the outer-box | |
389 | } | |
390 | Ok(()) | |
391 | } | |
392 | pub fn bclose(&mut self, span: codemap::Span) -> io::Result<()> { | |
393 | self.bclose_(span, indent_unit) | |
394 | } | |
395 | ||
e9174d1e SL |
396 | pub fn in_cbox(&self) -> bool { |
397 | match self.boxes.last() { | |
398 | Some(&last_box) => last_box == pp::Breaks::Consistent, | |
b039eaaf | 399 | None => false, |
e9174d1e SL |
400 | } |
401 | } | |
b039eaaf | 402 | pub fn space_if_not_bol(&mut self) -> io::Result<()> { |
e9174d1e | 403 | if !self.is_bol() { |
b039eaaf | 404 | try!(space(&mut self.s)); |
e9174d1e SL |
405 | } |
406 | Ok(()) | |
407 | } | |
b039eaaf | 408 | pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) -> io::Result<()> { |
e9174d1e SL |
409 | if !self.is_bol() { |
410 | break_offset(&mut self.s, n, off) | |
411 | } else { | |
412 | if off != 0 && self.s.last_token().is_hardbreak_tok() { | |
413 | // We do something pretty sketchy here: tuck the nonzero | |
414 | // offset-adjustment we were going to deposit along with the | |
415 | // break into the previous hardbreak. | |
416 | self.s.replace_last_token(pp::hardbreak_tok_offset(off)); | |
417 | } | |
418 | Ok(()) | |
419 | } | |
420 | } | |
421 | ||
422 | // Synthesizes a comment that was not textually present in the original source | |
423 | // file. | |
424 | pub fn synth_comment(&mut self, text: String) -> io::Result<()> { | |
425 | try!(word(&mut self.s, "/*")); | |
426 | try!(space(&mut self.s)); | |
427 | try!(word(&mut self.s, &text[..])); | |
428 | try!(space(&mut self.s)); | |
429 | word(&mut self.s, "*/") | |
430 | } | |
431 | ||
e9174d1e SL |
432 | |
433 | pub fn commasep_cmnt<T, F, G>(&mut self, | |
434 | b: Breaks, | |
435 | elts: &[T], | |
436 | mut op: F, | |
b039eaaf SL |
437 | mut get_span: G) |
438 | -> io::Result<()> | |
439 | where F: FnMut(&mut State, &T) -> io::Result<()>, | |
440 | G: FnMut(&T) -> codemap::Span | |
e9174d1e SL |
441 | { |
442 | try!(self.rbox(0, b)); | |
443 | let len = elts.len(); | |
444 | let mut i = 0; | |
445 | for elt in elts { | |
446 | try!(self.maybe_print_comment(get_span(elt).hi)); | |
447 | try!(op(self, elt)); | |
448 | i += 1; | |
449 | if i < len { | |
450 | try!(word(&mut self.s, ",")); | |
b039eaaf | 451 | try!(self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi))); |
e9174d1e SL |
452 | try!(self.space_if_not_bol()); |
453 | } | |
454 | } | |
455 | self.end() | |
456 | } | |
457 | ||
b039eaaf | 458 | pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<hir::Expr>]) -> io::Result<()> { |
7453a54e | 459 | self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span) |
e9174d1e SL |
460 | } |
461 | ||
b039eaaf | 462 | pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> { |
e9174d1e | 463 | try!(self.print_inner_attributes(attrs)); |
92a42be0 SL |
464 | for item_id in &_mod.item_ids { |
465 | try!(self.print_item_id(item_id)); | |
e9174d1e SL |
466 | } |
467 | Ok(()) | |
468 | } | |
469 | ||
b039eaaf SL |
470 | pub fn print_foreign_mod(&mut self, |
471 | nmod: &hir::ForeignMod, | |
472 | attrs: &[ast::Attribute]) | |
473 | -> io::Result<()> { | |
e9174d1e SL |
474 | try!(self.print_inner_attributes(attrs)); |
475 | for item in &nmod.items { | |
92a42be0 | 476 | try!(self.print_foreign_item(item)); |
e9174d1e SL |
477 | } |
478 | Ok(()) | |
479 | } | |
480 | ||
b039eaaf | 481 | pub fn print_opt_lifetime(&mut self, lifetime: &Option<hir::Lifetime>) -> io::Result<()> { |
e9174d1e SL |
482 | if let Some(l) = *lifetime { |
483 | try!(self.print_lifetime(&l)); | |
484 | try!(self.nbsp()); | |
485 | } | |
486 | Ok(()) | |
487 | } | |
488 | ||
489 | pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> { | |
490 | try!(self.maybe_print_comment(ty.span.lo)); | |
491 | try!(self.ibox(0)); | |
492 | match ty.node { | |
493 | hir::TyVec(ref ty) => { | |
494 | try!(word(&mut self.s, "[")); | |
7453a54e | 495 | try!(self.print_type(&ty)); |
e9174d1e SL |
496 | try!(word(&mut self.s, "]")); |
497 | } | |
498 | hir::TyPtr(ref mt) => { | |
499 | try!(word(&mut self.s, "*")); | |
500 | match mt.mutbl { | |
501 | hir::MutMutable => try!(self.word_nbsp("mut")), | |
502 | hir::MutImmutable => try!(self.word_nbsp("const")), | |
503 | } | |
7453a54e | 504 | try!(self.print_type(&mt.ty)); |
e9174d1e SL |
505 | } |
506 | hir::TyRptr(ref lifetime, ref mt) => { | |
507 | try!(word(&mut self.s, "&")); | |
508 | try!(self.print_opt_lifetime(lifetime)); | |
509 | try!(self.print_mt(mt)); | |
510 | } | |
511 | hir::TyTup(ref elts) => { | |
512 | try!(self.popen()); | |
7453a54e | 513 | try!(self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(&ty))); |
e9174d1e SL |
514 | if elts.len() == 1 { |
515 | try!(word(&mut self.s, ",")); | |
516 | } | |
517 | try!(self.pclose()); | |
518 | } | |
e9174d1e SL |
519 | hir::TyBareFn(ref f) => { |
520 | let generics = hir::Generics { | |
521 | lifetimes: f.lifetimes.clone(), | |
9cc50fc6 | 522 | ty_params: hir::HirVec::new(), |
e9174d1e SL |
523 | where_clause: hir::WhereClause { |
524 | id: ast::DUMMY_NODE_ID, | |
9cc50fc6 | 525 | predicates: hir::HirVec::new(), |
e9174d1e SL |
526 | }, |
527 | }; | |
7453a54e | 528 | try!(self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &generics, None)); |
e9174d1e SL |
529 | } |
530 | hir::TyPath(None, ref path) => { | |
531 | try!(self.print_path(path, false, 0)); | |
532 | } | |
533 | hir::TyPath(Some(ref qself), ref path) => { | |
534 | try!(self.print_qpath(path, qself, false)) | |
535 | } | |
536 | hir::TyObjectSum(ref ty, ref bounds) => { | |
7453a54e | 537 | try!(self.print_type(&ty)); |
e9174d1e SL |
538 | try!(self.print_bounds("+", &bounds[..])); |
539 | } | |
540 | hir::TyPolyTraitRef(ref bounds) => { | |
541 | try!(self.print_bounds("", &bounds[..])); | |
542 | } | |
543 | hir::TyFixedLengthVec(ref ty, ref v) => { | |
544 | try!(word(&mut self.s, "[")); | |
7453a54e | 545 | try!(self.print_type(&ty)); |
e9174d1e | 546 | try!(word(&mut self.s, "; ")); |
7453a54e | 547 | try!(self.print_expr(&v)); |
e9174d1e SL |
548 | try!(word(&mut self.s, "]")); |
549 | } | |
550 | hir::TyTypeof(ref e) => { | |
551 | try!(word(&mut self.s, "typeof(")); | |
7453a54e | 552 | try!(self.print_expr(&e)); |
e9174d1e SL |
553 | try!(word(&mut self.s, ")")); |
554 | } | |
555 | hir::TyInfer => { | |
556 | try!(word(&mut self.s, "_")); | |
557 | } | |
558 | } | |
559 | self.end() | |
560 | } | |
561 | ||
b039eaaf | 562 | pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) -> io::Result<()> { |
e9174d1e SL |
563 | try!(self.hardbreak_if_not_bol()); |
564 | try!(self.maybe_print_comment(item.span.lo)); | |
565 | try!(self.print_outer_attributes(&item.attrs)); | |
566 | match item.node { | |
567 | hir::ForeignItemFn(ref decl, ref generics) => { | |
568 | try!(self.head("")); | |
b039eaaf SL |
569 | try!(self.print_fn(decl, |
570 | hir::Unsafety::Normal, | |
e9174d1e | 571 | hir::Constness::NotConst, |
7453a54e | 572 | Abi::Rust, |
b039eaaf SL |
573 | Some(item.name), |
574 | generics, | |
575 | None, | |
576 | item.vis)); | |
e9174d1e SL |
577 | try!(self.end()); // end head-ibox |
578 | try!(word(&mut self.s, ";")); | |
579 | self.end() // end the outer fn box | |
580 | } | |
581 | hir::ForeignItemStatic(ref t, m) => { | |
b039eaaf | 582 | try!(self.head(&visibility_qualified(item.vis, "static"))); |
e9174d1e SL |
583 | if m { |
584 | try!(self.word_space("mut")); | |
585 | } | |
b039eaaf | 586 | try!(self.print_name(item.name)); |
e9174d1e | 587 | try!(self.word_space(":")); |
7453a54e | 588 | try!(self.print_type(&t)); |
e9174d1e SL |
589 | try!(word(&mut self.s, ";")); |
590 | try!(self.end()); // end the head-ibox | |
591 | self.end() // end the outer cbox | |
592 | } | |
593 | } | |
594 | } | |
595 | ||
596 | fn print_associated_const(&mut self, | |
b039eaaf | 597 | name: ast::Name, |
e9174d1e SL |
598 | ty: &hir::Ty, |
599 | default: Option<&hir::Expr>, | |
600 | vis: hir::Visibility) | |
b039eaaf | 601 | -> io::Result<()> { |
e9174d1e SL |
602 | try!(word(&mut self.s, &visibility_qualified(vis, ""))); |
603 | try!(self.word_space("const")); | |
b039eaaf | 604 | try!(self.print_name(name)); |
e9174d1e SL |
605 | try!(self.word_space(":")); |
606 | try!(self.print_type(ty)); | |
607 | if let Some(expr) = default { | |
608 | try!(space(&mut self.s)); | |
609 | try!(self.word_space("=")); | |
610 | try!(self.print_expr(expr)); | |
611 | } | |
612 | word(&mut self.s, ";") | |
613 | } | |
614 | ||
615 | fn print_associated_type(&mut self, | |
b039eaaf | 616 | name: ast::Name, |
e9174d1e SL |
617 | bounds: Option<&hir::TyParamBounds>, |
618 | ty: Option<&hir::Ty>) | |
619 | -> io::Result<()> { | |
620 | try!(self.word_space("type")); | |
b039eaaf | 621 | try!(self.print_name(name)); |
e9174d1e SL |
622 | if let Some(bounds) = bounds { |
623 | try!(self.print_bounds(":", bounds)); | |
624 | } | |
625 | if let Some(ty) = ty { | |
626 | try!(space(&mut self.s)); | |
627 | try!(self.word_space("=")); | |
628 | try!(self.print_type(ty)); | |
629 | } | |
630 | word(&mut self.s, ";") | |
631 | } | |
632 | ||
92a42be0 SL |
633 | pub fn print_item_id(&mut self, item_id: &hir::ItemId) -> io::Result<()> { |
634 | if let Some(krate) = self.krate { | |
635 | // skip nested items if krate context was not provided | |
636 | let item = &krate.items[&item_id.id]; | |
637 | self.print_item(item) | |
638 | } else { | |
639 | Ok(()) | |
640 | } | |
641 | } | |
642 | ||
e9174d1e SL |
643 | /// Pretty-print an item |
644 | pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> { | |
645 | try!(self.hardbreak_if_not_bol()); | |
646 | try!(self.maybe_print_comment(item.span.lo)); | |
647 | try!(self.print_outer_attributes(&item.attrs)); | |
648 | try!(self.ann.pre(self, NodeItem(item))); | |
649 | match item.node { | |
650 | hir::ItemExternCrate(ref optional_path) => { | |
b039eaaf | 651 | try!(self.head(&visibility_qualified(item.vis, "extern crate"))); |
e9174d1e SL |
652 | if let Some(p) = *optional_path { |
653 | let val = p.as_str(); | |
654 | if val.contains("-") { | |
7453a54e | 655 | try!(self.print_string(&val, ast::StrStyle::Cooked)); |
e9174d1e SL |
656 | } else { |
657 | try!(self.print_name(p)); | |
658 | } | |
659 | try!(space(&mut self.s)); | |
660 | try!(word(&mut self.s, "as")); | |
661 | try!(space(&mut self.s)); | |
662 | } | |
b039eaaf | 663 | try!(self.print_name(item.name)); |
e9174d1e SL |
664 | try!(word(&mut self.s, ";")); |
665 | try!(self.end()); // end inner head-block | |
666 | try!(self.end()); // end outer head-block | |
667 | } | |
668 | hir::ItemUse(ref vp) => { | |
b039eaaf | 669 | try!(self.head(&visibility_qualified(item.vis, "use"))); |
7453a54e | 670 | try!(self.print_view_path(&vp)); |
e9174d1e SL |
671 | try!(word(&mut self.s, ";")); |
672 | try!(self.end()); // end inner head-block | |
673 | try!(self.end()); // end outer head-block | |
674 | } | |
675 | hir::ItemStatic(ref ty, m, ref expr) => { | |
b039eaaf | 676 | try!(self.head(&visibility_qualified(item.vis, "static"))); |
e9174d1e SL |
677 | if m == hir::MutMutable { |
678 | try!(self.word_space("mut")); | |
679 | } | |
b039eaaf | 680 | try!(self.print_name(item.name)); |
e9174d1e | 681 | try!(self.word_space(":")); |
7453a54e | 682 | try!(self.print_type(&ty)); |
e9174d1e SL |
683 | try!(space(&mut self.s)); |
684 | try!(self.end()); // end the head-ibox | |
685 | ||
686 | try!(self.word_space("=")); | |
7453a54e | 687 | try!(self.print_expr(&expr)); |
e9174d1e SL |
688 | try!(word(&mut self.s, ";")); |
689 | try!(self.end()); // end the outer cbox | |
690 | } | |
691 | hir::ItemConst(ref ty, ref expr) => { | |
b039eaaf SL |
692 | try!(self.head(&visibility_qualified(item.vis, "const"))); |
693 | try!(self.print_name(item.name)); | |
e9174d1e | 694 | try!(self.word_space(":")); |
7453a54e | 695 | try!(self.print_type(&ty)); |
e9174d1e SL |
696 | try!(space(&mut self.s)); |
697 | try!(self.end()); // end the head-ibox | |
698 | ||
699 | try!(self.word_space("=")); | |
7453a54e | 700 | try!(self.print_expr(&expr)); |
e9174d1e SL |
701 | try!(word(&mut self.s, ";")); |
702 | try!(self.end()); // end the outer cbox | |
703 | } | |
704 | hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, ref body) => { | |
705 | try!(self.head("")); | |
b039eaaf SL |
706 | try!(self.print_fn(decl, |
707 | unsafety, | |
708 | constness, | |
709 | abi, | |
710 | Some(item.name), | |
711 | typarams, | |
712 | None, | |
713 | item.vis)); | |
e9174d1e | 714 | try!(word(&mut self.s, " ")); |
7453a54e | 715 | try!(self.print_block_with_attrs(&body, &item.attrs)); |
e9174d1e SL |
716 | } |
717 | hir::ItemMod(ref _mod) => { | |
b039eaaf SL |
718 | try!(self.head(&visibility_qualified(item.vis, "mod"))); |
719 | try!(self.print_name(item.name)); | |
e9174d1e SL |
720 | try!(self.nbsp()); |
721 | try!(self.bopen()); | |
722 | try!(self.print_mod(_mod, &item.attrs)); | |
723 | try!(self.bclose(item.span)); | |
724 | } | |
725 | hir::ItemForeignMod(ref nmod) => { | |
726 | try!(self.head("extern")); | |
727 | try!(self.word_nbsp(&nmod.abi.to_string())); | |
728 | try!(self.bopen()); | |
729 | try!(self.print_foreign_mod(nmod, &item.attrs)); | |
730 | try!(self.bclose(item.span)); | |
731 | } | |
732 | hir::ItemTy(ref ty, ref params) => { | |
733 | try!(self.ibox(indent_unit)); | |
734 | try!(self.ibox(0)); | |
735 | try!(self.word_nbsp(&visibility_qualified(item.vis, "type"))); | |
b039eaaf | 736 | try!(self.print_name(item.name)); |
e9174d1e SL |
737 | try!(self.print_generics(params)); |
738 | try!(self.end()); // end the inner ibox | |
739 | ||
740 | try!(self.print_where_clause(¶ms.where_clause)); | |
741 | try!(space(&mut self.s)); | |
742 | try!(self.word_space("=")); | |
7453a54e | 743 | try!(self.print_type(&ty)); |
e9174d1e SL |
744 | try!(word(&mut self.s, ";")); |
745 | try!(self.end()); // end the outer ibox | |
746 | } | |
747 | hir::ItemEnum(ref enum_definition, ref params) => { | |
b039eaaf | 748 | try!(self.print_enum_def(enum_definition, params, item.name, item.span, item.vis)); |
e9174d1e SL |
749 | } |
750 | hir::ItemStruct(ref struct_def, ref generics) => { | |
b039eaaf SL |
751 | try!(self.head(&visibility_qualified(item.vis, "struct"))); |
752 | try!(self.print_struct(struct_def, generics, item.name, item.span, true)); | |
e9174d1e SL |
753 | } |
754 | ||
755 | hir::ItemDefaultImpl(unsafety, ref trait_ref) => { | |
756 | try!(self.head("")); | |
757 | try!(self.print_visibility(item.vis)); | |
758 | try!(self.print_unsafety(unsafety)); | |
759 | try!(self.word_nbsp("impl")); | |
760 | try!(self.print_trait_ref(trait_ref)); | |
761 | try!(space(&mut self.s)); | |
762 | try!(self.word_space("for")); | |
763 | try!(self.word_space("..")); | |
764 | try!(self.bopen()); | |
765 | try!(self.bclose(item.span)); | |
766 | } | |
767 | hir::ItemImpl(unsafety, | |
768 | polarity, | |
769 | ref generics, | |
770 | ref opt_trait, | |
771 | ref ty, | |
772 | ref impl_items) => { | |
773 | try!(self.head("")); | |
774 | try!(self.print_visibility(item.vis)); | |
775 | try!(self.print_unsafety(unsafety)); | |
776 | try!(self.word_nbsp("impl")); | |
777 | ||
778 | if generics.is_parameterized() { | |
779 | try!(self.print_generics(generics)); | |
780 | try!(space(&mut self.s)); | |
781 | } | |
782 | ||
783 | match polarity { | |
784 | hir::ImplPolarity::Negative => { | |
785 | try!(word(&mut self.s, "!")); | |
b039eaaf | 786 | } |
e9174d1e SL |
787 | _ => {} |
788 | } | |
789 | ||
790 | match opt_trait { | |
791 | &Some(ref t) => { | |
792 | try!(self.print_trait_ref(t)); | |
793 | try!(space(&mut self.s)); | |
794 | try!(self.word_space("for")); | |
795 | } | |
796 | &None => {} | |
797 | } | |
798 | ||
7453a54e | 799 | try!(self.print_type(&ty)); |
e9174d1e SL |
800 | try!(self.print_where_clause(&generics.where_clause)); |
801 | ||
802 | try!(space(&mut self.s)); | |
803 | try!(self.bopen()); | |
804 | try!(self.print_inner_attributes(&item.attrs)); | |
805 | for impl_item in impl_items { | |
806 | try!(self.print_impl_item(impl_item)); | |
807 | } | |
808 | try!(self.bclose(item.span)); | |
809 | } | |
810 | hir::ItemTrait(unsafety, ref generics, ref bounds, ref trait_items) => { | |
811 | try!(self.head("")); | |
812 | try!(self.print_visibility(item.vis)); | |
813 | try!(self.print_unsafety(unsafety)); | |
814 | try!(self.word_nbsp("trait")); | |
b039eaaf | 815 | try!(self.print_name(item.name)); |
e9174d1e SL |
816 | try!(self.print_generics(generics)); |
817 | let mut real_bounds = Vec::with_capacity(bounds.len()); | |
818 | for b in bounds.iter() { | |
819 | if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b { | |
820 | try!(space(&mut self.s)); | |
821 | try!(self.word_space("for ?")); | |
822 | try!(self.print_trait_ref(&ptr.trait_ref)); | |
823 | } else { | |
824 | real_bounds.push(b.clone()); | |
825 | } | |
826 | } | |
827 | try!(self.print_bounds(":", &real_bounds[..])); | |
828 | try!(self.print_where_clause(&generics.where_clause)); | |
829 | try!(word(&mut self.s, " ")); | |
830 | try!(self.bopen()); | |
831 | for trait_item in trait_items { | |
832 | try!(self.print_trait_item(trait_item)); | |
833 | } | |
834 | try!(self.bclose(item.span)); | |
835 | } | |
836 | } | |
837 | self.ann.post(self, NodeItem(item)) | |
838 | } | |
839 | ||
840 | fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> { | |
841 | self.print_path(&t.path, false, 0) | |
842 | } | |
843 | ||
844 | fn print_formal_lifetime_list(&mut self, lifetimes: &[hir::LifetimeDef]) -> io::Result<()> { | |
845 | if !lifetimes.is_empty() { | |
846 | try!(word(&mut self.s, "for<")); | |
847 | let mut comma = false; | |
848 | for lifetime_def in lifetimes { | |
849 | if comma { | |
850 | try!(self.word_space(",")) | |
851 | } | |
852 | try!(self.print_lifetime_def(lifetime_def)); | |
853 | comma = true; | |
854 | } | |
855 | try!(word(&mut self.s, ">")); | |
856 | } | |
857 | Ok(()) | |
858 | } | |
859 | ||
860 | fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef) -> io::Result<()> { | |
861 | try!(self.print_formal_lifetime_list(&t.bound_lifetimes)); | |
862 | self.print_trait_ref(&t.trait_ref) | |
863 | } | |
864 | ||
b039eaaf SL |
865 | pub fn print_enum_def(&mut self, |
866 | enum_definition: &hir::EnumDef, | |
867 | generics: &hir::Generics, | |
868 | name: ast::Name, | |
e9174d1e | 869 | span: codemap::Span, |
b039eaaf SL |
870 | visibility: hir::Visibility) |
871 | -> io::Result<()> { | |
e9174d1e | 872 | try!(self.head(&visibility_qualified(visibility, "enum"))); |
b039eaaf | 873 | try!(self.print_name(name)); |
e9174d1e SL |
874 | try!(self.print_generics(generics)); |
875 | try!(self.print_where_clause(&generics.where_clause)); | |
876 | try!(space(&mut self.s)); | |
877 | self.print_variants(&enum_definition.variants, span) | |
878 | } | |
879 | ||
880 | pub fn print_variants(&mut self, | |
92a42be0 | 881 | variants: &[hir::Variant], |
b039eaaf SL |
882 | span: codemap::Span) |
883 | -> io::Result<()> { | |
e9174d1e SL |
884 | try!(self.bopen()); |
885 | for v in variants { | |
886 | try!(self.space_if_not_bol()); | |
887 | try!(self.maybe_print_comment(v.span.lo)); | |
888 | try!(self.print_outer_attributes(&v.node.attrs)); | |
889 | try!(self.ibox(indent_unit)); | |
92a42be0 | 890 | try!(self.print_variant(v)); |
e9174d1e SL |
891 | try!(word(&mut self.s, ",")); |
892 | try!(self.end()); | |
893 | try!(self.maybe_print_trailing_comment(v.span, None)); | |
894 | } | |
895 | self.bclose(span) | |
896 | } | |
897 | ||
898 | pub fn print_visibility(&mut self, vis: hir::Visibility) -> io::Result<()> { | |
899 | match vis { | |
900 | hir::Public => self.word_nbsp("pub"), | |
b039eaaf | 901 | hir::Inherited => Ok(()), |
e9174d1e SL |
902 | } |
903 | } | |
904 | ||
905 | pub fn print_struct(&mut self, | |
b039eaaf | 906 | struct_def: &hir::VariantData, |
e9174d1e | 907 | generics: &hir::Generics, |
b039eaaf SL |
908 | name: ast::Name, |
909 | span: codemap::Span, | |
910 | print_finalizer: bool) | |
911 | -> io::Result<()> { | |
912 | try!(self.print_name(name)); | |
e9174d1e | 913 | try!(self.print_generics(generics)); |
b039eaaf SL |
914 | if !struct_def.is_struct() { |
915 | if struct_def.is_tuple() { | |
e9174d1e | 916 | try!(self.popen()); |
92a42be0 SL |
917 | try!(self.commasep(Inconsistent, struct_def.fields(), |s, field| { |
918 | match field.node.kind { | |
919 | hir::NamedField(..) => panic!("unexpected named field"), | |
920 | hir::UnnamedField(vis) => { | |
921 | try!(s.print_visibility(vis)); | |
922 | try!(s.maybe_print_comment(field.span.lo)); | |
7453a54e | 923 | s.print_type(&field.node.ty) |
92a42be0 SL |
924 | } |
925 | } | |
926 | })); | |
e9174d1e SL |
927 | try!(self.pclose()); |
928 | } | |
929 | try!(self.print_where_clause(&generics.where_clause)); | |
b039eaaf SL |
930 | if print_finalizer { |
931 | try!(word(&mut self.s, ";")); | |
932 | } | |
e9174d1e SL |
933 | try!(self.end()); |
934 | self.end() // close the outer-box | |
935 | } else { | |
936 | try!(self.print_where_clause(&generics.where_clause)); | |
937 | try!(self.nbsp()); | |
938 | try!(self.bopen()); | |
939 | try!(self.hardbreak_if_not_bol()); | |
940 | ||
b039eaaf | 941 | for field in struct_def.fields() { |
e9174d1e SL |
942 | match field.node.kind { |
943 | hir::UnnamedField(..) => panic!("unexpected unnamed field"), | |
b039eaaf | 944 | hir::NamedField(name, visibility) => { |
e9174d1e SL |
945 | try!(self.hardbreak_if_not_bol()); |
946 | try!(self.maybe_print_comment(field.span.lo)); | |
947 | try!(self.print_outer_attributes(&field.node.attrs)); | |
948 | try!(self.print_visibility(visibility)); | |
b039eaaf | 949 | try!(self.print_name(name)); |
e9174d1e | 950 | try!(self.word_nbsp(":")); |
7453a54e | 951 | try!(self.print_type(&field.node.ty)); |
e9174d1e SL |
952 | try!(word(&mut self.s, ",")); |
953 | } | |
954 | } | |
955 | } | |
956 | ||
957 | self.bclose(span) | |
958 | } | |
959 | } | |
960 | ||
961 | pub fn print_variant(&mut self, v: &hir::Variant) -> io::Result<()> { | |
b039eaaf SL |
962 | try!(self.head("")); |
963 | let generics = ::util::empty_generics(); | |
964 | try!(self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)); | |
e9174d1e SL |
965 | match v.node.disr_expr { |
966 | Some(ref d) => { | |
967 | try!(space(&mut self.s)); | |
968 | try!(self.word_space("=")); | |
7453a54e | 969 | self.print_expr(&d) |
e9174d1e | 970 | } |
b039eaaf | 971 | _ => Ok(()), |
e9174d1e SL |
972 | } |
973 | } | |
e9174d1e | 974 | pub fn print_method_sig(&mut self, |
b039eaaf | 975 | name: ast::Name, |
e9174d1e SL |
976 | m: &hir::MethodSig, |
977 | vis: hir::Visibility) | |
978 | -> io::Result<()> { | |
979 | self.print_fn(&m.decl, | |
980 | m.unsafety, | |
981 | m.constness, | |
982 | m.abi, | |
b039eaaf | 983 | Some(name), |
e9174d1e SL |
984 | &m.generics, |
985 | Some(&m.explicit_self.node), | |
986 | vis) | |
987 | } | |
988 | ||
b039eaaf | 989 | pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> { |
e9174d1e SL |
990 | try!(self.ann.pre(self, NodeSubItem(ti.id))); |
991 | try!(self.hardbreak_if_not_bol()); | |
992 | try!(self.maybe_print_comment(ti.span.lo)); | |
993 | try!(self.print_outer_attributes(&ti.attrs)); | |
994 | match ti.node { | |
995 | hir::ConstTraitItem(ref ty, ref default) => { | |
b039eaaf SL |
996 | try!(self.print_associated_const(ti.name, |
997 | &ty, | |
e9174d1e SL |
998 | default.as_ref().map(|expr| &**expr), |
999 | hir::Inherited)); | |
1000 | } | |
1001 | hir::MethodTraitItem(ref sig, ref body) => { | |
1002 | if body.is_some() { | |
1003 | try!(self.head("")); | |
1004 | } | |
b039eaaf | 1005 | try!(self.print_method_sig(ti.name, sig, hir::Inherited)); |
e9174d1e SL |
1006 | if let Some(ref body) = *body { |
1007 | try!(self.nbsp()); | |
1008 | try!(self.print_block_with_attrs(body, &ti.attrs)); | |
1009 | } else { | |
1010 | try!(word(&mut self.s, ";")); | |
1011 | } | |
1012 | } | |
1013 | hir::TypeTraitItem(ref bounds, ref default) => { | |
b039eaaf SL |
1014 | try!(self.print_associated_type(ti.name, |
1015 | Some(bounds), | |
e9174d1e SL |
1016 | default.as_ref().map(|ty| &**ty))); |
1017 | } | |
1018 | } | |
1019 | self.ann.post(self, NodeSubItem(ti.id)) | |
1020 | } | |
1021 | ||
1022 | pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> { | |
1023 | try!(self.ann.pre(self, NodeSubItem(ii.id))); | |
1024 | try!(self.hardbreak_if_not_bol()); | |
1025 | try!(self.maybe_print_comment(ii.span.lo)); | |
1026 | try!(self.print_outer_attributes(&ii.attrs)); | |
1027 | match ii.node { | |
92a42be0 | 1028 | hir::ImplItemKind::Const(ref ty, ref expr) => { |
b039eaaf | 1029 | try!(self.print_associated_const(ii.name, &ty, Some(&expr), ii.vis)); |
e9174d1e | 1030 | } |
92a42be0 | 1031 | hir::ImplItemKind::Method(ref sig, ref body) => { |
e9174d1e | 1032 | try!(self.head("")); |
b039eaaf | 1033 | try!(self.print_method_sig(ii.name, sig, ii.vis)); |
e9174d1e SL |
1034 | try!(self.nbsp()); |
1035 | try!(self.print_block_with_attrs(body, &ii.attrs)); | |
1036 | } | |
92a42be0 | 1037 | hir::ImplItemKind::Type(ref ty) => { |
b039eaaf | 1038 | try!(self.print_associated_type(ii.name, None, Some(ty))); |
e9174d1e SL |
1039 | } |
1040 | } | |
1041 | self.ann.post(self, NodeSubItem(ii.id)) | |
1042 | } | |
1043 | ||
e9174d1e SL |
1044 | pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> { |
1045 | try!(self.maybe_print_comment(st.span.lo)); | |
1046 | match st.node { | |
1047 | hir::StmtDecl(ref decl, _) => { | |
7453a54e | 1048 | try!(self.print_decl(&decl)); |
e9174d1e SL |
1049 | } |
1050 | hir::StmtExpr(ref expr, _) => { | |
1051 | try!(self.space_if_not_bol()); | |
7453a54e | 1052 | try!(self.print_expr(&expr)); |
e9174d1e SL |
1053 | } |
1054 | hir::StmtSemi(ref expr, _) => { | |
1055 | try!(self.space_if_not_bol()); | |
7453a54e | 1056 | try!(self.print_expr(&expr)); |
e9174d1e SL |
1057 | try!(word(&mut self.s, ";")); |
1058 | } | |
1059 | } | |
1060 | if stmt_ends_with_semi(&st.node) { | |
1061 | try!(word(&mut self.s, ";")); | |
1062 | } | |
1063 | self.maybe_print_trailing_comment(st.span, None) | |
1064 | } | |
1065 | ||
1066 | pub fn print_block(&mut self, blk: &hir::Block) -> io::Result<()> { | |
1067 | self.print_block_with_attrs(blk, &[]) | |
1068 | } | |
1069 | ||
1070 | pub fn print_block_unclosed(&mut self, blk: &hir::Block) -> io::Result<()> { | |
1071 | self.print_block_unclosed_indent(blk, indent_unit) | |
1072 | } | |
1073 | ||
b039eaaf SL |
1074 | pub fn print_block_unclosed_indent(&mut self, |
1075 | blk: &hir::Block, | |
1076 | indented: usize) | |
1077 | -> io::Result<()> { | |
e9174d1e SL |
1078 | self.print_block_maybe_unclosed(blk, indented, &[], false) |
1079 | } | |
1080 | ||
1081 | pub fn print_block_with_attrs(&mut self, | |
1082 | blk: &hir::Block, | |
b039eaaf SL |
1083 | attrs: &[ast::Attribute]) |
1084 | -> io::Result<()> { | |
e9174d1e SL |
1085 | self.print_block_maybe_unclosed(blk, indent_unit, attrs, true) |
1086 | } | |
1087 | ||
1088 | pub fn print_block_maybe_unclosed(&mut self, | |
1089 | blk: &hir::Block, | |
1090 | indented: usize, | |
b039eaaf SL |
1091 | attrs: &[ast::Attribute], |
1092 | close_box: bool) | |
1093 | -> io::Result<()> { | |
e9174d1e | 1094 | match blk.rules { |
b039eaaf SL |
1095 | hir::UnsafeBlock(..) => try!(self.word_space("unsafe")), |
1096 | hir::PushUnsafeBlock(..) => try!(self.word_space("push_unsafe")), | |
1097 | hir::PopUnsafeBlock(..) => try!(self.word_space("pop_unsafe")), | |
1098 | hir::PushUnstableBlock => try!(self.word_space("push_unstable")), | |
1099 | hir::PopUnstableBlock => try!(self.word_space("pop_unstable")), | |
1100 | hir::DefaultBlock => (), | |
e9174d1e SL |
1101 | } |
1102 | try!(self.maybe_print_comment(blk.span.lo)); | |
1103 | try!(self.ann.pre(self, NodeBlock(blk))); | |
1104 | try!(self.bopen()); | |
1105 | ||
1106 | try!(self.print_inner_attributes(attrs)); | |
1107 | ||
1108 | for st in &blk.stmts { | |
92a42be0 | 1109 | try!(self.print_stmt(st)); |
e9174d1e SL |
1110 | } |
1111 | match blk.expr { | |
1112 | Some(ref expr) => { | |
1113 | try!(self.space_if_not_bol()); | |
7453a54e | 1114 | try!(self.print_expr(&expr)); |
e9174d1e SL |
1115 | try!(self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi))); |
1116 | } | |
b039eaaf | 1117 | _ => (), |
e9174d1e SL |
1118 | } |
1119 | try!(self.bclose_maybe_open(blk.span, indented, close_box)); | |
1120 | self.ann.post(self, NodeBlock(blk)) | |
1121 | } | |
1122 | ||
1123 | fn print_else(&mut self, els: Option<&hir::Expr>) -> io::Result<()> { | |
1124 | match els { | |
1125 | Some(_else) => { | |
1126 | match _else.node { | |
1127 | // "another else-if" | |
1128 | hir::ExprIf(ref i, ref then, ref e) => { | |
1129 | try!(self.cbox(indent_unit - 1)); | |
1130 | try!(self.ibox(0)); | |
1131 | try!(word(&mut self.s, " else if ")); | |
7453a54e | 1132 | try!(self.print_expr(&i)); |
e9174d1e | 1133 | try!(space(&mut self.s)); |
7453a54e | 1134 | try!(self.print_block(&then)); |
e9174d1e SL |
1135 | self.print_else(e.as_ref().map(|e| &**e)) |
1136 | } | |
1137 | // "final else" | |
1138 | hir::ExprBlock(ref b) => { | |
1139 | try!(self.cbox(indent_unit - 1)); | |
1140 | try!(self.ibox(0)); | |
1141 | try!(word(&mut self.s, " else ")); | |
7453a54e | 1142 | self.print_block(&b) |
e9174d1e SL |
1143 | } |
1144 | // BLEAH, constraints would be great here | |
1145 | _ => { | |
1146 | panic!("print_if saw if with weird alternative"); | |
1147 | } | |
1148 | } | |
1149 | } | |
b039eaaf | 1150 | _ => Ok(()), |
e9174d1e SL |
1151 | } |
1152 | } | |
1153 | ||
b039eaaf SL |
1154 | pub fn print_if(&mut self, |
1155 | test: &hir::Expr, | |
1156 | blk: &hir::Block, | |
1157 | elseopt: Option<&hir::Expr>) | |
1158 | -> io::Result<()> { | |
e9174d1e SL |
1159 | try!(self.head("if")); |
1160 | try!(self.print_expr(test)); | |
1161 | try!(space(&mut self.s)); | |
1162 | try!(self.print_block(blk)); | |
1163 | self.print_else(elseopt) | |
1164 | } | |
1165 | ||
b039eaaf SL |
1166 | pub fn print_if_let(&mut self, |
1167 | pat: &hir::Pat, | |
1168 | expr: &hir::Expr, | |
1169 | blk: &hir::Block, | |
1170 | elseopt: Option<&hir::Expr>) | |
1171 | -> io::Result<()> { | |
e9174d1e SL |
1172 | try!(self.head("if let")); |
1173 | try!(self.print_pat(pat)); | |
1174 | try!(space(&mut self.s)); | |
1175 | try!(self.word_space("=")); | |
1176 | try!(self.print_expr(expr)); | |
1177 | try!(space(&mut self.s)); | |
1178 | try!(self.print_block(blk)); | |
1179 | self.print_else(elseopt) | |
1180 | } | |
1181 | ||
1182 | ||
1183 | fn print_call_post(&mut self, args: &[P<hir::Expr>]) -> io::Result<()> { | |
1184 | try!(self.popen()); | |
1185 | try!(self.commasep_exprs(Inconsistent, args)); | |
1186 | self.pclose() | |
1187 | } | |
1188 | ||
1189 | pub fn print_expr_maybe_paren(&mut self, expr: &hir::Expr) -> io::Result<()> { | |
1190 | let needs_par = needs_parentheses(expr); | |
1191 | if needs_par { | |
1192 | try!(self.popen()); | |
1193 | } | |
1194 | try!(self.print_expr(expr)); | |
1195 | if needs_par { | |
1196 | try!(self.pclose()); | |
1197 | } | |
1198 | Ok(()) | |
1199 | } | |
1200 | ||
e9174d1e SL |
1201 | fn print_expr_vec(&mut self, exprs: &[P<hir::Expr>]) -> io::Result<()> { |
1202 | try!(self.ibox(indent_unit)); | |
1203 | try!(word(&mut self.s, "[")); | |
1204 | try!(self.commasep_exprs(Inconsistent, &exprs[..])); | |
1205 | try!(word(&mut self.s, "]")); | |
1206 | self.end() | |
1207 | } | |
1208 | ||
b039eaaf | 1209 | fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::Expr) -> io::Result<()> { |
e9174d1e SL |
1210 | try!(self.ibox(indent_unit)); |
1211 | try!(word(&mut self.s, "[")); | |
1212 | try!(self.print_expr(element)); | |
1213 | try!(self.word_space(";")); | |
1214 | try!(self.print_expr(count)); | |
1215 | try!(word(&mut self.s, "]")); | |
1216 | self.end() | |
1217 | } | |
1218 | ||
1219 | fn print_expr_struct(&mut self, | |
1220 | path: &hir::Path, | |
1221 | fields: &[hir::Field], | |
b039eaaf SL |
1222 | wth: &Option<P<hir::Expr>>) |
1223 | -> io::Result<()> { | |
e9174d1e | 1224 | try!(self.print_path(path, true, 0)); |
b039eaaf SL |
1225 | try!(word(&mut self.s, "{")); |
1226 | try!(self.commasep_cmnt(Consistent, | |
1227 | &fields[..], | |
1228 | |s, field| { | |
1229 | try!(s.ibox(indent_unit)); | |
1230 | try!(s.print_name(field.name.node)); | |
1231 | try!(s.word_space(":")); | |
7453a54e | 1232 | try!(s.print_expr(&field.expr)); |
b039eaaf SL |
1233 | s.end() |
1234 | }, | |
1235 | |f| f.span)); | |
1236 | match *wth { | |
1237 | Some(ref expr) => { | |
1238 | try!(self.ibox(indent_unit)); | |
1239 | if !fields.is_empty() { | |
1240 | try!(word(&mut self.s, ",")); | |
1241 | try!(space(&mut self.s)); | |
e9174d1e | 1242 | } |
b039eaaf | 1243 | try!(word(&mut self.s, "..")); |
7453a54e | 1244 | try!(self.print_expr(&expr)); |
b039eaaf | 1245 | try!(self.end()); |
e9174d1e | 1246 | } |
b039eaaf SL |
1247 | _ => if !fields.is_empty() { |
1248 | try!(word(&mut self.s, ",")) | |
1249 | }, | |
e9174d1e | 1250 | } |
b039eaaf | 1251 | try!(word(&mut self.s, "}")); |
e9174d1e SL |
1252 | Ok(()) |
1253 | } | |
1254 | ||
1255 | fn print_expr_tup(&mut self, exprs: &[P<hir::Expr>]) -> io::Result<()> { | |
1256 | try!(self.popen()); | |
1257 | try!(self.commasep_exprs(Inconsistent, &exprs[..])); | |
1258 | if exprs.len() == 1 { | |
1259 | try!(word(&mut self.s, ",")); | |
1260 | } | |
1261 | self.pclose() | |
1262 | } | |
1263 | ||
b039eaaf | 1264 | fn print_expr_call(&mut self, func: &hir::Expr, args: &[P<hir::Expr>]) -> io::Result<()> { |
e9174d1e SL |
1265 | try!(self.print_expr_maybe_paren(func)); |
1266 | self.print_call_post(args) | |
1267 | } | |
1268 | ||
1269 | fn print_expr_method_call(&mut self, | |
b039eaaf | 1270 | name: Spanned<ast::Name>, |
e9174d1e | 1271 | tys: &[P<hir::Ty>], |
b039eaaf SL |
1272 | args: &[P<hir::Expr>]) |
1273 | -> io::Result<()> { | |
e9174d1e | 1274 | let base_args = &args[1..]; |
7453a54e | 1275 | try!(self.print_expr(&args[0])); |
e9174d1e | 1276 | try!(word(&mut self.s, ".")); |
b039eaaf | 1277 | try!(self.print_name(name.node)); |
e9174d1e SL |
1278 | if !tys.is_empty() { |
1279 | try!(word(&mut self.s, "::<")); | |
7453a54e | 1280 | try!(self.commasep(Inconsistent, tys, |s, ty| s.print_type(&ty))); |
e9174d1e SL |
1281 | try!(word(&mut self.s, ">")); |
1282 | } | |
1283 | self.print_call_post(base_args) | |
1284 | } | |
1285 | ||
1286 | fn print_expr_binary(&mut self, | |
1287 | op: hir::BinOp, | |
1288 | lhs: &hir::Expr, | |
b039eaaf SL |
1289 | rhs: &hir::Expr) |
1290 | -> io::Result<()> { | |
e9174d1e SL |
1291 | try!(self.print_expr(lhs)); |
1292 | try!(space(&mut self.s)); | |
1293 | try!(self.word_space(::util::binop_to_string(op.node))); | |
1294 | self.print_expr(rhs) | |
1295 | } | |
1296 | ||
b039eaaf | 1297 | fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr) -> io::Result<()> { |
e9174d1e SL |
1298 | try!(word(&mut self.s, ::util::unop_to_string(op))); |
1299 | self.print_expr_maybe_paren(expr) | |
1300 | } | |
1301 | ||
1302 | fn print_expr_addr_of(&mut self, | |
1303 | mutability: hir::Mutability, | |
b039eaaf SL |
1304 | expr: &hir::Expr) |
1305 | -> io::Result<()> { | |
e9174d1e SL |
1306 | try!(word(&mut self.s, "&")); |
1307 | try!(self.print_mutability(mutability)); | |
1308 | self.print_expr_maybe_paren(expr) | |
1309 | } | |
1310 | ||
1311 | pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> { | |
1312 | try!(self.maybe_print_comment(expr.span.lo)); | |
1313 | try!(self.ibox(indent_unit)); | |
1314 | try!(self.ann.pre(self, NodeExpr(expr))); | |
1315 | match expr.node { | |
b039eaaf SL |
1316 | hir::ExprBox(ref expr) => { |
1317 | try!(self.word_space("box")); | |
1318 | try!(self.print_expr(expr)); | |
e9174d1e SL |
1319 | } |
1320 | hir::ExprVec(ref exprs) => { | |
1321 | try!(self.print_expr_vec(&exprs[..])); | |
1322 | } | |
1323 | hir::ExprRepeat(ref element, ref count) => { | |
7453a54e | 1324 | try!(self.print_expr_repeat(&element, &count)); |
e9174d1e SL |
1325 | } |
1326 | hir::ExprStruct(ref path, ref fields, ref wth) => { | |
1327 | try!(self.print_expr_struct(path, &fields[..], wth)); | |
1328 | } | |
1329 | hir::ExprTup(ref exprs) => { | |
1330 | try!(self.print_expr_tup(&exprs[..])); | |
1331 | } | |
1332 | hir::ExprCall(ref func, ref args) => { | |
7453a54e | 1333 | try!(self.print_expr_call(&func, &args[..])); |
e9174d1e | 1334 | } |
b039eaaf SL |
1335 | hir::ExprMethodCall(name, ref tys, ref args) => { |
1336 | try!(self.print_expr_method_call(name, &tys[..], &args[..])); | |
e9174d1e SL |
1337 | } |
1338 | hir::ExprBinary(op, ref lhs, ref rhs) => { | |
7453a54e | 1339 | try!(self.print_expr_binary(op, &lhs, &rhs)); |
e9174d1e SL |
1340 | } |
1341 | hir::ExprUnary(op, ref expr) => { | |
7453a54e | 1342 | try!(self.print_expr_unary(op, &expr)); |
e9174d1e SL |
1343 | } |
1344 | hir::ExprAddrOf(m, ref expr) => { | |
7453a54e | 1345 | try!(self.print_expr_addr_of(m, &expr)); |
e9174d1e SL |
1346 | } |
1347 | hir::ExprLit(ref lit) => { | |
7453a54e | 1348 | try!(self.print_literal(&lit)); |
e9174d1e SL |
1349 | } |
1350 | hir::ExprCast(ref expr, ref ty) => { | |
7453a54e | 1351 | try!(self.print_expr(&expr)); |
e9174d1e SL |
1352 | try!(space(&mut self.s)); |
1353 | try!(self.word_space("as")); | |
7453a54e | 1354 | try!(self.print_type(&ty)); |
e9174d1e | 1355 | } |
9cc50fc6 | 1356 | hir::ExprType(ref expr, ref ty) => { |
7453a54e | 1357 | try!(self.print_expr(&expr)); |
9cc50fc6 | 1358 | try!(self.word_space(":")); |
7453a54e | 1359 | try!(self.print_type(&ty)); |
9cc50fc6 | 1360 | } |
e9174d1e | 1361 | hir::ExprIf(ref test, ref blk, ref elseopt) => { |
7453a54e | 1362 | try!(self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))); |
e9174d1e SL |
1363 | } |
1364 | hir::ExprWhile(ref test, ref blk, opt_ident) => { | |
1365 | if let Some(ident) = opt_ident { | |
b039eaaf | 1366 | try!(self.print_name(ident.name)); |
e9174d1e SL |
1367 | try!(self.word_space(":")); |
1368 | } | |
1369 | try!(self.head("while")); | |
7453a54e | 1370 | try!(self.print_expr(&test)); |
e9174d1e | 1371 | try!(space(&mut self.s)); |
7453a54e | 1372 | try!(self.print_block(&blk)); |
e9174d1e SL |
1373 | } |
1374 | hir::ExprLoop(ref blk, opt_ident) => { | |
1375 | if let Some(ident) = opt_ident { | |
b039eaaf | 1376 | try!(self.print_name(ident.name)); |
e9174d1e SL |
1377 | try!(self.word_space(":")); |
1378 | } | |
1379 | try!(self.head("loop")); | |
1380 | try!(space(&mut self.s)); | |
7453a54e | 1381 | try!(self.print_block(&blk)); |
e9174d1e SL |
1382 | } |
1383 | hir::ExprMatch(ref expr, ref arms, _) => { | |
1384 | try!(self.cbox(indent_unit)); | |
1385 | try!(self.ibox(4)); | |
1386 | try!(self.word_nbsp("match")); | |
7453a54e | 1387 | try!(self.print_expr(&expr)); |
e9174d1e SL |
1388 | try!(space(&mut self.s)); |
1389 | try!(self.bopen()); | |
1390 | for arm in arms { | |
1391 | try!(self.print_arm(arm)); | |
1392 | } | |
1393 | try!(self.bclose_(expr.span, indent_unit)); | |
1394 | } | |
1395 | hir::ExprClosure(capture_clause, ref decl, ref body) => { | |
1396 | try!(self.print_capture_clause(capture_clause)); | |
1397 | ||
7453a54e | 1398 | try!(self.print_fn_block_args(&decl)); |
e9174d1e SL |
1399 | try!(space(&mut self.s)); |
1400 | ||
1401 | let default_return = match decl.output { | |
1402 | hir::DefaultReturn(..) => true, | |
b039eaaf | 1403 | _ => false, |
e9174d1e SL |
1404 | }; |
1405 | ||
1406 | if !default_return || !body.stmts.is_empty() || body.expr.is_none() { | |
7453a54e | 1407 | try!(self.print_block_unclosed(&body)); |
e9174d1e SL |
1408 | } else { |
1409 | // we extract the block, so as not to create another set of boxes | |
1410 | match body.expr.as_ref().unwrap().node { | |
1411 | hir::ExprBlock(ref blk) => { | |
7453a54e | 1412 | try!(self.print_block_unclosed(&blk)); |
e9174d1e SL |
1413 | } |
1414 | _ => { | |
1415 | // this is a bare expression | |
1416 | try!(self.print_expr(body.expr.as_ref().map(|e| &**e).unwrap())); | |
1417 | try!(self.end()); // need to close a box | |
1418 | } | |
1419 | } | |
1420 | } | |
1421 | // a box will be closed by print_expr, but we didn't want an overall | |
1422 | // wrapper so we closed the corresponding opening. so create an | |
1423 | // empty box to satisfy the close. | |
1424 | try!(self.ibox(0)); | |
1425 | } | |
1426 | hir::ExprBlock(ref blk) => { | |
1427 | // containing cbox, will be closed by print-block at } | |
1428 | try!(self.cbox(indent_unit)); | |
1429 | // head-box, will be closed by print-block after { | |
1430 | try!(self.ibox(0)); | |
7453a54e | 1431 | try!(self.print_block(&blk)); |
e9174d1e SL |
1432 | } |
1433 | hir::ExprAssign(ref lhs, ref rhs) => { | |
7453a54e | 1434 | try!(self.print_expr(&lhs)); |
e9174d1e SL |
1435 | try!(space(&mut self.s)); |
1436 | try!(self.word_space("=")); | |
7453a54e | 1437 | try!(self.print_expr(&rhs)); |
e9174d1e SL |
1438 | } |
1439 | hir::ExprAssignOp(op, ref lhs, ref rhs) => { | |
7453a54e | 1440 | try!(self.print_expr(&lhs)); |
e9174d1e SL |
1441 | try!(space(&mut self.s)); |
1442 | try!(word(&mut self.s, ::util::binop_to_string(op.node))); | |
1443 | try!(self.word_space("=")); | |
7453a54e | 1444 | try!(self.print_expr(&rhs)); |
e9174d1e | 1445 | } |
b039eaaf | 1446 | hir::ExprField(ref expr, name) => { |
7453a54e | 1447 | try!(self.print_expr(&expr)); |
e9174d1e | 1448 | try!(word(&mut self.s, ".")); |
b039eaaf | 1449 | try!(self.print_name(name.node)); |
e9174d1e SL |
1450 | } |
1451 | hir::ExprTupField(ref expr, id) => { | |
7453a54e | 1452 | try!(self.print_expr(&expr)); |
e9174d1e SL |
1453 | try!(word(&mut self.s, ".")); |
1454 | try!(self.print_usize(id.node)); | |
1455 | } | |
1456 | hir::ExprIndex(ref expr, ref index) => { | |
7453a54e | 1457 | try!(self.print_expr(&expr)); |
e9174d1e | 1458 | try!(word(&mut self.s, "[")); |
7453a54e | 1459 | try!(self.print_expr(&index)); |
e9174d1e SL |
1460 | try!(word(&mut self.s, "]")); |
1461 | } | |
1462 | hir::ExprRange(ref start, ref end) => { | |
1463 | if let &Some(ref e) = start { | |
7453a54e | 1464 | try!(self.print_expr(&e)); |
e9174d1e SL |
1465 | } |
1466 | try!(word(&mut self.s, "..")); | |
1467 | if let &Some(ref e) = end { | |
7453a54e | 1468 | try!(self.print_expr(&e)); |
e9174d1e SL |
1469 | } |
1470 | } | |
1471 | hir::ExprPath(None, ref path) => { | |
1472 | try!(self.print_path(path, true, 0)) | |
1473 | } | |
1474 | hir::ExprPath(Some(ref qself), ref path) => { | |
1475 | try!(self.print_qpath(path, qself, true)) | |
1476 | } | |
1477 | hir::ExprBreak(opt_ident) => { | |
1478 | try!(word(&mut self.s, "break")); | |
1479 | try!(space(&mut self.s)); | |
1480 | if let Some(ident) = opt_ident { | |
b039eaaf | 1481 | try!(self.print_name(ident.node.name)); |
e9174d1e SL |
1482 | try!(space(&mut self.s)); |
1483 | } | |
1484 | } | |
1485 | hir::ExprAgain(opt_ident) => { | |
1486 | try!(word(&mut self.s, "continue")); | |
1487 | try!(space(&mut self.s)); | |
1488 | if let Some(ident) = opt_ident { | |
b039eaaf | 1489 | try!(self.print_name(ident.node.name)); |
e9174d1e SL |
1490 | try!(space(&mut self.s)) |
1491 | } | |
1492 | } | |
1493 | hir::ExprRet(ref result) => { | |
1494 | try!(word(&mut self.s, "return")); | |
1495 | match *result { | |
1496 | Some(ref expr) => { | |
1497 | try!(word(&mut self.s, " ")); | |
7453a54e | 1498 | try!(self.print_expr(&expr)); |
e9174d1e | 1499 | } |
b039eaaf | 1500 | _ => (), |
e9174d1e SL |
1501 | } |
1502 | } | |
1503 | hir::ExprInlineAsm(ref a) => { | |
1504 | try!(word(&mut self.s, "asm!")); | |
1505 | try!(self.popen()); | |
1506 | try!(self.print_string(&a.asm, a.asm_str_style)); | |
1507 | try!(self.word_space(":")); | |
1508 | ||
9cc50fc6 SL |
1509 | try!(self.commasep(Inconsistent, &a.outputs, |s, out| { |
1510 | match out.constraint.slice_shift_char() { | |
1511 | Some(('=', operand)) if out.is_rw => { | |
7453a54e | 1512 | try!(s.print_string(&format!("+{}", operand), ast::StrStyle::Cooked)) |
92a42be0 | 1513 | } |
7453a54e | 1514 | _ => try!(s.print_string(&out.constraint, ast::StrStyle::Cooked)), |
92a42be0 SL |
1515 | } |
1516 | try!(s.popen()); | |
7453a54e | 1517 | try!(s.print_expr(&out.expr)); |
92a42be0 SL |
1518 | try!(s.pclose()); |
1519 | Ok(()) | |
1520 | })); | |
e9174d1e SL |
1521 | try!(space(&mut self.s)); |
1522 | try!(self.word_space(":")); | |
1523 | ||
92a42be0 | 1524 | try!(self.commasep(Inconsistent, &a.inputs, |s, &(ref co, ref o)| { |
7453a54e | 1525 | try!(s.print_string(&co, ast::StrStyle::Cooked)); |
92a42be0 | 1526 | try!(s.popen()); |
7453a54e | 1527 | try!(s.print_expr(&o)); |
92a42be0 SL |
1528 | try!(s.pclose()); |
1529 | Ok(()) | |
1530 | })); | |
e9174d1e SL |
1531 | try!(space(&mut self.s)); |
1532 | try!(self.word_space(":")); | |
1533 | ||
92a42be0 | 1534 | try!(self.commasep(Inconsistent, &a.clobbers, |s, co| { |
7453a54e | 1535 | try!(s.print_string(&co, ast::StrStyle::Cooked)); |
92a42be0 SL |
1536 | Ok(()) |
1537 | })); | |
e9174d1e | 1538 | |
92a42be0 | 1539 | let mut options = vec![]; |
e9174d1e SL |
1540 | if a.volatile { |
1541 | options.push("volatile"); | |
1542 | } | |
1543 | if a.alignstack { | |
1544 | options.push("alignstack"); | |
1545 | } | |
b039eaaf | 1546 | if a.dialect == ast::AsmDialect::Intel { |
e9174d1e SL |
1547 | options.push("intel"); |
1548 | } | |
1549 | ||
1550 | if !options.is_empty() { | |
1551 | try!(space(&mut self.s)); | |
1552 | try!(self.word_space(":")); | |
7453a54e SL |
1553 | try!(self.commasep(Inconsistent, &options, |s, &co| { |
1554 | try!(s.print_string(co, ast::StrStyle::Cooked)); | |
92a42be0 SL |
1555 | Ok(()) |
1556 | })); | |
e9174d1e SL |
1557 | } |
1558 | ||
1559 | try!(self.pclose()); | |
1560 | } | |
e9174d1e SL |
1561 | } |
1562 | try!(self.ann.post(self, NodeExpr(expr))); | |
1563 | self.end() | |
1564 | } | |
1565 | ||
1566 | pub fn print_local_decl(&mut self, loc: &hir::Local) -> io::Result<()> { | |
7453a54e | 1567 | try!(self.print_pat(&loc.pat)); |
e9174d1e SL |
1568 | if let Some(ref ty) = loc.ty { |
1569 | try!(self.word_space(":")); | |
7453a54e | 1570 | try!(self.print_type(&ty)); |
e9174d1e SL |
1571 | } |
1572 | Ok(()) | |
1573 | } | |
1574 | ||
1575 | pub fn print_decl(&mut self, decl: &hir::Decl) -> io::Result<()> { | |
1576 | try!(self.maybe_print_comment(decl.span.lo)); | |
1577 | match decl.node { | |
1578 | hir::DeclLocal(ref loc) => { | |
1579 | try!(self.space_if_not_bol()); | |
1580 | try!(self.ibox(indent_unit)); | |
1581 | try!(self.word_nbsp("let")); | |
1582 | ||
1583 | try!(self.ibox(indent_unit)); | |
7453a54e | 1584 | try!(self.print_local_decl(&loc)); |
e9174d1e SL |
1585 | try!(self.end()); |
1586 | if let Some(ref init) = loc.init { | |
1587 | try!(self.nbsp()); | |
1588 | try!(self.word_space("=")); | |
7453a54e | 1589 | try!(self.print_expr(&init)); |
e9174d1e SL |
1590 | } |
1591 | self.end() | |
1592 | } | |
92a42be0 SL |
1593 | hir::DeclItem(ref item) => { |
1594 | self.print_item_id(item) | |
1595 | } | |
e9174d1e SL |
1596 | } |
1597 | } | |
1598 | ||
e9174d1e SL |
1599 | pub fn print_usize(&mut self, i: usize) -> io::Result<()> { |
1600 | word(&mut self.s, &i.to_string()) | |
1601 | } | |
1602 | ||
1603 | pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { | |
1604 | try!(word(&mut self.s, &name.as_str())); | |
1605 | self.ann.post(self, NodeName(&name)) | |
1606 | } | |
1607 | ||
b039eaaf | 1608 | pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) -> io::Result<()> { |
e9174d1e SL |
1609 | try!(self.print_local_decl(loc)); |
1610 | try!(space(&mut self.s)); | |
1611 | try!(self.word_space("in")); | |
1612 | self.print_expr(coll) | |
1613 | } | |
1614 | ||
1615 | fn print_path(&mut self, | |
1616 | path: &hir::Path, | |
1617 | colons_before_params: bool, | |
1618 | depth: usize) | |
b039eaaf | 1619 | -> io::Result<()> { |
e9174d1e SL |
1620 | try!(self.maybe_print_comment(path.span.lo)); |
1621 | ||
1622 | let mut first = !path.global; | |
92a42be0 | 1623 | for segment in &path.segments[..path.segments.len() - depth] { |
e9174d1e SL |
1624 | if first { |
1625 | first = false | |
1626 | } else { | |
1627 | try!(word(&mut self.s, "::")) | |
1628 | } | |
1629 | ||
b039eaaf | 1630 | try!(self.print_name(segment.identifier.name)); |
e9174d1e SL |
1631 | |
1632 | try!(self.print_path_parameters(&segment.parameters, colons_before_params)); | |
1633 | } | |
1634 | ||
1635 | Ok(()) | |
1636 | } | |
1637 | ||
1638 | fn print_qpath(&mut self, | |
1639 | path: &hir::Path, | |
1640 | qself: &hir::QSelf, | |
1641 | colons_before_params: bool) | |
b039eaaf | 1642 | -> io::Result<()> { |
e9174d1e SL |
1643 | try!(word(&mut self.s, "<")); |
1644 | try!(self.print_type(&qself.ty)); | |
1645 | if qself.position > 0 { | |
1646 | try!(space(&mut self.s)); | |
1647 | try!(self.word_space("as")); | |
1648 | let depth = path.segments.len() - qself.position; | |
1649 | try!(self.print_path(&path, false, depth)); | |
1650 | } | |
1651 | try!(word(&mut self.s, ">")); | |
1652 | try!(word(&mut self.s, "::")); | |
1653 | let item_segment = path.segments.last().unwrap(); | |
b039eaaf | 1654 | try!(self.print_name(item_segment.identifier.name)); |
e9174d1e SL |
1655 | self.print_path_parameters(&item_segment.parameters, colons_before_params) |
1656 | } | |
1657 | ||
1658 | fn print_path_parameters(&mut self, | |
1659 | parameters: &hir::PathParameters, | |
1660 | colons_before_params: bool) | |
b039eaaf | 1661 | -> io::Result<()> { |
e9174d1e SL |
1662 | if parameters.is_empty() { |
1663 | return Ok(()); | |
1664 | } | |
1665 | ||
1666 | if colons_before_params { | |
1667 | try!(word(&mut self.s, "::")) | |
1668 | } | |
1669 | ||
1670 | match *parameters { | |
1671 | hir::AngleBracketedParameters(ref data) => { | |
1672 | try!(word(&mut self.s, "<")); | |
1673 | ||
1674 | let mut comma = false; | |
1675 | for lifetime in &data.lifetimes { | |
1676 | if comma { | |
1677 | try!(self.word_space(",")) | |
1678 | } | |
1679 | try!(self.print_lifetime(lifetime)); | |
1680 | comma = true; | |
1681 | } | |
1682 | ||
1683 | if !data.types.is_empty() { | |
1684 | if comma { | |
1685 | try!(self.word_space(",")) | |
1686 | } | |
7453a54e | 1687 | try!(self.commasep(Inconsistent, &data.types, |s, ty| s.print_type(&ty))); |
b039eaaf | 1688 | comma = true; |
e9174d1e SL |
1689 | } |
1690 | ||
1691 | for binding in data.bindings.iter() { | |
1692 | if comma { | |
1693 | try!(self.word_space(",")) | |
1694 | } | |
b039eaaf | 1695 | try!(self.print_name(binding.name)); |
e9174d1e SL |
1696 | try!(space(&mut self.s)); |
1697 | try!(self.word_space("=")); | |
7453a54e | 1698 | try!(self.print_type(&binding.ty)); |
e9174d1e SL |
1699 | comma = true; |
1700 | } | |
1701 | ||
1702 | try!(word(&mut self.s, ">")) | |
1703 | } | |
1704 | ||
1705 | hir::ParenthesizedParameters(ref data) => { | |
1706 | try!(word(&mut self.s, "(")); | |
7453a54e | 1707 | try!(self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(&ty))); |
e9174d1e SL |
1708 | try!(word(&mut self.s, ")")); |
1709 | ||
1710 | match data.output { | |
b039eaaf | 1711 | None => {} |
e9174d1e SL |
1712 | Some(ref ty) => { |
1713 | try!(self.space_if_not_bol()); | |
1714 | try!(self.word_space("->")); | |
7453a54e | 1715 | try!(self.print_type(&ty)); |
e9174d1e SL |
1716 | } |
1717 | } | |
1718 | } | |
1719 | } | |
1720 | ||
1721 | Ok(()) | |
1722 | } | |
1723 | ||
1724 | pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> { | |
1725 | try!(self.maybe_print_comment(pat.span.lo)); | |
1726 | try!(self.ann.pre(self, NodePat(pat))); | |
92a42be0 SL |
1727 | // Pat isn't normalized, but the beauty of it |
1728 | // is that it doesn't matter | |
e9174d1e | 1729 | match pat.node { |
7453a54e SL |
1730 | PatKind::Wild => try!(word(&mut self.s, "_")), |
1731 | PatKind::Ident(binding_mode, ref path1, ref sub) => { | |
e9174d1e SL |
1732 | match binding_mode { |
1733 | hir::BindByRef(mutbl) => { | |
1734 | try!(self.word_nbsp("ref")); | |
1735 | try!(self.print_mutability(mutbl)); | |
1736 | } | |
1737 | hir::BindByValue(hir::MutImmutable) => {} | |
1738 | hir::BindByValue(hir::MutMutable) => { | |
1739 | try!(self.word_nbsp("mut")); | |
1740 | } | |
1741 | } | |
b039eaaf | 1742 | try!(self.print_name(path1.node.name)); |
e9174d1e SL |
1743 | match *sub { |
1744 | Some(ref p) => { | |
1745 | try!(word(&mut self.s, "@")); | |
7453a54e | 1746 | try!(self.print_pat(&p)); |
e9174d1e | 1747 | } |
b039eaaf | 1748 | None => (), |
e9174d1e SL |
1749 | } |
1750 | } | |
7453a54e | 1751 | PatKind::TupleStruct(ref path, ref args_) => { |
e9174d1e SL |
1752 | try!(self.print_path(path, true, 0)); |
1753 | match *args_ { | |
1754 | None => try!(word(&mut self.s, "(..)")), | |
1755 | Some(ref args) => { | |
7453a54e SL |
1756 | try!(self.popen()); |
1757 | try!(self.commasep(Inconsistent, &args[..], |s, p| s.print_pat(&p))); | |
1758 | try!(self.pclose()); | |
e9174d1e SL |
1759 | } |
1760 | } | |
1761 | } | |
7453a54e SL |
1762 | PatKind::Path(ref path) => { |
1763 | try!(self.print_path(path, true, 0)); | |
1764 | } | |
1765 | PatKind::QPath(ref qself, ref path) => { | |
e9174d1e SL |
1766 | try!(self.print_qpath(path, qself, false)); |
1767 | } | |
7453a54e | 1768 | PatKind::Struct(ref path, ref fields, etc) => { |
e9174d1e SL |
1769 | try!(self.print_path(path, true, 0)); |
1770 | try!(self.nbsp()); | |
1771 | try!(self.word_space("{")); | |
b039eaaf SL |
1772 | try!(self.commasep_cmnt(Consistent, |
1773 | &fields[..], | |
1774 | |s, f| { | |
1775 | try!(s.cbox(indent_unit)); | |
1776 | if !f.node.is_shorthand { | |
1777 | try!(s.print_name(f.node.name)); | |
1778 | try!(s.word_nbsp(":")); | |
1779 | } | |
7453a54e | 1780 | try!(s.print_pat(&f.node.pat)); |
b039eaaf SL |
1781 | s.end() |
1782 | }, | |
1783 | |f| f.node.pat.span)); | |
e9174d1e | 1784 | if etc { |
b039eaaf SL |
1785 | if !fields.is_empty() { |
1786 | try!(self.word_space(",")); | |
1787 | } | |
e9174d1e SL |
1788 | try!(word(&mut self.s, "..")); |
1789 | } | |
1790 | try!(space(&mut self.s)); | |
1791 | try!(word(&mut self.s, "}")); | |
1792 | } | |
7453a54e | 1793 | PatKind::Tup(ref elts) => { |
e9174d1e | 1794 | try!(self.popen()); |
7453a54e | 1795 | try!(self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))); |
e9174d1e SL |
1796 | if elts.len() == 1 { |
1797 | try!(word(&mut self.s, ",")); | |
1798 | } | |
1799 | try!(self.pclose()); | |
1800 | } | |
7453a54e | 1801 | PatKind::Box(ref inner) => { |
e9174d1e | 1802 | try!(word(&mut self.s, "box ")); |
7453a54e | 1803 | try!(self.print_pat(&inner)); |
e9174d1e | 1804 | } |
7453a54e | 1805 | PatKind::Ref(ref inner, mutbl) => { |
e9174d1e SL |
1806 | try!(word(&mut self.s, "&")); |
1807 | if mutbl == hir::MutMutable { | |
1808 | try!(word(&mut self.s, "mut ")); | |
1809 | } | |
7453a54e | 1810 | try!(self.print_pat(&inner)); |
e9174d1e | 1811 | } |
7453a54e SL |
1812 | PatKind::Lit(ref e) => try!(self.print_expr(&e)), |
1813 | PatKind::Range(ref begin, ref end) => { | |
1814 | try!(self.print_expr(&begin)); | |
e9174d1e SL |
1815 | try!(space(&mut self.s)); |
1816 | try!(word(&mut self.s, "...")); | |
7453a54e | 1817 | try!(self.print_expr(&end)); |
e9174d1e | 1818 | } |
7453a54e | 1819 | PatKind::Vec(ref before, ref slice, ref after) => { |
e9174d1e | 1820 | try!(word(&mut self.s, "[")); |
7453a54e | 1821 | try!(self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p))); |
e9174d1e | 1822 | if let Some(ref p) = *slice { |
b039eaaf SL |
1823 | if !before.is_empty() { |
1824 | try!(self.word_space(",")); | |
1825 | } | |
7453a54e SL |
1826 | if p.node != PatKind::Wild { |
1827 | try!(self.print_pat(&p)); | |
e9174d1e | 1828 | } |
92a42be0 | 1829 | try!(word(&mut self.s, "..")); |
b039eaaf SL |
1830 | if !after.is_empty() { |
1831 | try!(self.word_space(",")); | |
1832 | } | |
e9174d1e | 1833 | } |
7453a54e | 1834 | try!(self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(&p))); |
e9174d1e SL |
1835 | try!(word(&mut self.s, "]")); |
1836 | } | |
1837 | } | |
1838 | self.ann.post(self, NodePat(pat)) | |
1839 | } | |
1840 | ||
1841 | fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> { | |
1842 | // I have no idea why this check is necessary, but here it | |
1843 | // is :( | |
1844 | if arm.attrs.is_empty() { | |
1845 | try!(space(&mut self.s)); | |
1846 | } | |
1847 | try!(self.cbox(indent_unit)); | |
1848 | try!(self.ibox(0)); | |
1849 | try!(self.print_outer_attributes(&arm.attrs)); | |
1850 | let mut first = true; | |
1851 | for p in &arm.pats { | |
1852 | if first { | |
1853 | first = false; | |
1854 | } else { | |
1855 | try!(space(&mut self.s)); | |
1856 | try!(self.word_space("|")); | |
1857 | } | |
7453a54e | 1858 | try!(self.print_pat(&p)); |
e9174d1e SL |
1859 | } |
1860 | try!(space(&mut self.s)); | |
1861 | if let Some(ref e) = arm.guard { | |
1862 | try!(self.word_space("if")); | |
7453a54e | 1863 | try!(self.print_expr(&e)); |
e9174d1e SL |
1864 | try!(space(&mut self.s)); |
1865 | } | |
1866 | try!(self.word_space("=>")); | |
1867 | ||
1868 | match arm.body.node { | |
1869 | hir::ExprBlock(ref blk) => { | |
1870 | // the block will close the pattern's ibox | |
7453a54e | 1871 | try!(self.print_block_unclosed_indent(&blk, indent_unit)); |
e9174d1e SL |
1872 | |
1873 | // If it is a user-provided unsafe block, print a comma after it | |
1874 | if let hir::UnsafeBlock(hir::UserProvided) = blk.rules { | |
1875 | try!(word(&mut self.s, ",")); | |
1876 | } | |
1877 | } | |
1878 | _ => { | |
1879 | try!(self.end()); // close the ibox for the pattern | |
7453a54e | 1880 | try!(self.print_expr(&arm.body)); |
e9174d1e SL |
1881 | try!(word(&mut self.s, ",")); |
1882 | } | |
1883 | } | |
1884 | self.end() // close enclosing cbox | |
1885 | } | |
1886 | ||
1887 | // Returns whether it printed anything | |
1888 | fn print_explicit_self(&mut self, | |
1889 | explicit_self: &hir::ExplicitSelf_, | |
b039eaaf SL |
1890 | mutbl: hir::Mutability) |
1891 | -> io::Result<bool> { | |
e9174d1e SL |
1892 | try!(self.print_mutability(mutbl)); |
1893 | match *explicit_self { | |
b039eaaf SL |
1894 | hir::SelfStatic => { |
1895 | return Ok(false); | |
1896 | } | |
e9174d1e SL |
1897 | hir::SelfValue(_) => { |
1898 | try!(word(&mut self.s, "self")); | |
1899 | } | |
1900 | hir::SelfRegion(ref lt, m, _) => { | |
1901 | try!(word(&mut self.s, "&")); | |
1902 | try!(self.print_opt_lifetime(lt)); | |
1903 | try!(self.print_mutability(m)); | |
1904 | try!(word(&mut self.s, "self")); | |
1905 | } | |
1906 | hir::SelfExplicit(ref typ, _) => { | |
1907 | try!(word(&mut self.s, "self")); | |
1908 | try!(self.word_space(":")); | |
7453a54e | 1909 | try!(self.print_type(&typ)); |
e9174d1e SL |
1910 | } |
1911 | } | |
1912 | return Ok(true); | |
1913 | } | |
1914 | ||
1915 | pub fn print_fn(&mut self, | |
1916 | decl: &hir::FnDecl, | |
1917 | unsafety: hir::Unsafety, | |
1918 | constness: hir::Constness, | |
7453a54e | 1919 | abi: Abi, |
b039eaaf | 1920 | name: Option<ast::Name>, |
e9174d1e SL |
1921 | generics: &hir::Generics, |
1922 | opt_explicit_self: Option<&hir::ExplicitSelf_>, | |
b039eaaf SL |
1923 | vis: hir::Visibility) |
1924 | -> io::Result<()> { | |
e9174d1e SL |
1925 | try!(self.print_fn_header_info(unsafety, constness, abi, vis)); |
1926 | ||
1927 | if let Some(name) = name { | |
1928 | try!(self.nbsp()); | |
b039eaaf | 1929 | try!(self.print_name(name)); |
e9174d1e SL |
1930 | } |
1931 | try!(self.print_generics(generics)); | |
1932 | try!(self.print_fn_args_and_ret(decl, opt_explicit_self)); | |
1933 | self.print_where_clause(&generics.where_clause) | |
1934 | } | |
1935 | ||
b039eaaf SL |
1936 | pub fn print_fn_args(&mut self, |
1937 | decl: &hir::FnDecl, | |
7453a54e SL |
1938 | opt_explicit_self: Option<&hir::ExplicitSelf_>, |
1939 | is_closure: bool) | |
b039eaaf | 1940 | -> io::Result<()> { |
e9174d1e SL |
1941 | // It is unfortunate to duplicate the commasep logic, but we want the |
1942 | // self type and the args all in the same box. | |
1943 | try!(self.rbox(0, Inconsistent)); | |
1944 | let mut first = true; | |
1945 | if let Some(explicit_self) = opt_explicit_self { | |
1946 | let m = match explicit_self { | |
1947 | &hir::SelfStatic => hir::MutImmutable, | |
1948 | _ => match decl.inputs[0].pat.node { | |
7453a54e | 1949 | PatKind::Ident(hir::BindByValue(m), _, _) => m, |
b039eaaf SL |
1950 | _ => hir::MutImmutable, |
1951 | }, | |
e9174d1e SL |
1952 | }; |
1953 | first = !try!(self.print_explicit_self(explicit_self, m)); | |
1954 | } | |
1955 | ||
1956 | // HACK(eddyb) ignore the separately printed self argument. | |
1957 | let args = if first { | |
1958 | &decl.inputs[..] | |
1959 | } else { | |
1960 | &decl.inputs[1..] | |
1961 | }; | |
1962 | ||
1963 | for arg in args { | |
b039eaaf SL |
1964 | if first { |
1965 | first = false; | |
1966 | } else { | |
1967 | try!(self.word_space(",")); | |
1968 | } | |
7453a54e | 1969 | try!(self.print_arg(arg, is_closure)); |
e9174d1e SL |
1970 | } |
1971 | ||
1972 | self.end() | |
1973 | } | |
1974 | ||
b039eaaf SL |
1975 | pub fn print_fn_args_and_ret(&mut self, |
1976 | decl: &hir::FnDecl, | |
e9174d1e | 1977 | opt_explicit_self: Option<&hir::ExplicitSelf_>) |
b039eaaf | 1978 | -> io::Result<()> { |
e9174d1e | 1979 | try!(self.popen()); |
7453a54e | 1980 | try!(self.print_fn_args(decl, opt_explicit_self, false)); |
e9174d1e SL |
1981 | if decl.variadic { |
1982 | try!(word(&mut self.s, ", ...")); | |
1983 | } | |
1984 | try!(self.pclose()); | |
1985 | ||
1986 | self.print_fn_output(decl) | |
1987 | } | |
1988 | ||
b039eaaf | 1989 | pub fn print_fn_block_args(&mut self, decl: &hir::FnDecl) -> io::Result<()> { |
e9174d1e | 1990 | try!(word(&mut self.s, "|")); |
7453a54e | 1991 | try!(self.print_fn_args(decl, None, true)); |
e9174d1e SL |
1992 | try!(word(&mut self.s, "|")); |
1993 | ||
1994 | if let hir::DefaultReturn(..) = decl.output { | |
1995 | return Ok(()); | |
1996 | } | |
1997 | ||
1998 | try!(self.space_if_not_bol()); | |
1999 | try!(self.word_space("->")); | |
2000 | match decl.output { | |
2001 | hir::Return(ref ty) => { | |
7453a54e | 2002 | try!(self.print_type(&ty)); |
e9174d1e SL |
2003 | self.maybe_print_comment(ty.span.lo) |
2004 | } | |
2005 | hir::DefaultReturn(..) => unreachable!(), | |
2006 | hir::NoReturn(span) => { | |
2007 | try!(self.word_nbsp("!")); | |
2008 | self.maybe_print_comment(span.lo) | |
2009 | } | |
2010 | } | |
2011 | } | |
2012 | ||
b039eaaf | 2013 | pub fn print_capture_clause(&mut self, capture_clause: hir::CaptureClause) -> io::Result<()> { |
e9174d1e SL |
2014 | match capture_clause { |
2015 | hir::CaptureByValue => self.word_space("move"), | |
2016 | hir::CaptureByRef => Ok(()), | |
2017 | } | |
2018 | } | |
2019 | ||
b039eaaf | 2020 | pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::TyParamBound]) -> io::Result<()> { |
e9174d1e SL |
2021 | if !bounds.is_empty() { |
2022 | try!(word(&mut self.s, prefix)); | |
2023 | let mut first = true; | |
2024 | for bound in bounds { | |
2025 | try!(self.nbsp()); | |
2026 | if first { | |
2027 | first = false; | |
2028 | } else { | |
2029 | try!(self.word_space("+")); | |
2030 | } | |
2031 | ||
2032 | try!(match *bound { | |
2033 | TraitTyParamBound(ref tref, TraitBoundModifier::None) => { | |
2034 | self.print_poly_trait_ref(tref) | |
2035 | } | |
2036 | TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => { | |
2037 | try!(word(&mut self.s, "?")); | |
2038 | self.print_poly_trait_ref(tref) | |
2039 | } | |
2040 | RegionTyParamBound(ref lt) => { | |
2041 | self.print_lifetime(lt) | |
2042 | } | |
2043 | }) | |
2044 | } | |
2045 | Ok(()) | |
2046 | } else { | |
2047 | Ok(()) | |
2048 | } | |
2049 | } | |
2050 | ||
b039eaaf | 2051 | pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> { |
e9174d1e SL |
2052 | self.print_name(lifetime.name) |
2053 | } | |
2054 | ||
b039eaaf | 2055 | pub fn print_lifetime_def(&mut self, lifetime: &hir::LifetimeDef) -> io::Result<()> { |
e9174d1e SL |
2056 | try!(self.print_lifetime(&lifetime.lifetime)); |
2057 | let mut sep = ":"; | |
2058 | for v in &lifetime.bounds { | |
2059 | try!(word(&mut self.s, sep)); | |
2060 | try!(self.print_lifetime(v)); | |
2061 | sep = "+"; | |
2062 | } | |
2063 | Ok(()) | |
2064 | } | |
2065 | ||
b039eaaf | 2066 | pub fn print_generics(&mut self, generics: &hir::Generics) -> io::Result<()> { |
e9174d1e SL |
2067 | let total = generics.lifetimes.len() + generics.ty_params.len(); |
2068 | if total == 0 { | |
2069 | return Ok(()); | |
2070 | } | |
2071 | ||
2072 | try!(word(&mut self.s, "<")); | |
2073 | ||
2074 | let mut ints = Vec::new(); | |
2075 | for i in 0..total { | |
2076 | ints.push(i); | |
2077 | } | |
2078 | ||
92a42be0 SL |
2079 | try!(self.commasep(Inconsistent, &ints[..], |s, &idx| { |
2080 | if idx < generics.lifetimes.len() { | |
2081 | let lifetime = &generics.lifetimes[idx]; | |
2082 | s.print_lifetime_def(lifetime) | |
2083 | } else { | |
2084 | let idx = idx - generics.lifetimes.len(); | |
2085 | let param = &generics.ty_params[idx]; | |
2086 | s.print_ty_param(param) | |
2087 | } | |
2088 | })); | |
e9174d1e SL |
2089 | |
2090 | try!(word(&mut self.s, ">")); | |
2091 | Ok(()) | |
2092 | } | |
2093 | ||
2094 | pub fn print_ty_param(&mut self, param: &hir::TyParam) -> io::Result<()> { | |
b039eaaf | 2095 | try!(self.print_name(param.name)); |
e9174d1e SL |
2096 | try!(self.print_bounds(":", ¶m.bounds)); |
2097 | match param.default { | |
2098 | Some(ref default) => { | |
2099 | try!(space(&mut self.s)); | |
2100 | try!(self.word_space("=")); | |
7453a54e | 2101 | self.print_type(&default) |
e9174d1e | 2102 | } |
b039eaaf | 2103 | _ => Ok(()), |
e9174d1e SL |
2104 | } |
2105 | } | |
2106 | ||
b039eaaf | 2107 | pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Result<()> { |
e9174d1e | 2108 | if where_clause.predicates.is_empty() { |
92a42be0 | 2109 | return Ok(()); |
e9174d1e SL |
2110 | } |
2111 | ||
2112 | try!(space(&mut self.s)); | |
2113 | try!(self.word_space("where")); | |
2114 | ||
2115 | for (i, predicate) in where_clause.predicates.iter().enumerate() { | |
2116 | if i != 0 { | |
2117 | try!(self.word_space(",")); | |
2118 | } | |
2119 | ||
2120 | match predicate { | |
2121 | &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{ref bound_lifetimes, | |
2122 | ref bounded_ty, | |
2123 | ref bounds, | |
2124 | ..}) => { | |
2125 | try!(self.print_formal_lifetime_list(bound_lifetimes)); | |
7453a54e | 2126 | try!(self.print_type(&bounded_ty)); |
e9174d1e SL |
2127 | try!(self.print_bounds(":", bounds)); |
2128 | } | |
2129 | &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{ref lifetime, | |
2130 | ref bounds, | |
2131 | ..}) => { | |
2132 | try!(self.print_lifetime(lifetime)); | |
2133 | try!(word(&mut self.s, ":")); | |
2134 | ||
2135 | for (i, bound) in bounds.iter().enumerate() { | |
2136 | try!(self.print_lifetime(bound)); | |
2137 | ||
2138 | if i != 0 { | |
2139 | try!(word(&mut self.s, ":")); | |
2140 | } | |
2141 | } | |
2142 | } | |
2143 | &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref path, ref ty, ..}) => { | |
2144 | try!(self.print_path(path, false, 0)); | |
2145 | try!(space(&mut self.s)); | |
2146 | try!(self.word_space("=")); | |
7453a54e | 2147 | try!(self.print_type(&ty)); |
e9174d1e SL |
2148 | } |
2149 | } | |
2150 | } | |
2151 | ||
2152 | Ok(()) | |
2153 | } | |
2154 | ||
e9174d1e SL |
2155 | pub fn print_view_path(&mut self, vp: &hir::ViewPath) -> io::Result<()> { |
2156 | match vp.node { | |
b039eaaf | 2157 | hir::ViewPathSimple(name, ref path) => { |
e9174d1e SL |
2158 | try!(self.print_path(path, false, 0)); |
2159 | ||
b039eaaf | 2160 | if path.segments.last().unwrap().identifier.name != name { |
e9174d1e SL |
2161 | try!(space(&mut self.s)); |
2162 | try!(self.word_space("as")); | |
b039eaaf | 2163 | try!(self.print_name(name)); |
e9174d1e SL |
2164 | } |
2165 | ||
2166 | Ok(()) | |
2167 | } | |
2168 | ||
2169 | hir::ViewPathGlob(ref path) => { | |
2170 | try!(self.print_path(path, false, 0)); | |
2171 | word(&mut self.s, "::*") | |
2172 | } | |
2173 | ||
b039eaaf | 2174 | hir::ViewPathList(ref path, ref segments) => { |
e9174d1e SL |
2175 | if path.segments.is_empty() { |
2176 | try!(word(&mut self.s, "{")); | |
2177 | } else { | |
2178 | try!(self.print_path(path, false, 0)); | |
2179 | try!(word(&mut self.s, "::{")); | |
2180 | } | |
92a42be0 SL |
2181 | try!(self.commasep(Inconsistent, &segments[..], |s, w| { |
2182 | match w.node { | |
2183 | hir::PathListIdent { name, .. } => { | |
2184 | s.print_name(name) | |
2185 | } | |
2186 | hir::PathListMod { .. } => { | |
2187 | word(&mut s.s, "self") | |
2188 | } | |
2189 | } | |
2190 | })); | |
e9174d1e SL |
2191 | word(&mut self.s, "}") |
2192 | } | |
2193 | } | |
2194 | } | |
2195 | ||
b039eaaf | 2196 | pub fn print_mutability(&mut self, mutbl: hir::Mutability) -> io::Result<()> { |
e9174d1e SL |
2197 | match mutbl { |
2198 | hir::MutMutable => self.word_nbsp("mut"), | |
2199 | hir::MutImmutable => Ok(()), | |
2200 | } | |
2201 | } | |
2202 | ||
2203 | pub fn print_mt(&mut self, mt: &hir::MutTy) -> io::Result<()> { | |
2204 | try!(self.print_mutability(mt.mutbl)); | |
7453a54e | 2205 | self.print_type(&mt.ty) |
e9174d1e SL |
2206 | } |
2207 | ||
7453a54e | 2208 | pub fn print_arg(&mut self, input: &hir::Arg, is_closure: bool) -> io::Result<()> { |
e9174d1e SL |
2209 | try!(self.ibox(indent_unit)); |
2210 | match input.ty.node { | |
7453a54e | 2211 | hir::TyInfer if is_closure => try!(self.print_pat(&input.pat)), |
e9174d1e SL |
2212 | _ => { |
2213 | match input.pat.node { | |
7453a54e | 2214 | PatKind::Ident(_, ref path1, _) if |
e9174d1e SL |
2215 | path1.node.name == |
2216 | parse::token::special_idents::invalid.name => { | |
2217 | // Do nothing. | |
2218 | } | |
2219 | _ => { | |
7453a54e | 2220 | try!(self.print_pat(&input.pat)); |
e9174d1e SL |
2221 | try!(word(&mut self.s, ":")); |
2222 | try!(space(&mut self.s)); | |
2223 | } | |
2224 | } | |
7453a54e | 2225 | try!(self.print_type(&input.ty)); |
e9174d1e SL |
2226 | } |
2227 | } | |
2228 | self.end() | |
2229 | } | |
2230 | ||
2231 | pub fn print_fn_output(&mut self, decl: &hir::FnDecl) -> io::Result<()> { | |
2232 | if let hir::DefaultReturn(..) = decl.output { | |
2233 | return Ok(()); | |
2234 | } | |
2235 | ||
2236 | try!(self.space_if_not_bol()); | |
2237 | try!(self.ibox(indent_unit)); | |
2238 | try!(self.word_space("->")); | |
2239 | match decl.output { | |
b039eaaf | 2240 | hir::NoReturn(_) => try!(self.word_nbsp("!")), |
e9174d1e | 2241 | hir::DefaultReturn(..) => unreachable!(), |
7453a54e | 2242 | hir::Return(ref ty) => try!(self.print_type(&ty)), |
e9174d1e SL |
2243 | } |
2244 | try!(self.end()); | |
2245 | ||
2246 | match decl.output { | |
2247 | hir::Return(ref output) => self.maybe_print_comment(output.span.lo), | |
b039eaaf | 2248 | _ => Ok(()), |
e9174d1e SL |
2249 | } |
2250 | } | |
2251 | ||
2252 | pub fn print_ty_fn(&mut self, | |
7453a54e | 2253 | abi: Abi, |
e9174d1e SL |
2254 | unsafety: hir::Unsafety, |
2255 | decl: &hir::FnDecl, | |
b039eaaf | 2256 | name: Option<ast::Name>, |
e9174d1e SL |
2257 | generics: &hir::Generics, |
2258 | opt_explicit_self: Option<&hir::ExplicitSelf_>) | |
2259 | -> io::Result<()> { | |
2260 | try!(self.ibox(indent_unit)); | |
2261 | if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { | |
2262 | try!(word(&mut self.s, "for")); | |
2263 | try!(self.print_generics(generics)); | |
2264 | } | |
2265 | let generics = hir::Generics { | |
9cc50fc6 SL |
2266 | lifetimes: hir::HirVec::new(), |
2267 | ty_params: hir::HirVec::new(), | |
e9174d1e SL |
2268 | where_clause: hir::WhereClause { |
2269 | id: ast::DUMMY_NODE_ID, | |
9cc50fc6 | 2270 | predicates: hir::HirVec::new(), |
e9174d1e SL |
2271 | }, |
2272 | }; | |
2273 | try!(self.print_fn(decl, | |
2274 | unsafety, | |
2275 | hir::Constness::NotConst, | |
2276 | abi, | |
2277 | name, | |
2278 | &generics, | |
2279 | opt_explicit_self, | |
2280 | hir::Inherited)); | |
2281 | self.end() | |
2282 | } | |
2283 | ||
b039eaaf SL |
2284 | pub fn maybe_print_trailing_comment(&mut self, |
2285 | span: codemap::Span, | |
e9174d1e | 2286 | next_pos: Option<BytePos>) |
b039eaaf | 2287 | -> io::Result<()> { |
e9174d1e SL |
2288 | let cm = match self.cm { |
2289 | Some(cm) => cm, | |
b039eaaf | 2290 | _ => return Ok(()), |
e9174d1e SL |
2291 | }; |
2292 | match self.next_comment() { | |
2293 | Some(ref cmnt) => { | |
b039eaaf | 2294 | if (*cmnt).style != comments::Trailing { |
92a42be0 | 2295 | return Ok(()); |
b039eaaf | 2296 | } |
e9174d1e SL |
2297 | let span_line = cm.lookup_char_pos(span.hi); |
2298 | let comment_line = cm.lookup_char_pos((*cmnt).pos); | |
2299 | let mut next = (*cmnt).pos + BytePos(1); | |
b039eaaf SL |
2300 | match next_pos { |
2301 | None => (), | |
2302 | Some(p) => next = p, | |
2303 | } | |
e9174d1e | 2304 | if span.hi < (*cmnt).pos && (*cmnt).pos < next && |
b039eaaf SL |
2305 | span_line.line == comment_line.line { |
2306 | try!(self.print_comment(cmnt)); | |
2307 | self.cur_cmnt_and_lit.cur_cmnt += 1; | |
2308 | } | |
e9174d1e | 2309 | } |
b039eaaf | 2310 | _ => (), |
e9174d1e SL |
2311 | } |
2312 | Ok(()) | |
2313 | } | |
2314 | ||
2315 | pub fn print_remaining_comments(&mut self) -> io::Result<()> { | |
2316 | // If there aren't any remaining comments, then we need to manually | |
2317 | // make sure there is a line break at the end. | |
2318 | if self.next_comment().is_none() { | |
2319 | try!(hardbreak(&mut self.s)); | |
2320 | } | |
2321 | loop { | |
2322 | match self.next_comment() { | |
2323 | Some(ref cmnt) => { | |
2324 | try!(self.print_comment(cmnt)); | |
2325 | self.cur_cmnt_and_lit.cur_cmnt += 1; | |
2326 | } | |
b039eaaf | 2327 | _ => break, |
e9174d1e SL |
2328 | } |
2329 | } | |
2330 | Ok(()) | |
2331 | } | |
2332 | ||
e9174d1e | 2333 | pub fn print_opt_abi_and_extern_if_nondefault(&mut self, |
7453a54e | 2334 | opt_abi: Option<Abi>) |
b039eaaf | 2335 | -> io::Result<()> { |
e9174d1e | 2336 | match opt_abi { |
7453a54e | 2337 | Some(Abi::Rust) => Ok(()), |
e9174d1e SL |
2338 | Some(abi) => { |
2339 | try!(self.word_nbsp("extern")); | |
2340 | self.word_nbsp(&abi.to_string()) | |
2341 | } | |
b039eaaf | 2342 | None => Ok(()), |
e9174d1e SL |
2343 | } |
2344 | } | |
2345 | ||
7453a54e | 2346 | pub fn print_extern_opt_abi(&mut self, opt_abi: Option<Abi>) -> io::Result<()> { |
e9174d1e SL |
2347 | match opt_abi { |
2348 | Some(abi) => { | |
2349 | try!(self.word_nbsp("extern")); | |
2350 | self.word_nbsp(&abi.to_string()) | |
2351 | } | |
b039eaaf | 2352 | None => Ok(()), |
e9174d1e SL |
2353 | } |
2354 | } | |
2355 | ||
2356 | pub fn print_fn_header_info(&mut self, | |
2357 | unsafety: hir::Unsafety, | |
2358 | constness: hir::Constness, | |
7453a54e | 2359 | abi: Abi, |
b039eaaf SL |
2360 | vis: hir::Visibility) |
2361 | -> io::Result<()> { | |
e9174d1e SL |
2362 | try!(word(&mut self.s, &visibility_qualified(vis, ""))); |
2363 | try!(self.print_unsafety(unsafety)); | |
2364 | ||
2365 | match constness { | |
2366 | hir::Constness::NotConst => {} | |
b039eaaf | 2367 | hir::Constness::Const => try!(self.word_nbsp("const")), |
e9174d1e SL |
2368 | } |
2369 | ||
7453a54e | 2370 | if abi != Abi::Rust { |
e9174d1e SL |
2371 | try!(self.word_nbsp("extern")); |
2372 | try!(self.word_nbsp(&abi.to_string())); | |
2373 | } | |
2374 | ||
2375 | word(&mut self.s, "fn") | |
2376 | } | |
2377 | ||
2378 | pub fn print_unsafety(&mut self, s: hir::Unsafety) -> io::Result<()> { | |
2379 | match s { | |
2380 | hir::Unsafety::Normal => Ok(()), | |
2381 | hir::Unsafety::Unsafe => self.word_nbsp("unsafe"), | |
2382 | } | |
2383 | } | |
2384 | } | |
2385 | ||
e9174d1e SL |
2386 | // Dup'ed from parse::classify, but adapted for the HIR. |
2387 | /// Does this expression require a semicolon to be treated | |
2388 | /// as a statement? The negation of this: 'can this expression | |
2389 | /// be used as a statement without a semicolon' -- is used | |
2390 | /// as an early-bail-out in the parser so that, for instance, | |
2391 | /// if true {...} else {...} | |
2392 | /// |x| 5 | |
2393 | /// isn't parsed as (if true {...} else {...} | x) | 5 | |
2394 | fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool { | |
2395 | match e.node { | |
b039eaaf SL |
2396 | hir::ExprIf(..) | |
2397 | hir::ExprMatch(..) | | |
2398 | hir::ExprBlock(_) | | |
2399 | hir::ExprWhile(..) | | |
2400 | hir::ExprLoop(..) => false, | |
2401 | _ => true, | |
e9174d1e SL |
2402 | } |
2403 | } | |
2404 | ||
2405 | /// this statement requires a semicolon after it. | |
2406 | /// note that in one case (stmt_semi), we've already | |
2407 | /// seen the semicolon, and thus don't need another. | |
2408 | fn stmt_ends_with_semi(stmt: &hir::Stmt_) -> bool { | |
2409 | match *stmt { | |
2410 | hir::StmtDecl(ref d, _) => { | |
2411 | match d.node { | |
2412 | hir::DeclLocal(_) => true, | |
b039eaaf | 2413 | hir::DeclItem(_) => false, |
e9174d1e SL |
2414 | } |
2415 | } | |
b039eaaf | 2416 | hir::StmtExpr(ref e, _) => { |
7453a54e | 2417 | expr_requires_semi_to_be_stmt(&e) |
b039eaaf SL |
2418 | } |
2419 | hir::StmtSemi(..) => { | |
2420 | false | |
2421 | } | |
e9174d1e SL |
2422 | } |
2423 | } |