// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The various pretty print routines.

pub use self::UserIdentifiedItem::*;
pub use self::PpSourceMode::*;
pub use self::PpMode::*;
use self::NodesMatchingUII::*;

use {abort_on_err, driver};

use rustc::ty::{self, TyCtxt, Resolutions, AllArenas};
use rustc::cfg;
use rustc::cfg::graphviz::LabelledCFG;
use rustc::middle::cstore::CrateStore;
use rustc::session::Session;
use rustc::session::config::{Input, OutputFilenames};
use rustc_borrowck as borrowck;
use rustc_borrowck::graphviz as borrowck_dot;

use rustc_mir::util::{write_mir_pretty, write_mir_graphviz};

use syntax::ast::{self, BlockCheckMode};
use syntax::fold::{self, Folder};
use syntax::print::{pprust};
use syntax::print::pprust::PrintState;
use syntax::ptr::P;
use syntax::util::small_vector::SmallVector;
use syntax_pos::{self, FileName};

use graphviz as dot;

use std::cell::Cell;
use std::fs::File;
use std::io::{self, Write};
use std::option;
use std::path::Path;
use std::str::FromStr;
use std::mem;

use rustc::hir::map as hir_map;
use rustc::hir::map::blocks;
use rustc::hir;
use rustc::hir::print as pprust_hir;

#[derive(Copy, Clone, PartialEq, Debug)]
pub enum PpSourceMode {
    PpmNormal,
    PpmEveryBodyLoops,
    PpmExpanded,
    PpmIdentified,
    PpmExpandedIdentified,
    PpmExpandedHygiene,
    PpmTyped,
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub enum PpFlowGraphMode {
    Default,
    /// Drops the labels from the edges in the flowgraph output. This
    /// is mostly for use in the --unpretty flowgraph run-make tests,
    /// since the labels are largely uninteresting in those cases and
    /// have become a pain to maintain.
    UnlabelledEdges,
}
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum PpMode {
    PpmSource(PpSourceMode),
    PpmHir(PpSourceMode),
    PpmHirTree(PpSourceMode),
    PpmFlowGraph(PpFlowGraphMode),
    PpmMir,
    PpmMirCFG,
}

impl PpMode {
    pub fn needs_ast_map(&self, opt_uii: &Option<UserIdentifiedItem>) -> bool {
        match *self {
            PpmSource(PpmNormal) |
            PpmSource(PpmEveryBodyLoops) |
            PpmSource(PpmIdentified) => opt_uii.is_some(),

            PpmSource(PpmExpanded) |
            PpmSource(PpmExpandedIdentified) |
            PpmSource(PpmExpandedHygiene) |
            PpmHir(_) |
            PpmHirTree(_) |
            PpmMir |
            PpmMirCFG |
            PpmFlowGraph(_) => true,
            PpmSource(PpmTyped) => panic!("invalid state"),
        }
    }

    pub fn needs_analysis(&self) -> bool {
        match *self {
            PpmMir | PpmMirCFG | PpmFlowGraph(_) => true,
            _ => false,
        }
    }
}

pub fn parse_pretty(sess: &Session,
                    name: &str,
                    extended: bool)
                    -> (PpMode, Option<UserIdentifiedItem>) {
    let mut split = name.splitn(2, '=');
    let first = split.next().unwrap();
    let opt_second = split.next();
    let first = match (first, extended) {
        ("normal", _) => PpmSource(PpmNormal),
        ("identified", _) => PpmSource(PpmIdentified),
        ("everybody_loops", true) => PpmSource(PpmEveryBodyLoops),
        ("expanded", _) => PpmSource(PpmExpanded),
        ("expanded,identified", _) => PpmSource(PpmExpandedIdentified),
        ("expanded,hygiene", _) => PpmSource(PpmExpandedHygiene),
        ("hir", true) => PpmHir(PpmNormal),
        ("hir,identified", true) => PpmHir(PpmIdentified),
        ("hir,typed", true) => PpmHir(PpmTyped),
        ("hir-tree", true) => PpmHirTree(PpmNormal),
        ("mir", true) => PpmMir,
        ("mir-cfg", true) => PpmMirCFG,
        ("flowgraph", true) => PpmFlowGraph(PpFlowGraphMode::Default),
        ("flowgraph,unlabelled", true) => PpmFlowGraph(PpFlowGraphMode::UnlabelledEdges),
        _ => {
            if extended {
                sess.fatal(&format!("argument to `unpretty` must be one of `normal`, \
                                     `expanded`, `flowgraph[,unlabelled]=<nodeid>`, \
                                     `identified`, `expanded,identified`, `everybody_loops`, \
                                     `hir`, `hir,identified`, `hir,typed`, or `mir`; got {}",
                                    name));
            } else {
                sess.fatal(&format!("argument to `pretty` must be one of `normal`, `expanded`, \
                                     `identified`, or `expanded,identified`; got {}",
                                    name));
            }
        }
    };
    let opt_second = opt_second.and_then(|s| s.parse::<UserIdentifiedItem>().ok());
    (first, opt_second)
}



// This slightly awkward construction is to allow for each PpMode to
// choose whether it needs to do analyses (which can consume the
// Session) and then pass through the session (now attached to the
// analysis results) on to the chosen pretty-printer, along with the
// `&PpAnn` object.
//
// Note that since the `&PrinterSupport` is freshly constructed on each
// call, it would not make sense to try to attach the lifetime of `self`
// to the lifetime of the `&PrinterObject`.
//
// (The `use_once_payload` is working around the current lack of once
// functions in the compiler.)

impl PpSourceMode {
    /// Constructs a `PrinterSupport` object and passes it to `f`.
    fn call_with_pp_support<'tcx, A, F>(&self,
                                           sess: &'tcx Session,
                                           hir_map: Option<&hir_map::Map<'tcx>>,
                                           f: F)
                                           -> A
        where F: FnOnce(&PrinterSupport) -> A
    {
        match *self {
            PpmNormal | PpmEveryBodyLoops | PpmExpanded => {
                let annotation = NoAnn {
                    sess,
                    hir_map: hir_map.map(|m| m.clone()),
                };
                f(&annotation)
            }

            PpmIdentified | PpmExpandedIdentified => {
                let annotation = IdentifiedAnnotation {
                    sess,
                    hir_map: hir_map.map(|m| m.clone()),
                };
                f(&annotation)
            }
            PpmExpandedHygiene => {
                let annotation = HygieneAnnotation {
                    sess,
                };
                f(&annotation)
            }
            _ => panic!("Should use call_with_pp_support_hir"),
        }
    }
    fn call_with_pp_support_hir<'tcx, A, F>(&self,
                                               sess: &'tcx Session,
                                               cstore: &'tcx CrateStore,
                                               hir_map: &hir_map::Map<'tcx>,
                                               analysis: &ty::CrateAnalysis,
                                               resolutions: &Resolutions,
                                               arenas: &'tcx AllArenas<'tcx>,
                                               output_filenames: &OutputFilenames,
                                               id: &str,
                                               f: F)
                                               -> A
        where F: FnOnce(&HirPrinterSupport, &hir::Crate) -> A
    {
        match *self {
            PpmNormal => {
                let annotation = NoAnn {
                    sess,
                    hir_map: Some(hir_map.clone()),
                };
                f(&annotation, hir_map.forest.krate())
            }

            PpmIdentified => {
                let annotation = IdentifiedAnnotation {
                    sess,
                    hir_map: Some(hir_map.clone()),
                };
                f(&annotation, hir_map.forest.krate())
            }
            PpmTyped => {
                let control = &driver::CompileController::basic();
                abort_on_err(driver::phase_3_run_analysis_passes(control,
                                                                 sess,
                                                                 cstore,
                                                                 hir_map.clone(),
                                                                 analysis.clone(),
                                                                 resolutions.clone(),
                                                                 arenas,
                                                                 id,
                                                                 output_filenames,
                                                                 |tcx, _, _, _| {
                    let empty_tables = ty::TypeckTables::empty(None);
                    let annotation = TypedAnnotation {
                        tcx,
                        tables: Cell::new(&empty_tables)
                    };
                    let _ignore = tcx.dep_graph.in_ignore();
                    f(&annotation, hir_map.forest.krate())
                }),
                             sess)
            }
            _ => panic!("Should use call_with_pp_support"),
        }
    }
}

trait PrinterSupport: pprust::PpAnn {
    /// Provides a uniform interface for re-extracting a reference to a
    /// `Session` from a value that now owns it.
    fn sess<'a>(&'a self) -> &'a Session;

    /// Produces the pretty-print annotation object.
    ///
    /// (Rust does not yet support upcasting from a trait object to
    /// an object for one of its super-traits.)
    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn;
}

trait HirPrinterSupport<'hir>: pprust_hir::PpAnn {
    /// Provides a uniform interface for re-extracting a reference to a
    /// `Session` from a value that now owns it.
    fn sess<'a>(&'a self) -> &'a Session;

    /// Provides a uniform interface for re-extracting a reference to an
    /// `hir_map::Map` from a value that now owns it.
    fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>>;

    /// Produces the pretty-print annotation object.
    ///
    /// (Rust does not yet support upcasting from a trait object to
    /// an object for one of its super-traits.)
    fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn;

    /// Computes an user-readable representation of a path, if possible.
    fn node_path(&self, id: ast::NodeId) -> Option<String> {
        self.hir_map().and_then(|map| map.def_path_from_id(id)).map(|path| {
            path.data
                .into_iter()
                .map(|elem| elem.data.to_string())
                .collect::<Vec<_>>()
                .join("::")
        })
    }
}

struct NoAnn<'hir> {
    sess: &'hir Session,
    hir_map: Option<hir_map::Map<'hir>>,
}

impl<'hir> PrinterSupport for NoAnn<'hir> {
    fn sess<'a>(&'a self) -> &'a Session {
        self.sess
    }

    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn {
        self
    }
}

impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> {
    fn sess<'a>(&'a self) -> &'a Session {
        self.sess
    }

    fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>> {
        self.hir_map.as_ref()
    }

    fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn {
        self
    }
}

impl<'hir> pprust::PpAnn for NoAnn<'hir> {}
impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> {
    fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested)
              -> io::Result<()> {
        if let Some(ref map) = self.hir_map {
            pprust_hir::PpAnn::nested(map, state, nested)
        } else {
            Ok(())
        }
    }
}

struct IdentifiedAnnotation<'hir> {
    sess: &'hir Session,
    hir_map: Option<hir_map::Map<'hir>>,
}

impl<'hir> PrinterSupport for IdentifiedAnnotation<'hir> {
    fn sess<'a>(&'a self) -> &'a Session {
        self.sess
    }

    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn {
        self
    }
}

impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> {
    fn pre(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> {
        match node {
            pprust::NodeExpr(_) => s.popen(),
            _ => Ok(()),
        }
    }
    fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> {
        match node {
            pprust::NodeIdent(_) |
            pprust::NodeName(_) => Ok(()),

            pprust::NodeItem(item) => {
                s.s.space()?;
                s.synth_comment(item.id.to_string())
            }
            pprust::NodeSubItem(id) => {
                s.s.space()?;
                s.synth_comment(id.to_string())
            }
            pprust::NodeBlock(blk) => {
                s.s.space()?;
                s.synth_comment(format!("block {}", blk.id))
            }
            pprust::NodeExpr(expr) => {
                s.s.space()?;
                s.synth_comment(expr.id.to_string())?;
                s.pclose()
            }
            pprust::NodePat(pat) => {
                s.s.space()?;
                s.synth_comment(format!("pat {}", pat.id))
            }
        }
    }
}

impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> {
    fn sess<'a>(&'a self) -> &'a Session {
        self.sess
    }

    fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>> {
        self.hir_map.as_ref()
    }

    fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn {
        self
    }
}

impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
    fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested)
              -> io::Result<()> {
        if let Some(ref map) = self.hir_map {
            pprust_hir::PpAnn::nested(map, state, nested)
        } else {
            Ok(())
        }
    }
    fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
        match node {
            pprust_hir::NodeExpr(_) => s.popen(),
            _ => Ok(()),
        }
    }
    fn post(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
        match node {
            pprust_hir::NodeName(_) => Ok(()),
            pprust_hir::NodeItem(item) => {
                s.s.space()?;
                s.synth_comment(format!("node_id: {} hir local_id: {}",
                                        item.id, item.hir_id.local_id.0))
            }
            pprust_hir::NodeSubItem(id) => {
                s.s.space()?;
                s.synth_comment(id.to_string())
            }
            pprust_hir::NodeBlock(blk) => {
                s.s.space()?;
                s.synth_comment(format!("block node_id: {} hir local_id: {}",
                                        blk.id, blk.hir_id.local_id.0))
            }
            pprust_hir::NodeExpr(expr) => {
                s.s.space()?;
                s.synth_comment(format!("node_id: {} hir local_id: {}",
                                        expr.id, expr.hir_id.local_id.0))?;
                s.pclose()
            }
            pprust_hir::NodePat(pat) => {
                s.s.space()?;
                s.synth_comment(format!("pat node_id: {} hir local_id: {}",
                                        pat.id, pat.hir_id.local_id.0))
            }
        }
    }
}

struct HygieneAnnotation<'a> {
    sess: &'a Session
}

impl<'a> PrinterSupport for HygieneAnnotation<'a> {
    fn sess(&self) -> &Session {
        self.sess
    }

    fn pp_ann(&self) -> &pprust::PpAnn {
        self
    }
}

impl<'a> pprust::PpAnn for HygieneAnnotation<'a> {
    fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> {
        match node {
            pprust::NodeIdent(&ast::Ident { name, ctxt }) => {
                s.s.space()?;
                // FIXME #16420: this doesn't display the connections
                // between syntax contexts
                s.synth_comment(format!("{}{:?}", name.as_u32(), ctxt))
            }
            pprust::NodeName(&name) => {
                s.s.space()?;
                s.synth_comment(name.as_u32().to_string())
            }
            _ => Ok(()),
        }
    }
}


struct TypedAnnotation<'a, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    tables: Cell<&'a ty::TypeckTables<'tcx>>,
}

impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> {
    fn sess<'a>(&'a self) -> &'a Session {
        &self.tcx.sess
    }

    fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'tcx>> {
        Some(&self.tcx.hir)
    }

    fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn {
        self
    }

    fn node_path(&self, id: ast::NodeId) -> Option<String> {
        Some(self.tcx.node_path_str(id))
    }
}

impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
    fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested)
              -> io::Result<()> {
        let old_tables = self.tables.get();
        if let pprust_hir::Nested::Body(id) = nested {
            self.tables.set(self.tcx.body_tables(id));
        }
        pprust_hir::PpAnn::nested(&self.tcx.hir, state, nested)?;
        self.tables.set(old_tables);
        Ok(())
    }
    fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
        match node {
            pprust_hir::NodeExpr(_) => s.popen(),
            _ => Ok(()),
        }
    }
    fn post(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
        match node {
            pprust_hir::NodeExpr(expr) => {
                s.s.space()?;
                s.s.word("as")?;
                s.s.space()?;
                s.s.word(&self.tables.get().expr_ty(expr).to_string())?;
                s.pclose()
            }
            _ => Ok(()),
        }
    }
}

fn gather_flowgraph_variants(sess: &Session) -> Vec<borrowck_dot::Variant> {
    let print_loans = sess.opts.debugging_opts.flowgraph_print_loans;
    let print_moves = sess.opts.debugging_opts.flowgraph_print_moves;
    let print_assigns = sess.opts.debugging_opts.flowgraph_print_assigns;
    let print_all = sess.opts.debugging_opts.flowgraph_print_all;
    let mut variants = Vec::new();
    if print_all || print_loans {
        variants.push(borrowck_dot::Loans);
    }
    if print_all || print_moves {
        variants.push(borrowck_dot::Moves);
    }
    if print_all || print_assigns {
        variants.push(borrowck_dot::Assigns);
    }
    variants
}

#[derive(Clone, Debug)]
pub enum UserIdentifiedItem {
    ItemViaNode(ast::NodeId),
    ItemViaPath(Vec<String>),
}

impl FromStr for UserIdentifiedItem {
    type Err = ();
    fn from_str(s: &str) -> Result<UserIdentifiedItem, ()> {
        Ok(s.parse()
            .map(ast::NodeId::new)
            .map(ItemViaNode)
            .unwrap_or_else(|_| ItemViaPath(s.split("::").map(|s| s.to_string()).collect())))
    }
}

enum NodesMatchingUII<'a, 'hir: 'a> {
    NodesMatchingDirect(option::IntoIter<ast::NodeId>),
    NodesMatchingSuffix(hir_map::NodesMatchingSuffix<'a, 'hir>),
}

impl<'a, 'hir> Iterator for NodesMatchingUII<'a, 'hir> {
    type Item = ast::NodeId;

    fn next(&mut self) -> Option<ast::NodeId> {
        match self {
            &mut NodesMatchingDirect(ref mut iter) => iter.next(),
            &mut NodesMatchingSuffix(ref mut iter) => iter.next(),
        }
    }
}

impl UserIdentifiedItem {
    fn reconstructed_input(&self) -> String {
        match *self {
            ItemViaNode(node_id) => node_id.to_string(),
            ItemViaPath(ref parts) => parts.join("::"),
        }
    }

    fn all_matching_node_ids<'a, 'hir>(&'a self,
                                       map: &'a hir_map::Map<'hir>)
                                       -> NodesMatchingUII<'a, 'hir> {
        match *self {
            ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()),
            ItemViaPath(ref parts) => NodesMatchingSuffix(map.nodes_matching_suffix(&parts)),
        }
    }

    fn to_one_node_id(self, user_option: &str, sess: &Session, map: &hir_map::Map) -> ast::NodeId {
        let fail_because = |is_wrong_because| -> ast::NodeId {
            let message = format!("{} needs NodeId (int) or unique path suffix (b::c::d); got \
                                   {}, which {}",
                                  user_option,
                                  self.reconstructed_input(),
                                  is_wrong_because);
            sess.fatal(&message)
        };

        let mut saw_node = ast::DUMMY_NODE_ID;
        let mut seen = 0;
        for node in self.all_matching_node_ids(map) {
            saw_node = node;
            seen += 1;
            if seen > 1 {
                fail_because("does not resolve uniquely");
            }
        }
        if seen == 0 {
            fail_because("does not resolve to any item");
        }

        assert!(seen == 1);
        return saw_node;
    }
}

// Note: Also used by librustdoc, see PR #43348. Consider moving this struct elsewhere.
//
// FIXME: Currently the `everybody_loops` transformation is not applied to:
//  * `const fn`, due to issue #43636 that `loop` is not supported for const evaluation. We are
//    waiting for miri to fix that.
//  * `impl Trait`, due to issue #43869 that functions returning impl Trait cannot be diverging.
//    Solving this may require `!` to implement every trait, which relies on the an even more
//    ambitious form of the closed RFC #1637. See also [#34511].
//
// [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401
pub struct ReplaceBodyWithLoop<'a> {
    within_static_or_const: bool,
    sess: &'a Session,
}

impl<'a> ReplaceBodyWithLoop<'a> {
    pub fn new(sess: &'a Session) -> ReplaceBodyWithLoop<'a> {
        ReplaceBodyWithLoop { within_static_or_const: false, sess }
    }

    fn run<R, F: FnOnce(&mut Self) -> R>(&mut self, is_const: bool, action: F) -> R {
        let old_const = mem::replace(&mut self.within_static_or_const, is_const);
        let ret = action(self);
        self.within_static_or_const = old_const;
        ret
    }

    fn should_ignore_fn(ret_ty: &ast::FnDecl) -> bool {
        if let ast::FunctionRetTy::Ty(ref ty) = ret_ty.output {
            fn involves_impl_trait(ty: &ast::Ty) -> bool {
                match ty.node {
                    ast::TyKind::ImplTrait(_) => true,
                    ast::TyKind::Slice(ref subty) |
                    ast::TyKind::Array(ref subty, _) |
                    ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. }) |
                    ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. }) |
                    ast::TyKind::Paren(ref subty) => involves_impl_trait(subty),
                    ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()),
                    ast::TyKind::Path(_, ref path) => path.segments.iter().any(|seg| {
                        match seg.parameters.as_ref().map(|p| &**p) {
                            None => false,
                            Some(&ast::PathParameters::AngleBracketed(ref data)) =>
                                any_involves_impl_trait(data.types.iter()) ||
                                any_involves_impl_trait(data.bindings.iter().map(|b| &b.ty)),
                            Some(&ast::PathParameters::Parenthesized(ref data)) =>
                                any_involves_impl_trait(data.inputs.iter()) ||
                                any_involves_impl_trait(data.output.iter()),
                        }
                    }),
                    _ => false,
                }
            }

            fn any_involves_impl_trait<'a, I: Iterator<Item = &'a P<ast::Ty>>>(mut it: I) -> bool {
                it.any(|subty| involves_impl_trait(subty))
            }

            involves_impl_trait(ty)
        } else {
            false
        }
    }
}

impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
    fn fold_item_kind(&mut self, i: ast::ItemKind) -> ast::ItemKind {
        let is_const = match i {
            ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true,
            ast::ItemKind::Fn(ref decl, _, ref constness, _, _, _) =>
                constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
            _ => false,
        };
        self.run(is_const, |s| fold::noop_fold_item_kind(i, s))
    }

    fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector<ast::TraitItem> {
        let is_const = match i.node {
            ast::TraitItemKind::Const(..) => true,
            ast::TraitItemKind::Method(ast::MethodSig { ref decl, ref constness, .. }, _) =>
                constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
            _ => false,
        };
        self.run(is_const, |s| fold::noop_fold_trait_item(i, s))
    }

    fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVector<ast::ImplItem> {
        let is_const = match i.node {
            ast::ImplItemKind::Const(..) => true,
            ast::ImplItemKind::Method(ast::MethodSig { ref decl, ref constness, .. }, _) =>
                constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
            _ => false,
        };
        self.run(is_const, |s| fold::noop_fold_impl_item(i, s))
    }

    fn fold_block(&mut self, b: P<ast::Block>) -> P<ast::Block> {
        fn expr_to_block(rules: ast::BlockCheckMode,
                         recovered: bool,
                         e: Option<P<ast::Expr>>,
                         sess: &Session) -> P<ast::Block> {
            P(ast::Block {
                stmts: e.map(|e| {
                        ast::Stmt {
                            id: sess.next_node_id(),
                            span: e.span,
                            node: ast::StmtKind::Expr(e),
                        }
                    })
                    .into_iter()
                    .collect(),
                rules,
                id: sess.next_node_id(),
                span: syntax_pos::DUMMY_SP,
                recovered,
            })
        }

        if !self.within_static_or_const {

            let empty_block = expr_to_block(BlockCheckMode::Default, false, None, self.sess);
            let loop_expr = P(ast::Expr {
                node: ast::ExprKind::Loop(empty_block, None),
                id: self.sess.next_node_id(),
                span: syntax_pos::DUMMY_SP,
                attrs: ast::ThinVec::new(),
            });

            expr_to_block(b.rules, b.recovered, Some(loop_expr), self.sess)

        } else {
            fold::noop_fold_block(b, self)
        }
    }

    // in general the pretty printer processes unexpanded code, so
    // we override the default `fold_mac` method which panics.
    fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
        fold::noop_fold_mac(mac, self)
    }
}

fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
                                       tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       code: blocks::Code<'tcx>,
                                       mode: PpFlowGraphMode,
                                       mut out: W)
                                       -> io::Result<()> {
    let body_id = match code {
        blocks::Code::Expr(expr) => {
            // Find the function this expression is from.
            let mut node_id = expr.id;
            loop {
                let node = tcx.hir.get(node_id);
                if let Some(n) = hir::map::blocks::FnLikeNode::from_node(node) {
                    break n.body();
                }
                let parent = tcx.hir.get_parent_node(node_id);
                assert!(node_id != parent);
                node_id = parent;
            }
        }
        blocks::Code::FnLike(fn_like) => fn_like.body(),
    };
    let body = tcx.hir.body(body_id);
    let cfg = cfg::CFG::new(tcx, &body);
    let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges;
    let lcfg = LabelledCFG {
        tcx,
        cfg: &cfg,
        name: format!("node_{}", code.id()),
        labelled_edges,
    };

    match code {
        _ if variants.is_empty() => {
            let r = dot::render(&lcfg, &mut out);
            return expand_err_details(r);
        }
        blocks::Code::Expr(_) => {
            tcx.sess.err("--pretty flowgraph with -Z flowgraph-print annotations requires \
                          fn-like node id.");
            return Ok(());
        }
        blocks::Code::FnLike(fn_like) => {
            let (bccx, analysis_data) =
                borrowck::build_borrowck_dataflow_data_for_fn(tcx, fn_like.body(), &cfg);

            let lcfg = borrowck_dot::DataflowLabeller {
                inner: lcfg,
                variants,
                borrowck_ctxt: &bccx,
                analysis_data: &analysis_data,
            };
            let r = dot::render(&lcfg, &mut out);
            return expand_err_details(r);
        }
    }

    fn expand_err_details(r: io::Result<()>) -> io::Result<()> {
        r.map_err(|ioerr| {
            io::Error::new(io::ErrorKind::Other,
                           format!("graphviz::render failed: {}", ioerr))
        })
    }
}

pub fn fold_crate(sess: &Session, krate: ast::Crate, ppm: PpMode) -> ast::Crate {
    if let PpmSource(PpmEveryBodyLoops) = ppm {
        let mut fold = ReplaceBodyWithLoop::new(sess);
        fold.fold_crate(krate)
    } else {
        krate
    }
}

fn get_source(input: &Input, sess: &Session) -> (Vec<u8>, FileName) {
    let src_name = driver::source_name(input);
    let src = sess.codemap()
        .get_filemap(&src_name)
        .unwrap()
        .src
        .as_ref()
        .unwrap()
        .as_bytes()
        .to_vec();
    (src, src_name)
}

fn write_output(out: Vec<u8>, ofile: Option<&Path>) {
    match ofile {
        None => print!("{}", String::from_utf8(out).unwrap()),
        Some(p) => {
            match File::create(p) {
                Ok(mut w) => w.write_all(&out).unwrap(),
                Err(e) => panic!("print-print failed to open {} due to {}", p.display(), e),
            }
        }
    }
}

pub fn print_after_parsing(sess: &Session,
                           input: &Input,
                           krate: &ast::Crate,
                           ppm: PpMode,
                           ofile: Option<&Path>) {
    let (src, src_name) = get_source(input, sess);

    let mut rdr = &*src;
    let mut out = Vec::new();

    if let PpmSource(s) = ppm {
        // Silently ignores an identified node.
        let out: &mut Write = &mut out;
        s.call_with_pp_support(sess, None, move |annotation| {
                debug!("pretty printing source code {:?}", s);
                let sess = annotation.sess();
                pprust::print_crate(sess.codemap(),
                                    &sess.parse_sess,
                                    krate,
                                    src_name,
                                    &mut rdr,
                                    box out,
                                    annotation.pp_ann(),
                                    false)
            })
            .unwrap()
    } else {
        unreachable!();
    };

    write_output(out, ofile);
}

pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                                cstore: &'tcx CrateStore,
                                                hir_map: &hir_map::Map<'tcx>,
                                                analysis: &ty::CrateAnalysis,
                                                resolutions: &Resolutions,
                                                input: &Input,
                                                krate: &ast::Crate,
                                                crate_name: &str,
                                                ppm: PpMode,
                                                arenas: &'tcx AllArenas<'tcx>,
                                                output_filenames: &OutputFilenames,
                                                opt_uii: Option<UserIdentifiedItem>,
                                                ofile: Option<&Path>) {
    if ppm.needs_analysis() {
        print_with_analysis(sess,
                            cstore,
                            hir_map,
                            analysis,
                            resolutions,
                            crate_name,
                            arenas,
                            output_filenames,
                            ppm,
                            opt_uii,
                            ofile);
        return;
    }

    let (src, src_name) = get_source(input, sess);

    let mut rdr = &src[..];
    let mut out = Vec::new();

    match (ppm, opt_uii) {
            (PpmSource(s), _) => {
                // Silently ignores an identified node.
                let out: &mut Write = &mut out;
                s.call_with_pp_support(sess, Some(hir_map), move |annotation| {
                    debug!("pretty printing source code {:?}", s);
                    let sess = annotation.sess();
                    pprust::print_crate(sess.codemap(),
                                        &sess.parse_sess,
                                        krate,
                                        src_name,
                                        &mut rdr,
                                        box out,
                                        annotation.pp_ann(),
                                        true)
                })
            }

            (PpmHir(s), None) => {
                let out: &mut Write = &mut out;
                s.call_with_pp_support_hir(sess,
                                           cstore,
                                           hir_map,
                                           analysis,
                                           resolutions,
                                           arenas,
                                           output_filenames,
                                           crate_name,
                                           move |annotation, krate| {
                    debug!("pretty printing source code {:?}", s);
                    let sess = annotation.sess();
                    pprust_hir::print_crate(sess.codemap(),
                                            &sess.parse_sess,
                                            krate,
                                            src_name,
                                            &mut rdr,
                                            box out,
                                            annotation.pp_ann(),
                                            true)
                })
            }

            (PpmHirTree(s), None) => {
                let out: &mut Write = &mut out;
                s.call_with_pp_support_hir(sess,
                                           cstore,
                                           hir_map,
                                           analysis,
                                           resolutions,
                                           arenas,
                                           output_filenames,
                                           crate_name,
                                           move |_annotation, krate| {
                    debug!("pretty printing source code {:?}", s);
                    write!(out, "{:#?}", krate)
                })
            }

            (PpmHir(s), Some(uii)) => {
                let out: &mut Write = &mut out;
                s.call_with_pp_support_hir(sess,
                                           cstore,
                                           hir_map,
                                           analysis,
                                           resolutions,
                                           arenas,
                                           output_filenames,
                                           crate_name,
                                           move |annotation, _| {
                    debug!("pretty printing source code {:?}", s);
                    let sess = annotation.sess();
                    let hir_map = annotation.hir_map().expect("--unpretty missing HIR map");
                    let mut pp_state = pprust_hir::State::new_from_input(sess.codemap(),
                                                                         &sess.parse_sess,
                                                                         src_name,
                                                                         &mut rdr,
                                                                         box out,
                                                                         annotation.pp_ann(),
                                                                         true);
                    for node_id in uii.all_matching_node_ids(hir_map) {
                        let node = hir_map.get(node_id);
                        pp_state.print_node(node)?;
                        pp_state.s.space()?;
                        let path = annotation.node_path(node_id)
                            .expect("--unpretty missing node paths");
                        pp_state.synth_comment(path)?;
                        pp_state.s.hardbreak()?;
                    }
                    pp_state.s.eof()
                })
            }

            (PpmHirTree(s), Some(uii)) => {
                let out: &mut Write = &mut out;
                s.call_with_pp_support_hir(sess,
                                           cstore,
                                           hir_map,
                                           analysis,
                                           resolutions,
                                           arenas,
                                           output_filenames,
                                           crate_name,
                                           move |_annotation, _krate| {
                    debug!("pretty printing source code {:?}", s);
                    for node_id in uii.all_matching_node_ids(hir_map) {
                        let node = hir_map.get(node_id);
                        write!(out, "{:#?}", node)?;
                    }
                    Ok(())
                })
            }

            _ => unreachable!(),
        }
        .unwrap();

    write_output(out, ofile);
}

// In an ideal world, this would be a public function called by the driver after
// analsysis is performed. However, we want to call `phase_3_run_analysis_passes`
// with a different callback than the standard driver, so that isn't easy.
// Instead, we call that function ourselves.
fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
                                       cstore: &'a CrateStore,
                                       hir_map: &hir_map::Map<'tcx>,
                                       analysis: &ty::CrateAnalysis,
                                       resolutions: &Resolutions,
                                       crate_name: &str,
                                       arenas: &'tcx AllArenas<'tcx>,
                                       output_filenames: &OutputFilenames,
                                       ppm: PpMode,
                                       uii: Option<UserIdentifiedItem>,
                                       ofile: Option<&Path>) {
    let nodeid = if let Some(uii) = uii {
        debug!("pretty printing for {:?}", uii);
        Some(uii.to_one_node_id("--unpretty", sess, &hir_map))
    } else {
        debug!("pretty printing for whole crate");
        None
    };

    let mut out = Vec::new();

    let control = &driver::CompileController::basic();
    abort_on_err(driver::phase_3_run_analysis_passes(control,
                                                     sess,
                                                     cstore,
                                                     hir_map.clone(),
                                                     analysis.clone(),
                                                     resolutions.clone(),
                                                     arenas,
                                                     crate_name,
                                                     output_filenames,
                                                     |tcx, _, _, _| {
        match ppm {
            PpmMir | PpmMirCFG => {
                if let Some(nodeid) = nodeid {
                    let def_id = tcx.hir.local_def_id(nodeid);
                    match ppm {
                        PpmMir => write_mir_pretty(tcx, Some(def_id), &mut out),
                        PpmMirCFG => write_mir_graphviz(tcx, Some(def_id), &mut out),
                        _ => unreachable!(),
                    }?;
                } else {
                    match ppm {
                        PpmMir => write_mir_pretty(tcx, None, &mut out),
                        PpmMirCFG => write_mir_graphviz(tcx, None, &mut out),
                        _ => unreachable!(),
                    }?;
                }
                Ok(())
            }
            PpmFlowGraph(mode) => {
                let nodeid =
                    nodeid.expect("`pretty flowgraph=..` needs NodeId (int) or unique path \
                                   suffix (b::c::d)");
                let node = tcx.hir.find(nodeid).unwrap_or_else(|| {
                    tcx.sess.fatal(&format!("--pretty flowgraph couldn't find id: {}", nodeid))
                });

                match blocks::Code::from_node(&tcx.hir, nodeid) {
                    Some(code) => {
                        let variants = gather_flowgraph_variants(tcx.sess);

                        let out: &mut Write = &mut out;

                        print_flowgraph(variants, tcx, code, mode, out)
                    }
                    None => {
                        let message = format!("--pretty=flowgraph needs block, fn, or method; \
                                               got {:?}",
                                              node);

                        tcx.sess.span_fatal(tcx.hir.span(nodeid), &message)
                    }
                }
            }
            _ => unreachable!(),
        }
    }),
                 sess)
        .unwrap();

    write_output(out, ofile);
}
