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