1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 pub use self::AnnNode
::*;
14 use ast
::{self, TokenTree}
;
15 use ast
::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}
;
17 use attr
::ThinAttributesExt
;
18 use util
::parser
::AssocOp
;
20 use attr
::{AttrMetaMethods, AttributeMethods}
;
21 use codemap
::{self, CodeMap, BytePos}
;
23 use parse
::token
::{self, BinOpToken, Token, InternedString}
;
24 use parse
::lexer
::comments
;
26 use print
::pp
::{self, break_offset, word, space, zerobreak, hardbreak}
;
27 use print
::pp
::{Breaks, eof}
;
28 use print
::pp
::Breaks
::{Consistent, Inconsistent}
;
33 use std
::io
::{self, Write, Read}
;
36 pub enum AnnNode
<'a
> {
37 NodeIdent(&'a ast
::Ident
),
38 NodeName(&'a ast
::Name
),
39 NodeBlock(&'a ast
::Block
),
40 NodeItem(&'a ast
::Item
),
41 NodeSubItem(ast
::NodeId
),
42 NodeExpr(&'a ast
::Expr
),
43 NodePat(&'a ast
::Pat
),
47 fn pre(&self, _state
: &mut State
, _node
: AnnNode
) -> io
::Result
<()> { Ok(()) }
48 fn post(&self, _state
: &mut State
, _node
: AnnNode
) -> io
::Result
<()> { Ok(()) }
51 #[derive(Copy, Clone)]
54 impl PpAnn
for NoAnn {}
56 #[derive(Copy, Clone)]
57 pub struct CurrentCommentAndLiteral
{
62 pub struct State
<'a
> {
63 pub s
: pp
::Printer
<'a
>,
64 cm
: Option
<&'a CodeMap
>,
65 comments
: Option
<Vec
<comments
::Comment
> >,
66 literals
: Option
<Vec
<comments
::Literal
> >,
67 cur_cmnt_and_lit
: CurrentCommentAndLiteral
,
68 boxes
: Vec
<pp
::Breaks
>,
72 pub fn rust_printer
<'a
>(writer
: Box
<Write
+'a
>) -> State
<'a
> {
73 static NO_ANN
: NoAnn
= NoAnn
;
74 rust_printer_annotated(writer
, &NO_ANN
)
77 pub fn rust_printer_annotated
<'a
>(writer
: Box
<Write
+'a
>,
78 ann
: &'a PpAnn
) -> State
<'a
> {
80 s
: pp
::mk_printer(writer
, DEFAULT_COLUMNS
),
84 cur_cmnt_and_lit
: CurrentCommentAndLiteral
{
93 pub const INDENT_UNIT
: usize = 4;
95 pub const DEFAULT_COLUMNS
: usize = 78;
97 /// Requires you to pass an input filename and reader so that
98 /// it can scan the input text for comments and literals to
100 pub fn print_crate
<'a
>(cm
: &'a CodeMap
,
101 span_diagnostic
: &errors
::Handler
,
107 is_expanded
: bool
) -> io
::Result
<()> {
108 let mut s
= State
::new_from_input(cm
,
115 if is_expanded
&& !std_inject
::no_std(krate
) {
116 // We need to print `#![no_std]` (and its feature gate) so that
117 // compiling pretty-printed source won't inject libstd again.
118 // However we don't want these attributes in the AST because
119 // of the feature gate, so we fake them up here.
121 // #![feature(prelude_import)]
122 let prelude_import_meta
= attr
::mk_word_item(InternedString
::new("prelude_import"));
123 let list
= attr
::mk_list_item(InternedString
::new("feature"),
124 vec
![prelude_import_meta
]);
125 let fake_attr
= attr
::mk_attr_inner(attr
::mk_attr_id(), list
);
126 try
!(s
.print_attribute(&fake_attr
));
129 let no_std_meta
= attr
::mk_word_item(InternedString
::new("no_std"));
130 let fake_attr
= attr
::mk_attr_inner(attr
::mk_attr_id(), no_std_meta
);
131 try
!(s
.print_attribute(&fake_attr
));
134 try
!(s
.print_mod(&krate
.module
, &krate
.attrs
));
135 try
!(s
.print_remaining_comments());
140 pub fn new_from_input(cm
: &'a CodeMap
,
141 span_diagnostic
: &errors
::Handler
,
146 is_expanded
: bool
) -> State
<'a
> {
147 let (cmnts
, lits
) = comments
::gather_comments_and_literals(
157 // If the code is post expansion, don't use the table of
158 // literals, since it doesn't correspond with the literals
159 // in the AST anymore.
160 if is_expanded { None }
else { Some(lits) }
)
163 pub fn new(cm
: &'a CodeMap
,
166 comments
: Option
<Vec
<comments
::Comment
>>,
167 literals
: Option
<Vec
<comments
::Literal
>>) -> State
<'a
> {
169 s
: pp
::mk_printer(out
, DEFAULT_COLUMNS
),
173 cur_cmnt_and_lit
: CurrentCommentAndLiteral
{
183 pub fn to_string
<F
>(f
: F
) -> String
where
184 F
: FnOnce(&mut State
) -> io
::Result
<()>,
186 let mut wr
= Vec
::new();
188 let mut printer
= rust_printer(Box
::new(&mut wr
));
189 f(&mut printer
).unwrap();
190 eof(&mut printer
.s
).unwrap();
192 String
::from_utf8(wr
).unwrap()
195 pub fn binop_to_string(op
: BinOpToken
) -> &'
static str {
201 token
::Percent
=> "%",
210 pub fn token_to_string(tok
: &Token
) -> String
{
212 token
::Eq
=> "=".to_string(),
213 token
::Lt
=> "<".to_string(),
214 token
::Le
=> "<=".to_string(),
215 token
::EqEq
=> "==".to_string(),
216 token
::Ne
=> "!=".to_string(),
217 token
::Ge
=> ">=".to_string(),
218 token
::Gt
=> ">".to_string(),
219 token
::Not
=> "!".to_string(),
220 token
::Tilde
=> "~".to_string(),
221 token
::OrOr
=> "||".to_string(),
222 token
::AndAnd
=> "&&".to_string(),
223 token
::BinOp(op
) => binop_to_string(op
).to_string(),
224 token
::BinOpEq(op
) => format
!("{}=", binop_to_string(op
)),
226 /* Structural symbols */
227 token
::At
=> "@".to_string(),
228 token
::Dot
=> ".".to_string(),
229 token
::DotDot
=> "..".to_string(),
230 token
::DotDotDot
=> "...".to_string(),
231 token
::Comma
=> ",".to_string(),
232 token
::Semi
=> ";".to_string(),
233 token
::Colon
=> ":".to_string(),
234 token
::ModSep
=> "::".to_string(),
235 token
::RArrow
=> "->".to_string(),
236 token
::LArrow
=> "<-".to_string(),
237 token
::FatArrow
=> "=>".to_string(),
238 token
::OpenDelim(token
::Paren
) => "(".to_string(),
239 token
::CloseDelim(token
::Paren
) => ")".to_string(),
240 token
::OpenDelim(token
::Bracket
) => "[".to_string(),
241 token
::CloseDelim(token
::Bracket
) => "]".to_string(),
242 token
::OpenDelim(token
::Brace
) => "{".to_string(),
243 token
::CloseDelim(token
::Brace
) => "}".to_string(),
244 token
::Pound
=> "#".to_string(),
245 token
::Dollar
=> "$".to_string(),
246 token
::Question
=> "?".to_string(),
249 token
::Literal(lit
, suf
) => {
250 let mut out
= match lit
{
251 token
::Byte(b
) => format
!("b'{}'", b
),
252 token
::Char(c
) => format
!("'{}'", c
),
253 token
::Float(c
) => c
.to_string(),
254 token
::Integer(c
) => c
.to_string(),
255 token
::Str_(s
) => format
!("\"{}\"", s
),
256 token
::StrRaw(s
, n
) => format
!("r{delim}\"{string}\"{delim}",
257 delim
=repeat("#", n
),
259 token
::ByteStr(v
) => format
!("b\"{}\"", v
),
260 token
::ByteStrRaw(s
, n
) => format
!("br{delim}\"{string}\"{delim}",
261 delim
=repeat("#", n
),
265 if let Some(s
) = suf
{
266 out
.push_str(&s
.as_str())
272 /* Name components */
273 token
::Ident(s
, _
) => s
.to_string(),
274 token
::Lifetime(s
) => s
.to_string(),
275 token
::Underscore
=> "_".to_string(),
278 token
::DocComment(s
) => s
.to_string(),
279 token
::SubstNt(s
, _
) => format
!("${}", s
),
280 token
::MatchNt(s
, t
, _
, _
) => format
!("${}:{}", s
, t
),
281 token
::Eof
=> "<eof>".to_string(),
282 token
::Whitespace
=> " ".to_string(),
283 token
::Comment
=> "/* */".to_string(),
284 token
::Shebang(s
) => format
!("/* shebang: {}*/", s
),
286 token
::SpecialVarNt(var
) => format
!("${}", var
.as_str()),
288 token
::Interpolated(ref nt
) => match *nt
{
289 token
::NtExpr(ref e
) => expr_to_string(&**e
),
290 token
::NtMeta(ref e
) => meta_item_to_string(&**e
),
291 token
::NtTy(ref e
) => ty_to_string(&**e
),
292 token
::NtPath(ref e
) => path_to_string(&**e
),
293 token
::NtItem(ref e
) => item_to_string(&**e
),
294 token
::NtBlock(ref e
) => block_to_string(&**e
),
295 token
::NtStmt(ref e
) => stmt_to_string(&**e
),
296 token
::NtPat(ref e
) => pat_to_string(&**e
),
297 token
::NtIdent(ref e
, _
) => ident_to_string(e
.node
),
298 token
::NtTT(ref e
) => tt_to_string(&**e
),
299 token
::NtArm(ref e
) => arm_to_string(&*e
),
300 token
::NtImplItem(ref e
) => impl_item_to_string(&**e
),
301 token
::NtTraitItem(ref e
) => trait_item_to_string(&**e
),
302 token
::NtGenerics(ref e
) => generics_to_string(&*e
),
303 token
::NtWhereClause(ref e
) => where_clause_to_string(&*e
),
304 token
::NtArg(ref e
) => arg_to_string(&*e
),
309 pub fn ty_to_string(ty
: &ast
::Ty
) -> String
{
310 to_string(|s
| s
.print_type(ty
))
313 pub fn bounds_to_string(bounds
: &[ast
::TyParamBound
]) -> String
{
314 to_string(|s
| s
.print_bounds("", bounds
))
317 pub fn pat_to_string(pat
: &ast
::Pat
) -> String
{
318 to_string(|s
| s
.print_pat(pat
))
321 pub fn arm_to_string(arm
: &ast
::Arm
) -> String
{
322 to_string(|s
| s
.print_arm(arm
))
325 pub fn expr_to_string(e
: &ast
::Expr
) -> String
{
326 to_string(|s
| s
.print_expr(e
))
329 pub fn lifetime_to_string(e
: &ast
::Lifetime
) -> String
{
330 to_string(|s
| s
.print_lifetime(e
))
333 pub fn tt_to_string(tt
: &ast
::TokenTree
) -> String
{
334 to_string(|s
| s
.print_tt(tt
))
337 pub fn tts_to_string(tts
: &[ast
::TokenTree
]) -> String
{
338 to_string(|s
| s
.print_tts(tts
))
341 pub fn stmt_to_string(stmt
: &ast
::Stmt
) -> String
{
342 to_string(|s
| s
.print_stmt(stmt
))
345 pub fn attr_to_string(attr
: &ast
::Attribute
) -> String
{
346 to_string(|s
| s
.print_attribute(attr
))
349 pub fn item_to_string(i
: &ast
::Item
) -> String
{
350 to_string(|s
| s
.print_item(i
))
353 pub fn impl_item_to_string(i
: &ast
::ImplItem
) -> String
{
354 to_string(|s
| s
.print_impl_item(i
))
357 pub fn trait_item_to_string(i
: &ast
::TraitItem
) -> String
{
358 to_string(|s
| s
.print_trait_item(i
))
361 pub fn generics_to_string(generics
: &ast
::Generics
) -> String
{
362 to_string(|s
| s
.print_generics(generics
))
365 pub fn where_clause_to_string(i
: &ast
::WhereClause
) -> String
{
366 to_string(|s
| s
.print_where_clause(i
))
369 pub fn fn_block_to_string(p
: &ast
::FnDecl
) -> String
{
370 to_string(|s
| s
.print_fn_block_args(p
))
373 pub fn path_to_string(p
: &ast
::Path
) -> String
{
374 to_string(|s
| s
.print_path(p
, false, 0))
377 pub fn ident_to_string(id
: ast
::Ident
) -> String
{
378 to_string(|s
| s
.print_ident(id
))
381 pub fn fun_to_string(decl
: &ast
::FnDecl
,
382 unsafety
: ast
::Unsafety
,
383 constness
: ast
::Constness
,
385 opt_explicit_self
: Option
<&ast
::ExplicitSelf_
>,
386 generics
: &ast
::Generics
)
390 try
!(s
.print_fn(decl
, unsafety
, constness
, abi
::Rust
, Some(name
),
391 generics
, opt_explicit_self
, ast
::Inherited
));
392 try
!(s
.end()); // Close the head box
393 s
.end() // Close the outer box
397 pub fn block_to_string(blk
: &ast
::Block
) -> String
{
399 // containing cbox, will be closed by print-block at }
400 try
!(s
.cbox(INDENT_UNIT
));
401 // head-ibox, will be closed by print-block after {
407 pub fn meta_item_to_string(mi
: &ast
::MetaItem
) -> String
{
408 to_string(|s
| s
.print_meta_item(mi
))
411 pub fn attribute_to_string(attr
: &ast
::Attribute
) -> String
{
412 to_string(|s
| s
.print_attribute(attr
))
415 pub fn lit_to_string(l
: &ast
::Lit
) -> String
{
416 to_string(|s
| s
.print_literal(l
))
419 pub fn explicit_self_to_string(explicit_self
: &ast
::ExplicitSelf_
) -> String
{
420 to_string(|s
| s
.print_explicit_self(explicit_self
, ast
::MutImmutable
).map(|_
| {}
))
423 pub fn variant_to_string(var
: &ast
::Variant
) -> String
{
424 to_string(|s
| s
.print_variant(var
))
427 pub fn arg_to_string(arg
: &ast
::Arg
) -> String
{
428 to_string(|s
| s
.print_arg(arg
))
431 pub fn mac_to_string(arg
: &ast
::Mac
) -> String
{
432 to_string(|s
| s
.print_mac(arg
, ::parse
::token
::Paren
))
435 pub fn visibility_qualified(vis
: ast
::Visibility
, s
: &str) -> String
{
437 ast
::Public
=> format
!("pub {}", s
),
438 ast
::Inherited
=> s
.to_string()
442 fn needs_parentheses(expr
: &ast
::Expr
) -> bool
{
444 ast
::ExprAssign(..) | ast
::ExprBinary(..) |
445 ast
::ExprClosure(..) |
446 ast
::ExprAssignOp(..) | ast
::ExprCast(..) |
447 ast
::ExprInPlace(..) | ast
::ExprType(..) => true,
452 pub trait PrintState
<'a
> {
453 fn writer(&mut self) -> &mut pp
::Printer
<'a
>;
454 fn boxes(&mut self) -> &mut Vec
<pp
::Breaks
>;
455 fn comments(&mut self) -> &mut Option
<Vec
<comments
::Comment
>>;
456 fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral
;
457 fn literals(&self) -> &Option
<Vec
<comments
::Literal
>>;
459 fn word_space(&mut self, w
: &str) -> io
::Result
<()> {
460 try
!(word(self.writer(), w
));
464 fn popen(&mut self) -> io
::Result
<()> { word(self.writer(), "(") }
466 fn pclose(&mut self) -> io
::Result
<()> { word(self.writer(), ")") }
468 fn is_begin(&mut self) -> bool
{
469 match self.writer().last_token() {
470 pp
::Token
::Begin(_
) => true,
475 fn is_end(&mut self) -> bool
{
476 match self.writer().last_token() {
477 pp
::Token
::End
=> true,
482 // is this the beginning of a line?
483 fn is_bol(&mut self) -> bool
{
484 self.writer().last_token().is_eof() || self.writer().last_token().is_hardbreak_tok()
487 fn hardbreak_if_not_bol(&mut self) -> io
::Result
<()> {
489 try
!(hardbreak(self.writer()))
495 fn rbox(&mut self, u
: usize, b
: pp
::Breaks
) -> io
::Result
<()> {
496 self.boxes().push(b
);
497 pp
::rbox(self.writer(), u
, b
)
500 fn ibox(&mut self, u
: usize) -> io
::Result
<()> {
501 self.boxes().push(pp
::Breaks
::Inconsistent
);
502 pp
::ibox(self.writer(), u
)
505 fn end(&mut self) -> io
::Result
<()> {
506 self.boxes().pop().unwrap();
507 pp
::end(self.writer())
510 fn commasep
<T
, F
>(&mut self, b
: Breaks
, elts
: &[T
], mut op
: F
) -> io
::Result
<()>
511 where F
: FnMut(&mut Self, &T
) -> io
::Result
<()>,
513 try
!(self.rbox(0, b
));
514 let mut first
= true;
516 if first { first = false; }
else { try!(self.word_space(",")); }
522 fn next_lit(&mut self, pos
: BytePos
) -> Option
<comments
::Literal
> {
523 let mut cur_lit
= self.cur_cmnt_and_lit().cur_lit
;
525 let mut result
= None
;
527 if let &Some(ref lits
) = self.literals()
529 while cur_lit
< lits
.len() {
530 let ltrl
= (*lits
)[cur_lit
].clone();
531 if ltrl
.pos
> pos { break; }
540 self.cur_cmnt_and_lit().cur_lit
= cur_lit
;
544 fn maybe_print_comment(&mut self, pos
: BytePos
) -> io
::Result
<()> {
546 match self.next_comment() {
548 if (*cmnt
).pos
< pos
{
549 try
!(self.print_comment(cmnt
));
550 self.cur_cmnt_and_lit().cur_cmnt
+= 1;
559 fn print_comment(&mut self,
560 cmnt
: &comments
::Comment
) -> io
::Result
<()> {
563 assert_eq
!(cmnt
.lines
.len(), 1);
564 try
!(zerobreak(self.writer()));
565 try
!(word(self.writer(), &cmnt
.lines
[0]));
566 zerobreak(self.writer())
568 comments
::Isolated
=> {
569 try
!(self.hardbreak_if_not_bol());
570 for line
in &cmnt
.lines
{
571 // Don't print empty lines because they will end up as trailing
573 if !line
.is_empty() {
574 try
!(word(self.writer(), &line
[..]));
576 try
!(hardbreak(self.writer()));
580 comments
::Trailing
=> {
581 try
!(word(self.writer(), " "));
582 if cmnt
.lines
.len() == 1 {
583 try
!(word(self.writer(), &cmnt
.lines
[0]));
584 hardbreak(self.writer())
587 for line
in &cmnt
.lines
{
588 if !line
.is_empty() {
589 try
!(word(self.writer(), &line
[..]));
591 try
!(hardbreak(self.writer()));
596 comments
::BlankLine
=> {
597 // We need to do at least one, possibly two hardbreaks.
598 let is_semi
= match self.writer().last_token() {
599 pp
::Token
::String(s
, _
) => ";" == s
,
602 if is_semi
|| self.is_begin() || self.is_end() {
603 try
!(hardbreak(self.writer()));
605 hardbreak(self.writer())
610 fn next_comment(&mut self) -> Option
<comments
::Comment
> {
611 let cur_cmnt
= self.cur_cmnt_and_lit().cur_cmnt
;
612 match *self.comments() {
614 if cur_cmnt
< cmnts
.len() {
615 Some(cmnts
[cur_cmnt
].clone())
624 fn print_literal(&mut self, lit
: &ast
::Lit
) -> io
::Result
<()> {
625 try
!(self.maybe_print_comment(lit
.span
.lo
));
626 match self.next_lit(lit
.span
.lo
) {
628 return word(self.writer(), &(*ltrl
).lit
);
633 ast
::LitStr(ref st
, style
) => self.print_string(&st
, style
),
634 ast
::LitByte(byte
) => {
635 let mut res
= String
::from("b'");
636 res
.extend(ascii
::escape_default(byte
).map(|c
| c
as char));
638 word(self.writer(), &res
[..])
640 ast
::LitChar(ch
) => {
641 let mut res
= String
::from("'");
642 res
.extend(ch
.escape_default());
644 word(self.writer(), &res
[..])
646 ast
::LitInt(i
, t
) => {
648 ast
::SignedIntLit(st
, ast
::Plus
) => {
650 &st
.val_to_string(i
as i64))
652 ast
::SignedIntLit(st
, ast
::Minus
) => {
653 let istr
= st
.val_to_string(-(i
as i64));
655 &format
!("-{}", istr
))
657 ast
::UnsignedIntLit(ut
) => {
658 word(self.writer(), &ut
.val_to_string(i
))
660 ast
::UnsuffixedIntLit(ast
::Plus
) => {
661 word(self.writer(), &format
!("{}", i
))
663 ast
::UnsuffixedIntLit(ast
::Minus
) => {
664 word(self.writer(), &format
!("-{}", i
))
668 ast
::LitFloat(ref f
, t
) => {
675 ast
::LitFloatUnsuffixed(ref f
) => word(self.writer(), &f
[..]),
676 ast
::LitBool(val
) => {
677 if val { word(self.writer(), "true") }
else { word(self.writer(), "false") }
679 ast
::LitByteStr(ref v
) => {
680 let mut escaped
: String
= String
::new();
681 for &ch
in v
.iter() {
682 escaped
.extend(ascii
::escape_default(ch
)
683 .map(|c
| c
as char));
685 word(self.writer(), &format
!("b\"{}\"", escaped
))
690 fn print_string(&mut self, st
: &str,
691 style
: ast
::StrStyle
) -> io
::Result
<()> {
692 let st
= match style
{
694 (format
!("\"{}\"", st
.escape_default()))
697 (format
!("r{delim}\"{string}\"{delim}",
698 delim
=repeat("#", n
),
702 word(self.writer(), &st
[..])
705 fn print_inner_attributes(&mut self,
706 attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
707 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, false, true)
710 fn print_inner_attributes_no_trailing_hardbreak(&mut self,
711 attrs
: &[ast
::Attribute
])
713 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, false, false)
716 fn print_outer_attributes(&mut self,
717 attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
718 self.print_either_attributes(attrs
, ast
::AttrStyle
::Outer
, false, true)
721 fn print_inner_attributes_inline(&mut self,
722 attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
723 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, true, true)
726 fn print_outer_attributes_inline(&mut self,
727 attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
728 self.print_either_attributes(attrs
, ast
::AttrStyle
::Outer
, true, true)
731 fn print_either_attributes(&mut self,
732 attrs
: &[ast
::Attribute
],
733 kind
: ast
::AttrStyle
,
735 trailing_hardbreak
: bool
) -> io
::Result
<()> {
738 if attr
.node
.style
== kind
{
739 try
!(self.print_attribute_inline(attr
, is_inline
));
746 if count
> 0 && trailing_hardbreak
&& !is_inline
{
747 try
!(self.hardbreak_if_not_bol());
752 fn print_attribute(&mut self, attr
: &ast
::Attribute
) -> io
::Result
<()> {
753 self.print_attribute_inline(attr
, false)
756 fn print_attribute_inline(&mut self, attr
: &ast
::Attribute
,
757 is_inline
: bool
) -> io
::Result
<()> {
759 try
!(self.hardbreak_if_not_bol());
761 try
!(self.maybe_print_comment(attr
.span
.lo
));
762 if attr
.node
.is_sugared_doc
{
763 word(self.writer(), &attr
.value_str().unwrap())
765 match attr
.node
.style
{
766 ast
::AttrStyle
::Inner
=> try
!(word(self.writer(), "#![")),
767 ast
::AttrStyle
::Outer
=> try
!(word(self.writer(), "#[")),
769 try
!(self.print_meta_item(&*attr
.meta()));
770 word(self.writer(), "]")
774 fn print_meta_item(&mut self, item
: &ast
::MetaItem
) -> io
::Result
<()> {
775 try
!(self.ibox(INDENT_UNIT
));
777 ast
::MetaWord(ref name
) => {
778 try
!(word(self.writer(), &name
));
780 ast
::MetaNameValue(ref name
, ref value
) => {
781 try
!(self.word_space(&name
[..]));
782 try
!(self.word_space("="));
783 try
!(self.print_literal(value
));
785 ast
::MetaList(ref name
, ref items
) => {
786 try
!(word(self.writer(), &name
));
788 try
!(self.commasep(Consistent
,
790 |s
, i
| s
.print_meta_item(&**i
)));
797 fn space_if_not_bol(&mut self) -> io
::Result
<()> {
798 if !self.is_bol() { try!(space(self.writer())); }
802 fn nbsp(&mut self) -> io
::Result
<()> { word(self.writer(), " ") }
805 impl<'a
> PrintState
<'a
> for State
<'a
> {
806 fn writer(&mut self) -> &mut pp
::Printer
<'a
> {
810 fn boxes(&mut self) -> &mut Vec
<pp
::Breaks
> {
814 fn comments(&mut self) -> &mut Option
<Vec
<comments
::Comment
>> {
818 fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral
{
819 &mut self.cur_cmnt_and_lit
822 fn literals(&self) -> &Option
<Vec
<comments
::Literal
>> {
828 pub fn cbox(&mut self, u
: usize) -> io
::Result
<()> {
829 self.boxes
.push(pp
::Breaks
::Consistent
);
830 pp
::cbox(&mut self.s
, u
)
833 pub fn word_nbsp(&mut self, w
: &str) -> io
::Result
<()> {
834 try
!(word(&mut self.s
, w
));
838 pub fn head(&mut self, w
: &str) -> io
::Result
<()> {
839 // outer-box is consistent
840 try
!(self.cbox(INDENT_UNIT
));
841 // head-box is inconsistent
842 try
!(self.ibox(w
.len() + 1));
843 // keyword that starts the head
845 try
!(self.word_nbsp(w
));
850 pub fn bopen(&mut self) -> io
::Result
<()> {
851 try
!(word(&mut self.s
, "{"));
852 self.end() // close the head-box
855 pub fn bclose_(&mut self, span
: codemap
::Span
,
856 indented
: usize) -> io
::Result
<()> {
857 self.bclose_maybe_open(span
, indented
, true)
859 pub fn bclose_maybe_open(&mut self, span
: codemap
::Span
,
860 indented
: usize, close_box
: bool
) -> io
::Result
<()> {
861 try
!(self.maybe_print_comment(span
.hi
));
862 try
!(self.break_offset_if_not_bol(1, -(indented
as isize)));
863 try
!(word(&mut self.s
, "}"));
865 try
!(self.end()); // close the outer-box
869 pub fn bclose(&mut self, span
: codemap
::Span
) -> io
::Result
<()> {
870 self.bclose_(span
, INDENT_UNIT
)
873 pub fn in_cbox(&self) -> bool
{
874 match self.boxes
.last() {
875 Some(&last_box
) => last_box
== pp
::Breaks
::Consistent
,
880 pub fn break_offset_if_not_bol(&mut self, n
: usize,
881 off
: isize) -> io
::Result
<()> {
883 break_offset(&mut self.s
, n
, off
)
885 if off
!= 0 && self.s
.last_token().is_hardbreak_tok() {
886 // We do something pretty sketchy here: tuck the nonzero
887 // offset-adjustment we were going to deposit along with the
888 // break into the previous hardbreak.
889 self.s
.replace_last_token(pp
::hardbreak_tok_offset(off
));
895 // Synthesizes a comment that was not textually present in the original source
897 pub fn synth_comment(&mut self, text
: String
) -> io
::Result
<()> {
898 try
!(word(&mut self.s
, "/*"));
899 try
!(space(&mut self.s
));
900 try
!(word(&mut self.s
, &text
[..]));
901 try
!(space(&mut self.s
));
902 word(&mut self.s
, "*/")
907 pub fn commasep_cmnt
<T
, F
, G
>(&mut self,
911 mut get_span
: G
) -> io
::Result
<()> where
912 F
: FnMut(&mut State
, &T
) -> io
::Result
<()>,
913 G
: FnMut(&T
) -> codemap
::Span
,
915 try
!(self.rbox(0, b
));
916 let len
= elts
.len();
919 try
!(self.maybe_print_comment(get_span(elt
).hi
));
923 try
!(word(&mut self.s
, ","));
924 try
!(self.maybe_print_trailing_comment(get_span(elt
),
925 Some(get_span(&elts
[i
]).hi
)));
926 try
!(self.space_if_not_bol());
932 pub fn commasep_exprs(&mut self, b
: Breaks
,
933 exprs
: &[P
<ast
::Expr
>]) -> io
::Result
<()> {
934 self.commasep_cmnt(b
, exprs
, |s
, e
| s
.print_expr(&**e
), |e
| e
.span
)
937 pub fn print_mod(&mut self, _mod
: &ast
::Mod
,
938 attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
939 try
!(self.print_inner_attributes(attrs
));
940 for item
in &_mod
.items
{
941 try
!(self.print_item(&**item
));
946 pub fn print_foreign_mod(&mut self, nmod
: &ast
::ForeignMod
,
947 attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
948 try
!(self.print_inner_attributes(attrs
));
949 for item
in &nmod
.items
{
950 try
!(self.print_foreign_item(&**item
));
955 pub fn print_opt_lifetime(&mut self,
956 lifetime
: &Option
<ast
::Lifetime
>) -> io
::Result
<()> {
957 if let Some(l
) = *lifetime
{
958 try
!(self.print_lifetime(&l
));
964 pub fn print_type(&mut self, ty
: &ast
::Ty
) -> io
::Result
<()> {
965 try
!(self.maybe_print_comment(ty
.span
.lo
));
968 ast
::TyVec(ref ty
) => {
969 try
!(word(&mut self.s
, "["));
970 try
!(self.print_type(&**ty
));
971 try
!(word(&mut self.s
, "]"));
973 ast
::TyPtr(ref mt
) => {
974 try
!(word(&mut self.s
, "*"));
976 ast
::MutMutable
=> try
!(self.word_nbsp("mut")),
977 ast
::MutImmutable
=> try
!(self.word_nbsp("const")),
979 try
!(self.print_type(&*mt
.ty
));
981 ast
::TyRptr(ref lifetime
, ref mt
) => {
982 try
!(word(&mut self.s
, "&"));
983 try
!(self.print_opt_lifetime(lifetime
));
984 try
!(self.print_mt(mt
));
986 ast
::TyTup(ref elts
) => {
988 try
!(self.commasep(Inconsistent
, &elts
[..],
989 |s
, ty
| s
.print_type(&**ty
)));
991 try
!(word(&mut self.s
, ","));
995 ast
::TyParen(ref typ
) => {
997 try
!(self.print_type(&**typ
));
1000 ast
::TyBareFn(ref f
) => {
1001 let generics
= ast
::Generics
{
1002 lifetimes
: f
.lifetimes
.clone(),
1003 ty_params
: P
::empty(),
1004 where_clause
: ast
::WhereClause
{
1005 id
: ast
::DUMMY_NODE_ID
,
1006 predicates
: Vec
::new(),
1009 try
!(self.print_ty_fn(f
.abi
,
1016 ast
::TyPath(None
, ref path
) => {
1017 try
!(self.print_path(path
, false, 0));
1019 ast
::TyPath(Some(ref qself
), ref path
) => {
1020 try
!(self.print_qpath(path
, qself
, false))
1022 ast
::TyObjectSum(ref ty
, ref bounds
) => {
1023 try
!(self.print_type(&**ty
));
1024 try
!(self.print_bounds("+", &bounds
[..]));
1026 ast
::TyPolyTraitRef(ref bounds
) => {
1027 try
!(self.print_bounds("", &bounds
[..]));
1029 ast
::TyFixedLengthVec(ref ty
, ref v
) => {
1030 try
!(word(&mut self.s
, "["));
1031 try
!(self.print_type(&**ty
));
1032 try
!(word(&mut self.s
, "; "));
1033 try
!(self.print_expr(&**v
));
1034 try
!(word(&mut self.s
, "]"));
1036 ast
::TyTypeof(ref e
) => {
1037 try
!(word(&mut self.s
, "typeof("));
1038 try
!(self.print_expr(&**e
));
1039 try
!(word(&mut self.s
, ")"));
1042 try
!(word(&mut self.s
, "_"));
1044 ast
::TyMac(ref m
) => {
1045 try
!(self.print_mac(m
, token
::Paren
));
1051 pub fn print_foreign_item(&mut self,
1052 item
: &ast
::ForeignItem
) -> io
::Result
<()> {
1053 try
!(self.hardbreak_if_not_bol());
1054 try
!(self.maybe_print_comment(item
.span
.lo
));
1055 try
!(self.print_outer_attributes(&item
.attrs
));
1057 ast
::ForeignItemFn(ref decl
, ref generics
) => {
1058 try
!(self.head(""));
1059 try
!(self.print_fn(decl
, ast
::Unsafety
::Normal
,
1060 ast
::Constness
::NotConst
,
1061 abi
::Rust
, Some(item
.ident
),
1062 generics
, None
, item
.vis
));
1063 try
!(self.end()); // end head-ibox
1064 try
!(word(&mut self.s
, ";"));
1065 self.end() // end the outer fn box
1067 ast
::ForeignItemStatic(ref t
, m
) => {
1068 try
!(self.head(&visibility_qualified(item
.vis
,
1071 try
!(self.word_space("mut"));
1073 try
!(self.print_ident(item
.ident
));
1074 try
!(self.word_space(":"));
1075 try
!(self.print_type(&**t
));
1076 try
!(word(&mut self.s
, ";"));
1077 try
!(self.end()); // end the head-ibox
1078 self.end() // end the outer cbox
1083 fn print_associated_const(&mut self,
1086 default: Option
<&ast
::Expr
>,
1087 vis
: ast
::Visibility
)
1090 try
!(word(&mut self.s
, &visibility_qualified(vis
, "")));
1091 try
!(self.word_space("const"));
1092 try
!(self.print_ident(ident
));
1093 try
!(self.word_space(":"));
1094 try
!(self.print_type(ty
));
1095 if let Some(expr
) = default {
1096 try
!(space(&mut self.s
));
1097 try
!(self.word_space("="));
1098 try
!(self.print_expr(expr
));
1100 word(&mut self.s
, ";")
1103 fn print_associated_type(&mut self,
1105 bounds
: Option
<&ast
::TyParamBounds
>,
1106 ty
: Option
<&ast
::Ty
>)
1108 try
!(self.word_space("type"));
1109 try
!(self.print_ident(ident
));
1110 if let Some(bounds
) = bounds
{
1111 try
!(self.print_bounds(":", bounds
));
1113 if let Some(ty
) = ty
{
1114 try
!(space(&mut self.s
));
1115 try
!(self.word_space("="));
1116 try
!(self.print_type(ty
));
1118 word(&mut self.s
, ";")
1121 /// Pretty-print an item
1122 pub fn print_item(&mut self, item
: &ast
::Item
) -> io
::Result
<()> {
1123 try
!(self.hardbreak_if_not_bol());
1124 try
!(self.maybe_print_comment(item
.span
.lo
));
1125 try
!(self.print_outer_attributes(&item
.attrs
));
1126 try
!(self.ann
.pre(self, NodeItem(item
)));
1128 ast
::ItemExternCrate(ref optional_path
) => {
1129 try
!(self.head(&visibility_qualified(item
.vis
,
1131 if let Some(p
) = *optional_path
{
1132 let val
= p
.as_str();
1133 if val
.contains("-") {
1134 try
!(self.print_string(&val
, ast
::CookedStr
));
1136 try
!(self.print_name(p
));
1138 try
!(space(&mut self.s
));
1139 try
!(word(&mut self.s
, "as"));
1140 try
!(space(&mut self.s
));
1142 try
!(self.print_ident(item
.ident
));
1143 try
!(word(&mut self.s
, ";"));
1144 try
!(self.end()); // end inner head-block
1145 try
!(self.end()); // end outer head-block
1147 ast
::ItemUse(ref vp
) => {
1148 try
!(self.head(&visibility_qualified(item
.vis
,
1150 try
!(self.print_view_path(&**vp
));
1151 try
!(word(&mut self.s
, ";"));
1152 try
!(self.end()); // end inner head-block
1153 try
!(self.end()); // end outer head-block
1155 ast
::ItemStatic(ref ty
, m
, ref expr
) => {
1156 try
!(self.head(&visibility_qualified(item
.vis
,
1158 if m
== ast
::MutMutable
{
1159 try
!(self.word_space("mut"));
1161 try
!(self.print_ident(item
.ident
));
1162 try
!(self.word_space(":"));
1163 try
!(self.print_type(&**ty
));
1164 try
!(space(&mut self.s
));
1165 try
!(self.end()); // end the head-ibox
1167 try
!(self.word_space("="));
1168 try
!(self.print_expr(&**expr
));
1169 try
!(word(&mut self.s
, ";"));
1170 try
!(self.end()); // end the outer cbox
1172 ast
::ItemConst(ref ty
, ref expr
) => {
1173 try
!(self.head(&visibility_qualified(item
.vis
,
1175 try
!(self.print_ident(item
.ident
));
1176 try
!(self.word_space(":"));
1177 try
!(self.print_type(&**ty
));
1178 try
!(space(&mut self.s
));
1179 try
!(self.end()); // end the head-ibox
1181 try
!(self.word_space("="));
1182 try
!(self.print_expr(&**expr
));
1183 try
!(word(&mut self.s
, ";"));
1184 try
!(self.end()); // end the outer cbox
1186 ast
::ItemFn(ref decl
, unsafety
, constness
, abi
, ref typarams
, ref body
) => {
1187 try
!(self.head(""));
1198 try
!(word(&mut self.s
, " "));
1199 try
!(self.print_block_with_attrs(&**body
, &item
.attrs
));
1201 ast
::ItemMod(ref _mod
) => {
1202 try
!(self.head(&visibility_qualified(item
.vis
,
1204 try
!(self.print_ident(item
.ident
));
1207 try
!(self.print_mod(_mod
, &item
.attrs
));
1208 try
!(self.bclose(item
.span
));
1210 ast
::ItemForeignMod(ref nmod
) => {
1211 try
!(self.head("extern"));
1212 try
!(self.word_nbsp(&nmod
.abi
.to_string()));
1214 try
!(self.print_foreign_mod(nmod
, &item
.attrs
));
1215 try
!(self.bclose(item
.span
));
1217 ast
::ItemTy(ref ty
, ref params
) => {
1218 try
!(self.ibox(INDENT_UNIT
));
1220 try
!(self.word_nbsp(&visibility_qualified(item
.vis
, "type")));
1221 try
!(self.print_ident(item
.ident
));
1222 try
!(self.print_generics(params
));
1223 try
!(self.end()); // end the inner ibox
1225 try
!(self.print_where_clause(¶ms
.where_clause
));
1226 try
!(space(&mut self.s
));
1227 try
!(self.word_space("="));
1228 try
!(self.print_type(&**ty
));
1229 try
!(word(&mut self.s
, ";"));
1230 try
!(self.end()); // end the outer ibox
1232 ast
::ItemEnum(ref enum_definition
, ref params
) => {
1233 try
!(self.print_enum_def(
1241 ast
::ItemStruct(ref struct_def
, ref generics
) => {
1242 try
!(self.head(&visibility_qualified(item
.vis
,"struct")));
1243 try
!(self.print_struct(&struct_def
, generics
, item
.ident
, item
.span
, true));
1246 ast
::ItemDefaultImpl(unsafety
, ref trait_ref
) => {
1247 try
!(self.head(""));
1248 try
!(self.print_visibility(item
.vis
));
1249 try
!(self.print_unsafety(unsafety
));
1250 try
!(self.word_nbsp("impl"));
1251 try
!(self.print_trait_ref(trait_ref
));
1252 try
!(space(&mut self.s
));
1253 try
!(self.word_space("for"));
1254 try
!(self.word_space(".."));
1256 try
!(self.bclose(item
.span
));
1258 ast
::ItemImpl(unsafety
,
1263 ref impl_items
) => {
1264 try
!(self.head(""));
1265 try
!(self.print_visibility(item
.vis
));
1266 try
!(self.print_unsafety(unsafety
));
1267 try
!(self.word_nbsp("impl"));
1269 if generics
.is_parameterized() {
1270 try
!(self.print_generics(generics
));
1271 try
!(space(&mut self.s
));
1275 ast
::ImplPolarity
::Negative
=> {
1276 try
!(word(&mut self.s
, "!"));
1283 try
!(self.print_trait_ref(t
));
1284 try
!(space(&mut self.s
));
1285 try
!(self.word_space("for"));
1290 try
!(self.print_type(&**ty
));
1291 try
!(self.print_where_clause(&generics
.where_clause
));
1293 try
!(space(&mut self.s
));
1295 try
!(self.print_inner_attributes(&item
.attrs
));
1296 for impl_item
in impl_items
{
1297 try
!(self.print_impl_item(impl_item
));
1299 try
!(self.bclose(item
.span
));
1301 ast
::ItemTrait(unsafety
, ref generics
, ref bounds
, ref trait_items
) => {
1302 try
!(self.head(""));
1303 try
!(self.print_visibility(item
.vis
));
1304 try
!(self.print_unsafety(unsafety
));
1305 try
!(self.word_nbsp("trait"));
1306 try
!(self.print_ident(item
.ident
));
1307 try
!(self.print_generics(generics
));
1308 let mut real_bounds
= Vec
::with_capacity(bounds
.len());
1309 for b
in bounds
.iter() {
1310 if let TraitTyParamBound(ref ptr
, ast
::TraitBoundModifier
::Maybe
) = *b
{
1311 try
!(space(&mut self.s
));
1312 try
!(self.word_space("for ?"));
1313 try
!(self.print_trait_ref(&ptr
.trait_ref
));
1315 real_bounds
.push(b
.clone());
1318 try
!(self.print_bounds(":", &real_bounds
[..]));
1319 try
!(self.print_where_clause(&generics
.where_clause
));
1320 try
!(word(&mut self.s
, " "));
1322 for trait_item
in trait_items
{
1323 try
!(self.print_trait_item(trait_item
));
1325 try
!(self.bclose(item
.span
));
1327 ast
::ItemMac(codemap
::Spanned { ref node, .. }
) => {
1328 try
!(self.print_visibility(item
.vis
));
1329 try
!(self.print_path(&node
.path
, false, 0));
1330 try
!(word(&mut self.s
, "! "));
1331 try
!(self.print_ident(item
.ident
));
1332 try
!(self.cbox(INDENT_UNIT
));
1334 try
!(self.print_tts(&node
.tts
[..]));
1335 try
!(self.pclose());
1336 try
!(word(&mut self.s
, ";"));
1340 self.ann
.post(self, NodeItem(item
))
1343 fn print_trait_ref(&mut self, t
: &ast
::TraitRef
) -> io
::Result
<()> {
1344 self.print_path(&t
.path
, false, 0)
1347 fn print_formal_lifetime_list(&mut self, lifetimes
: &[ast
::LifetimeDef
]) -> io
::Result
<()> {
1348 if !lifetimes
.is_empty() {
1349 try
!(word(&mut self.s
, "for<"));
1350 let mut comma
= false;
1351 for lifetime_def
in lifetimes
{
1353 try
!(self.word_space(","))
1355 try
!(self.print_lifetime_def(lifetime_def
));
1358 try
!(word(&mut self.s
, ">"));
1363 fn print_poly_trait_ref(&mut self, t
: &ast
::PolyTraitRef
) -> io
::Result
<()> {
1364 try
!(self.print_formal_lifetime_list(&t
.bound_lifetimes
));
1365 self.print_trait_ref(&t
.trait_ref
)
1368 pub fn print_enum_def(&mut self, enum_definition
: &ast
::EnumDef
,
1369 generics
: &ast
::Generics
, ident
: ast
::Ident
,
1370 span
: codemap
::Span
,
1371 visibility
: ast
::Visibility
) -> io
::Result
<()> {
1372 try
!(self.head(&visibility_qualified(visibility
, "enum")));
1373 try
!(self.print_ident(ident
));
1374 try
!(self.print_generics(generics
));
1375 try
!(self.print_where_clause(&generics
.where_clause
));
1376 try
!(space(&mut self.s
));
1377 self.print_variants(&enum_definition
.variants
, span
)
1380 pub fn print_variants(&mut self,
1381 variants
: &[P
<ast
::Variant
>],
1382 span
: codemap
::Span
) -> io
::Result
<()> {
1385 try
!(self.space_if_not_bol());
1386 try
!(self.maybe_print_comment(v
.span
.lo
));
1387 try
!(self.print_outer_attributes(&v
.node
.attrs
));
1388 try
!(self.ibox(INDENT_UNIT
));
1389 try
!(self.print_variant(&**v
));
1390 try
!(word(&mut self.s
, ","));
1392 try
!(self.maybe_print_trailing_comment(v
.span
, None
));
1397 pub fn print_visibility(&mut self, vis
: ast
::Visibility
) -> io
::Result
<()> {
1399 ast
::Public
=> self.word_nbsp("pub"),
1400 ast
::Inherited
=> Ok(())
1404 pub fn print_struct(&mut self,
1405 struct_def
: &ast
::VariantData
,
1406 generics
: &ast
::Generics
,
1408 span
: codemap
::Span
,
1409 print_finalizer
: bool
) -> io
::Result
<()> {
1410 try
!(self.print_ident(ident
));
1411 try
!(self.print_generics(generics
));
1412 if !struct_def
.is_struct() {
1413 if struct_def
.is_tuple() {
1416 Inconsistent
, struct_def
.fields(),
1418 match field
.node
.kind
{
1419 ast
::NamedField(..) => panic
!("unexpected named field"),
1420 ast
::UnnamedField(vis
) => {
1421 try
!(s
.print_visibility(vis
));
1422 try
!(s
.maybe_print_comment(field
.span
.lo
));
1423 s
.print_type(&*field
.node
.ty
)
1428 try
!(self.pclose());
1430 try
!(self.print_where_clause(&generics
.where_clause
));
1431 if print_finalizer
{
1432 try
!(word(&mut self.s
, ";"));
1435 self.end() // close the outer-box
1437 try
!(self.print_where_clause(&generics
.where_clause
));
1440 try
!(self.hardbreak_if_not_bol());
1442 for field
in struct_def
.fields() {
1443 match field
.node
.kind
{
1444 ast
::UnnamedField(..) => panic
!("unexpected unnamed field"),
1445 ast
::NamedField(ident
, visibility
) => {
1446 try
!(self.hardbreak_if_not_bol());
1447 try
!(self.maybe_print_comment(field
.span
.lo
));
1448 try
!(self.print_outer_attributes(&field
.node
.attrs
));
1449 try
!(self.print_visibility(visibility
));
1450 try
!(self.print_ident(ident
));
1451 try
!(self.word_nbsp(":"));
1452 try
!(self.print_type(&*field
.node
.ty
));
1453 try
!(word(&mut self.s
, ","));
1462 /// This doesn't deserve to be called "pretty" printing, but it should be
1463 /// meaning-preserving. A quick hack that might help would be to look at the
1464 /// spans embedded in the TTs to decide where to put spaces and newlines.
1465 /// But it'd be better to parse these according to the grammar of the
1466 /// appropriate macro, transcribe back into the grammar we just parsed from,
1467 /// and then pretty-print the resulting AST nodes (so, e.g., we print
1468 /// expression arguments as expressions). It can be done! I think.
1469 pub fn print_tt(&mut self, tt
: &ast
::TokenTree
) -> io
::Result
<()> {
1471 TokenTree
::Token(_
, ref tk
) => {
1472 try
!(word(&mut self.s
, &token_to_string(tk
)));
1474 parse
::token
::DocComment(..) => {
1475 hardbreak(&mut self.s
)
1480 TokenTree
::Delimited(_
, ref delimed
) => {
1481 try
!(word(&mut self.s
, &token_to_string(&delimed
.open_token())));
1482 try
!(space(&mut self.s
));
1483 try
!(self.print_tts(&delimed
.tts
));
1484 try
!(space(&mut self.s
));
1485 word(&mut self.s
, &token_to_string(&delimed
.close_token()))
1487 TokenTree
::Sequence(_
, ref seq
) => {
1488 try
!(word(&mut self.s
, "$("));
1489 for tt_elt
in &seq
.tts
{
1490 try
!(self.print_tt(tt_elt
));
1492 try
!(word(&mut self.s
, ")"));
1493 match seq
.separator
{
1495 try
!(word(&mut self.s
, &token_to_string(tk
)));
1500 ast
::ZeroOrMore
=> word(&mut self.s
, "*"),
1501 ast
::OneOrMore
=> word(&mut self.s
, "+"),
1507 pub fn print_tts(&mut self, tts
: &[ast
::TokenTree
]) -> io
::Result
<()> {
1509 let mut suppress_space
= false;
1510 for (i
, tt
) in tts
.iter().enumerate() {
1511 if i
!= 0 && !suppress_space
{
1512 try
!(space(&mut self.s
));
1514 try
!(self.print_tt(tt
));
1515 // There should be no space between the module name and the following `::` in paths,
1516 // otherwise imported macros get re-parsed from crate metadata incorrectly (#20701)
1517 suppress_space
= match *tt
{
1518 TokenTree
::Token(_
, token
::Ident(_
, token
::ModName
)) |
1519 TokenTree
::Token(_
, token
::MatchNt(_
, _
, _
, token
::ModName
)) |
1520 TokenTree
::Token(_
, token
::SubstNt(_
, token
::ModName
)) => true,
1527 pub fn print_variant(&mut self, v
: &ast
::Variant
) -> io
::Result
<()> {
1528 try
!(self.head(""));
1529 let generics
= ast
::Generics
::default();
1530 try
!(self.print_struct(&v
.node
.data
, &generics
, v
.node
.name
, v
.span
, false));
1531 match v
.node
.disr_expr
{
1533 try
!(space(&mut self.s
));
1534 try
!(self.word_space("="));
1535 self.print_expr(&**d
)
1541 pub fn print_method_sig(&mut self,
1544 vis
: ast
::Visibility
)
1546 self.print_fn(&m
.decl
,
1552 Some(&m
.explicit_self
.node
),
1556 pub fn print_trait_item(&mut self, ti
: &ast
::TraitItem
)
1558 try
!(self.ann
.pre(self, NodeSubItem(ti
.id
)));
1559 try
!(self.hardbreak_if_not_bol());
1560 try
!(self.maybe_print_comment(ti
.span
.lo
));
1561 try
!(self.print_outer_attributes(&ti
.attrs
));
1563 ast
::ConstTraitItem(ref ty
, ref default) => {
1564 try
!(self.print_associated_const(ti
.ident
, &ty
,
1565 default.as_ref().map(|expr
| &**expr
),
1568 ast
::MethodTraitItem(ref sig
, ref body
) => {
1570 try
!(self.head(""));
1572 try
!(self.print_method_sig(ti
.ident
, sig
, ast
::Inherited
));
1573 if let Some(ref body
) = *body
{
1575 try
!(self.print_block_with_attrs(body
, &ti
.attrs
));
1577 try
!(word(&mut self.s
, ";"));
1580 ast
::TypeTraitItem(ref bounds
, ref default) => {
1581 try
!(self.print_associated_type(ti
.ident
, Some(bounds
),
1582 default.as_ref().map(|ty
| &**ty
)));
1585 self.ann
.post(self, NodeSubItem(ti
.id
))
1588 pub fn print_impl_item(&mut self, ii
: &ast
::ImplItem
) -> io
::Result
<()> {
1589 try
!(self.ann
.pre(self, NodeSubItem(ii
.id
)));
1590 try
!(self.hardbreak_if_not_bol());
1591 try
!(self.maybe_print_comment(ii
.span
.lo
));
1592 try
!(self.print_outer_attributes(&ii
.attrs
));
1594 ast
::ImplItemKind
::Const(ref ty
, ref expr
) => {
1595 try
!(self.print_associated_const(ii
.ident
, &ty
, Some(&expr
), ii
.vis
));
1597 ast
::ImplItemKind
::Method(ref sig
, ref body
) => {
1598 try
!(self.head(""));
1599 try
!(self.print_method_sig(ii
.ident
, sig
, ii
.vis
));
1601 try
!(self.print_block_with_attrs(body
, &ii
.attrs
));
1603 ast
::ImplItemKind
::Type(ref ty
) => {
1604 try
!(self.print_associated_type(ii
.ident
, None
, Some(ty
)));
1606 ast
::ImplItemKind
::Macro(codemap
::Spanned { ref node, .. }
) => {
1607 // code copied from ItemMac:
1608 try
!(self.print_path(&node
.path
, false, 0));
1609 try
!(word(&mut self.s
, "! "));
1610 try
!(self.cbox(INDENT_UNIT
));
1612 try
!(self.print_tts(&node
.tts
[..]));
1613 try
!(self.pclose());
1614 try
!(word(&mut self.s
, ";"));
1618 self.ann
.post(self, NodeSubItem(ii
.id
))
1621 pub fn print_stmt(&mut self, st
: &ast
::Stmt
) -> io
::Result
<()> {
1622 try
!(self.maybe_print_comment(st
.span
.lo
));
1624 ast
::StmtDecl(ref decl
, _
) => {
1625 try
!(self.print_decl(&**decl
));
1627 ast
::StmtExpr(ref expr
, _
) => {
1628 try
!(self.space_if_not_bol());
1629 try
!(self.print_expr_outer_attr_style(&**expr
, false));
1631 ast
::StmtSemi(ref expr
, _
) => {
1632 try
!(self.space_if_not_bol());
1633 try
!(self.print_expr_outer_attr_style(&**expr
, false));
1634 try
!(word(&mut self.s
, ";"));
1636 ast
::StmtMac(ref mac
, style
, ref attrs
) => {
1637 try
!(self.space_if_not_bol());
1638 try
!(self.print_outer_attributes(attrs
.as_attr_slice()));
1639 let delim
= match style
{
1640 ast
::MacStmtWithBraces
=> token
::Brace
,
1643 try
!(self.print_mac(&**mac
, delim
));
1645 ast
::MacStmtWithBraces
=> {}
1646 _
=> try
!(word(&mut self.s
, ";")),
1650 if parse
::classify
::stmt_ends_with_semi(&st
.node
) {
1651 try
!(word(&mut self.s
, ";"));
1653 self.maybe_print_trailing_comment(st
.span
, None
)
1656 pub fn print_block(&mut self, blk
: &ast
::Block
) -> io
::Result
<()> {
1657 self.print_block_with_attrs(blk
, &[])
1660 pub fn print_block_unclosed(&mut self, blk
: &ast
::Block
) -> io
::Result
<()> {
1661 self.print_block_unclosed_indent(blk
, INDENT_UNIT
)
1664 pub fn print_block_unclosed_with_attrs(&mut self, blk
: &ast
::Block
,
1665 attrs
: &[ast
::Attribute
])
1667 self.print_block_maybe_unclosed(blk
, INDENT_UNIT
, attrs
, false)
1670 pub fn print_block_unclosed_indent(&mut self, blk
: &ast
::Block
,
1671 indented
: usize) -> io
::Result
<()> {
1672 self.print_block_maybe_unclosed(blk
, indented
, &[], false)
1675 pub fn print_block_with_attrs(&mut self,
1677 attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
1678 self.print_block_maybe_unclosed(blk
, INDENT_UNIT
, attrs
, true)
1681 pub fn print_block_maybe_unclosed(&mut self,
1684 attrs
: &[ast
::Attribute
],
1685 close_box
: bool
) -> io
::Result
<()> {
1687 ast
::UnsafeBlock(..) => try
!(self.word_space("unsafe")),
1688 ast
::DefaultBlock
=> ()
1690 try
!(self.maybe_print_comment(blk
.span
.lo
));
1691 try
!(self.ann
.pre(self, NodeBlock(blk
)));
1694 try
!(self.print_inner_attributes(attrs
));
1696 for st
in &blk
.stmts
{
1697 try
!(self.print_stmt(&**st
));
1701 try
!(self.space_if_not_bol());
1702 try
!(self.print_expr_outer_attr_style(&**expr
, false));
1703 try
!(self.maybe_print_trailing_comment(expr
.span
, Some(blk
.span
.hi
)));
1707 try
!(self.bclose_maybe_open(blk
.span
, indented
, close_box
));
1708 self.ann
.post(self, NodeBlock(blk
))
1711 fn print_else(&mut self, els
: Option
<&ast
::Expr
>) -> io
::Result
<()> {
1715 // "another else-if"
1716 ast
::ExprIf(ref i
, ref then
, ref e
) => {
1717 try
!(self.cbox(INDENT_UNIT
- 1));
1719 try
!(word(&mut self.s
, " else if "));
1720 try
!(self.print_expr(&**i
));
1721 try
!(space(&mut self.s
));
1722 try
!(self.print_block(&**then
));
1723 self.print_else(e
.as_ref().map(|e
| &**e
))
1725 // "another else-if-let"
1726 ast
::ExprIfLet(ref pat
, ref expr
, ref then
, ref e
) => {
1727 try
!(self.cbox(INDENT_UNIT
- 1));
1729 try
!(word(&mut self.s
, " else if let "));
1730 try
!(self.print_pat(&**pat
));
1731 try
!(space(&mut self.s
));
1732 try
!(self.word_space("="));
1733 try
!(self.print_expr(&**expr
));
1734 try
!(space(&mut self.s
));
1735 try
!(self.print_block(&**then
));
1736 self.print_else(e
.as_ref().map(|e
| &**e
))
1739 ast
::ExprBlock(ref b
) => {
1740 try
!(self.cbox(INDENT_UNIT
- 1));
1742 try
!(word(&mut self.s
, " else "));
1743 self.print_block(&**b
)
1745 // BLEAH, constraints would be great here
1747 panic
!("print_if saw if with weird alternative");
1755 pub fn print_if(&mut self, test
: &ast
::Expr
, blk
: &ast
::Block
,
1756 elseopt
: Option
<&ast
::Expr
>) -> io
::Result
<()> {
1757 try
!(self.head("if"));
1758 try
!(self.print_expr(test
));
1759 try
!(space(&mut self.s
));
1760 try
!(self.print_block(blk
));
1761 self.print_else(elseopt
)
1764 pub fn print_if_let(&mut self, pat
: &ast
::Pat
, expr
: &ast
::Expr
, blk
: &ast
::Block
,
1765 elseopt
: Option
<&ast
::Expr
>) -> io
::Result
<()> {
1766 try
!(self.head("if let"));
1767 try
!(self.print_pat(pat
));
1768 try
!(space(&mut self.s
));
1769 try
!(self.word_space("="));
1770 try
!(self.print_expr(expr
));
1771 try
!(space(&mut self.s
));
1772 try
!(self.print_block(blk
));
1773 self.print_else(elseopt
)
1776 pub fn print_mac(&mut self, m
: &ast
::Mac
, delim
: token
::DelimToken
)
1778 try
!(self.print_path(&m
.node
.path
, false, 0));
1779 try
!(word(&mut self.s
, "!"));
1781 token
::Paren
=> try
!(self.popen()),
1782 token
::Bracket
=> try
!(word(&mut self.s
, "[")),
1784 // head-ibox, will be closed by bopen()
1786 // Don't ask me why the regular bopen() does
1787 // more then just opening a brace...
1791 try
!(self.print_tts(&m
.node
.tts
));
1793 token
::Paren
=> self.pclose(),
1794 token
::Bracket
=> word(&mut self.s
, "]"),
1795 token
::Brace
=> self.bclose(m
.span
),
1800 fn print_call_post(&mut self, args
: &[P
<ast
::Expr
>]) -> io
::Result
<()> {
1802 try
!(self.commasep_exprs(Inconsistent
, args
));
1806 pub fn check_expr_bin_needs_paren(&mut self, sub_expr
: &ast
::Expr
,
1807 binop
: ast
::BinOp
) -> bool
{
1808 match sub_expr
.node
{
1809 ast
::ExprBinary(ref sub_op
, _
, _
) => {
1810 if AssocOp
::from_ast_binop(sub_op
.node
).precedence() <
1811 AssocOp
::from_ast_binop(binop
.node
).precedence() {
1821 pub fn print_expr_maybe_paren(&mut self, expr
: &ast
::Expr
) -> io
::Result
<()> {
1822 let needs_par
= needs_parentheses(expr
);
1826 try
!(self.print_expr(expr
));
1828 try
!(self.pclose());
1833 fn print_expr_in_place(&mut self,
1835 expr
: &ast
::Expr
) -> io
::Result
<()> {
1836 try
!(self.print_expr_maybe_paren(place
));
1837 try
!(space(&mut self.s
));
1838 try
!(self.word_space("<-"));
1839 self.print_expr_maybe_paren(expr
)
1842 fn print_expr_vec(&mut self, exprs
: &[P
<ast
::Expr
>],
1843 attrs
: &[Attribute
]) -> io
::Result
<()> {
1844 try
!(self.ibox(INDENT_UNIT
));
1845 try
!(word(&mut self.s
, "["));
1846 try
!(self.print_inner_attributes_inline(attrs
));
1847 try
!(self.commasep_exprs(Inconsistent
, &exprs
[..]));
1848 try
!(word(&mut self.s
, "]"));
1852 fn print_expr_repeat(&mut self,
1853 element
: &ast
::Expr
,
1855 attrs
: &[Attribute
]) -> io
::Result
<()> {
1856 try
!(self.ibox(INDENT_UNIT
));
1857 try
!(word(&mut self.s
, "["));
1858 try
!(self.print_inner_attributes_inline(attrs
));
1859 try
!(self.print_expr(element
));
1860 try
!(self.word_space(";"));
1861 try
!(self.print_expr(count
));
1862 try
!(word(&mut self.s
, "]"));
1866 fn print_expr_struct(&mut self,
1868 fields
: &[ast
::Field
],
1869 wth
: &Option
<P
<ast
::Expr
>>,
1870 attrs
: &[Attribute
]) -> io
::Result
<()> {
1871 try
!(self.print_path(path
, true, 0));
1872 try
!(word(&mut self.s
, "{"));
1873 try
!(self.print_inner_attributes_inline(attrs
));
1874 try
!(self.commasep_cmnt(
1878 try
!(s
.ibox(INDENT_UNIT
));
1879 try
!(s
.print_ident(field
.ident
.node
));
1880 try
!(s
.word_space(":"));
1881 try
!(s
.print_expr(&*field
.expr
));
1887 try
!(self.ibox(INDENT_UNIT
));
1888 if !fields
.is_empty() {
1889 try
!(word(&mut self.s
, ","));
1890 try
!(space(&mut self.s
));
1892 try
!(word(&mut self.s
, ".."));
1893 try
!(self.print_expr(&**expr
));
1896 _
=> if !fields
.is_empty() {
1897 try
!(word(&mut self.s
, ","))
1900 try
!(word(&mut self.s
, "}"));
1904 fn print_expr_tup(&mut self, exprs
: &[P
<ast
::Expr
>],
1905 attrs
: &[Attribute
]) -> io
::Result
<()> {
1907 try
!(self.print_inner_attributes_inline(attrs
));
1908 try
!(self.commasep_exprs(Inconsistent
, &exprs
[..]));
1909 if exprs
.len() == 1 {
1910 try
!(word(&mut self.s
, ","));
1915 fn print_expr_call(&mut self,
1917 args
: &[P
<ast
::Expr
>]) -> io
::Result
<()> {
1918 try
!(self.print_expr_maybe_paren(func
));
1919 self.print_call_post(args
)
1922 fn print_expr_method_call(&mut self,
1923 ident
: ast
::SpannedIdent
,
1925 args
: &[P
<ast
::Expr
>]) -> io
::Result
<()> {
1926 let base_args
= &args
[1..];
1927 try
!(self.print_expr(&*args
[0]));
1928 try
!(word(&mut self.s
, "."));
1929 try
!(self.print_ident(ident
.node
));
1930 if !tys
.is_empty() {
1931 try
!(word(&mut self.s
, "::<"));
1932 try
!(self.commasep(Inconsistent
, tys
,
1933 |s
, ty
| s
.print_type(&**ty
)));
1934 try
!(word(&mut self.s
, ">"));
1936 self.print_call_post(base_args
)
1939 fn print_expr_binary(&mut self,
1942 rhs
: &ast
::Expr
) -> io
::Result
<()> {
1943 if self.check_expr_bin_needs_paren(lhs
, op
) {
1944 try
!(self.print_expr_maybe_paren(lhs
));
1946 try
!(self.print_expr(lhs
));
1948 try
!(space(&mut self.s
));
1949 try
!(self.word_space(op
.node
.to_string()));
1950 if self.check_expr_bin_needs_paren(rhs
, op
) {
1951 self.print_expr_maybe_paren(rhs
)
1953 self.print_expr(rhs
)
1957 fn print_expr_unary(&mut self,
1959 expr
: &ast
::Expr
) -> io
::Result
<()> {
1960 try
!(word(&mut self.s
, ast
::UnOp
::to_string(op
)));
1961 self.print_expr_maybe_paren(expr
)
1964 fn print_expr_addr_of(&mut self,
1965 mutability
: ast
::Mutability
,
1966 expr
: &ast
::Expr
) -> io
::Result
<()> {
1967 try
!(word(&mut self.s
, "&"));
1968 try
!(self.print_mutability(mutability
));
1969 self.print_expr_maybe_paren(expr
)
1972 pub fn print_expr(&mut self, expr
: &ast
::Expr
) -> io
::Result
<()> {
1973 self.print_expr_outer_attr_style(expr
, true)
1976 fn print_expr_outer_attr_style(&mut self,
1978 is_inline
: bool
) -> io
::Result
<()> {
1979 try
!(self.maybe_print_comment(expr
.span
.lo
));
1981 let attrs
= expr
.attrs
.as_attr_slice();
1983 try
!(self.print_outer_attributes_inline(attrs
));
1985 try
!(self.print_outer_attributes(attrs
));
1988 try
!(self.ibox(INDENT_UNIT
));
1989 try
!(self.ann
.pre(self, NodeExpr(expr
)));
1991 ast
::ExprBox(ref expr
) => {
1992 try
!(self.word_space("box"));
1993 try
!(self.print_expr(expr
));
1995 ast
::ExprInPlace(ref place
, ref expr
) => {
1996 try
!(self.print_expr_in_place(place
, expr
));
1998 ast
::ExprVec(ref exprs
) => {
1999 try
!(self.print_expr_vec(&exprs
[..], attrs
));
2001 ast
::ExprRepeat(ref element
, ref count
) => {
2002 try
!(self.print_expr_repeat(&**element
, &**count
, attrs
));
2004 ast
::ExprStruct(ref path
, ref fields
, ref wth
) => {
2005 try
!(self.print_expr_struct(path
, &fields
[..], wth
, attrs
));
2007 ast
::ExprTup(ref exprs
) => {
2008 try
!(self.print_expr_tup(&exprs
[..], attrs
));
2010 ast
::ExprCall(ref func
, ref args
) => {
2011 try
!(self.print_expr_call(&**func
, &args
[..]));
2013 ast
::ExprMethodCall(ident
, ref tys
, ref args
) => {
2014 try
!(self.print_expr_method_call(ident
, &tys
[..], &args
[..]));
2016 ast
::ExprBinary(op
, ref lhs
, ref rhs
) => {
2017 try
!(self.print_expr_binary(op
, &**lhs
, &**rhs
));
2019 ast
::ExprUnary(op
, ref expr
) => {
2020 try
!(self.print_expr_unary(op
, &**expr
));
2022 ast
::ExprAddrOf(m
, ref expr
) => {
2023 try
!(self.print_expr_addr_of(m
, &**expr
));
2025 ast
::ExprLit(ref lit
) => {
2026 try
!(self.print_literal(&**lit
));
2028 ast
::ExprCast(ref expr
, ref ty
) => {
2029 if let ast
::ExprCast(..) = expr
.node
{
2030 try
!(self.print_expr(&**expr
));
2032 try
!(self.print_expr_maybe_paren(&**expr
));
2034 try
!(space(&mut self.s
));
2035 try
!(self.word_space("as"));
2036 try
!(self.print_type(&**ty
));
2038 ast
::ExprType(ref expr
, ref ty
) => {
2039 try
!(self.print_expr(&**expr
));
2040 try
!(self.word_space(":"));
2041 try
!(self.print_type(&**ty
));
2043 ast
::ExprIf(ref test
, ref blk
, ref elseopt
) => {
2044 try
!(self.print_if(&**test
, &**blk
, elseopt
.as_ref().map(|e
| &**e
)));
2046 ast
::ExprIfLet(ref pat
, ref expr
, ref blk
, ref elseopt
) => {
2047 try
!(self.print_if_let(&**pat
, &**expr
, &** blk
, elseopt
.as_ref().map(|e
| &**e
)));
2049 ast
::ExprWhile(ref test
, ref blk
, opt_ident
) => {
2050 if let Some(ident
) = opt_ident
{
2051 try
!(self.print_ident(ident
));
2052 try
!(self.word_space(":"));
2054 try
!(self.head("while"));
2055 try
!(self.print_expr(&**test
));
2056 try
!(space(&mut self.s
));
2057 try
!(self.print_block_with_attrs(&**blk
, attrs
));
2059 ast
::ExprWhileLet(ref pat
, ref expr
, ref blk
, opt_ident
) => {
2060 if let Some(ident
) = opt_ident
{
2061 try
!(self.print_ident(ident
));
2062 try
!(self.word_space(":"));
2064 try
!(self.head("while let"));
2065 try
!(self.print_pat(&**pat
));
2066 try
!(space(&mut self.s
));
2067 try
!(self.word_space("="));
2068 try
!(self.print_expr(&**expr
));
2069 try
!(space(&mut self.s
));
2070 try
!(self.print_block_with_attrs(&**blk
, attrs
));
2072 ast
::ExprForLoop(ref pat
, ref iter
, ref blk
, opt_ident
) => {
2073 if let Some(ident
) = opt_ident
{
2074 try
!(self.print_ident(ident
));
2075 try
!(self.word_space(":"));
2077 try
!(self.head("for"));
2078 try
!(self.print_pat(&**pat
));
2079 try
!(space(&mut self.s
));
2080 try
!(self.word_space("in"));
2081 try
!(self.print_expr(&**iter
));
2082 try
!(space(&mut self.s
));
2083 try
!(self.print_block_with_attrs(&**blk
, attrs
));
2085 ast
::ExprLoop(ref blk
, opt_ident
) => {
2086 if let Some(ident
) = opt_ident
{
2087 try
!(self.print_ident(ident
));
2088 try
!(self.word_space(":"));
2090 try
!(self.head("loop"));
2091 try
!(space(&mut self.s
));
2092 try
!(self.print_block_with_attrs(&**blk
, attrs
));
2094 ast
::ExprMatch(ref expr
, ref arms
) => {
2095 try
!(self.cbox(INDENT_UNIT
));
2097 try
!(self.word_nbsp("match"));
2098 try
!(self.print_expr(&**expr
));
2099 try
!(space(&mut self.s
));
2101 try
!(self.print_inner_attributes_no_trailing_hardbreak(attrs
));
2103 try
!(self.print_arm(arm
));
2105 try
!(self.bclose_(expr
.span
, INDENT_UNIT
));
2107 ast
::ExprClosure(capture_clause
, ref decl
, ref body
) => {
2108 try
!(self.print_capture_clause(capture_clause
));
2110 try
!(self.print_fn_block_args(&**decl
));
2111 try
!(space(&mut self.s
));
2113 let default_return
= match decl
.output
{
2114 ast
::DefaultReturn(..) => true,
2118 if !default_return
|| !body
.stmts
.is_empty() || body
.expr
.is_none() {
2119 try
!(self.print_block_unclosed(&**body
));
2121 // we extract the block, so as not to create another set of boxes
2122 let i_expr
= body
.expr
.as_ref().unwrap();
2124 ast
::ExprBlock(ref blk
) => {
2125 try
!(self.print_block_unclosed_with_attrs(
2127 i_expr
.attrs
.as_attr_slice()));
2130 // this is a bare expression
2131 try
!(self.print_expr(&**i_expr
));
2132 try
!(self.end()); // need to close a box
2136 // a box will be closed by print_expr, but we didn't want an overall
2137 // wrapper so we closed the corresponding opening. so create an
2138 // empty box to satisfy the close.
2141 ast
::ExprBlock(ref blk
) => {
2142 // containing cbox, will be closed by print-block at }
2143 try
!(self.cbox(INDENT_UNIT
));
2144 // head-box, will be closed by print-block after {
2146 try
!(self.print_block_with_attrs(&**blk
, attrs
));
2148 ast
::ExprAssign(ref lhs
, ref rhs
) => {
2149 try
!(self.print_expr(&**lhs
));
2150 try
!(space(&mut self.s
));
2151 try
!(self.word_space("="));
2152 try
!(self.print_expr(&**rhs
));
2154 ast
::ExprAssignOp(op
, ref lhs
, ref rhs
) => {
2155 try
!(self.print_expr(&**lhs
));
2156 try
!(space(&mut self.s
));
2157 try
!(word(&mut self.s
, op
.node
.to_string()));
2158 try
!(self.word_space("="));
2159 try
!(self.print_expr(&**rhs
));
2161 ast
::ExprField(ref expr
, id
) => {
2162 try
!(self.print_expr(&**expr
));
2163 try
!(word(&mut self.s
, "."));
2164 try
!(self.print_ident(id
.node
));
2166 ast
::ExprTupField(ref expr
, id
) => {
2167 try
!(self.print_expr(&**expr
));
2168 try
!(word(&mut self.s
, "."));
2169 try
!(self.print_usize(id
.node
));
2171 ast
::ExprIndex(ref expr
, ref index
) => {
2172 try
!(self.print_expr(&**expr
));
2173 try
!(word(&mut self.s
, "["));
2174 try
!(self.print_expr(&**index
));
2175 try
!(word(&mut self.s
, "]"));
2177 ast
::ExprRange(ref start
, ref end
) => {
2178 if let &Some(ref e
) = start
{
2179 try
!(self.print_expr(&**e
));
2181 try
!(word(&mut self.s
, ".."));
2182 if let &Some(ref e
) = end
{
2183 try
!(self.print_expr(&**e
));
2186 ast
::ExprPath(None
, ref path
) => {
2187 try
!(self.print_path(path
, true, 0))
2189 ast
::ExprPath(Some(ref qself
), ref path
) => {
2190 try
!(self.print_qpath(path
, qself
, true))
2192 ast
::ExprBreak(opt_ident
) => {
2193 try
!(word(&mut self.s
, "break"));
2194 try
!(space(&mut self.s
));
2195 if let Some(ident
) = opt_ident
{
2196 try
!(self.print_ident(ident
.node
));
2197 try
!(space(&mut self.s
));
2200 ast
::ExprAgain(opt_ident
) => {
2201 try
!(word(&mut self.s
, "continue"));
2202 try
!(space(&mut self.s
));
2203 if let Some(ident
) = opt_ident
{
2204 try
!(self.print_ident(ident
.node
));
2205 try
!(space(&mut self.s
))
2208 ast
::ExprRet(ref result
) => {
2209 try
!(word(&mut self.s
, "return"));
2212 try
!(word(&mut self.s
, " "));
2213 try
!(self.print_expr(&**expr
));
2218 ast
::ExprInlineAsm(ref a
) => {
2219 try
!(word(&mut self.s
, "asm!"));
2221 try
!(self.print_string(&a
.asm
, a
.asm_str_style
));
2222 try
!(self.word_space(":"));
2224 try
!(self.commasep(Inconsistent
, &a
.outputs
,
2226 match out
.constraint
.slice_shift_char() {
2227 Some(('
='
, operand
)) if out
.is_rw
=> {
2228 try
!(s
.print_string(&format
!("+{}", operand
),
2231 _
=> try
!(s
.print_string(&out
.constraint
, ast
::CookedStr
))
2234 try
!(s
.print_expr(&*out
.expr
));
2238 try
!(space(&mut self.s
));
2239 try
!(self.word_space(":"));
2241 try
!(self.commasep(Inconsistent
, &a
.inputs
,
2242 |s
, &(ref co
, ref o
)| {
2243 try
!(s
.print_string(&co
, ast
::CookedStr
));
2245 try
!(s
.print_expr(&**o
));
2249 try
!(space(&mut self.s
));
2250 try
!(self.word_space(":"));
2252 try
!(self.commasep(Inconsistent
, &a
.clobbers
,
2254 try
!(s
.print_string(&co
, ast
::CookedStr
));
2258 let mut options
= vec
!();
2260 options
.push("volatile");
2263 options
.push("alignstack");
2265 if a
.dialect
== ast
::AsmDialect
::Intel
{
2266 options
.push("intel");
2269 if !options
.is_empty() {
2270 try
!(space(&mut self.s
));
2271 try
!(self.word_space(":"));
2272 try
!(self.commasep(Inconsistent
, &*options
,
2274 try
!(s
.print_string(co
, ast
::CookedStr
));
2279 try
!(self.pclose());
2281 ast
::ExprMac(ref m
) => try
!(self.print_mac(m
, token
::Paren
)),
2282 ast
::ExprParen(ref e
) => {
2284 try
!(self.print_inner_attributes_inline(attrs
));
2285 try
!(self.print_expr(&**e
));
2286 try
!(self.pclose());
2289 try
!(self.ann
.post(self, NodeExpr(expr
)));
2293 pub fn print_local_decl(&mut self, loc
: &ast
::Local
) -> io
::Result
<()> {
2294 try
!(self.print_pat(&*loc
.pat
));
2295 if let Some(ref ty
) = loc
.ty
{
2296 try
!(self.word_space(":"));
2297 try
!(self.print_type(&**ty
));
2302 pub fn print_decl(&mut self, decl
: &ast
::Decl
) -> io
::Result
<()> {
2303 try
!(self.maybe_print_comment(decl
.span
.lo
));
2305 ast
::DeclLocal(ref loc
) => {
2306 try
!(self.print_outer_attributes(loc
.attrs
.as_attr_slice()));
2307 try
!(self.space_if_not_bol());
2308 try
!(self.ibox(INDENT_UNIT
));
2309 try
!(self.word_nbsp("let"));
2311 try
!(self.ibox(INDENT_UNIT
));
2312 try
!(self.print_local_decl(&**loc
));
2314 if let Some(ref init
) = loc
.init
{
2316 try
!(self.word_space("="));
2317 try
!(self.print_expr(&**init
));
2321 ast
::DeclItem(ref item
) => self.print_item(&**item
)
2325 pub fn print_ident(&mut self, ident
: ast
::Ident
) -> io
::Result
<()> {
2326 try
!(word(&mut self.s
, &ident
.name
.as_str()));
2327 self.ann
.post(self, NodeIdent(&ident
))
2330 pub fn print_usize(&mut self, i
: usize) -> io
::Result
<()> {
2331 word(&mut self.s
, &i
.to_string())
2334 pub fn print_name(&mut self, name
: ast
::Name
) -> io
::Result
<()> {
2335 try
!(word(&mut self.s
, &name
.as_str()));
2336 self.ann
.post(self, NodeName(&name
))
2339 pub fn print_for_decl(&mut self, loc
: &ast
::Local
,
2340 coll
: &ast
::Expr
) -> io
::Result
<()> {
2341 try
!(self.print_local_decl(loc
));
2342 try
!(space(&mut self.s
));
2343 try
!(self.word_space("in"));
2344 self.print_expr(coll
)
2347 fn print_path(&mut self,
2349 colons_before_params
: bool
,
2353 try
!(self.maybe_print_comment(path
.span
.lo
));
2355 let mut first
= !path
.global
;
2356 for segment
in &path
.segments
[..path
.segments
.len()-depth
] {
2360 try
!(word(&mut self.s
, "::"))
2363 try
!(self.print_ident(segment
.identifier
));
2365 try
!(self.print_path_parameters(&segment
.parameters
, colons_before_params
));
2371 fn print_qpath(&mut self,
2374 colons_before_params
: bool
)
2377 try
!(word(&mut self.s
, "<"));
2378 try
!(self.print_type(&qself
.ty
));
2379 if qself
.position
> 0 {
2380 try
!(space(&mut self.s
));
2381 try
!(self.word_space("as"));
2382 let depth
= path
.segments
.len() - qself
.position
;
2383 try
!(self.print_path(&path
, false, depth
));
2385 try
!(word(&mut self.s
, ">"));
2386 try
!(word(&mut self.s
, "::"));
2387 let item_segment
= path
.segments
.last().unwrap();
2388 try
!(self.print_ident(item_segment
.identifier
));
2389 self.print_path_parameters(&item_segment
.parameters
, colons_before_params
)
2392 fn print_path_parameters(&mut self,
2393 parameters
: &ast
::PathParameters
,
2394 colons_before_params
: bool
)
2397 if parameters
.is_empty() {
2401 if colons_before_params
{
2402 try
!(word(&mut self.s
, "::"))
2406 ast
::PathParameters
::AngleBracketed(ref data
) => {
2407 try
!(word(&mut self.s
, "<"));
2409 let mut comma
= false;
2410 for lifetime
in &data
.lifetimes
{
2412 try
!(self.word_space(","))
2414 try
!(self.print_lifetime(lifetime
));
2418 if !data
.types
.is_empty() {
2420 try
!(self.word_space(","))
2425 |s
, ty
| s
.print_type(&**ty
)));
2429 for binding
in data
.bindings
.iter() {
2431 try
!(self.word_space(","))
2433 try
!(self.print_ident(binding
.ident
));
2434 try
!(space(&mut self.s
));
2435 try
!(self.word_space("="));
2436 try
!(self.print_type(&*binding
.ty
));
2440 try
!(word(&mut self.s
, ">"))
2443 ast
::PathParameters
::Parenthesized(ref data
) => {
2444 try
!(word(&mut self.s
, "("));
2448 |s
, ty
| s
.print_type(&**ty
)));
2449 try
!(word(&mut self.s
, ")"));
2454 try
!(self.space_if_not_bol());
2455 try
!(self.word_space("->"));
2456 try
!(self.print_type(&**ty
));
2465 pub fn print_pat(&mut self, pat
: &ast
::Pat
) -> io
::Result
<()> {
2466 try
!(self.maybe_print_comment(pat
.span
.lo
));
2467 try
!(self.ann
.pre(self, NodePat(pat
)));
2468 /* Pat isn't normalized, but the beauty of it
2469 is that it doesn't matter */
2471 ast
::PatWild
=> try
!(word(&mut self.s
, "_")),
2472 ast
::PatIdent(binding_mode
, ref path1
, ref sub
) => {
2473 match binding_mode
{
2474 ast
::BindingMode
::ByRef(mutbl
) => {
2475 try
!(self.word_nbsp("ref"));
2476 try
!(self.print_mutability(mutbl
));
2478 ast
::BindingMode
::ByValue(ast
::MutImmutable
) => {}
2479 ast
::BindingMode
::ByValue(ast
::MutMutable
) => {
2480 try
!(self.word_nbsp("mut"));
2483 try
!(self.print_ident(path1
.node
));
2486 try
!(word(&mut self.s
, "@"));
2487 try
!(self.print_pat(&**p
));
2492 ast
::PatEnum(ref path
, ref args_
) => {
2493 try
!(self.print_path(path
, true, 0));
2495 None
=> try
!(word(&mut self.s
, "(..)")),
2497 if !args
.is_empty() {
2499 try
!(self.commasep(Inconsistent
, &args
[..],
2500 |s
, p
| s
.print_pat(&**p
)));
2501 try
!(self.pclose());
2506 ast
::PatQPath(ref qself
, ref path
) => {
2507 try
!(self.print_qpath(path
, qself
, false));
2509 ast
::PatStruct(ref path
, ref fields
, etc
) => {
2510 try
!(self.print_path(path
, true, 0));
2512 try
!(self.word_space("{"));
2513 try
!(self.commasep_cmnt(
2514 Consistent
, &fields
[..],
2516 try
!(s
.cbox(INDENT_UNIT
));
2517 if !f
.node
.is_shorthand
{
2518 try
!(s
.print_ident(f
.node
.ident
));
2519 try
!(s
.word_nbsp(":"));
2521 try
!(s
.print_pat(&*f
.node
.pat
));
2524 |f
| f
.node
.pat
.span
));
2526 if !fields
.is_empty() { try!(self.word_space(",")); }
2527 try
!(word(&mut self.s
, ".."));
2529 try
!(space(&mut self.s
));
2530 try
!(word(&mut self.s
, "}"));
2532 ast
::PatTup(ref elts
) => {
2534 try
!(self.commasep(Inconsistent
,
2536 |s
, p
| s
.print_pat(&**p
)));
2537 if elts
.len() == 1 {
2538 try
!(word(&mut self.s
, ","));
2540 try
!(self.pclose());
2542 ast
::PatBox(ref inner
) => {
2543 try
!(word(&mut self.s
, "box "));
2544 try
!(self.print_pat(&**inner
));
2546 ast
::PatRegion(ref inner
, mutbl
) => {
2547 try
!(word(&mut self.s
, "&"));
2548 if mutbl
== ast
::MutMutable
{
2549 try
!(word(&mut self.s
, "mut "));
2551 try
!(self.print_pat(&**inner
));
2553 ast
::PatLit(ref e
) => try
!(self.print_expr(&**e
)),
2554 ast
::PatRange(ref begin
, ref end
) => {
2555 try
!(self.print_expr(&**begin
));
2556 try
!(space(&mut self.s
));
2557 try
!(word(&mut self.s
, "..."));
2558 try
!(self.print_expr(&**end
));
2560 ast
::PatVec(ref before
, ref slice
, ref after
) => {
2561 try
!(word(&mut self.s
, "["));
2562 try
!(self.commasep(Inconsistent
,
2564 |s
, p
| s
.print_pat(&**p
)));
2565 if let Some(ref p
) = *slice
{
2566 if !before
.is_empty() { try!(self.word_space(",")); }
2567 if p
.node
!= ast
::PatWild
{
2568 try
!(self.print_pat(&**p
));
2570 try
!(word(&mut self.s
, ".."));
2571 if !after
.is_empty() { try!(self.word_space(",")); }
2573 try
!(self.commasep(Inconsistent
,
2575 |s
, p
| s
.print_pat(&**p
)));
2576 try
!(word(&mut self.s
, "]"));
2578 ast
::PatMac(ref m
) => try
!(self.print_mac(m
, token
::Paren
)),
2580 self.ann
.post(self, NodePat(pat
))
2583 fn print_arm(&mut self, arm
: &ast
::Arm
) -> io
::Result
<()> {
2584 // I have no idea why this check is necessary, but here it
2586 if arm
.attrs
.is_empty() {
2587 try
!(space(&mut self.s
));
2589 try
!(self.cbox(INDENT_UNIT
));
2591 try
!(self.print_outer_attributes(&arm
.attrs
));
2592 let mut first
= true;
2593 for p
in &arm
.pats
{
2597 try
!(space(&mut self.s
));
2598 try
!(self.word_space("|"));
2600 try
!(self.print_pat(&**p
));
2602 try
!(space(&mut self.s
));
2603 if let Some(ref e
) = arm
.guard
{
2604 try
!(self.word_space("if"));
2605 try
!(self.print_expr(&**e
));
2606 try
!(space(&mut self.s
));
2608 try
!(self.word_space("=>"));
2610 match arm
.body
.node
{
2611 ast
::ExprBlock(ref blk
) => {
2612 // the block will close the pattern's ibox
2613 try
!(self.print_block_unclosed_indent(&**blk
, INDENT_UNIT
));
2615 // If it is a user-provided unsafe block, print a comma after it
2616 if let ast
::UnsafeBlock(ast
::UserProvided
) = blk
.rules
{
2617 try
!(word(&mut self.s
, ","));
2621 try
!(self.end()); // close the ibox for the pattern
2622 try
!(self.print_expr(&*arm
.body
));
2623 try
!(word(&mut self.s
, ","));
2626 self.end() // close enclosing cbox
2629 // Returns whether it printed anything
2630 fn print_explicit_self(&mut self,
2631 explicit_self
: &ast
::ExplicitSelf_
,
2632 mutbl
: ast
::Mutability
) -> io
::Result
<bool
> {
2633 try
!(self.print_mutability(mutbl
));
2634 match *explicit_self
{
2635 ast
::SelfStatic
=> { return Ok(false); }
2636 ast
::SelfValue(_
) => {
2637 try
!(word(&mut self.s
, "self"));
2639 ast
::SelfRegion(ref lt
, m
, _
) => {
2640 try
!(word(&mut self.s
, "&"));
2641 try
!(self.print_opt_lifetime(lt
));
2642 try
!(self.print_mutability(m
));
2643 try
!(word(&mut self.s
, "self"));
2645 ast
::SelfExplicit(ref typ
, _
) => {
2646 try
!(word(&mut self.s
, "self"));
2647 try
!(self.word_space(":"));
2648 try
!(self.print_type(&**typ
));
2654 pub fn print_fn(&mut self,
2656 unsafety
: ast
::Unsafety
,
2657 constness
: ast
::Constness
,
2659 name
: Option
<ast
::Ident
>,
2660 generics
: &ast
::Generics
,
2661 opt_explicit_self
: Option
<&ast
::ExplicitSelf_
>,
2662 vis
: ast
::Visibility
) -> io
::Result
<()> {
2663 try
!(self.print_fn_header_info(unsafety
, constness
, abi
, vis
));
2665 if let Some(name
) = name
{
2667 try
!(self.print_ident(name
));
2669 try
!(self.print_generics(generics
));
2670 try
!(self.print_fn_args_and_ret(decl
, opt_explicit_self
));
2671 self.print_where_clause(&generics
.where_clause
)
2674 pub fn print_fn_args(&mut self, decl
: &ast
::FnDecl
,
2675 opt_explicit_self
: Option
<&ast
::ExplicitSelf_
>)
2677 // It is unfortunate to duplicate the commasep logic, but we want the
2678 // self type and the args all in the same box.
2679 try
!(self.rbox(0, Inconsistent
));
2680 let mut first
= true;
2681 if let Some(explicit_self
) = opt_explicit_self
{
2682 let m
= match *explicit_self
{
2683 ast
::SelfStatic
=> ast
::MutImmutable
,
2684 _
=> match decl
.inputs
[0].pat
.node
{
2685 ast
::PatIdent(ast
::BindingMode
::ByValue(m
), _
, _
) => m
,
2686 _
=> ast
::MutImmutable
2689 first
= !try
!(self.print_explicit_self(explicit_self
, m
));
2692 // HACK(eddyb) ignore the separately printed self argument.
2693 let args
= if first
{
2700 if first { first = false; }
else { try!(self.word_space(",")); }
2701 try
!(self.print_arg(arg
));
2707 pub fn print_fn_args_and_ret(&mut self, decl
: &ast
::FnDecl
,
2708 opt_explicit_self
: Option
<&ast
::ExplicitSelf_
>)
2711 try
!(self.print_fn_args(decl
, opt_explicit_self
));
2713 try
!(word(&mut self.s
, ", ..."));
2715 try
!(self.pclose());
2717 self.print_fn_output(decl
)
2720 pub fn print_fn_block_args(
2724 try
!(word(&mut self.s
, "|"));
2725 try
!(self.print_fn_args(decl
, None
));
2726 try
!(word(&mut self.s
, "|"));
2728 if let ast
::DefaultReturn(..) = decl
.output
{
2732 try
!(self.space_if_not_bol());
2733 try
!(self.word_space("->"));
2735 ast
::Return(ref ty
) => {
2736 try
!(self.print_type(&**ty
));
2737 self.maybe_print_comment(ty
.span
.lo
)
2739 ast
::DefaultReturn(..) => unreachable
!(),
2740 ast
::NoReturn(span
) => {
2741 try
!(self.word_nbsp("!"));
2742 self.maybe_print_comment(span
.lo
)
2747 pub fn print_capture_clause(&mut self, capture_clause
: ast
::CaptureClause
)
2749 match capture_clause
{
2750 ast
::CaptureByValue
=> self.word_space("move"),
2751 ast
::CaptureByRef
=> Ok(()),
2755 pub fn print_bounds(&mut self,
2757 bounds
: &[ast
::TyParamBound
])
2759 if !bounds
.is_empty() {
2760 try
!(word(&mut self.s
, prefix
));
2761 let mut first
= true;
2762 for bound
in bounds
{
2767 try
!(self.word_space("+"));
2771 TraitTyParamBound(ref tref
, TraitBoundModifier
::None
) => {
2772 self.print_poly_trait_ref(tref
)
2774 TraitTyParamBound(ref tref
, TraitBoundModifier
::Maybe
) => {
2775 try
!(word(&mut self.s
, "?"));
2776 self.print_poly_trait_ref(tref
)
2778 RegionTyParamBound(ref lt
) => {
2779 self.print_lifetime(lt
)
2789 pub fn print_lifetime(&mut self,
2790 lifetime
: &ast
::Lifetime
)
2793 self.print_name(lifetime
.name
)
2796 pub fn print_lifetime_def(&mut self,
2797 lifetime
: &ast
::LifetimeDef
)
2800 try
!(self.print_lifetime(&lifetime
.lifetime
));
2802 for v
in &lifetime
.bounds
{
2803 try
!(word(&mut self.s
, sep
));
2804 try
!(self.print_lifetime(v
));
2810 pub fn print_generics(&mut self,
2811 generics
: &ast
::Generics
)
2814 let total
= generics
.lifetimes
.len() + generics
.ty_params
.len();
2819 try
!(word(&mut self.s
, "<"));
2821 let mut ints
= Vec
::new();
2826 try
!(self.commasep(Inconsistent
, &ints
[..], |s
, &idx
| {
2827 if idx
< generics
.lifetimes
.len() {
2828 let lifetime
= &generics
.lifetimes
[idx
];
2829 s
.print_lifetime_def(lifetime
)
2831 let idx
= idx
- generics
.lifetimes
.len();
2832 let param
= &generics
.ty_params
[idx
];
2833 s
.print_ty_param(param
)
2837 try
!(word(&mut self.s
, ">"));
2841 pub fn print_ty_param(&mut self, param
: &ast
::TyParam
) -> io
::Result
<()> {
2842 try
!(self.print_ident(param
.ident
));
2843 try
!(self.print_bounds(":", ¶m
.bounds
));
2844 match param
.default {
2845 Some(ref default) => {
2846 try
!(space(&mut self.s
));
2847 try
!(self.word_space("="));
2848 self.print_type(&**default)
2854 pub fn print_where_clause(&mut self, where_clause
: &ast
::WhereClause
)
2856 if where_clause
.predicates
.is_empty() {
2860 try
!(space(&mut self.s
));
2861 try
!(self.word_space("where"));
2863 for (i
, predicate
) in where_clause
.predicates
.iter().enumerate() {
2865 try
!(self.word_space(","));
2869 ast
::WherePredicate
::BoundPredicate(ast
::WhereBoundPredicate
{ref bound_lifetimes
,
2873 try
!(self.print_formal_lifetime_list(bound_lifetimes
));
2874 try
!(self.print_type(&**bounded_ty
));
2875 try
!(self.print_bounds(":", bounds
));
2877 ast
::WherePredicate
::RegionPredicate(ast
::WhereRegionPredicate
{ref lifetime
,
2880 try
!(self.print_lifetime(lifetime
));
2881 try
!(word(&mut self.s
, ":"));
2883 for (i
, bound
) in bounds
.iter().enumerate() {
2884 try
!(self.print_lifetime(bound
));
2887 try
!(word(&mut self.s
, ":"));
2891 ast
::WherePredicate
::EqPredicate(ast
::WhereEqPredicate{ref path, ref ty, ..}
) => {
2892 try
!(self.print_path(path
, false, 0));
2893 try
!(space(&mut self.s
));
2894 try
!(self.word_space("="));
2895 try
!(self.print_type(&**ty
));
2903 pub fn print_view_path(&mut self, vp
: &ast
::ViewPath
) -> io
::Result
<()> {
2905 ast
::ViewPathSimple(ident
, ref path
) => {
2906 try
!(self.print_path(path
, false, 0));
2908 if path
.segments
.last().unwrap().identifier
.name
!=
2910 try
!(space(&mut self.s
));
2911 try
!(self.word_space("as"));
2912 try
!(self.print_ident(ident
));
2918 ast
::ViewPathGlob(ref path
) => {
2919 try
!(self.print_path(path
, false, 0));
2920 word(&mut self.s
, "::*")
2923 ast
::ViewPathList(ref path
, ref idents
) => {
2924 if path
.segments
.is_empty() {
2925 try
!(word(&mut self.s
, "{"));
2927 try
!(self.print_path(path
, false, 0));
2928 try
!(word(&mut self.s
, "::{"));
2930 try
!(self.commasep(Inconsistent
, &idents
[..], |s
, w
| {
2932 ast
::PathListIdent { name, rename, .. }
=> {
2933 try
!(s
.print_ident(name
));
2934 if let Some(ident
) = rename
{
2935 try
!(space(&mut s
.s
));
2936 try
!(s
.word_space("as"));
2937 try
!(s
.print_ident(ident
));
2941 ast
::PathListMod { rename, .. }
=> {
2942 try
!(word(&mut s
.s
, "self"));
2943 if let Some(ident
) = rename
{
2944 try
!(space(&mut s
.s
));
2945 try
!(s
.word_space("as"));
2946 try
!(s
.print_ident(ident
));
2952 word(&mut self.s
, "}")
2957 pub fn print_mutability(&mut self,
2958 mutbl
: ast
::Mutability
) -> io
::Result
<()> {
2960 ast
::MutMutable
=> self.word_nbsp("mut"),
2961 ast
::MutImmutable
=> Ok(()),
2965 pub fn print_mt(&mut self, mt
: &ast
::MutTy
) -> io
::Result
<()> {
2966 try
!(self.print_mutability(mt
.mutbl
));
2967 self.print_type(&*mt
.ty
)
2970 pub fn print_arg(&mut self, input
: &ast
::Arg
) -> io
::Result
<()> {
2971 try
!(self.ibox(INDENT_UNIT
));
2972 match input
.ty
.node
{
2973 ast
::TyInfer
=> try
!(self.print_pat(&*input
.pat
)),
2975 match input
.pat
.node
{
2976 ast
::PatIdent(_
, ref path1
, _
) if
2978 parse
::token
::special_idents
::invalid
.name
=> {
2982 try
!(self.print_pat(&*input
.pat
));
2983 try
!(word(&mut self.s
, ":"));
2984 try
!(space(&mut self.s
));
2987 try
!(self.print_type(&*input
.ty
));
2993 pub fn print_fn_output(&mut self, decl
: &ast
::FnDecl
) -> io
::Result
<()> {
2994 if let ast
::DefaultReturn(..) = decl
.output
{
2998 try
!(self.space_if_not_bol());
2999 try
!(self.ibox(INDENT_UNIT
));
3000 try
!(self.word_space("->"));
3003 try
!(self.word_nbsp("!")),
3004 ast
::DefaultReturn(..) => unreachable
!(),
3005 ast
::Return(ref ty
) =>
3006 try
!(self.print_type(&**ty
))
3011 ast
::Return(ref output
) => self.maybe_print_comment(output
.span
.lo
),
3016 pub fn print_ty_fn(&mut self,
3018 unsafety
: ast
::Unsafety
,
3020 name
: Option
<ast
::Ident
>,
3021 generics
: &ast
::Generics
,
3022 opt_explicit_self
: Option
<&ast
::ExplicitSelf_
>)
3024 try
!(self.ibox(INDENT_UNIT
));
3025 if !generics
.lifetimes
.is_empty() || !generics
.ty_params
.is_empty() {
3026 try
!(word(&mut self.s
, "for"));
3027 try
!(self.print_generics(generics
));
3029 let generics
= ast
::Generics
{
3030 lifetimes
: Vec
::new(),
3031 ty_params
: P
::empty(),
3032 where_clause
: ast
::WhereClause
{
3033 id
: ast
::DUMMY_NODE_ID
,
3034 predicates
: Vec
::new(),
3037 try
!(self.print_fn(decl
,
3039 ast
::Constness
::NotConst
,
3048 pub fn maybe_print_trailing_comment(&mut self, span
: codemap
::Span
,
3049 next_pos
: Option
<BytePos
>)
3051 let cm
= match self.cm
{
3055 match self.next_comment() {
3057 if (*cmnt
).style
!= comments
::Trailing { return Ok(()) }
3058 let span_line
= cm
.lookup_char_pos(span
.hi
);
3059 let comment_line
= cm
.lookup_char_pos((*cmnt
).pos
);
3060 let mut next
= (*cmnt
).pos
+ BytePos(1);
3061 match next_pos { None => (), Some(p) => next = p }
3062 if span
.hi
< (*cmnt
).pos
&& (*cmnt
).pos
< next
&&
3063 span_line
.line
== comment_line
.line
{
3064 try
!(self.print_comment(cmnt
));
3065 self.cur_cmnt_and_lit
.cur_cmnt
+= 1;
3073 pub fn print_remaining_comments(&mut self) -> io
::Result
<()> {
3074 // If there aren't any remaining comments, then we need to manually
3075 // make sure there is a line break at the end.
3076 if self.next_comment().is_none() {
3077 try
!(hardbreak(&mut self.s
));
3080 match self.next_comment() {
3082 try
!(self.print_comment(cmnt
));
3083 self.cur_cmnt_and_lit
.cur_cmnt
+= 1;
3091 pub fn print_opt_abi_and_extern_if_nondefault(&mut self,
3092 opt_abi
: Option
<abi
::Abi
>)
3095 Some(abi
::Rust
) => Ok(()),
3097 try
!(self.word_nbsp("extern"));
3098 self.word_nbsp(&abi
.to_string())
3104 pub fn print_extern_opt_abi(&mut self,
3105 opt_abi
: Option
<abi
::Abi
>) -> io
::Result
<()> {
3108 try
!(self.word_nbsp("extern"));
3109 self.word_nbsp(&abi
.to_string())
3115 pub fn print_fn_header_info(&mut self,
3116 unsafety
: ast
::Unsafety
,
3117 constness
: ast
::Constness
,
3119 vis
: ast
::Visibility
) -> io
::Result
<()> {
3120 try
!(word(&mut self.s
, &visibility_qualified(vis
, "")));
3123 ast
::Constness
::NotConst
=> {}
3124 ast
::Constness
::Const
=> try
!(self.word_nbsp("const"))
3127 try
!(self.print_unsafety(unsafety
));
3129 if abi
!= abi
::Rust
{
3130 try
!(self.word_nbsp("extern"));
3131 try
!(self.word_nbsp(&abi
.to_string()));
3134 word(&mut self.s
, "fn")
3137 pub fn print_unsafety(&mut self, s
: ast
::Unsafety
) -> io
::Result
<()> {
3139 ast
::Unsafety
::Normal
=> Ok(()),
3140 ast
::Unsafety
::Unsafe
=> self.word_nbsp("unsafe"),
3145 fn repeat(s
: &str, n
: usize) -> String { iter::repeat(s).take(n).collect() }
3157 fn test_fun_to_string() {
3158 let abba_ident
= token
::str_to_ident("abba");
3160 let decl
= ast
::FnDecl
{
3162 output
: ast
::DefaultReturn(codemap
::DUMMY_SP
),
3165 let generics
= ast
::Generics
::default();
3166 assert_eq
!(fun_to_string(&decl
, ast
::Unsafety
::Normal
,
3167 ast
::Constness
::NotConst
,
3174 fn test_variant_to_string() {
3175 let ident
= token
::str_to_ident("principal_skinner");
3177 let var
= codemap
::respan(codemap
::DUMMY_SP
, ast
::Variant_
{
3180 // making this up as I go.... ?
3181 data
: ast
::VariantData
::Unit(ast
::DUMMY_NODE_ID
),
3185 let varstr
= variant_to_string(&var
);
3186 assert_eq
!(varstr
, "principal_skinner");
3190 fn test_signed_int_to_string() {
3191 let pos_int
= ast
::LitInt(42, ast
::SignedIntLit(ast
::TyI32
, ast
::Plus
));
3192 let neg_int
= ast
::LitInt((!42 + 1) as u64, ast
::SignedIntLit(ast
::TyI32
, ast
::Minus
));
3193 assert_eq
!(format
!("-{}", lit_to_string(&codemap
::dummy_spanned(pos_int
))),
3194 lit_to_string(&codemap
::dummy_spanned(neg_int
)));