1 // Copyright 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 //! The various pretty print routines.
13 pub use self::UserIdentifiedItem
::*;
14 pub use self::PpSourceMode
::*;
15 pub use self::PpMode
::*;
16 use self::NodesMatchingUII
::*;
18 use rustc_trans
::back
::link
;
22 use rustc
::middle
::ty
;
23 use rustc
::middle
::cfg
;
24 use rustc
::middle
::cfg
::graphviz
::LabelledCFG
;
25 use rustc
::session
::Session
;
26 use rustc
::session
::config
::Input
;
27 use rustc_borrowck
as borrowck
;
28 use rustc_borrowck
::graphviz
as borrowck_dot
;
29 use rustc_resolve
as resolve
;
30 use rustc_metadata
::cstore
::CStore
;
34 use syntax
::fold
::{self, Folder}
;
35 use syntax
::print
::{pp, pprust}
;
36 use syntax
::print
::pprust
::PrintState
;
38 use syntax
::util
::small_vector
::SmallVector
;
43 use std
::io
::{self, Write}
;
45 use std
::path
::PathBuf
;
46 use std
::str::FromStr
;
48 use rustc
::front
::map
as hir_map
;
49 use rustc
::front
::map
::{blocks, NodePrinter}
;
51 use rustc_front
::lowering
::{lower_crate, LoweringContext}
;
52 use rustc_front
::print
::pprust
as pprust_hir
;
54 #[derive(Copy, Clone, PartialEq, Debug)]
55 pub enum PpSourceMode
{
60 PpmExpandedIdentified
,
65 #[derive(Copy, Clone, PartialEq, Debug)]
66 pub enum PpFlowGraphMode
{
68 /// Drops the labels from the edges in the flowgraph output. This
69 /// is mostly for use in the --unpretty flowgraph run-make tests,
70 /// since the labels are largely uninteresting in those cases and
71 /// have become a pain to maintain.
74 #[derive(Copy, Clone, PartialEq, Debug)]
76 PpmSource(PpSourceMode
),
78 PpmFlowGraph(PpFlowGraphMode
),
81 pub fn parse_pretty(sess
: &Session
,
84 -> (PpMode
, Option
<UserIdentifiedItem
>) {
85 let mut split
= name
.splitn(2, '
='
);
86 let first
= split
.next().unwrap();
87 let opt_second
= split
.next();
88 let first
= match (first
, extended
) {
89 ("normal", _
) => PpmSource(PpmNormal
),
90 ("identified", _
) => PpmSource(PpmIdentified
),
91 ("everybody_loops", true) => PpmSource(PpmEveryBodyLoops
),
92 ("expanded", _
) => PpmSource(PpmExpanded
),
93 ("expanded,identified", _
) => PpmSource(PpmExpandedIdentified
),
94 ("expanded,hygiene", _
) => PpmSource(PpmExpandedHygiene
),
95 ("hir", true) => PpmHir(PpmNormal
),
96 ("hir,identified", true) => PpmHir(PpmIdentified
),
97 ("hir,typed", true) => PpmHir(PpmTyped
),
98 ("flowgraph", true) => PpmFlowGraph(PpFlowGraphMode
::Default
),
99 ("flowgraph,unlabelled", true) => PpmFlowGraph(PpFlowGraphMode
::UnlabelledEdges
),
102 sess
.fatal(&format
!("argument to `unpretty` must be one of `normal`, \
103 `expanded`, `flowgraph[,unlabelled]=<nodeid>`, \
104 `identified`, `expanded,identified`, `everybody_loops`, \
105 `hir`, `hir,identified`, or `hir,typed`; got {}",
108 sess
.fatal(&format
!("argument to `pretty` must be one of `normal`, `expanded`, \
109 `identified`, or `expanded,identified`; got {}",
114 let opt_second
= opt_second
.and_then(|s
| s
.parse
::<UserIdentifiedItem
>().ok());
120 // This slightly awkward construction is to allow for each PpMode to
121 // choose whether it needs to do analyses (which can consume the
122 // Session) and then pass through the session (now attached to the
123 // analysis results) on to the chosen pretty-printer, along with the
126 // Note that since the `&PrinterSupport` is freshly constructed on each
127 // call, it would not make sense to try to attach the lifetime of `self`
128 // to the lifetime of the `&PrinterObject`.
130 // (The `use_once_payload` is working around the current lack of once
131 // functions in the compiler.)
134 /// Constructs a `PrinterSupport` object and passes it to `f`.
135 fn call_with_pp_support
<'tcx
, A
, B
, F
>(&self,
137 ast_map
: Option
<hir_map
::Map
<'tcx
>>,
141 where F
: FnOnce(&PrinterSupport
, B
) -> A
144 PpmNormal
| PpmEveryBodyLoops
| PpmExpanded
=> {
145 let annotation
= NoAnn
{
149 f(&annotation
, payload
)
152 PpmIdentified
| PpmExpandedIdentified
=> {
153 let annotation
= IdentifiedAnnotation
{
157 f(&annotation
, payload
)
159 PpmExpandedHygiene
=> {
160 let annotation
= HygieneAnnotation
{
164 f(&annotation
, payload
)
166 _
=> panic
!("Should use call_with_pp_support_hir"),
169 fn call_with_pp_support_hir
<'tcx
, A
, B
, F
>(&self,
172 ast_map
: &hir_map
::Map
<'tcx
>,
173 arenas
: &'tcx ty
::CtxtArenas
<'tcx
>,
178 where F
: FnOnce(&HirPrinterSupport
, B
, &hir
::Crate
) -> A
182 let annotation
= NoAnn
{
184 ast_map
: Some(ast_map
.clone()),
186 f(&annotation
, payload
, &ast_map
.forest
.krate
)
190 let annotation
= IdentifiedAnnotation
{
192 ast_map
: Some(ast_map
.clone()),
194 f(&annotation
, payload
, &ast_map
.forest
.krate
)
197 driver
::phase_3_run_analysis_passes(sess
,
202 resolve
::MakeGlobMap
::No
,
204 let annotation
= TypedAnnotation
{
209 &ast_map
.forest
.krate
)
212 _
=> panic
!("Should use call_with_pp_support"),
217 trait PrinterSupport
<'ast
>: pprust
::PpAnn
{
218 /// Provides a uniform interface for re-extracting a reference to a
219 /// `Session` from a value that now owns it.
220 fn sess
<'a
>(&'a
self) -> &'a Session
;
222 /// Provides a uniform interface for re-extracting a reference to an
223 /// `hir_map::Map` from a value that now owns it.
224 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'ast
>>;
226 /// Produces the pretty-print annotation object.
228 /// (Rust does not yet support upcasting from a trait object to
229 /// an object for one of its super-traits.)
230 fn pp_ann
<'a
>(&'a
self) -> &'a pprust
::PpAnn
;
233 trait HirPrinterSupport
<'ast
>: pprust_hir
::PpAnn
{
234 /// Provides a uniform interface for re-extracting a reference to a
235 /// `Session` from a value that now owns it.
236 fn sess
<'a
>(&'a
self) -> &'a Session
;
238 /// Provides a uniform interface for re-extracting a reference to an
239 /// `hir_map::Map` from a value that now owns it.
240 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'ast
>>;
242 /// Produces the pretty-print annotation object.
244 /// (Rust does not yet support upcasting from a trait object to
245 /// an object for one of its super-traits.)
246 fn pp_ann
<'a
>(&'a
self) -> &'a pprust_hir
::PpAnn
;
251 ast_map
: Option
<hir_map
::Map
<'ast
>>,
254 impl<'ast
> PrinterSupport
<'ast
> for NoAnn
<'ast
> {
255 fn sess
<'a
>(&'a
self) -> &'a Session
{
259 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'ast
>> {
260 self.ast_map
.as_ref()
263 fn pp_ann
<'a
>(&'a
self) -> &'a pprust
::PpAnn
{
268 impl<'ast
> HirPrinterSupport
<'ast
> for NoAnn
<'ast
> {
269 fn sess
<'a
>(&'a
self) -> &'a Session
{
273 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'ast
>> {
274 self.ast_map
.as_ref()
277 fn pp_ann
<'a
>(&'a
self) -> &'a pprust_hir
::PpAnn
{
282 impl<'ast
> pprust
::PpAnn
for NoAnn
<'ast
> {}
283 impl<'ast
> pprust_hir
::PpAnn
for NoAnn
<'ast
> {}
285 struct IdentifiedAnnotation
<'ast
> {
287 ast_map
: Option
<hir_map
::Map
<'ast
>>,
290 impl<'ast
> PrinterSupport
<'ast
> for IdentifiedAnnotation
<'ast
> {
291 fn sess
<'a
>(&'a
self) -> &'a Session
{
295 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'ast
>> {
296 self.ast_map
.as_ref()
299 fn pp_ann
<'a
>(&'a
self) -> &'a pprust
::PpAnn
{
304 impl<'ast
> pprust
::PpAnn
for IdentifiedAnnotation
<'ast
> {
305 fn pre(&self, s
: &mut pprust
::State
, node
: pprust
::AnnNode
) -> io
::Result
<()> {
307 pprust
::NodeExpr(_
) => s
.popen(),
311 fn post(&self, s
: &mut pprust
::State
, node
: pprust
::AnnNode
) -> io
::Result
<()> {
313 pprust
::NodeIdent(_
) | pprust
::NodeName(_
) => Ok(()),
315 pprust
::NodeItem(item
) => {
316 try
!(pp
::space(&mut s
.s
));
317 s
.synth_comment(item
.id
.to_string())
319 pprust
::NodeSubItem(id
) => {
320 try
!(pp
::space(&mut s
.s
));
321 s
.synth_comment(id
.to_string())
323 pprust
::NodeBlock(blk
) => {
324 try
!(pp
::space(&mut s
.s
));
325 s
.synth_comment(format
!("block {}", blk
.id
))
327 pprust
::NodeExpr(expr
) => {
328 try
!(pp
::space(&mut s
.s
));
329 try
!(s
.synth_comment(expr
.id
.to_string()));
332 pprust
::NodePat(pat
) => {
333 try
!(pp
::space(&mut s
.s
));
334 s
.synth_comment(format
!("pat {}", pat
.id
))
340 impl<'ast
> HirPrinterSupport
<'ast
> for IdentifiedAnnotation
<'ast
> {
341 fn sess
<'a
>(&'a
self) -> &'a Session
{
345 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'ast
>> {
346 self.ast_map
.as_ref()
349 fn pp_ann
<'a
>(&'a
self) -> &'a pprust_hir
::PpAnn
{
354 impl<'ast
> pprust_hir
::PpAnn
for IdentifiedAnnotation
<'ast
> {
355 fn pre(&self, s
: &mut pprust_hir
::State
, node
: pprust_hir
::AnnNode
) -> io
::Result
<()> {
357 pprust_hir
::NodeExpr(_
) => s
.popen(),
361 fn post(&self, s
: &mut pprust_hir
::State
, node
: pprust_hir
::AnnNode
) -> io
::Result
<()> {
363 pprust_hir
::NodeName(_
) => Ok(()),
364 pprust_hir
::NodeItem(item
) => {
365 try
!(pp
::space(&mut s
.s
));
366 s
.synth_comment(item
.id
.to_string())
368 pprust_hir
::NodeSubItem(id
) => {
369 try
!(pp
::space(&mut s
.s
));
370 s
.synth_comment(id
.to_string())
372 pprust_hir
::NodeBlock(blk
) => {
373 try
!(pp
::space(&mut s
.s
));
374 s
.synth_comment(format
!("block {}", blk
.id
))
376 pprust_hir
::NodeExpr(expr
) => {
377 try
!(pp
::space(&mut s
.s
));
378 try
!(s
.synth_comment(expr
.id
.to_string()));
381 pprust_hir
::NodePat(pat
) => {
382 try
!(pp
::space(&mut s
.s
));
383 s
.synth_comment(format
!("pat {}", pat
.id
))
389 struct HygieneAnnotation
<'ast
> {
391 ast_map
: Option
<hir_map
::Map
<'ast
>>,
394 impl<'ast
> PrinterSupport
<'ast
> for HygieneAnnotation
<'ast
> {
395 fn sess
<'a
>(&'a
self) -> &'a Session
{
399 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'ast
>> {
400 self.ast_map
.as_ref()
403 fn pp_ann
<'a
>(&'a
self) -> &'a pprust
::PpAnn
{
408 impl<'ast
> pprust
::PpAnn
for HygieneAnnotation
<'ast
> {
409 fn post(&self, s
: &mut pprust
::State
, node
: pprust
::AnnNode
) -> io
::Result
<()> {
411 pprust
::NodeIdent(&ast
::Ident { name: ast::Name(nm), ctxt }
) => {
412 try
!(pp
::space(&mut s
.s
));
413 // FIXME #16420: this doesn't display the connections
414 // between syntax contexts
415 s
.synth_comment(format
!("{}#{}", nm
, ctxt
.0))
417 pprust
::NodeName(&ast
::Name(nm
)) => {
418 try
!(pp
::space(&mut s
.s
));
419 s
.synth_comment(nm
.to_string())
427 struct TypedAnnotation
<'a
, 'tcx
: 'a
> {
428 tcx
: &'a ty
::ctxt
<'tcx
>,
431 impl<'b
, 'tcx
> HirPrinterSupport
<'tcx
> for TypedAnnotation
<'b
, 'tcx
> {
432 fn sess
<'a
>(&'a
self) -> &'a Session
{
436 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'tcx
>> {
440 fn pp_ann
<'a
>(&'a
self) -> &'a pprust_hir
::PpAnn
{
445 impl<'a
, 'tcx
> pprust_hir
::PpAnn
for TypedAnnotation
<'a
, 'tcx
> {
446 fn pre(&self, s
: &mut pprust_hir
::State
, node
: pprust_hir
::AnnNode
) -> io
::Result
<()> {
448 pprust_hir
::NodeExpr(_
) => s
.popen(),
452 fn post(&self, s
: &mut pprust_hir
::State
, node
: pprust_hir
::AnnNode
) -> io
::Result
<()> {
454 pprust_hir
::NodeExpr(expr
) => {
455 try
!(pp
::space(&mut s
.s
));
456 try
!(pp
::word(&mut s
.s
, "as"));
457 try
!(pp
::space(&mut s
.s
));
458 try
!(pp
::word(&mut s
.s
, &self.tcx
.expr_ty(expr
).to_string()));
466 fn gather_flowgraph_variants(sess
: &Session
) -> Vec
<borrowck_dot
::Variant
> {
467 let print_loans
= sess
.opts
.debugging_opts
.flowgraph_print_loans
;
468 let print_moves
= sess
.opts
.debugging_opts
.flowgraph_print_moves
;
469 let print_assigns
= sess
.opts
.debugging_opts
.flowgraph_print_assigns
;
470 let print_all
= sess
.opts
.debugging_opts
.flowgraph_print_all
;
471 let mut variants
= Vec
::new();
472 if print_all
|| print_loans
{
473 variants
.push(borrowck_dot
::Loans
);
475 if print_all
|| print_moves
{
476 variants
.push(borrowck_dot
::Moves
);
478 if print_all
|| print_assigns
{
479 variants
.push(borrowck_dot
::Assigns
);
484 #[derive(Clone, Debug)]
485 pub enum UserIdentifiedItem
{
486 ItemViaNode(ast
::NodeId
),
487 ItemViaPath(Vec
<String
>),
490 impl FromStr
for UserIdentifiedItem
{
492 fn from_str(s
: &str) -> Result
<UserIdentifiedItem
, ()> {
495 .unwrap_or_else(|_
| ItemViaPath(s
.split("::").map(|s
| s
.to_string()).collect())))
499 enum NodesMatchingUII
<'a
, 'ast
: 'a
> {
500 NodesMatchingDirect(option
::IntoIter
<ast
::NodeId
>),
501 NodesMatchingSuffix(hir_map
::NodesMatchingSuffix
<'a
, 'ast
>),
504 impl<'a
, 'ast
> Iterator
for NodesMatchingUII
<'a
, 'ast
> {
505 type Item
= ast
::NodeId
;
507 fn next(&mut self) -> Option
<ast
::NodeId
> {
509 &mut NodesMatchingDirect(ref mut iter
) => iter
.next(),
510 &mut NodesMatchingSuffix(ref mut iter
) => iter
.next(),
515 impl UserIdentifiedItem
{
516 fn reconstructed_input(&self) -> String
{
518 ItemViaNode(node_id
) => node_id
.to_string(),
519 ItemViaPath(ref parts
) => parts
.join("::"),
523 fn all_matching_node_ids
<'a
, 'ast
>(&'a
self,
524 map
: &'a hir_map
::Map
<'ast
>)
525 -> NodesMatchingUII
<'a
, 'ast
> {
527 ItemViaNode(node_id
) => NodesMatchingDirect(Some(node_id
).into_iter()),
528 ItemViaPath(ref parts
) => NodesMatchingSuffix(map
.nodes_matching_suffix(&parts
[..])),
532 fn to_one_node_id(self, user_option
: &str, sess
: &Session
, map
: &hir_map
::Map
) -> ast
::NodeId
{
533 let fail_because
= |is_wrong_because
| -> ast
::NodeId
{
534 let message
= format
!("{} needs NodeId (int) or unique path suffix (b::c::d); got \
537 self.reconstructed_input(),
539 sess
.fatal(&message
[..])
542 let mut saw_node
= ast
::DUMMY_NODE_ID
;
544 for node
in self.all_matching_node_ids(map
) {
548 fail_because("does not resolve uniquely");
552 fail_because("does not resolve to any item");
560 fn needs_ast_map(ppm
: &PpMode
, opt_uii
: &Option
<UserIdentifiedItem
>) -> bool
{
562 PpmSource(PpmNormal
) |
563 PpmSource(PpmEveryBodyLoops
) |
564 PpmSource(PpmIdentified
) => opt_uii
.is_some(),
566 PpmSource(PpmExpanded
) |
567 PpmSource(PpmExpandedIdentified
) |
568 PpmSource(PpmExpandedHygiene
) |
570 PpmFlowGraph(_
) => true,
571 PpmSource(PpmTyped
) => panic
!("invalid state"),
575 fn needs_expansion(ppm
: &PpMode
) -> bool
{
577 PpmSource(PpmNormal
) |
578 PpmSource(PpmEveryBodyLoops
) |
579 PpmSource(PpmIdentified
) => false,
581 PpmSource(PpmExpanded
) |
582 PpmSource(PpmExpandedIdentified
) |
583 PpmSource(PpmExpandedHygiene
) |
585 PpmFlowGraph(_
) => true,
586 PpmSource(PpmTyped
) => panic
!("invalid state"),
590 struct ReplaceBodyWithLoop
{
591 within_static_or_const
: bool
,
594 impl ReplaceBodyWithLoop
{
595 fn new() -> ReplaceBodyWithLoop
{
596 ReplaceBodyWithLoop { within_static_or_const: false }
600 impl fold
::Folder
for ReplaceBodyWithLoop
{
601 fn fold_item_underscore(&mut self, i
: ast
::Item_
) -> ast
::Item_
{
603 ast
::ItemStatic(..) | ast
::ItemConst(..) => {
604 self.within_static_or_const
= true;
605 let ret
= fold
::noop_fold_item_underscore(i
, self);
606 self.within_static_or_const
= false;
610 fold
::noop_fold_item_underscore(i
, self)
615 fn fold_trait_item(&mut self, i
: P
<ast
::TraitItem
>) -> SmallVector
<P
<ast
::TraitItem
>> {
617 ast
::ConstTraitItem(..) => {
618 self.within_static_or_const
= true;
619 let ret
= fold
::noop_fold_trait_item(i
, self);
620 self.within_static_or_const
= false;
623 _
=> fold
::noop_fold_trait_item(i
, self),
627 fn fold_impl_item(&mut self, i
: P
<ast
::ImplItem
>) -> SmallVector
<P
<ast
::ImplItem
>> {
629 ast
::ImplItemKind
::Const(..) => {
630 self.within_static_or_const
= true;
631 let ret
= fold
::noop_fold_impl_item(i
, self);
632 self.within_static_or_const
= false;
635 _
=> fold
::noop_fold_impl_item(i
, self),
639 fn fold_block(&mut self, b
: P
<ast
::Block
>) -> P
<ast
::Block
> {
640 fn expr_to_block(rules
: ast
::BlockCheckMode
, e
: Option
<P
<ast
::Expr
>>) -> P
<ast
::Block
> {
645 id
: ast
::DUMMY_NODE_ID
,
646 span
: codemap
::DUMMY_SP
,
650 if !self.within_static_or_const
{
652 let empty_block
= expr_to_block(ast
::DefaultBlock
, None
);
653 let loop_expr
= P(ast
::Expr
{
654 node
: ast
::ExprLoop(empty_block
, None
),
655 id
: ast
::DUMMY_NODE_ID
,
656 span
: codemap
::DUMMY_SP
,
660 expr_to_block(b
.rules
, Some(loop_expr
))
663 fold
::noop_fold_block(b
, self)
667 // in general the pretty printer processes unexpanded code, so
668 // we override the default `fold_mac` method which panics.
669 fn fold_mac(&mut self, mac
: ast
::Mac
) -> ast
::Mac
{
670 fold
::noop_fold_mac(mac
, self)
674 pub fn pretty_print_input(sess
: Session
,
676 cfg
: ast
::CrateConfig
,
679 opt_uii
: Option
<UserIdentifiedItem
>,
680 ofile
: Option
<PathBuf
>) {
681 let krate
= driver
::phase_1_parse_input(&sess
, cfg
, input
);
683 let krate
= if let PpmSource(PpmEveryBodyLoops
) = ppm
{
684 let mut fold
= ReplaceBodyWithLoop
::new();
685 fold
.fold_crate(krate
)
690 let id
= link
::find_crate_name(Some(&sess
), &krate
.attrs
, input
);
692 let is_expanded
= needs_expansion(&ppm
);
693 let compute_ast_map
= needs_ast_map(&ppm
, &opt_uii
);
694 let krate
= if compute_ast_map
{
695 match driver
::phase_2_configure_and_expand(&sess
, &cstore
, krate
, &id
[..], None
) {
697 Some(k
) => driver
::assign_node_ids(&sess
, k
),
703 // There is some twisted, god-forsaken tangle of lifetimes here which makes
704 // the ordering of stuff super-finicky.
706 let lcx
= LoweringContext
::new(&sess
, Some(&krate
));
707 let arenas
= ty
::CtxtArenas
::new();
708 let ast_map
= if compute_ast_map
{
709 hir_forest
= hir_map
::Forest
::new(lower_crate(&lcx
, &krate
));
710 let map
= driver
::make_map(&sess
, &mut hir_forest
);
716 let src_name
= driver
::source_name(input
);
717 let src
= sess
.codemap()
718 .get_filemap(&src_name
[..])
724 let mut rdr
= &src
[..];
726 let mut out
= Vec
::new();
728 match (ppm
, opt_uii
) {
729 (PpmSource(s
), _
) => {
730 // Silently ignores an identified node.
731 let out
: &mut Write
= &mut out
;
732 s
.call_with_pp_support(&sess
, ast_map
, box out
, |annotation
, out
| {
733 debug
!("pretty printing source code {:?}", s
);
734 let sess
= annotation
.sess();
735 pprust
::print_crate(sess
.codemap(),
738 src_name
.to_string(),
746 (PpmHir(s
), None
) => {
747 let out
: &mut Write
= &mut out
;
748 s
.call_with_pp_support_hir(&sess
,
754 |annotation
, out
, krate
| {
755 debug
!("pretty printing source code {:?}", s
);
756 let sess
= annotation
.sess();
757 pprust_hir
::print_crate(sess
.codemap(),
760 src_name
.to_string(),
768 (PpmHir(s
), Some(uii
)) => {
769 let out
: &mut Write
= &mut out
;
770 s
.call_with_pp_support_hir(&sess
,
776 |annotation
, (out
,uii
), _
| {
777 debug
!("pretty printing source code {:?}", s
);
778 let sess
= annotation
.sess();
779 let ast_map
= annotation
.ast_map().expect("--pretty missing ast_map");
781 pprust_hir
::State
::new_from_input(sess
.codemap(),
783 src_name
.to_string(),
788 Some(ast_map
.krate()));
789 for node_id
in uii
.all_matching_node_ids(ast_map
) {
790 let node
= ast_map
.get(node_id
);
791 try
!(pp_state
.print_node(&node
));
792 try
!(pp
::space(&mut pp_state
.s
));
793 try
!(pp_state
.synth_comment(ast_map
.path_to_string(node_id
)));
794 try
!(pp
::hardbreak(&mut pp_state
.s
));
796 pp
::eof(&mut pp_state
.s
)
800 (PpmFlowGraph(mode
), opt_uii
) => {
801 debug
!("pretty printing flow graph for {:?}", opt_uii
);
802 let uii
= opt_uii
.unwrap_or_else(|| {
803 sess
.fatal(&format
!("`pretty flowgraph=..` needs NodeId (int) or
805 unique path suffix (b::c::d)"))
808 let ast_map
= ast_map
.expect("--pretty flowgraph missing ast_map");
809 let nodeid
= uii
.to_one_node_id("--pretty", &sess
, &ast_map
);
811 let node
= ast_map
.find(nodeid
).unwrap_or_else(|| {
812 sess
.fatal(&format
!("--pretty flowgraph couldn't find id: {}", nodeid
))
815 let code
= blocks
::Code
::from_node(node
);
816 let out
: &mut Write
= &mut out
;
819 let variants
= gather_flowgraph_variants(&sess
);
820 driver
::phase_3_run_analysis_passes(&sess
,
825 resolve
::MakeGlobMap
::No
,
827 print_flowgraph(variants
,
835 let message
= format
!("--pretty=flowgraph needs block, fn, or method; got \
839 // point to what was found, if there's an
841 match ast_map
.opt_span(nodeid
) {
842 Some(sp
) => sess
.span_fatal(sp
, &message
[..]),
843 None
=> sess
.fatal(&message
[..]),
852 None
=> print
!("{}", String
::from_utf8(out
).unwrap()),
854 match File
::create(&p
) {
855 Ok(mut w
) => w
.write_all(&out
).unwrap(),
856 Err(e
) => panic
!("print-print failed to open {} due to {}", p
.display(), e
),
862 fn print_flowgraph
<W
: Write
>(variants
: Vec
<borrowck_dot
::Variant
>,
865 mode
: PpFlowGraphMode
,
868 let cfg
= match code
{
869 blocks
::BlockCode(block
) => cfg
::CFG
::new(tcx
, &*block
),
870 blocks
::FnLikeCode(fn_like
) => cfg
::CFG
::new(tcx
, &*fn_like
.body()),
872 let labelled_edges
= mode
!= PpFlowGraphMode
::UnlabelledEdges
;
873 let lcfg
= LabelledCFG
{
876 name
: format
!("node_{}", code
.id()),
877 labelled_edges
: labelled_edges
,
881 _
if variants
.is_empty() => {
882 let r
= dot
::render(&lcfg
, &mut out
);
883 return expand_err_details(r
);
885 blocks
::BlockCode(_
) => {
886 tcx
.sess
.err("--pretty flowgraph with -Z flowgraph-print annotations requires \
890 blocks
::FnLikeCode(fn_like
) => {
891 let (bccx
, analysis_data
) =
892 borrowck
::build_borrowck_dataflow_data_for_fn(tcx
,
893 fn_like
.to_fn_parts(),
896 let lcfg
= borrowck_dot
::DataflowLabeller
{
899 borrowck_ctxt
: &bccx
,
900 analysis_data
: &analysis_data
,
902 let r
= dot
::render(&lcfg
, &mut out
);
903 return expand_err_details(r
);
907 fn expand_err_details(r
: io
::Result
<()>) -> io
::Result
<()> {
909 io
::Error
::new(io
::ErrorKind
::Other
,
910 &format
!("graphviz::render failed: {}", ioerr
)[..])