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