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