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