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