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