]>
Commit | Line | Data |
---|---|---|
5099ac24 FG |
1 | mod delimited; |
2 | mod expr; | |
3 | mod item; | |
4 | ||
74b04a01 XL |
5 | use crate::pp::Breaks::{Consistent, Inconsistent}; |
6 | use crate::pp::{self, Breaks}; | |
7 | ||
74b04a01 | 8 | use rustc_ast::ptr::P; |
04454e1e | 9 | use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, Token, TokenKind}; |
f035d41b | 10 | use rustc_ast::tokenstream::{TokenStream, TokenTree}; |
3dfed10e XL |
11 | use rustc_ast::util::classify; |
12 | use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle}; | |
5099ac24 | 13 | use rustc_ast::util::parser; |
f2b60f7d FG |
14 | use rustc_ast::{self as ast, BlockCheckMode, Mutability, PatKind, RangeEnd, RangeSyntax}; |
15 | use rustc_ast::{attr, BindingAnnotation, ByRef, Term}; | |
04454e1e | 16 | use rustc_ast::{GenericArg, MacArgs, MacArgsEq}; |
3dfed10e XL |
17 | use rustc_ast::{GenericBound, SelfKind, TraitBoundModifier}; |
18 | use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass}; | |
19 | use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; | |
74b04a01 XL |
20 | use rustc_span::edition::Edition; |
21 | use rustc_span::source_map::{SourceMap, Spanned}; | |
f9f354fc | 22 | use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol}; |
dfeec247 | 23 | use rustc_span::{BytePos, FileName, Span}; |
1a4d82fc | 24 | |
f2b60f7d | 25 | use rustc_ast::attr::AttrIdGenerator; |
a1dfa0c6 | 26 | use std::borrow::Cow; |
416331ca | 27 | |
5099ac24 FG |
28 | pub use self::delimited::IterDelimited; |
29 | ||
416331ca XL |
30 | pub enum MacHeader<'a> { |
31 | Path(&'a ast::Path), | |
32 | Keyword(&'static str), | |
33 | } | |
1a4d82fc JJ |
34 | |
35 | pub enum AnnNode<'a> { | |
f9f354fc XL |
36 | Ident(&'a Ident), |
37 | Name(&'a Symbol), | |
b7449926 XL |
38 | Block(&'a ast::Block), |
39 | Item(&'a ast::Item), | |
40 | SubItem(ast::NodeId), | |
41 | Expr(&'a ast::Expr), | |
42 | Pat(&'a ast::Pat), | |
e1599b0c | 43 | Crate(&'a ast::Crate), |
223e47cc LB |
44 | } |
45 | ||
1a4d82fc | 46 | pub trait PpAnn { |
dfeec247 XL |
47 | fn pre(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {} |
48 | fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {} | |
223e47cc LB |
49 | } |
50 | ||
c34b1796 | 51 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
52 | pub struct NoAnn; |
53 | ||
54 | impl PpAnn for NoAnn {} | |
55 | ||
416331ca | 56 | pub struct Comments<'a> { |
74b04a01 | 57 | sm: &'a SourceMap, |
3dfed10e | 58 | comments: Vec<Comment>, |
416331ca | 59 | current: usize, |
223e47cc LB |
60 | } |
61 | ||
416331ca | 62 | impl<'a> Comments<'a> { |
74b04a01 | 63 | pub fn new(sm: &'a SourceMap, filename: FileName, input: String) -> Comments<'a> { |
3dfed10e | 64 | let comments = gather_comments(sm, filename, input); |
74b04a01 | 65 | Comments { sm, comments, current: 0 } |
416331ca XL |
66 | } |
67 | ||
3dfed10e | 68 | pub fn next(&self) -> Option<Comment> { |
416331ca XL |
69 | self.comments.get(self.current).cloned() |
70 | } | |
71 | ||
72 | pub fn trailing_comment( | |
29967ef6 | 73 | &self, |
dfeec247 | 74 | span: rustc_span::Span, |
416331ca | 75 | next_pos: Option<BytePos>, |
3dfed10e | 76 | ) -> Option<Comment> { |
416331ca | 77 | if let Some(cmnt) = self.next() { |
3dfed10e | 78 | if cmnt.style != CommentStyle::Trailing { |
dfeec247 XL |
79 | return None; |
80 | } | |
74b04a01 XL |
81 | let span_line = self.sm.lookup_char_pos(span.hi()); |
82 | let comment_line = self.sm.lookup_char_pos(cmnt.pos); | |
416331ca XL |
83 | let next = next_pos.unwrap_or_else(|| cmnt.pos + BytePos(1)); |
84 | if span.hi() < cmnt.pos && cmnt.pos < next && span_line.line == comment_line.line { | |
85 | return Some(cmnt); | |
86 | } | |
87 | } | |
88 | ||
89 | None | |
1a4d82fc JJ |
90 | } |
91 | } | |
92 | ||
416331ca XL |
93 | pub struct State<'a> { |
94 | pub s: pp::Printer, | |
95 | comments: Option<Comments<'a>>, | |
dfeec247 | 96 | ann: &'a (dyn PpAnn + 'a), |
416331ca | 97 | } |
1a4d82fc | 98 | |
923072b8 | 99 | pub(crate) const INDENT_UNIT: isize = 4; |
1a4d82fc JJ |
100 | |
101 | /// Requires you to pass an input filename and reader so that | |
48663c56 | 102 | /// it can scan the input text for comments to copy forward. |
dfeec247 | 103 | pub fn print_crate<'a>( |
74b04a01 | 104 | sm: &'a SourceMap, |
dfeec247 XL |
105 | krate: &ast::Crate, |
106 | filename: FileName, | |
107 | input: String, | |
108 | ann: &'a dyn PpAnn, | |
109 | is_expanded: bool, | |
74b04a01 | 110 | edition: Edition, |
f2b60f7d | 111 | g: &AttrIdGenerator, |
dfeec247 | 112 | ) -> String { |
6a06907d | 113 | let mut s = |
5099ac24 | 114 | State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann }; |
32a655c1 | 115 | |
fc512014 | 116 | if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) { |
85aaf69f SL |
117 | // We need to print `#![no_std]` (and its feature gate) so that |
118 | // compiling pretty-printed source won't inject libstd again. | |
e1599b0c | 119 | // However, we don't want these attributes in the AST because |
85aaf69f SL |
120 | // of the feature gate, so we fake them up here. |
121 | ||
e1599b0c | 122 | // `#![feature(prelude_import)]` |
f9f354fc XL |
123 | let pi_nested = attr::mk_nested_word_item(Ident::with_dummy_span(sym::prelude_import)); |
124 | let list = attr::mk_list_item(Ident::with_dummy_span(sym::feature), vec![pi_nested]); | |
f2b60f7d | 125 | let fake_attr = attr::mk_attr_inner(g, list); |
416331ca | 126 | s.print_attribute(&fake_attr); |
85aaf69f | 127 | |
e1599b0c XL |
128 | // Currently, in Rust 2018 we don't have `extern crate std;` at the crate |
129 | // root, so this is not needed, and actually breaks things. | |
74b04a01 | 130 | if edition == Edition::Edition2015 { |
e1599b0c | 131 | // `#![no_std]` |
f9f354fc | 132 | let no_std_meta = attr::mk_word_item(Ident::with_dummy_span(sym::no_std)); |
f2b60f7d | 133 | let fake_attr = attr::mk_attr_inner(g, no_std_meta); |
e1599b0c XL |
134 | s.print_attribute(&fake_attr); |
135 | } | |
85aaf69f SL |
136 | } |
137 | ||
6a06907d XL |
138 | s.print_inner_attributes(&krate.attrs); |
139 | for item in &krate.items { | |
140 | s.print_item(item); | |
141 | } | |
416331ca | 142 | s.print_remaining_comments(); |
e1599b0c | 143 | s.ann.post(&mut s, AnnNode::Crate(krate)); |
041b39d2 | 144 | s.s.eof() |
1a4d82fc JJ |
145 | } |
146 | ||
136023e0 XL |
147 | /// This makes printed token streams look slightly nicer, |
148 | /// and also addresses some specific regressions described in #63896 and #73345. | |
ba9703b0 | 149 | fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool { |
064997fb | 150 | if let TokenTree::Token(token, _) = prev { |
136023e0 | 151 | if matches!(token.kind, token::Dot | token::Dollar) { |
17df50a5 XL |
152 | return false; |
153 | } | |
3dfed10e XL |
154 | if let token::DocComment(comment_kind, ..) = token.kind { |
155 | return comment_kind != CommentKind::Line; | |
f035d41b XL |
156 | } |
157 | } | |
416331ca | 158 | match tt { |
064997fb | 159 | TokenTree::Token(token, _) => !matches!(token.kind, token::Comma | token::Not | token::Dot), |
04454e1e | 160 | TokenTree::Delimited(_, Delimiter::Parenthesis, _) => { |
064997fb | 161 | !matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. }, _)) |
29967ef6 | 162 | } |
04454e1e | 163 | TokenTree::Delimited(_, Delimiter::Bracket, _) => { |
064997fb | 164 | !matches!(prev, TokenTree::Token(Token { kind: token::Pound, .. }, _)) |
29967ef6 | 165 | } |
f035d41b | 166 | TokenTree::Delimited(..) => true, |
d9579d0f | 167 | } |
1a4d82fc JJ |
168 | } |
169 | ||
041b39d2 | 170 | fn binop_to_string(op: BinOpToken) -> &'static str { |
1a4d82fc | 171 | match op { |
dfeec247 XL |
172 | token::Plus => "+", |
173 | token::Minus => "-", | |
174 | token::Star => "*", | |
175 | token::Slash => "/", | |
176 | token::Percent => "%", | |
177 | token::Caret => "^", | |
178 | token::And => "&", | |
179 | token::Or => "|", | |
180 | token::Shl => "<<", | |
181 | token::Shr => ">>", | |
1a4d82fc JJ |
182 | } |
183 | } | |
184 | ||
3dfed10e XL |
185 | fn doc_comment_to_string( |
186 | comment_kind: CommentKind, | |
187 | attr_style: ast::AttrStyle, | |
188 | data: Symbol, | |
189 | ) -> String { | |
190 | match (comment_kind, attr_style) { | |
191 | (CommentKind::Line, ast::AttrStyle::Outer) => format!("///{}", data), | |
192 | (CommentKind::Line, ast::AttrStyle::Inner) => format!("//!{}", data), | |
193 | (CommentKind::Block, ast::AttrStyle::Outer) => format!("/**{}*/", data), | |
194 | (CommentKind::Block, ast::AttrStyle::Inner) => format!("/*!{}*/", data), | |
195 | } | |
196 | } | |
197 | ||
dc9dc135 XL |
198 | pub fn literal_to_string(lit: token::Lit) -> String { |
199 | let token::Lit { kind, symbol, suffix } = lit; | |
200 | let mut out = match kind { | |
dfeec247 XL |
201 | token::Byte => format!("b'{}'", symbol), |
202 | token::Char => format!("'{}'", symbol), | |
203 | token::Str => format!("\"{}\"", symbol), | |
204 | token::StrRaw(n) => { | |
205 | format!("r{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol) | |
206 | } | |
207 | token::ByteStr => format!("b\"{}\"", symbol), | |
208 | token::ByteStrRaw(n) => { | |
209 | format!("br{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol) | |
210 | } | |
211 | token::Integer | token::Float | token::Bool | token::Err => symbol.to_string(), | |
48663c56 XL |
212 | }; |
213 | ||
214 | if let Some(suffix) = suffix { | |
a2a8927a | 215 | out.push_str(suffix.as_str()) |
48663c56 XL |
216 | } |
217 | ||
218 | out | |
219 | } | |
220 | ||
416331ca XL |
221 | impl std::ops::Deref for State<'_> { |
222 | type Target = pp::Printer; | |
223 | fn deref(&self) -> &Self::Target { | |
224 | &self.s | |
1a4d82fc | 225 | } |
416331ca | 226 | } |
223e47cc | 227 | |
416331ca XL |
228 | impl std::ops::DerefMut for State<'_> { |
229 | fn deref_mut(&mut self) -> &mut Self::Target { | |
230 | &mut self.s | |
b039eaaf | 231 | } |
416331ca | 232 | } |
223e47cc | 233 | |
e1599b0c | 234 | pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::DerefMut { |
416331ca | 235 | fn comments(&mut self) -> &mut Option<Comments<'a>>; |
f9f354fc | 236 | fn print_ident(&mut self, ident: Ident); |
416331ca | 237 | fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool); |
223e47cc | 238 | |
dfeec247 XL |
239 | fn strsep<T, F>( |
240 | &mut self, | |
241 | sep: &'static str, | |
242 | space_before: bool, | |
243 | b: Breaks, | |
244 | elts: &[T], | |
245 | mut op: F, | |
246 | ) where | |
247 | F: FnMut(&mut Self, &T), | |
b039eaaf | 248 | { |
416331ca | 249 | self.rbox(0, b); |
e1599b0c XL |
250 | if let Some((first, rest)) = elts.split_first() { |
251 | op(self, first); | |
252 | for elt in rest { | |
253 | if space_before { | |
254 | self.space(); | |
255 | } | |
256 | self.word_space(sep); | |
257 | op(self, elt); | |
258 | } | |
b039eaaf | 259 | } |
416331ca | 260 | self.end(); |
b039eaaf SL |
261 | } |
262 | ||
e1599b0c | 263 | fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], op: F) |
dfeec247 XL |
264 | where |
265 | F: FnMut(&mut Self, &T), | |
e1599b0c XL |
266 | { |
267 | self.strsep(",", false, b, elts, op) | |
268 | } | |
269 | ||
a2a8927a XL |
270 | fn maybe_print_comment(&mut self, pos: BytePos) -> bool { |
271 | let mut has_comment = false; | |
c30ab7b3 SL |
272 | while let Some(ref cmnt) = self.next_comment() { |
273 | if cmnt.pos < pos { | |
a2a8927a | 274 | has_comment = true; |
416331ca | 275 | self.print_comment(cmnt); |
c30ab7b3 | 276 | } else { |
dfeec247 | 277 | break; |
b039eaaf SL |
278 | } |
279 | } | |
a2a8927a | 280 | has_comment |
b039eaaf SL |
281 | } |
282 | ||
3dfed10e | 283 | fn print_comment(&mut self, cmnt: &Comment) { |
416331ca | 284 | match cmnt.style { |
3dfed10e XL |
285 | CommentStyle::Mixed => { |
286 | if !self.is_beginning_of_line() { | |
287 | self.zerobreak(); | |
288 | } | |
289 | if let Some((last, lines)) = cmnt.lines.split_last() { | |
290 | self.ibox(0); | |
291 | ||
292 | for line in lines { | |
293 | self.word(line.clone()); | |
294 | self.hardbreak() | |
295 | } | |
296 | ||
297 | self.word(last.clone()); | |
298 | self.space(); | |
299 | ||
300 | self.end(); | |
301 | } | |
416331ca | 302 | self.zerobreak() |
b039eaaf | 303 | } |
3dfed10e | 304 | CommentStyle::Isolated => { |
416331ca | 305 | self.hardbreak_if_not_bol(); |
b039eaaf SL |
306 | for line in &cmnt.lines { |
307 | // Don't print empty lines because they will end up as trailing | |
e1599b0c | 308 | // whitespace. |
b039eaaf | 309 | if !line.is_empty() { |
416331ca | 310 | self.word(line.clone()); |
b039eaaf | 311 | } |
416331ca | 312 | self.hardbreak(); |
b039eaaf | 313 | } |
b039eaaf | 314 | } |
3dfed10e | 315 | CommentStyle::Trailing => { |
416331ca XL |
316 | if !self.is_beginning_of_line() { |
317 | self.word(" "); | |
c30ab7b3 | 318 | } |
b039eaaf | 319 | if cmnt.lines.len() == 1 { |
416331ca XL |
320 | self.word(cmnt.lines[0].clone()); |
321 | self.hardbreak() | |
b039eaaf | 322 | } else { |
5099ac24 | 323 | self.visual_align(); |
b039eaaf SL |
324 | for line in &cmnt.lines { |
325 | if !line.is_empty() { | |
416331ca | 326 | self.word(line.clone()); |
b039eaaf | 327 | } |
416331ca | 328 | self.hardbreak(); |
b039eaaf | 329 | } |
416331ca | 330 | self.end(); |
b039eaaf SL |
331 | } |
332 | } | |
3dfed10e | 333 | CommentStyle::BlankLine => { |
b039eaaf | 334 | // We need to do at least one, possibly two hardbreaks. |
416331ca | 335 | let twice = match self.last_token() { |
5099ac24 FG |
336 | Some(pp::Token::String(s)) => ";" == s, |
337 | Some(pp::Token::Begin(_)) => true, | |
338 | Some(pp::Token::End) => true, | |
dfeec247 | 339 | _ => false, |
b039eaaf | 340 | }; |
416331ca XL |
341 | if twice { |
342 | self.hardbreak(); | |
b039eaaf | 343 | } |
416331ca | 344 | self.hardbreak(); |
b039eaaf | 345 | } |
416331ca | 346 | } |
74b04a01 XL |
347 | if let Some(cmnts) = self.comments() { |
348 | cmnts.current += 1; | |
b039eaaf SL |
349 | } |
350 | } | |
351 | ||
3dfed10e | 352 | fn next_comment(&mut self) -> Option<Comment> { |
416331ca | 353 | self.comments().as_mut().and_then(|c| c.next()) |
b039eaaf SL |
354 | } |
355 | ||
a2a8927a XL |
356 | fn maybe_print_trailing_comment(&mut self, span: rustc_span::Span, next_pos: Option<BytePos>) { |
357 | if let Some(cmnts) = self.comments() { | |
358 | if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) { | |
359 | self.print_comment(&cmnt); | |
360 | } | |
361 | } | |
362 | } | |
363 | ||
364 | fn print_remaining_comments(&mut self) { | |
365 | // If there aren't any remaining comments, then we need to manually | |
366 | // make sure there is a line break at the end. | |
367 | if self.next_comment().is_none() { | |
368 | self.hardbreak(); | |
369 | } | |
370 | while let Some(ref cmnt) = self.next_comment() { | |
371 | self.print_comment(cmnt) | |
372 | } | |
373 | } | |
374 | ||
416331ca XL |
375 | fn print_literal(&mut self, lit: &ast::Lit) { |
376 | self.maybe_print_comment(lit.span.lo()); | |
f2b60f7d | 377 | self.word(lit.token_lit.to_string()) |
b039eaaf SL |
378 | } |
379 | ||
dfeec247 | 380 | fn print_string(&mut self, st: &str, style: ast::StrStyle) { |
b039eaaf | 381 | let st = match style { |
064997fb | 382 | ast::StrStyle::Cooked => format!("\"{}\"", st.escape_debug()), |
7453a54e | 383 | ast::StrStyle::Raw(n) => { |
dfeec247 | 384 | format!("r{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = st) |
b039eaaf SL |
385 | } |
386 | }; | |
416331ca | 387 | self.word(st) |
b039eaaf SL |
388 | } |
389 | ||
3dfed10e | 390 | fn print_symbol(&mut self, sym: Symbol, style: ast::StrStyle) { |
a2a8927a | 391 | self.print_string(sym.as_str(), style); |
3dfed10e XL |
392 | } |
393 | ||
a2a8927a | 394 | fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) -> bool { |
92a42be0 SL |
395 | self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true) |
396 | } | |
397 | ||
a2a8927a | 398 | fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) -> bool { |
92a42be0 | 399 | self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false) |
b039eaaf SL |
400 | } |
401 | ||
a2a8927a | 402 | fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) -> bool { |
92a42be0 SL |
403 | self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true) |
404 | } | |
405 | ||
a2a8927a | 406 | fn print_inner_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool { |
92a42be0 SL |
407 | self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true) |
408 | } | |
409 | ||
a2a8927a | 410 | fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool { |
92a42be0 SL |
411 | self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true) |
412 | } | |
413 | ||
dfeec247 XL |
414 | fn print_either_attributes( |
415 | &mut self, | |
416 | attrs: &[ast::Attribute], | |
417 | kind: ast::AttrStyle, | |
418 | is_inline: bool, | |
419 | trailing_hardbreak: bool, | |
a2a8927a XL |
420 | ) -> bool { |
421 | let mut printed = false; | |
b039eaaf | 422 | for attr in attrs { |
476ff2be | 423 | if attr.style == kind { |
416331ca | 424 | self.print_attribute_inline(attr, is_inline); |
3157f602 | 425 | if is_inline { |
416331ca | 426 | self.nbsp(); |
3157f602 | 427 | } |
a2a8927a | 428 | printed = true; |
b039eaaf SL |
429 | } |
430 | } | |
a2a8927a | 431 | if printed && trailing_hardbreak && !is_inline { |
416331ca | 432 | self.hardbreak_if_not_bol(); |
83c7162d | 433 | } |
a2a8927a | 434 | printed |
83c7162d XL |
435 | } |
436 | ||
416331ca | 437 | fn print_attribute(&mut self, attr: &ast::Attribute) { |
92a42be0 SL |
438 | self.print_attribute_inline(attr, false) |
439 | } | |
440 | ||
dfeec247 | 441 | fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) { |
92a42be0 | 442 | if !is_inline { |
416331ca | 443 | self.hardbreak_if_not_bol(); |
92a42be0 | 444 | } |
416331ca | 445 | self.maybe_print_comment(attr.span.lo()); |
60c5eb7d | 446 | match attr.kind { |
f2b60f7d | 447 | ast::AttrKind::Normal(ref normal) => { |
60c5eb7d XL |
448 | match attr.style { |
449 | ast::AttrStyle::Inner => self.word("#!["), | |
450 | ast::AttrStyle::Outer => self.word("#["), | |
451 | } | |
f2b60f7d | 452 | self.print_attr_item(&normal.item, attr.span); |
60c5eb7d XL |
453 | self.word("]"); |
454 | } | |
3dfed10e XL |
455 | ast::AttrKind::DocComment(comment_kind, data) => { |
456 | self.word(doc_comment_to_string(comment_kind, attr.style, data)); | |
60c5eb7d | 457 | self.hardbreak() |
416331ca | 458 | } |
e74abb32 XL |
459 | } |
460 | } | |
461 | ||
462 | fn print_attr_item(&mut self, item: &ast::AttrItem, span: Span) { | |
463 | self.ibox(0); | |
60c5eb7d XL |
464 | match &item.args { |
465 | MacArgs::Delimited(_, delim, tokens) => self.print_mac_common( | |
466 | Some(MacHeader::Path(&item.path)), | |
467 | false, | |
468 | None, | |
04454e1e | 469 | Some(delim.to_token()), |
f035d41b | 470 | tokens, |
60c5eb7d XL |
471 | true, |
472 | span, | |
473 | ), | |
04454e1e | 474 | MacArgs::Empty => { |
e74abb32 | 475 | self.print_path(&item.path, false, 0); |
04454e1e FG |
476 | } |
477 | MacArgs::Eq(_, MacArgsEq::Ast(expr)) => { | |
478 | self.print_path(&item.path, false, 0); | |
479 | self.space(); | |
480 | self.word_space("="); | |
481 | let token_str = self.expr_to_string(expr); | |
482 | self.word(token_str); | |
483 | } | |
484 | MacArgs::Eq(_, MacArgsEq::Hir(lit)) => { | |
485 | self.print_path(&item.path, false, 0); | |
486 | self.space(); | |
487 | self.word_space("="); | |
488 | let token_str = self.literal_to_string(lit); | |
489 | self.word(token_str); | |
cc61c64b | 490 | } |
b039eaaf | 491 | } |
e74abb32 | 492 | self.end(); |
b039eaaf | 493 | } |
1a4d82fc | 494 | |
416331ca | 495 | fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) { |
532ac7d7 | 496 | match item { |
dfeec247 XL |
497 | ast::NestedMetaItem::MetaItem(ref mi) => self.print_meta_item(mi), |
498 | ast::NestedMetaItem::Literal(ref lit) => self.print_literal(lit), | |
9e0c209e SL |
499 | } |
500 | } | |
501 | ||
416331ca XL |
502 | fn print_meta_item(&mut self, item: &ast::MetaItem) { |
503 | self.ibox(INDENT_UNIT); | |
e74abb32 | 504 | match item.kind { |
416331ca | 505 | ast::MetaItemKind::Word => self.print_path(&item.path, false, 0), |
476ff2be | 506 | ast::MetaItemKind::NameValue(ref value) => { |
416331ca XL |
507 | self.print_path(&item.path, false, 0); |
508 | self.space(); | |
509 | self.word_space("="); | |
510 | self.print_literal(value); | |
b039eaaf | 511 | } |
476ff2be | 512 | ast::MetaItemKind::List(ref items) => { |
416331ca XL |
513 | self.print_path(&item.path, false, 0); |
514 | self.popen(); | |
a2a8927a | 515 | self.commasep(Consistent, &items, |s, i| s.print_meta_list_item(i)); |
416331ca | 516 | self.pclose(); |
b039eaaf SL |
517 | } |
518 | } | |
416331ca | 519 | self.end(); |
b039eaaf | 520 | } |
92a42be0 | 521 | |
cc61c64b XL |
522 | /// This doesn't deserve to be called "pretty" printing, but it should be |
523 | /// meaning-preserving. A quick hack that might help would be to look at the | |
524 | /// spans embedded in the TTs to decide where to put spaces and newlines. | |
525 | /// But it'd be better to parse these according to the grammar of the | |
526 | /// appropriate macro, transcribe back into the grammar we just parsed from, | |
527 | /// and then pretty-print the resulting AST nodes (so, e.g., we print | |
528 | /// expression arguments as expressions). It can be done! I think. | |
f035d41b | 529 | fn print_tt(&mut self, tt: &TokenTree, convert_dollar_crate: bool) { |
cc61c64b | 530 | match tt { |
064997fb | 531 | TokenTree::Token(token, _) => { |
29967ef6 XL |
532 | let token_str = self.token_to_string_ext(&token, convert_dollar_crate); |
533 | self.word(token_str); | |
ba9703b0 XL |
534 | if let token::DocComment(..) = token.kind { |
535 | self.hardbreak() | |
cc61c64b XL |
536 | } |
537 | } | |
416331ca XL |
538 | TokenTree::Delimited(dspan, delim, tts) => { |
539 | self.print_mac_common( | |
dfeec247 XL |
540 | None, |
541 | false, | |
542 | None, | |
04454e1e | 543 | Some(*delim), |
dfeec247 XL |
544 | tts, |
545 | convert_dollar_crate, | |
546 | dspan.entire(), | |
416331ca XL |
547 | ); |
548 | } | |
cc61c64b XL |
549 | } |
550 | } | |
551 | ||
f035d41b XL |
552 | fn print_tts(&mut self, tts: &TokenStream, convert_dollar_crate: bool) { |
553 | let mut iter = tts.trees().peekable(); | |
ba9703b0 | 554 | while let Some(tt) = iter.next() { |
923072b8 | 555 | self.print_tt(tt, convert_dollar_crate); |
f035d41b | 556 | if let Some(next) = iter.peek() { |
923072b8 | 557 | if tt_prepend_space(next, tt) { |
f035d41b XL |
558 | self.space(); |
559 | } | |
cc61c64b | 560 | } |
cc61c64b | 561 | } |
cc61c64b XL |
562 | } |
563 | ||
416331ca XL |
564 | fn print_mac_common( |
565 | &mut self, | |
566 | header: Option<MacHeader<'_>>, | |
567 | has_bang: bool, | |
f9f354fc | 568 | ident: Option<Ident>, |
04454e1e | 569 | delim: Option<Delimiter>, |
f035d41b | 570 | tts: &TokenStream, |
416331ca XL |
571 | convert_dollar_crate: bool, |
572 | span: Span, | |
573 | ) { | |
04454e1e | 574 | if delim == Some(Delimiter::Brace) { |
416331ca XL |
575 | self.cbox(INDENT_UNIT); |
576 | } | |
577 | match header { | |
578 | Some(MacHeader::Path(path)) => self.print_path(path, false, 0), | |
579 | Some(MacHeader::Keyword(kw)) => self.word(kw), | |
580 | None => {} | |
581 | } | |
582 | if has_bang { | |
583 | self.word("!"); | |
584 | } | |
585 | if let Some(ident) = ident { | |
586 | self.nbsp(); | |
587 | self.print_ident(ident); | |
588 | } | |
589 | match delim { | |
04454e1e | 590 | Some(Delimiter::Brace) => { |
416331ca XL |
591 | if header.is_some() || has_bang || ident.is_some() { |
592 | self.nbsp(); | |
593 | } | |
594 | self.word("{"); | |
595 | if !tts.is_empty() { | |
596 | self.space(); | |
597 | } | |
04454e1e FG |
598 | self.ibox(0); |
599 | self.print_tts(tts, convert_dollar_crate); | |
600 | self.end(); | |
a2a8927a XL |
601 | let empty = tts.is_empty(); |
602 | self.bclose(span, empty); | |
603 | } | |
04454e1e FG |
604 | Some(delim) => { |
605 | let token_str = self.token_kind_to_string(&token::OpenDelim(delim)); | |
606 | self.word(token_str); | |
607 | self.ibox(0); | |
608 | self.print_tts(tts, convert_dollar_crate); | |
609 | self.end(); | |
29967ef6 | 610 | let token_str = self.token_kind_to_string(&token::CloseDelim(delim)); |
04454e1e FG |
611 | self.word(token_str); |
612 | } | |
613 | None => { | |
614 | self.ibox(0); | |
615 | self.print_tts(tts, convert_dollar_crate); | |
616 | self.end(); | |
29967ef6 | 617 | } |
ff7c6d11 | 618 | } |
b039eaaf SL |
619 | } |
620 | ||
94222f64 XL |
621 | fn print_mac_def( |
622 | &mut self, | |
623 | macro_def: &ast::MacroDef, | |
624 | ident: &Ident, | |
5099ac24 | 625 | sp: Span, |
94222f64 XL |
626 | print_visibility: impl FnOnce(&mut Self), |
627 | ) { | |
628 | let (kw, has_bang) = if macro_def.macro_rules { | |
629 | ("macro_rules", true) | |
630 | } else { | |
631 | print_visibility(self); | |
632 | ("macro", false) | |
633 | }; | |
634 | self.print_mac_common( | |
635 | Some(MacHeader::Keyword(kw)), | |
636 | has_bang, | |
637 | Some(*ident), | |
638 | macro_def.body.delim(), | |
639 | ¯o_def.body.inner_tokens(), | |
640 | true, | |
5099ac24 | 641 | sp, |
94222f64 XL |
642 | ); |
643 | if macro_def.body.need_semicolon() { | |
644 | self.word(";"); | |
645 | } | |
646 | } | |
647 | ||
416331ca XL |
648 | fn print_path(&mut self, path: &ast::Path, colons_before_params: bool, depth: usize) { |
649 | self.maybe_print_comment(path.span.lo()); | |
b039eaaf | 650 | |
416331ca XL |
651 | for (i, segment) in path.segments[..path.segments.len() - depth].iter().enumerate() { |
652 | if i > 0 { | |
653 | self.word("::") | |
654 | } | |
655 | self.print_path_segment(segment, colons_before_params); | |
656 | } | |
b039eaaf SL |
657 | } |
658 | ||
416331ca XL |
659 | fn print_path_segment(&mut self, segment: &ast::PathSegment, colons_before_params: bool) { |
660 | if segment.ident.name != kw::PathRoot { | |
661 | self.print_ident(segment.ident); | |
662 | if let Some(ref args) = segment.args { | |
663 | self.print_generic_args(args, colons_before_params); | |
664 | } | |
665 | } | |
b039eaaf | 666 | } |
1a4d82fc | 667 | |
416331ca | 668 | fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) { |
a1dfa0c6 | 669 | let w = w.into(); |
e1599b0c | 670 | // Outer-box is consistent. |
416331ca | 671 | self.cbox(INDENT_UNIT); |
e1599b0c | 672 | // Head-box is inconsistent. |
5099ac24 | 673 | self.ibox(0); |
e1599b0c | 674 | // Keyword that starts the head. |
1a4d82fc | 675 | if !w.is_empty() { |
416331ca | 676 | self.word_nbsp(w); |
223e47cc | 677 | } |
223e47cc | 678 | } |
223e47cc | 679 | |
416331ca XL |
680 | fn bopen(&mut self) { |
681 | self.word("{"); | |
e1599b0c | 682 | self.end(); // Close the head-box. |
1a4d82fc JJ |
683 | } |
684 | ||
a2a8927a XL |
685 | fn bclose_maybe_open(&mut self, span: rustc_span::Span, empty: bool, close_box: bool) { |
686 | let has_comment = self.maybe_print_comment(span.hi()); | |
687 | if !empty || has_comment { | |
688 | self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize)); | |
689 | } | |
416331ca | 690 | self.word("}"); |
1a4d82fc | 691 | if close_box { |
e1599b0c | 692 | self.end(); // Close the outer-box. |
223e47cc | 693 | } |
223e47cc | 694 | } |
223e47cc | 695 | |
a2a8927a XL |
696 | fn bclose(&mut self, span: rustc_span::Span, empty: bool) { |
697 | let close_box = true; | |
698 | self.bclose_maybe_open(span, empty, close_box) | |
223e47cc | 699 | } |
223e47cc | 700 | |
416331ca XL |
701 | fn break_offset_if_not_bol(&mut self, n: usize, off: isize) { |
702 | if !self.is_beginning_of_line() { | |
703 | self.break_offset(n, off) | |
5099ac24 FG |
704 | } else if off != 0 { |
705 | if let Some(last_token) = self.last_token_still_buffered() { | |
706 | if last_token.is_hardbreak_tok() { | |
707 | // We do something pretty sketchy here: tuck the nonzero | |
708 | // offset-adjustment we were going to deposit along with the | |
709 | // break into the previous hardbreak. | |
710 | self.replace_last_token_still_buffered(pp::Printer::hardbreak_tok_offset(off)); | |
711 | } | |
712 | } | |
416331ca XL |
713 | } |
714 | } | |
29967ef6 XL |
715 | |
716 | fn nonterminal_to_string(&self, nt: &Nonterminal) -> String { | |
717 | match *nt { | |
718 | token::NtExpr(ref e) => self.expr_to_string(e), | |
719 | token::NtMeta(ref e) => self.attr_item_to_string(e), | |
720 | token::NtTy(ref e) => self.ty_to_string(e), | |
721 | token::NtPath(ref e) => self.path_to_string(e), | |
722 | token::NtItem(ref e) => self.item_to_string(e), | |
723 | token::NtBlock(ref e) => self.block_to_string(e), | |
724 | token::NtStmt(ref e) => self.stmt_to_string(e), | |
725 | token::NtPat(ref e) => self.pat_to_string(e), | |
726 | token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw).to_string(), | |
727 | token::NtLifetime(e) => e.to_string(), | |
728 | token::NtLiteral(ref e) => self.expr_to_string(e), | |
29967ef6 XL |
729 | token::NtVis(ref e) => self.vis_to_string(e), |
730 | } | |
731 | } | |
732 | ||
733 | /// Print the token kind precisely, without converting `$crate` into its respective crate name. | |
94222f64 | 734 | fn token_kind_to_string(&self, tok: &TokenKind) -> Cow<'static, str> { |
29967ef6 XL |
735 | self.token_kind_to_string_ext(tok, None) |
736 | } | |
737 | ||
738 | fn token_kind_to_string_ext( | |
739 | &self, | |
740 | tok: &TokenKind, | |
741 | convert_dollar_crate: Option<Span>, | |
94222f64 | 742 | ) -> Cow<'static, str> { |
29967ef6 | 743 | match *tok { |
94222f64 XL |
744 | token::Eq => "=".into(), |
745 | token::Lt => "<".into(), | |
746 | token::Le => "<=".into(), | |
747 | token::EqEq => "==".into(), | |
748 | token::Ne => "!=".into(), | |
749 | token::Ge => ">=".into(), | |
750 | token::Gt => ">".into(), | |
751 | token::Not => "!".into(), | |
752 | token::Tilde => "~".into(), | |
753 | token::OrOr => "||".into(), | |
754 | token::AndAnd => "&&".into(), | |
755 | token::BinOp(op) => binop_to_string(op).into(), | |
756 | token::BinOpEq(op) => format!("{}=", binop_to_string(op)).into(), | |
29967ef6 XL |
757 | |
758 | /* Structural symbols */ | |
94222f64 XL |
759 | token::At => "@".into(), |
760 | token::Dot => ".".into(), | |
761 | token::DotDot => "..".into(), | |
762 | token::DotDotDot => "...".into(), | |
763 | token::DotDotEq => "..=".into(), | |
764 | token::Comma => ",".into(), | |
765 | token::Semi => ";".into(), | |
766 | token::Colon => ":".into(), | |
767 | token::ModSep => "::".into(), | |
768 | token::RArrow => "->".into(), | |
769 | token::LArrow => "<-".into(), | |
770 | token::FatArrow => "=>".into(), | |
04454e1e FG |
771 | token::OpenDelim(Delimiter::Parenthesis) => "(".into(), |
772 | token::CloseDelim(Delimiter::Parenthesis) => ")".into(), | |
773 | token::OpenDelim(Delimiter::Bracket) => "[".into(), | |
774 | token::CloseDelim(Delimiter::Bracket) => "]".into(), | |
775 | token::OpenDelim(Delimiter::Brace) => "{".into(), | |
776 | token::CloseDelim(Delimiter::Brace) => "}".into(), | |
777 | token::OpenDelim(Delimiter::Invisible) | token::CloseDelim(Delimiter::Invisible) => { | |
778 | "".into() | |
779 | } | |
94222f64 XL |
780 | token::Pound => "#".into(), |
781 | token::Dollar => "$".into(), | |
782 | token::Question => "?".into(), | |
783 | token::SingleQuote => "'".into(), | |
29967ef6 XL |
784 | |
785 | /* Literals */ | |
94222f64 | 786 | token::Literal(lit) => literal_to_string(lit).into(), |
29967ef6 XL |
787 | |
788 | /* Name components */ | |
789 | token::Ident(s, is_raw) => { | |
94222f64 | 790 | IdentPrinter::new(s, is_raw, convert_dollar_crate).to_string().into() |
29967ef6 | 791 | } |
94222f64 | 792 | token::Lifetime(s) => s.to_string().into(), |
29967ef6 XL |
793 | |
794 | /* Other */ | |
795 | token::DocComment(comment_kind, attr_style, data) => { | |
94222f64 | 796 | doc_comment_to_string(comment_kind, attr_style, data).into() |
29967ef6 | 797 | } |
94222f64 | 798 | token::Eof => "<eof>".into(), |
29967ef6 | 799 | |
94222f64 | 800 | token::Interpolated(ref nt) => self.nonterminal_to_string(nt).into(), |
29967ef6 XL |
801 | } |
802 | } | |
803 | ||
804 | /// Print the token precisely, without converting `$crate` into its respective crate name. | |
94222f64 | 805 | fn token_to_string(&self, token: &Token) -> Cow<'static, str> { |
29967ef6 XL |
806 | self.token_to_string_ext(token, false) |
807 | } | |
808 | ||
94222f64 | 809 | fn token_to_string_ext(&self, token: &Token, convert_dollar_crate: bool) -> Cow<'static, str> { |
29967ef6 XL |
810 | let convert_dollar_crate = convert_dollar_crate.then_some(token.span); |
811 | self.token_kind_to_string_ext(&token.kind, convert_dollar_crate) | |
812 | } | |
813 | ||
814 | fn ty_to_string(&self, ty: &ast::Ty) -> String { | |
a2a8927a | 815 | Self::to_string(|s| s.print_type(ty)) |
29967ef6 XL |
816 | } |
817 | ||
818 | fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String { | |
923072b8 | 819 | Self::to_string(|s| s.print_type_bounds(bounds)) |
29967ef6 XL |
820 | } |
821 | ||
822 | fn pat_to_string(&self, pat: &ast::Pat) -> String { | |
a2a8927a | 823 | Self::to_string(|s| s.print_pat(pat)) |
29967ef6 XL |
824 | } |
825 | ||
826 | fn expr_to_string(&self, e: &ast::Expr) -> String { | |
a2a8927a | 827 | Self::to_string(|s| s.print_expr(e)) |
29967ef6 XL |
828 | } |
829 | ||
04454e1e FG |
830 | fn literal_to_string(&self, lit: &ast::Lit) -> String { |
831 | Self::to_string(|s| s.print_literal(lit)) | |
832 | } | |
833 | ||
29967ef6 | 834 | fn tt_to_string(&self, tt: &TokenTree) -> String { |
a2a8927a | 835 | Self::to_string(|s| s.print_tt(tt, false)) |
29967ef6 XL |
836 | } |
837 | ||
838 | fn tts_to_string(&self, tokens: &TokenStream) -> String { | |
a2a8927a | 839 | Self::to_string(|s| s.print_tts(tokens, false)) |
29967ef6 XL |
840 | } |
841 | ||
842 | fn stmt_to_string(&self, stmt: &ast::Stmt) -> String { | |
a2a8927a | 843 | Self::to_string(|s| s.print_stmt(stmt)) |
29967ef6 XL |
844 | } |
845 | ||
846 | fn item_to_string(&self, i: &ast::Item) -> String { | |
a2a8927a | 847 | Self::to_string(|s| s.print_item(i)) |
29967ef6 XL |
848 | } |
849 | ||
04454e1e FG |
850 | fn assoc_item_to_string(&self, i: &ast::AssocItem) -> String { |
851 | Self::to_string(|s| s.print_assoc_item(i)) | |
852 | } | |
853 | ||
854 | fn foreign_item_to_string(&self, i: &ast::ForeignItem) -> String { | |
855 | Self::to_string(|s| s.print_foreign_item(i)) | |
856 | } | |
857 | ||
29967ef6 | 858 | fn generic_params_to_string(&self, generic_params: &[ast::GenericParam]) -> String { |
a2a8927a | 859 | Self::to_string(|s| s.print_generic_params(generic_params)) |
29967ef6 XL |
860 | } |
861 | ||
862 | fn path_to_string(&self, p: &ast::Path) -> String { | |
a2a8927a | 863 | Self::to_string(|s| s.print_path(p, false, 0)) |
29967ef6 XL |
864 | } |
865 | ||
866 | fn path_segment_to_string(&self, p: &ast::PathSegment) -> String { | |
a2a8927a | 867 | Self::to_string(|s| s.print_path_segment(p, false)) |
29967ef6 XL |
868 | } |
869 | ||
870 | fn vis_to_string(&self, v: &ast::Visibility) -> String { | |
a2a8927a | 871 | Self::to_string(|s| s.print_visibility(v)) |
29967ef6 XL |
872 | } |
873 | ||
874 | fn block_to_string(&self, blk: &ast::Block) -> String { | |
a2a8927a | 875 | Self::to_string(|s| { |
29967ef6 XL |
876 | // Containing cbox, will be closed by `print_block` at `}`. |
877 | s.cbox(INDENT_UNIT); | |
878 | // Head-ibox, will be closed by `print_block` after `{`. | |
879 | s.ibox(0); | |
880 | s.print_block(blk) | |
881 | }) | |
882 | } | |
883 | ||
884 | fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String { | |
a2a8927a | 885 | Self::to_string(|s| s.print_meta_list_item(li)) |
29967ef6 XL |
886 | } |
887 | ||
888 | fn attr_item_to_string(&self, ai: &ast::AttrItem) -> String { | |
a2a8927a | 889 | Self::to_string(|s| s.print_attr_item(ai, ai.path.span)) |
29967ef6 XL |
890 | } |
891 | ||
892 | fn attribute_to_string(&self, attr: &ast::Attribute) -> String { | |
a2a8927a | 893 | Self::to_string(|s| s.print_attribute(attr)) |
29967ef6 XL |
894 | } |
895 | ||
896 | fn param_to_string(&self, arg: &ast::Param) -> String { | |
a2a8927a | 897 | Self::to_string(|s| s.print_param(arg, false)) |
29967ef6 XL |
898 | } |
899 | ||
a2a8927a | 900 | fn to_string(f: impl FnOnce(&mut State<'_>)) -> String { |
29967ef6 | 901 | let mut printer = State::new(); |
29967ef6 XL |
902 | f(&mut printer); |
903 | printer.s.eof() | |
904 | } | |
416331ca XL |
905 | } |
906 | ||
907 | impl<'a> PrintState<'a> for State<'a> { | |
908 | fn comments(&mut self) -> &mut Option<Comments<'a>> { | |
909 | &mut self.comments | |
910 | } | |
911 | ||
f9f354fc | 912 | fn print_ident(&mut self, ident: Ident) { |
a2a8927a | 913 | self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); |
416331ca XL |
914 | self.ann.post(self, AnnNode::Ident(&ident)) |
915 | } | |
916 | ||
917 | fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool) { | |
918 | if colons_before_params { | |
a2a8927a | 919 | self.word("::") |
416331ca XL |
920 | } |
921 | ||
922 | match *args { | |
923 | ast::GenericArgs::AngleBracketed(ref data) => { | |
a2a8927a | 924 | self.word("<"); |
ba9703b0 XL |
925 | self.commasep(Inconsistent, &data.args, |s, arg| match arg { |
926 | ast::AngleBracketedArg::Arg(a) => s.print_generic_arg(a), | |
927 | ast::AngleBracketedArg::Constraint(c) => s.print_assoc_constraint(c), | |
416331ca | 928 | }); |
a2a8927a | 929 | self.word(">") |
416331ca XL |
930 | } |
931 | ||
932 | ast::GenericArgs::Parenthesized(ref data) => { | |
a2a8927a | 933 | self.word("("); |
dfeec247 | 934 | self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(ty)); |
a2a8927a | 935 | self.word(")"); |
dfeec247 | 936 | self.print_fn_ret_ty(&data.output); |
223e47cc | 937 | } |
223e47cc LB |
938 | } |
939 | } | |
416331ca | 940 | } |
223e47cc | 941 | |
416331ca | 942 | impl<'a> State<'a> { |
29967ef6 | 943 | pub fn new() -> State<'a> { |
5099ac24 | 944 | State { s: pp::Printer::new(), comments: None, ann: &NoAnn } |
29967ef6 XL |
945 | } |
946 | ||
923072b8 FG |
947 | pub(crate) fn commasep_cmnt<T, F, G>( |
948 | &mut self, | |
949 | b: Breaks, | |
950 | elts: &[T], | |
951 | mut op: F, | |
952 | mut get_span: G, | |
953 | ) where | |
416331ca | 954 | F: FnMut(&mut State<'_>, &T), |
dfeec247 | 955 | G: FnMut(&T) -> rustc_span::Span, |
1a4d82fc | 956 | { |
416331ca | 957 | self.rbox(0, b); |
1a4d82fc | 958 | let len = elts.len(); |
85aaf69f SL |
959 | let mut i = 0; |
960 | for elt in elts { | |
416331ca XL |
961 | self.maybe_print_comment(get_span(elt).hi()); |
962 | op(self, elt); | |
85aaf69f | 963 | i += 1; |
1a4d82fc | 964 | if i < len { |
a2a8927a | 965 | self.word(","); |
dfeec247 | 966 | self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi())); |
416331ca | 967 | self.space_if_not_bol(); |
1a4d82fc JJ |
968 | } |
969 | } | |
416331ca | 970 | self.end(); |
1a4d82fc | 971 | } |
223e47cc | 972 | |
923072b8 | 973 | pub(crate) fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<ast::Expr>]) { |
7cac9316 | 974 | self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span) |
1a4d82fc | 975 | } |
223e47cc | 976 | |
60c5eb7d | 977 | pub fn print_opt_lifetime(&mut self, lifetime: &Option<ast::Lifetime>) { |
8faf50e0 | 978 | if let Some(lt) = *lifetime { |
416331ca XL |
979 | self.print_lifetime(lt); |
980 | self.nbsp(); | |
1a4d82fc | 981 | } |
223e47cc | 982 | } |
223e47cc | 983 | |
5099ac24 | 984 | pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocConstraint) { |
ba9703b0 | 985 | self.print_ident(constraint.ident); |
6a06907d | 986 | constraint.gen_args.as_ref().map(|args| self.print_generic_args(args, false)); |
a2a8927a | 987 | self.space(); |
ba9703b0 | 988 | match &constraint.kind { |
5099ac24 | 989 | ast::AssocConstraintKind::Equality { term } => { |
ba9703b0 | 990 | self.word_space("="); |
5099ac24 FG |
991 | match term { |
992 | Term::Ty(ty) => self.print_type(ty), | |
04454e1e | 993 | Term::Const(c) => self.print_expr_anon_const(c, &[]), |
5099ac24 | 994 | } |
ba9703b0 | 995 | } |
923072b8 FG |
996 | ast::AssocConstraintKind::Bound { bounds } => { |
997 | if !bounds.is_empty() { | |
998 | self.word_nbsp(":"); | |
999 | self.print_type_bounds(&bounds); | |
1000 | } | |
1001 | } | |
ba9703b0 XL |
1002 | } |
1003 | } | |
1004 | ||
1005 | pub fn print_generic_arg(&mut self, generic_arg: &GenericArg) { | |
8faf50e0 XL |
1006 | match generic_arg { |
1007 | GenericArg::Lifetime(lt) => self.print_lifetime(*lt), | |
1008 | GenericArg::Type(ty) => self.print_type(ty), | |
9fa01778 | 1009 | GenericArg::Const(ct) => self.print_expr(&ct.value), |
8faf50e0 XL |
1010 | } |
1011 | } | |
1012 | ||
60c5eb7d | 1013 | pub fn print_type(&mut self, ty: &ast::Ty) { |
416331ca XL |
1014 | self.maybe_print_comment(ty.span.lo()); |
1015 | self.ibox(0); | |
e74abb32 | 1016 | match ty.kind { |
c30ab7b3 | 1017 | ast::TyKind::Slice(ref ty) => { |
a2a8927a | 1018 | self.word("["); |
416331ca | 1019 | self.print_type(ty); |
a2a8927a | 1020 | self.word("]"); |
1a4d82fc | 1021 | } |
7453a54e | 1022 | ast::TyKind::Ptr(ref mt) => { |
a2a8927a | 1023 | self.word("*"); |
60c5eb7d | 1024 | self.print_mt(mt, true); |
1a4d82fc | 1025 | } |
7453a54e | 1026 | ast::TyKind::Rptr(ref lifetime, ref mt) => { |
a2a8927a | 1027 | self.word("&"); |
416331ca | 1028 | self.print_opt_lifetime(lifetime); |
60c5eb7d | 1029 | self.print_mt(mt, false); |
1a4d82fc | 1030 | } |
5bcae85e | 1031 | ast::TyKind::Never => { |
a2a8927a | 1032 | self.word("!"); |
dfeec247 | 1033 | } |
7453a54e | 1034 | ast::TyKind::Tup(ref elts) => { |
416331ca | 1035 | self.popen(); |
a2a8927a | 1036 | self.commasep(Inconsistent, &elts, |s, ty| s.print_type(ty)); |
1a4d82fc | 1037 | if elts.len() == 1 { |
a2a8927a | 1038 | self.word(","); |
1a4d82fc | 1039 | } |
416331ca | 1040 | self.pclose(); |
1a4d82fc | 1041 | } |
7453a54e | 1042 | ast::TyKind::Paren(ref typ) => { |
416331ca XL |
1043 | self.popen(); |
1044 | self.print_type(typ); | |
1045 | self.pclose(); | |
1a4d82fc | 1046 | } |
7453a54e | 1047 | ast::TyKind::BareFn(ref f) => { |
dfeec247 | 1048 | self.print_ty_fn(f.ext, f.unsafety, &f.decl, None, &f.generic_params); |
1a4d82fc | 1049 | } |
7453a54e | 1050 | ast::TyKind::Path(None, ref path) => { |
416331ca | 1051 | self.print_path(path, false, 0); |
c34b1796 | 1052 | } |
dfeec247 | 1053 | ast::TyKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, false), |
abe05a73 | 1054 | ast::TyKind::TraitObject(ref bounds, syntax) => { |
923072b8 FG |
1055 | if syntax == ast::TraitObjectSyntax::Dyn { |
1056 | self.word_nbsp("dyn"); | |
1057 | } | |
1058 | self.print_type_bounds(bounds); | |
1a4d82fc | 1059 | } |
8faf50e0 | 1060 | ast::TyKind::ImplTrait(_, ref bounds) => { |
923072b8 FG |
1061 | self.word_nbsp("impl"); |
1062 | self.print_type_bounds(bounds); | |
5bcae85e | 1063 | } |
94b46f34 | 1064 | ast::TyKind::Array(ref ty, ref length) => { |
a2a8927a | 1065 | self.word("["); |
416331ca | 1066 | self.print_type(ty); |
a2a8927a | 1067 | self.word("; "); |
416331ca | 1068 | self.print_expr(&length.value); |
a2a8927a | 1069 | self.word("]"); |
1a4d82fc | 1070 | } |
7453a54e | 1071 | ast::TyKind::Typeof(ref e) => { |
a2a8927a | 1072 | self.word("typeof("); |
416331ca | 1073 | self.print_expr(&e.value); |
a2a8927a | 1074 | self.word(")"); |
1a4d82fc | 1075 | } |
7453a54e | 1076 | ast::TyKind::Infer => { |
a2a8927a | 1077 | self.word("_"); |
3157f602 | 1078 | } |
cc61c64b | 1079 | ast::TyKind::Err => { |
416331ca | 1080 | self.popen(); |
a2a8927a | 1081 | self.word("/*ERROR*/"); |
416331ca | 1082 | self.pclose(); |
cc61c64b | 1083 | } |
3157f602 | 1084 | ast::TyKind::ImplicitSelf => { |
a2a8927a | 1085 | self.word("Self"); |
1a4d82fc | 1086 | } |
ba9703b0 | 1087 | ast::TyKind::MacCall(ref m) => { |
416331ca | 1088 | self.print_mac(m); |
e9174d1e | 1089 | } |
532ac7d7 | 1090 | ast::TyKind::CVarArgs => { |
a2a8927a | 1091 | self.word("..."); |
532ac7d7 | 1092 | } |
223e47cc | 1093 | } |
416331ca | 1094 | self.end(); |
1a4d82fc JJ |
1095 | } |
1096 | ||
416331ca | 1097 | fn print_trait_ref(&mut self, t: &ast::TraitRef) { |
0531ce1d | 1098 | self.print_path(&t.path, false, 0) |
223e47cc | 1099 | } |
223e47cc | 1100 | |
dfeec247 | 1101 | fn print_formal_generic_params(&mut self, generic_params: &[ast::GenericParam]) { |
ff7c6d11 | 1102 | if !generic_params.is_empty() { |
a2a8927a | 1103 | self.word("for"); |
416331ca XL |
1104 | self.print_generic_params(generic_params); |
1105 | self.nbsp(); | |
1a4d82fc | 1106 | } |
85aaf69f | 1107 | } |
1a4d82fc | 1108 | |
416331ca XL |
1109 | fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) { |
1110 | self.print_formal_generic_params(&t.bound_generic_params); | |
1a4d82fc JJ |
1111 | self.print_trait_ref(&t.trait_ref) |
1112 | } | |
1113 | ||
923072b8 | 1114 | pub(crate) fn print_stmt(&mut self, st: &ast::Stmt) { |
416331ca | 1115 | self.maybe_print_comment(st.span.lo()); |
e74abb32 | 1116 | match st.kind { |
3157f602 | 1117 | ast::StmtKind::Local(ref loc) => { |
416331ca XL |
1118 | self.print_outer_attributes(&loc.attrs); |
1119 | self.space_if_not_bol(); | |
1120 | self.ibox(INDENT_UNIT); | |
1121 | self.word_nbsp("let"); | |
1122 | ||
1123 | self.ibox(INDENT_UNIT); | |
1124 | self.print_local_decl(loc); | |
1125 | self.end(); | |
94222f64 | 1126 | if let Some((init, els)) = loc.kind.init_else_opt() { |
416331ca XL |
1127 | self.nbsp(); |
1128 | self.word_space("="); | |
1129 | self.print_expr(init); | |
94222f64 XL |
1130 | if let Some(els) = els { |
1131 | self.cbox(INDENT_UNIT); | |
1132 | self.ibox(INDENT_UNIT); | |
a2a8927a | 1133 | self.word(" else "); |
94222f64 XL |
1134 | self.print_block(els); |
1135 | } | |
3157f602 | 1136 | } |
a2a8927a | 1137 | self.word(";"); |
94222f64 | 1138 | self.end(); // `let` ibox |
1a4d82fc | 1139 | } |
416331ca | 1140 | ast::StmtKind::Item(ref item) => self.print_item(item), |
3157f602 | 1141 | ast::StmtKind::Expr(ref expr) => { |
416331ca XL |
1142 | self.space_if_not_bol(); |
1143 | self.print_expr_outer_attr_style(expr, false); | |
60c5eb7d | 1144 | if classify::expr_requires_semi_to_be_stmt(expr) { |
a2a8927a | 1145 | self.word(";"); |
3157f602 | 1146 | } |
1a4d82fc | 1147 | } |
3157f602 | 1148 | ast::StmtKind::Semi(ref expr) => { |
74b04a01 XL |
1149 | self.space_if_not_bol(); |
1150 | self.print_expr_outer_attr_style(expr, false); | |
a2a8927a | 1151 | self.word(";"); |
74b04a01 XL |
1152 | } |
1153 | ast::StmtKind::Empty => { | |
1154 | self.space_if_not_bol(); | |
a2a8927a | 1155 | self.word(";"); |
1a4d82fc | 1156 | } |
ba9703b0 | 1157 | ast::StmtKind::MacCall(ref mac) => { |
416331ca | 1158 | self.space_if_not_bol(); |
1b1a35ee XL |
1159 | self.print_outer_attributes(&mac.attrs); |
1160 | self.print_mac(&mac.mac); | |
1161 | if mac.style == ast::MacStmtStyle::Semicolon { | |
a2a8927a | 1162 | self.word(";"); |
223e47cc LB |
1163 | } |
1164 | } | |
223e47cc | 1165 | } |
1a4d82fc | 1166 | self.maybe_print_trailing_comment(st.span, None) |
223e47cc | 1167 | } |
223e47cc | 1168 | |
923072b8 | 1169 | pub(crate) fn print_block(&mut self, blk: &ast::Block) { |
1a4d82fc JJ |
1170 | self.print_block_with_attrs(blk, &[]) |
1171 | } | |
970d7e83 | 1172 | |
923072b8 | 1173 | pub(crate) fn print_block_unclosed_indent(&mut self, blk: &ast::Block) { |
416331ca | 1174 | self.print_block_maybe_unclosed(blk, &[], false) |
1a4d82fc | 1175 | } |
223e47cc | 1176 | |
923072b8 | 1177 | pub(crate) fn print_block_with_attrs(&mut self, blk: &ast::Block, attrs: &[ast::Attribute]) { |
416331ca | 1178 | self.print_block_maybe_unclosed(blk, attrs, true) |
1a4d82fc | 1179 | } |
223e47cc | 1180 | |
923072b8 | 1181 | pub(crate) fn print_block_maybe_unclosed( |
dfeec247 XL |
1182 | &mut self, |
1183 | blk: &ast::Block, | |
1184 | attrs: &[ast::Attribute], | |
1185 | close_box: bool, | |
1186 | ) { | |
1a4d82fc | 1187 | match blk.rules { |
416331ca | 1188 | BlockCheckMode::Unsafe(..) => self.word_space("unsafe"), |
dfeec247 | 1189 | BlockCheckMode::Default => (), |
1a4d82fc | 1190 | } |
416331ca XL |
1191 | self.maybe_print_comment(blk.span.lo()); |
1192 | self.ann.pre(self, AnnNode::Block(blk)); | |
1193 | self.bopen(); | |
223e47cc | 1194 | |
a2a8927a | 1195 | let has_attrs = self.print_inner_attributes(attrs); |
970d7e83 | 1196 | |
3157f602 | 1197 | for (i, st) in blk.stmts.iter().enumerate() { |
e74abb32 | 1198 | match st.kind { |
3157f602 | 1199 | ast::StmtKind::Expr(ref expr) if i == blk.stmts.len() - 1 => { |
416331ca XL |
1200 | self.maybe_print_comment(st.span.lo()); |
1201 | self.space_if_not_bol(); | |
1202 | self.print_expr_outer_attr_style(expr, false); | |
1203 | self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi())); | |
3157f602 | 1204 | } |
416331ca | 1205 | _ => self.print_stmt(st), |
1a4d82fc | 1206 | } |
1a4d82fc | 1207 | } |
3157f602 | 1208 | |
a2a8927a XL |
1209 | let empty = !has_attrs && blk.stmts.is_empty(); |
1210 | self.bclose_maybe_open(blk.span, empty, close_box); | |
b7449926 | 1211 | self.ann.post(self, AnnNode::Block(blk)) |
1a4d82fc JJ |
1212 | } |
1213 | ||
94222f64 | 1214 | /// Print a `let pat = expr` expression. |
923072b8 | 1215 | pub(crate) fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr) { |
a2a8927a | 1216 | self.word("let "); |
e1599b0c | 1217 | self.print_pat(pat); |
a2a8927a | 1218 | self.space(); |
416331ca | 1219 | self.word_space("="); |
94222f64 XL |
1220 | let npals = || parser::needs_par_as_let_scrutinee(expr.precedence().order()); |
1221 | self.print_expr_cond_paren(expr, Self::cond_needs_par(expr) || npals()) | |
dc9dc135 XL |
1222 | } |
1223 | ||
923072b8 | 1224 | pub(crate) fn print_mac(&mut self, m: &ast::MacCall) { |
416331ca | 1225 | self.print_mac_common( |
e1599b0c | 1226 | Some(MacHeader::Path(&m.path)), |
416331ca XL |
1227 | true, |
1228 | None, | |
60c5eb7d | 1229 | m.args.delim(), |
f035d41b | 1230 | &m.args.inner_tokens(), |
416331ca | 1231 | true, |
60c5eb7d | 1232 | m.span(), |
416331ca | 1233 | ); |
223e47cc | 1234 | } |
223e47cc | 1235 | |
17df50a5 XL |
1236 | fn print_inline_asm(&mut self, asm: &ast::InlineAsm) { |
1237 | enum AsmArg<'a> { | |
1238 | Template(String), | |
1239 | Operand(&'a InlineAsmOperand), | |
94222f64 | 1240 | ClobberAbi(Symbol), |
17df50a5 XL |
1241 | Options(InlineAsmOptions), |
1242 | } | |
1243 | ||
94222f64 | 1244 | let mut args = vec![AsmArg::Template(InlineAsmTemplatePiece::to_string(&asm.template))]; |
17df50a5 | 1245 | args.extend(asm.operands.iter().map(|(o, _)| AsmArg::Operand(o))); |
3c0e092e XL |
1246 | for (abi, _) in &asm.clobber_abis { |
1247 | args.push(AsmArg::ClobberAbi(*abi)); | |
94222f64 | 1248 | } |
17df50a5 XL |
1249 | if !asm.options.is_empty() { |
1250 | args.push(AsmArg::Options(asm.options)); | |
1251 | } | |
1252 | ||
1253 | self.popen(); | |
1254 | self.commasep(Consistent, &args, |s, arg| match arg { | |
1255 | AsmArg::Template(template) => s.print_string(&template, ast::StrStyle::Cooked), | |
1256 | AsmArg::Operand(op) => { | |
1257 | let print_reg_or_class = |s: &mut Self, r: &InlineAsmRegOrRegClass| match r { | |
1258 | InlineAsmRegOrRegClass::Reg(r) => s.print_symbol(*r, ast::StrStyle::Cooked), | |
1259 | InlineAsmRegOrRegClass::RegClass(r) => s.word(r.to_string()), | |
1260 | }; | |
1261 | match op { | |
1262 | InlineAsmOperand::In { reg, expr } => { | |
1263 | s.word("in"); | |
1264 | s.popen(); | |
1265 | print_reg_or_class(s, reg); | |
1266 | s.pclose(); | |
1267 | s.space(); | |
1268 | s.print_expr(expr); | |
1269 | } | |
1270 | InlineAsmOperand::Out { reg, late, expr } => { | |
1271 | s.word(if *late { "lateout" } else { "out" }); | |
1272 | s.popen(); | |
1273 | print_reg_or_class(s, reg); | |
1274 | s.pclose(); | |
1275 | s.space(); | |
1276 | match expr { | |
1277 | Some(expr) => s.print_expr(expr), | |
1278 | None => s.word("_"), | |
1279 | } | |
1280 | } | |
1281 | InlineAsmOperand::InOut { reg, late, expr } => { | |
1282 | s.word(if *late { "inlateout" } else { "inout" }); | |
1283 | s.popen(); | |
1284 | print_reg_or_class(s, reg); | |
1285 | s.pclose(); | |
1286 | s.space(); | |
1287 | s.print_expr(expr); | |
1288 | } | |
1289 | InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => { | |
1290 | s.word(if *late { "inlateout" } else { "inout" }); | |
1291 | s.popen(); | |
1292 | print_reg_or_class(s, reg); | |
1293 | s.pclose(); | |
1294 | s.space(); | |
1295 | s.print_expr(in_expr); | |
1296 | s.space(); | |
1297 | s.word_space("=>"); | |
1298 | match out_expr { | |
1299 | Some(out_expr) => s.print_expr(out_expr), | |
1300 | None => s.word("_"), | |
1301 | } | |
1302 | } | |
1303 | InlineAsmOperand::Const { anon_const } => { | |
1304 | s.word("const"); | |
1305 | s.space(); | |
1306 | s.print_expr(&anon_const.value); | |
1307 | } | |
04454e1e | 1308 | InlineAsmOperand::Sym { sym } => { |
17df50a5 XL |
1309 | s.word("sym"); |
1310 | s.space(); | |
04454e1e FG |
1311 | if let Some(qself) = &sym.qself { |
1312 | s.print_qpath(&sym.path, qself, true); | |
1313 | } else { | |
1314 | s.print_path(&sym.path, true, 0); | |
1315 | } | |
17df50a5 XL |
1316 | } |
1317 | } | |
1318 | } | |
94222f64 XL |
1319 | AsmArg::ClobberAbi(abi) => { |
1320 | s.word("clobber_abi"); | |
1321 | s.popen(); | |
1322 | s.print_symbol(*abi, ast::StrStyle::Cooked); | |
1323 | s.pclose(); | |
1324 | } | |
17df50a5 XL |
1325 | AsmArg::Options(opts) => { |
1326 | s.word("options"); | |
1327 | s.popen(); | |
1328 | let mut options = vec![]; | |
1329 | if opts.contains(InlineAsmOptions::PURE) { | |
1330 | options.push("pure"); | |
1331 | } | |
1332 | if opts.contains(InlineAsmOptions::NOMEM) { | |
1333 | options.push("nomem"); | |
1334 | } | |
1335 | if opts.contains(InlineAsmOptions::READONLY) { | |
1336 | options.push("readonly"); | |
1337 | } | |
1338 | if opts.contains(InlineAsmOptions::PRESERVES_FLAGS) { | |
1339 | options.push("preserves_flags"); | |
1340 | } | |
1341 | if opts.contains(InlineAsmOptions::NORETURN) { | |
1342 | options.push("noreturn"); | |
1343 | } | |
1344 | if opts.contains(InlineAsmOptions::NOSTACK) { | |
1345 | options.push("nostack"); | |
1346 | } | |
1347 | if opts.contains(InlineAsmOptions::ATT_SYNTAX) { | |
1348 | options.push("att_syntax"); | |
1349 | } | |
136023e0 XL |
1350 | if opts.contains(InlineAsmOptions::RAW) { |
1351 | options.push("raw"); | |
1352 | } | |
a2a8927a XL |
1353 | if opts.contains(InlineAsmOptions::MAY_UNWIND) { |
1354 | options.push("may_unwind"); | |
1355 | } | |
17df50a5 XL |
1356 | s.commasep(Inconsistent, &options, |s, &opt| { |
1357 | s.word(opt); | |
1358 | }); | |
1359 | s.pclose(); | |
1360 | } | |
1361 | }); | |
1362 | self.pclose(); | |
1363 | } | |
1364 | ||
923072b8 | 1365 | pub(crate) fn print_local_decl(&mut self, loc: &ast::Local) { |
416331ca | 1366 | self.print_pat(&loc.pat); |
1a4d82fc | 1367 | if let Some(ref ty) = loc.ty { |
416331ca XL |
1368 | self.word_space(":"); |
1369 | self.print_type(ty); | |
1a4d82fc | 1370 | } |
223e47cc | 1371 | } |
223e47cc | 1372 | |
923072b8 | 1373 | pub(crate) fn print_name(&mut self, name: Symbol) { |
a2a8927a | 1374 | self.word(name.to_string()); |
b7449926 | 1375 | self.ann.post(self, AnnNode::Name(&name)) |
1a4d82fc JJ |
1376 | } |
1377 | ||
dfeec247 | 1378 | fn print_qpath(&mut self, path: &ast::Path, qself: &ast::QSelf, colons_before_params: bool) { |
a2a8927a | 1379 | self.word("<"); |
416331ca | 1380 | self.print_type(&qself.ty); |
c34b1796 | 1381 | if qself.position > 0 { |
a2a8927a | 1382 | self.space(); |
416331ca | 1383 | self.word_space("as"); |
c34b1796 | 1384 | let depth = path.segments.len() - qself.position; |
416331ca | 1385 | self.print_path(path, false, depth); |
c34b1796 | 1386 | } |
a2a8927a | 1387 | self.word(">"); |
fc512014 | 1388 | for item_segment in &path.segments[qself.position..] { |
a2a8927a | 1389 | self.word("::"); |
fc512014 XL |
1390 | self.print_ident(item_segment.ident); |
1391 | if let Some(ref args) = item_segment.args { | |
1392 | self.print_generic_args(args, colons_before_params) | |
1393 | } | |
32a655c1 | 1394 | } |
85aaf69f SL |
1395 | } |
1396 | ||
923072b8 | 1397 | pub(crate) fn print_pat(&mut self, pat: &ast::Pat) { |
416331ca XL |
1398 | self.maybe_print_comment(pat.span.lo()); |
1399 | self.ann.pre(self, AnnNode::Pat(pat)); | |
1a4d82fc | 1400 | /* Pat isn't normalized, but the beauty of it |
dfeec247 | 1401 | is that it doesn't matter */ |
e74abb32 | 1402 | match pat.kind { |
a2a8927a | 1403 | PatKind::Wild => self.word("_"), |
f2b60f7d FG |
1404 | PatKind::Ident(BindingAnnotation(by_ref, mutbl), ident, ref sub) => { |
1405 | if by_ref == ByRef::Yes { | |
1406 | self.word_nbsp("ref"); | |
1407 | } | |
1408 | if mutbl == Mutability::Mut { | |
1409 | self.word_nbsp("mut"); | |
1a4d82fc | 1410 | } |
416331ca | 1411 | self.print_ident(ident); |
3157f602 | 1412 | if let Some(ref p) = *sub { |
a2a8927a XL |
1413 | self.space(); |
1414 | self.word_space("@"); | |
416331ca | 1415 | self.print_pat(p); |
3157f602 XL |
1416 | } |
1417 | } | |
17df50a5 XL |
1418 | PatKind::TupleStruct(ref qself, ref path, ref elts) => { |
1419 | if let Some(qself) = qself { | |
1420 | self.print_qpath(path, qself, true); | |
1421 | } else { | |
1422 | self.print_path(path, true, 0); | |
1423 | } | |
416331ca | 1424 | self.popen(); |
a2a8927a | 1425 | self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p)); |
416331ca | 1426 | self.pclose(); |
1a4d82fc | 1427 | } |
e1599b0c | 1428 | PatKind::Or(ref pats) => { |
a2a8927a | 1429 | self.strsep("|", true, Inconsistent, &pats, |s, p| s.print_pat(p)); |
e1599b0c | 1430 | } |
3157f602 | 1431 | PatKind::Path(None, ref path) => { |
416331ca | 1432 | self.print_path(path, true, 0); |
7453a54e | 1433 | } |
3157f602 | 1434 | PatKind::Path(Some(ref qself), ref path) => { |
416331ca | 1435 | self.print_qpath(path, qself, false); |
d9579d0f | 1436 | } |
17df50a5 XL |
1437 | PatKind::Struct(ref qself, ref path, ref fields, etc) => { |
1438 | if let Some(qself) = qself { | |
1439 | self.print_qpath(path, qself, true); | |
1440 | } else { | |
1441 | self.print_path(path, true, 0); | |
1442 | } | |
416331ca | 1443 | self.nbsp(); |
a2a8927a XL |
1444 | self.word("{"); |
1445 | let empty = fields.is_empty() && !etc; | |
1446 | if !empty { | |
1447 | self.space(); | |
1448 | } | |
32a655c1 | 1449 | self.commasep_cmnt( |
dfeec247 | 1450 | Consistent, |
a2a8927a | 1451 | &fields, |
1a4d82fc | 1452 | |s, f| { |
416331ca | 1453 | s.cbox(INDENT_UNIT); |
e1599b0c XL |
1454 | if !f.is_shorthand { |
1455 | s.print_ident(f.ident); | |
416331ca | 1456 | s.word_nbsp(":"); |
1a4d82fc | 1457 | } |
e1599b0c | 1458 | s.print_pat(&f.pat); |
416331ca | 1459 | s.end(); |
1a4d82fc | 1460 | }, |
dfeec247 XL |
1461 | |f| f.pat.span, |
1462 | ); | |
1a4d82fc | 1463 | if etc { |
dfeec247 XL |
1464 | if !fields.is_empty() { |
1465 | self.word_space(","); | |
1466 | } | |
a2a8927a | 1467 | self.word(".."); |
416331ca | 1468 | } |
a2a8927a XL |
1469 | if !empty { |
1470 | self.space(); | |
1471 | } | |
1472 | self.word("}"); | |
416331ca XL |
1473 | } |
1474 | PatKind::Tuple(ref elts) => { | |
1475 | self.popen(); | |
a2a8927a | 1476 | self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p)); |
416331ca | 1477 | if elts.len() == 1 { |
a2a8927a | 1478 | self.word(","); |
1a4d82fc | 1479 | } |
416331ca | 1480 | self.pclose(); |
1a4d82fc | 1481 | } |
7453a54e | 1482 | PatKind::Box(ref inner) => { |
a2a8927a | 1483 | self.word("box "); |
416331ca | 1484 | self.print_pat(inner); |
1a4d82fc | 1485 | } |
7453a54e | 1486 | PatKind::Ref(ref inner, mutbl) => { |
a2a8927a | 1487 | self.word("&"); |
f2b60f7d | 1488 | if mutbl == Mutability::Mut { |
a2a8927a | 1489 | self.word("mut "); |
1a4d82fc | 1490 | } |
f2b60f7d | 1491 | if let PatKind::Ident(ast::BindingAnnotation::MUT, ..) = inner.kind { |
fc512014 XL |
1492 | self.popen(); |
1493 | self.print_pat(inner); | |
1494 | self.pclose(); | |
1495 | } else { | |
1496 | self.print_pat(inner); | |
1497 | } | |
1a4d82fc | 1498 | } |
416331ca | 1499 | PatKind::Lit(ref e) => self.print_expr(&**e), |
8faf50e0 | 1500 | PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => { |
dfeec247 XL |
1501 | if let Some(e) = begin { |
1502 | self.print_expr(e); | |
dfeec247 | 1503 | } |
32a655c1 | 1504 | match *end_kind { |
a2a8927a XL |
1505 | RangeEnd::Included(RangeSyntax::DotDotDot) => self.word("..."), |
1506 | RangeEnd::Included(RangeSyntax::DotDotEq) => self.word("..="), | |
1507 | RangeEnd::Excluded => self.word(".."), | |
1a4d82fc | 1508 | } |
dfeec247 XL |
1509 | if let Some(e) = end { |
1510 | self.print_expr(e); | |
1511 | } | |
416331ca XL |
1512 | } |
1513 | PatKind::Slice(ref elts) => { | |
a2a8927a XL |
1514 | self.word("["); |
1515 | self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p)); | |
1516 | self.word("]"); | |
1a4d82fc | 1517 | } |
a2a8927a | 1518 | PatKind::Rest => self.word(".."), |
0531ce1d | 1519 | PatKind::Paren(ref inner) => { |
416331ca XL |
1520 | self.popen(); |
1521 | self.print_pat(inner); | |
1522 | self.pclose(); | |
0531ce1d | 1523 | } |
ba9703b0 | 1524 | PatKind::MacCall(ref m) => self.print_mac(m), |
1a4d82fc | 1525 | } |
b7449926 | 1526 | self.ann.post(self, AnnNode::Pat(pat)) |
1a4d82fc | 1527 | } |
223e47cc | 1528 | |
416331ca | 1529 | fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) { |
3157f602 XL |
1530 | match explicit_self.node { |
1531 | SelfKind::Value(m) => { | |
60c5eb7d | 1532 | self.print_mutability(m, false); |
a2a8927a | 1533 | self.word("self") |
1a4d82fc | 1534 | } |
3157f602 | 1535 | SelfKind::Region(ref lt, m) => { |
a2a8927a | 1536 | self.word("&"); |
416331ca | 1537 | self.print_opt_lifetime(lt); |
60c5eb7d | 1538 | self.print_mutability(m, false); |
a2a8927a | 1539 | self.word("self") |
1a4d82fc | 1540 | } |
3157f602 | 1541 | SelfKind::Explicit(ref typ, m) => { |
60c5eb7d | 1542 | self.print_mutability(m, false); |
a2a8927a | 1543 | self.word("self"); |
416331ca | 1544 | self.word_space(":"); |
7cac9316 | 1545 | self.print_type(typ) |
1a4d82fc JJ |
1546 | } |
1547 | } | |
223e47cc | 1548 | } |
223e47cc | 1549 | |
923072b8 | 1550 | pub(crate) fn print_asyncness(&mut self, asyncness: ast::Async) { |
8faf50e0 | 1551 | if asyncness.is_async() { |
416331ca | 1552 | self.word_nbsp("async"); |
8faf50e0 | 1553 | } |
8faf50e0 XL |
1554 | } |
1555 | ||
923072b8 FG |
1556 | pub fn print_type_bounds(&mut self, bounds: &[ast::GenericBound]) { |
1557 | let mut first = true; | |
1558 | for bound in bounds { | |
1559 | if first { | |
1560 | first = false; | |
1561 | } else { | |
1562 | self.nbsp(); | |
1563 | self.word_space("+"); | |
1564 | } | |
1a4d82fc | 1565 | |
923072b8 FG |
1566 | match bound { |
1567 | GenericBound::Trait(tref, modifier) => { | |
1568 | if modifier == &TraitBoundModifier::Maybe { | |
1569 | self.word("?"); | |
1a4d82fc | 1570 | } |
923072b8 | 1571 | self.print_poly_trait_ref(tref); |
ff7c6d11 | 1572 | } |
923072b8 | 1573 | GenericBound::Outlives(lt) => self.print_lifetime(*lt), |
1a4d82fc | 1574 | } |
1a4d82fc JJ |
1575 | } |
1576 | } | |
223e47cc | 1577 | |
923072b8 | 1578 | pub(crate) fn print_lifetime(&mut self, lifetime: ast::Lifetime) { |
7cac9316 | 1579 | self.print_name(lifetime.ident.name) |
223e47cc | 1580 | } |
223e47cc | 1581 | |
923072b8 FG |
1582 | pub(crate) fn print_lifetime_bounds(&mut self, bounds: &ast::GenericBounds) { |
1583 | for (i, bound) in bounds.iter().enumerate() { | |
1584 | if i != 0 { | |
1585 | self.word(" + "); | |
1586 | } | |
1587 | match bound { | |
1588 | ast::GenericBound::Outlives(lt) => self.print_lifetime(*lt), | |
1589 | _ => panic!(), | |
3157f602 | 1590 | } |
223e47cc LB |
1591 | } |
1592 | } | |
223e47cc | 1593 | |
923072b8 | 1594 | pub(crate) fn print_generic_params(&mut self, generic_params: &[ast::GenericParam]) { |
ff7c6d11 | 1595 | if generic_params.is_empty() { |
416331ca | 1596 | return; |
1a4d82fc JJ |
1597 | } |
1598 | ||
a2a8927a | 1599 | self.word("<"); |
1a4d82fc | 1600 | |
ff7c6d11 | 1601 | self.commasep(Inconsistent, &generic_params, |s, param| { |
416331ca XL |
1602 | s.print_outer_attributes_inline(¶m.attrs); |
1603 | ||
8faf50e0 XL |
1604 | match param.kind { |
1605 | ast::GenericParamKind::Lifetime => { | |
8faf50e0 | 1606 | let lt = ast::Lifetime { id: param.id, ident: param.ident }; |
923072b8 FG |
1607 | s.print_lifetime(lt); |
1608 | if !param.bounds.is_empty() { | |
1609 | s.word_nbsp(":"); | |
1610 | s.print_lifetime_bounds(¶m.bounds) | |
1611 | } | |
9fa01778 | 1612 | } |
8faf50e0 | 1613 | ast::GenericParamKind::Type { ref default } => { |
416331ca | 1614 | s.print_ident(param.ident); |
923072b8 FG |
1615 | if !param.bounds.is_empty() { |
1616 | s.word_nbsp(":"); | |
1617 | s.print_type_bounds(¶m.bounds); | |
1618 | } | |
416331ca | 1619 | if let Some(ref default) = default { |
a2a8927a | 1620 | s.space(); |
416331ca XL |
1621 | s.word_space("="); |
1622 | s.print_type(default) | |
8faf50e0 XL |
1623 | } |
1624 | } | |
5869c6ff | 1625 | ast::GenericParamKind::Const { ref ty, kw_span: _, ref default } => { |
416331ca XL |
1626 | s.word_space("const"); |
1627 | s.print_ident(param.ident); | |
a2a8927a | 1628 | s.space(); |
416331ca XL |
1629 | s.word_space(":"); |
1630 | s.print_type(ty); | |
923072b8 FG |
1631 | if !param.bounds.is_empty() { |
1632 | s.word_nbsp(":"); | |
1633 | s.print_type_bounds(¶m.bounds); | |
1634 | } | |
cdc7bbd5 | 1635 | if let Some(ref default) = default { |
a2a8927a | 1636 | s.space(); |
cdc7bbd5 XL |
1637 | s.word_space("="); |
1638 | s.print_expr(&default.value); | |
5869c6ff | 1639 | } |
9fa01778 | 1640 | } |
1a4d82fc | 1641 | } |
416331ca | 1642 | }); |
1a4d82fc | 1643 | |
a2a8927a | 1644 | self.word(">"); |
223e47cc | 1645 | } |
223e47cc | 1646 | |
60c5eb7d | 1647 | pub fn print_mutability(&mut self, mutbl: ast::Mutability, print_const: bool) { |
1a4d82fc | 1648 | match mutbl { |
dfeec247 XL |
1649 | ast::Mutability::Mut => self.word_nbsp("mut"), |
1650 | ast::Mutability::Not => { | |
1651 | if print_const { | |
1652 | self.word_nbsp("const"); | |
1653 | } | |
1654 | } | |
1a4d82fc JJ |
1655 | } |
1656 | } | |
1657 | ||
923072b8 | 1658 | pub(crate) fn print_mt(&mut self, mt: &ast::MutTy, print_const: bool) { |
60c5eb7d | 1659 | self.print_mutability(mt.mutbl, print_const); |
7453a54e | 1660 | self.print_type(&mt.ty) |
223e47cc | 1661 | } |
223e47cc | 1662 | |
923072b8 | 1663 | pub(crate) fn print_param(&mut self, input: &ast::Param, is_closure: bool) { |
416331ca XL |
1664 | self.ibox(INDENT_UNIT); |
1665 | ||
1666 | self.print_outer_attributes_inline(&input.attrs); | |
1667 | ||
e74abb32 | 1668 | match input.ty.kind { |
416331ca | 1669 | ast::TyKind::Infer if is_closure => self.print_pat(&input.pat), |
1a4d82fc | 1670 | _ => { |
a7813a04 | 1671 | if let Some(eself) = input.to_self() { |
416331ca | 1672 | self.print_explicit_self(&eself); |
a7813a04 | 1673 | } else { |
e74abb32 | 1674 | let invalid = if let PatKind::Ident(_, ident, _) = input.pat.kind { |
5869c6ff | 1675 | ident.name == kw::Empty |
3157f602 XL |
1676 | } else { |
1677 | false | |
1678 | }; | |
a7813a04 | 1679 | if !invalid { |
416331ca | 1680 | self.print_pat(&input.pat); |
a2a8927a XL |
1681 | self.word(":"); |
1682 | self.space(); | |
1a4d82fc | 1683 | } |
416331ca | 1684 | self.print_type(&input.ty); |
1a4d82fc | 1685 | } |
1a4d82fc | 1686 | } |
223e47cc | 1687 | } |
416331ca | 1688 | self.end(); |
223e47cc | 1689 | } |
223e47cc | 1690 | |
923072b8 | 1691 | pub(crate) fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FnRetTy) { |
74b04a01 | 1692 | if let ast::FnRetTy::Ty(ty) = fn_ret_ty { |
dfeec247 XL |
1693 | self.space_if_not_bol(); |
1694 | self.ibox(INDENT_UNIT); | |
1695 | self.word_space("->"); | |
1696 | self.print_type(ty); | |
1697 | self.end(); | |
1698 | self.maybe_print_comment(ty.span.lo()); | |
1a4d82fc JJ |
1699 | } |
1700 | } | |
1701 | ||
923072b8 | 1702 | pub(crate) fn print_ty_fn( |
dfeec247 XL |
1703 | &mut self, |
1704 | ext: ast::Extern, | |
74b04a01 | 1705 | unsafety: ast::Unsafe, |
dfeec247 | 1706 | decl: &ast::FnDecl, |
f9f354fc | 1707 | name: Option<Ident>, |
dfeec247 XL |
1708 | generic_params: &[ast::GenericParam], |
1709 | ) { | |
416331ca | 1710 | self.ibox(INDENT_UNIT); |
a2a8927a | 1711 | self.print_formal_generic_params(generic_params); |
c34b1796 | 1712 | let generics = ast::Generics { |
ff7c6d11 | 1713 | params: Vec::new(), |
f035d41b XL |
1714 | where_clause: ast::WhereClause { |
1715 | has_where_token: false, | |
1716 | predicates: Vec::new(), | |
1717 | span: rustc_span::DUMMY_SP, | |
1718 | }, | |
dfeec247 | 1719 | span: rustc_span::DUMMY_SP, |
c34b1796 | 1720 | }; |
74b04a01 XL |
1721 | let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() }; |
1722 | self.print_fn(decl, header, name, &generics); | |
416331ca | 1723 | self.end(); |
223e47cc LB |
1724 | } |
1725 | ||
923072b8 | 1726 | pub(crate) fn print_fn_header_info(&mut self, header: ast::FnHeader) { |
74b04a01 XL |
1727 | self.print_constness(header.constness); |
1728 | self.print_asyncness(header.asyncness); | |
416331ca | 1729 | self.print_unsafety(header.unsafety); |
b039eaaf | 1730 | |
60c5eb7d XL |
1731 | match header.ext { |
1732 | ast::Extern::None => {} | |
064997fb | 1733 | ast::Extern::Implicit(_) => { |
60c5eb7d XL |
1734 | self.word_nbsp("extern"); |
1735 | } | |
064997fb | 1736 | ast::Extern::Explicit(abi, _) => { |
60c5eb7d XL |
1737 | self.word_nbsp("extern"); |
1738 | self.print_literal(&abi.as_lit()); | |
1739 | self.nbsp(); | |
1740 | } | |
1a4d82fc JJ |
1741 | } |
1742 | ||
a2a8927a | 1743 | self.word("fn") |
1a4d82fc JJ |
1744 | } |
1745 | ||
923072b8 | 1746 | pub(crate) fn print_unsafety(&mut self, s: ast::Unsafe) { |
1a4d82fc | 1747 | match s { |
74b04a01 XL |
1748 | ast::Unsafe::No => {} |
1749 | ast::Unsafe::Yes(_) => self.word_nbsp("unsafe"), | |
1a4d82fc | 1750 | } |
223e47cc | 1751 | } |
abe05a73 | 1752 | |
923072b8 | 1753 | pub(crate) fn print_constness(&mut self, s: ast::Const) { |
dfeec247 | 1754 | match s { |
74b04a01 XL |
1755 | ast::Const::No => {} |
1756 | ast::Const::Yes(_) => self.word_nbsp("const"), | |
dfeec247 XL |
1757 | } |
1758 | } | |
1759 | ||
923072b8 | 1760 | pub(crate) fn print_is_auto(&mut self, s: ast::IsAuto) { |
abe05a73 XL |
1761 | match s { |
1762 | ast::IsAuto::Yes => self.word_nbsp("auto"), | |
416331ca | 1763 | ast::IsAuto::No => {} |
abe05a73 XL |
1764 | } |
1765 | } | |
223e47cc | 1766 | } |