//! Write the output of rustc's analysis to an implementor of Dump.
//!
//! Dumping the analysis is implemented by walking the AST and getting a bunch of
//! info out from all over the place. We use `DefId`s to identify objects. The
//! tricky part is getting syntactic (span, source text) and semantic (reference
//! `DefId`s) information for parts of expressions which the compiler has discarded.
//! E.g., in a path `foo::bar::baz`, the compiler only keeps a span for the whole
//! path and a reference to `baz`, but we want spans and references for all three
//! idents.
//!
//! SpanUtils is used to manipulate spans. In particular, to extract sub-spans
//! from spans (e.g., the span for `bar` from the above example path).
//! DumpVisitor walks the AST and processes it, and Dumper is used for
//! recording the output.

use rustc::hir::def::{Res, DefKind as HirDefKind};
use rustc::hir::def_id::DefId;
use rustc::session::config::Input;
use rustc::span_bug;
use rustc::ty::{self, DefIdTree, TyCtxt};
use rustc_data_structures::fx::FxHashSet;

use std::path::Path;
use std::env;

use syntax::ast::{self, Attribute, NodeId, PatKind};
use syntax::parse::token;
use syntax::visit::{self, Visitor};
use syntax::print::pprust::{
    bounds_to_string,
    generic_params_to_string,
    ty_to_string
};
use syntax::ptr::P;
use syntax::source_map::{DUMMY_SP, respan};
use syntax::walk_list;
use syntax_pos::*;

use crate::{escape, generated_code, id_from_def_id, id_from_node_id, lower_attributes,
            PathCollector, SaveContext};
use crate::dumper::{Access, Dumper};
use crate::span_utils::SpanUtils;
use crate::sig;

use rls_data::{CompilationOptions, CratePreludeData, Def, DefKind, GlobalCrateId, Import,
               ImportKind, Ref, RefKind, Relation, RelationKind, SpanData};

use log::{debug, error};

macro_rules! down_cast_data {
    ($id:ident, $kind:ident, $sp:expr) => {
        let $id = if let super::Data::$kind(data) = $id {
            data
        } else {
            span_bug!($sp, "unexpected data kind: {:?}", $id);
        };
    };
}

macro_rules! access_from {
    ($save_ctxt:expr, $item:expr, $id:expr) => {
        Access {
            public: $item.vis.node.is_pub(),
            reachable: $save_ctxt.access_levels.is_reachable($id),
        }
    };
}

macro_rules! access_from_vis {
    ($save_ctxt:expr, $vis:expr, $id:expr) => {
        Access {
            public: $vis.node.is_pub(),
            reachable: $save_ctxt.access_levels.is_reachable($id),
        }
    };
}

pub struct DumpVisitor<'l, 'tcx> {
    pub save_ctxt: SaveContext<'l, 'tcx>,
    tcx: TyCtxt<'tcx>,
    dumper: Dumper,

    span: SpanUtils<'l>,

    // Set of macro definition (callee) spans, and the set
    // of macro use (callsite) spans. We store these to ensure
    // we only write one macro def per unique macro definition, and
    // one macro use per unique callsite span.
    // mac_defs: FxHashSet<Span>,
    // macro_calls: FxHashSet<Span>,
}

impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
    pub fn new(
        save_ctxt: SaveContext<'l, 'tcx>,
    ) -> DumpVisitor<'l, 'tcx> {
        let span_utils = SpanUtils::new(&save_ctxt.tcx.sess);
        let dumper = Dumper::new(save_ctxt.config.clone());
        DumpVisitor {
            tcx: save_ctxt.tcx,
            save_ctxt,
            dumper,
            span: span_utils,
            // mac_defs: FxHashSet::default(),
            // macro_calls: FxHashSet::default(),
        }
    }

    pub fn analysis(&self) -> &rls_data::Analysis {
        self.dumper.analysis()
    }

    fn nest_tables<F>(&mut self, item_id: NodeId, f: F)
    where
        F: FnOnce(&mut Self),
    {
        let item_def_id = self.tcx.hir().local_def_id_from_node_id(item_id);
        if self.tcx.has_typeck_tables(item_def_id) {
            let tables = self.tcx.typeck_tables_of(item_def_id);
            let old_tables = self.save_ctxt.tables;
            self.save_ctxt.tables = tables;
            f(self);
            self.save_ctxt.tables = old_tables;
        } else {
            f(self);
        }
    }

    fn span_from_span(&self, span: Span) -> SpanData {
        self.save_ctxt.span_from_span(span)
    }

    fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
        self.save_ctxt.lookup_def_id(ref_id)
    }

    pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
        let source_file = self.tcx.sess.local_crate_source_file.as_ref();
        let crate_root = source_file.map(|source_file| {
            let source_file = Path::new(source_file);
            match source_file.file_name() {
                Some(_) => source_file.parent().unwrap().display(),
                None => source_file.display(),
            }.to_string()
        });

        let data = CratePreludeData {
            crate_id: GlobalCrateId {
                name: name.into(),
                disambiguator: self.tcx
                    .sess
                    .local_crate_disambiguator()
                    .to_fingerprint()
                    .as_value(),
            },
            crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
            external_crates: self.save_ctxt.get_external_crates(),
            span: self.span_from_span(krate.span),
        };

        self.dumper.crate_prelude(data);
    }

    pub fn dump_compilation_options(&mut self, input: &Input, crate_name: &str) {
        // Apply possible `remap-path-prefix` remapping to the input source file
        // (and don't include remapping args anymore)
        let (program, arguments) = {
            let remap_arg_indices = {
                let mut indices = FxHashSet::default();
                // Args are guaranteed to be valid UTF-8 (checked early)
                for (i, e) in env::args().enumerate() {
                    if e.starts_with("--remap-path-prefix=") {
                        indices.insert(i);
                    } else if e == "--remap-path-prefix" {
                        indices.insert(i);
                        indices.insert(i + 1);
                    }
                }
                indices
            };

            let mut args = env::args()
                .enumerate()
                .filter(|(i, _)| !remap_arg_indices.contains(i))
                .map(|(_, arg)| {
                    match input {
                        Input::File(ref path) if path == Path::new(&arg) => {
                            let mapped = &self.tcx.sess.local_crate_source_file;
                            mapped
                                .as_ref()
                                .unwrap()
                                .to_string_lossy()
                                .into()
                        },
                        _ => arg,
                    }
                });

            (args.next().unwrap(), args.collect())
        };

        let data = CompilationOptions {
            directory: self.tcx.sess.working_dir.0.clone(),
            program,
            arguments,
            output: self.save_ctxt.compilation_output(crate_name),
        };

        self.dumper.compilation_opts(data);
    }

    fn write_sub_paths(&mut self, path: &ast::Path) {
        for seg in &path.segments {
            if let Some(data) = self.save_ctxt.get_path_segment_data(seg) {
                self.dumper.dump_ref(data);
            }
        }
    }

    // As write_sub_paths, but does not process the last ident in the path (assuming it
    // will be processed elsewhere). See note on write_sub_paths about global.
    fn write_sub_paths_truncated(&mut self, path: &ast::Path) {
        for seg in &path.segments[..path.segments.len() - 1] {
            if let Some(data) = self.save_ctxt.get_path_segment_data(seg) {
                self.dumper.dump_ref(data);
            }
        }
    }

    fn process_formals(&mut self, formals: &'l [ast::Param], qualname: &str) {
        for arg in formals {
            self.visit_pat(&arg.pat);
            let mut collector = PathCollector::new();
            collector.visit_pat(&arg.pat);

            for (id, ident, ..) in collector.collected_idents {
                let hir_id = self.tcx.hir().node_to_hir_id(id);
                let typ = match self.save_ctxt.tables.node_type_opt(hir_id) {
                    Some(s) => s.to_string(),
                    None => continue,
                };
                if !self.span.filter_generated(ident.span) {
                    let id = id_from_node_id(id, &self.save_ctxt);
                    let span = self.span_from_span(ident.span);

                    self.dumper.dump_def(
                        &Access {
                            public: false,
                            reachable: false,
                        },
                        Def {
                            kind: DefKind::Local,
                            id,
                            span,
                            name: ident.to_string(),
                            qualname: format!("{}::{}", qualname, ident.to_string()),
                            value: typ,
                            parent: None,
                            children: vec![],
                            decl_id: None,
                            docs: String::new(),
                            sig: None,
                            attributes: vec![],
                        },
                    );
                }
            }
        }
    }

    fn process_method(
        &mut self,
        sig: &'l ast::MethodSig,
        body: Option<&'l ast::Block>,
        id: ast::NodeId,
        ident: ast::Ident,
        generics: &'l ast::Generics,
        vis: ast::Visibility,
        span: Span,
    ) {
        debug!("process_method: {}:{}", id, ident);

        let hir_id = self.tcx.hir().node_to_hir_id(id);
        self.nest_tables(id, |v| {
            if let Some(mut method_data) = v.save_ctxt.get_method_data(id, ident, span) {
                v.process_formals(&sig.decl.inputs, &method_data.qualname);
                v.process_generic_params(&generics, &method_data.qualname, id);

                method_data.value = crate::make_signature(&sig.decl, &generics);
                method_data.sig = sig::method_signature(id, ident, generics, sig, &v.save_ctxt);

                v.dumper.dump_def(&access_from_vis!(v.save_ctxt, vis, hir_id), method_data);
            }

            // walk arg and return types
            for arg in &sig.decl.inputs {
                v.visit_ty(&arg.ty);
            }

            if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output {
                v.visit_ty(ret_ty);
            }

            // walk the fn body
            if let Some(body) = body {
                v.visit_block(body);
            }
        });
    }

    fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) {
        let field_data = self.save_ctxt.get_field_data(field, parent_id);
        if let Some(field_data) = field_data {
            let hir_id = self.tcx.hir().node_to_hir_id(field.id);
            self.dumper.dump_def(&access_from!(self.save_ctxt, field, hir_id), field_data);
        }
    }

    // Dump generic params bindings, then visit_generics
    fn process_generic_params(
        &mut self,
        generics: &'l ast::Generics,
        prefix: &str,
        id: NodeId,
    ) {
        for param in &generics.params {
            match param.kind {
                ast::GenericParamKind::Lifetime { .. } => {}
                ast::GenericParamKind::Type { .. } => {
                    let param_ss = param.ident.span;
                    let name = escape(self.span.snippet(param_ss));
                    // Append $id to name to make sure each one is unique.
                    let qualname = format!("{}::{}${}", prefix, name, id);
                    if !self.span.filter_generated(param_ss) {
                        let id = id_from_node_id(param.id, &self.save_ctxt);
                        let span = self.span_from_span(param_ss);

                        self.dumper.dump_def(
                            &Access {
                                public: false,
                                reachable: false,
                            },
                            Def {
                                kind: DefKind::Type,
                                id,
                                span,
                                name,
                                qualname,
                                value: String::new(),
                                parent: None,
                                children: vec![],
                                decl_id: None,
                                docs: String::new(),
                                sig: None,
                                attributes: vec![],
                            },
                        );
                    }
                }
                ast::GenericParamKind::Const { .. } => {}
            }
        }
        self.visit_generics(generics);
    }

    fn process_fn(
        &mut self,
        item: &'l ast::Item,
        decl: &'l ast::FnDecl,
        ty_params: &'l ast::Generics,
        body: &'l ast::Block,
    ) {
        let hir_id = self.tcx.hir().node_to_hir_id(item.id);
        self.nest_tables(item.id, |v| {
            if let Some(fn_data) = v.save_ctxt.get_item_data(item) {
                down_cast_data!(fn_data, DefData, item.span);
                v.process_formals(&decl.inputs, &fn_data.qualname);
                v.process_generic_params(ty_params, &fn_data.qualname, item.id);

                v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), fn_data);
            }

            for arg in &decl.inputs {
                v.visit_ty(&arg.ty)
            }

            if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
                if let ast::TyKind::ImplTrait(..) = ret_ty.node {
                    // FIXME: Opaque type desugaring prevents us from easily
                    // processing trait bounds. See `visit_ty` for more details.
                } else {
                    v.visit_ty(&ret_ty);
                }
            }

            v.visit_block(&body);
        });
    }

    fn process_static_or_const_item(
        &mut self,
        item: &'l ast::Item,
        typ: &'l ast::Ty,
        expr: &'l ast::Expr,
    ) {
        let hir_id = self.tcx.hir().node_to_hir_id(item.id);
        self.nest_tables(item.id, |v| {
            if let Some(var_data) = v.save_ctxt.get_item_data(item) {
                down_cast_data!(var_data, DefData, item.span);
                v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), var_data);
            }
            v.visit_ty(&typ);
            v.visit_expr(expr);
        });
    }

    fn process_assoc_const(
        &mut self,
        id: ast::NodeId,
        ident: ast::Ident,
        typ: &'l ast::Ty,
        expr: Option<&'l ast::Expr>,
        parent_id: DefId,
        vis: ast::Visibility,
        attrs: &'l [Attribute],
    ) {
        let qualname = format!("::{}",
            self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(id)));

        if !self.span.filter_generated(ident.span) {
            let sig = sig::assoc_const_signature(id, ident.name, typ, expr, &self.save_ctxt);
            let span = self.span_from_span(ident.span);
            let hir_id = self.tcx.hir().node_to_hir_id(id);

            self.dumper.dump_def(
                &access_from_vis!(self.save_ctxt, vis, hir_id),
                Def {
                    kind: DefKind::Const,
                    id: id_from_node_id(id, &self.save_ctxt),
                    span,
                    name: ident.name.to_string(),
                    qualname,
                    value: ty_to_string(&typ),
                    parent: Some(id_from_def_id(parent_id)),
                    children: vec![],
                    decl_id: None,
                    docs: self.save_ctxt.docs_for_attrs(attrs),
                    sig,
                    attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
                },
            );
        }

        // walk type and init value
        self.nest_tables(id, |v| {
            v.visit_ty(typ);
            if let Some(expr) = expr {
                v.visit_expr(expr);
            }
        });
    }

    // FIXME tuple structs should generate tuple-specific data.
    fn process_struct(
        &mut self,
        item: &'l ast::Item,
        def: &'l ast::VariantData,
        ty_params: &'l ast::Generics,
    ) {
        debug!("process_struct {:?} {:?}", item, item.span);
        let name = item.ident.to_string();
        let qualname = format!("::{}",
            self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));

        let kind = match item.node {
            ast::ItemKind::Struct(_, _) => DefKind::Struct,
            ast::ItemKind::Union(_, _) => DefKind::Union,
            _ => unreachable!(),
        };

        let (value, fields) = match item.node {
            ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, ..), ..) |
            ast::ItemKind::Union(ast::VariantData::Struct(ref fields, ..), ..) => {
                let include_priv_fields = !self.save_ctxt.config.pub_only;
                let fields_str = fields
                    .iter()
                    .enumerate()
                    .filter_map(|(i, f)| {
                        if include_priv_fields || f.vis.node.is_pub() {
                            f.ident
                                .map(|i| i.to_string())
                                .or_else(|| Some(i.to_string()))
                        } else {
                            None
                        }
                    })
                    .collect::<Vec<_>>()
                    .join(", ");
                let value = format!("{} {{ {} }}", name, fields_str);
                (
                    value,
                    fields
                        .iter()
                        .map(|f| id_from_node_id(f.id, &self.save_ctxt))
                        .collect(),
                )
            }
            _ => (String::new(), vec![]),
        };

        if !self.span.filter_generated(item.ident.span) {
            let span = self.span_from_span(item.ident.span);
            let hir_id = self.tcx.hir().node_to_hir_id(item.id);
            self.dumper.dump_def(
                &access_from!(self.save_ctxt, item, hir_id),
                Def {
                    kind,
                    id: id_from_node_id(item.id, &self.save_ctxt),
                    span,
                    name,
                    qualname: qualname.clone(),
                    value,
                    parent: None,
                    children: fields,
                    decl_id: None,
                    docs: self.save_ctxt.docs_for_attrs(&item.attrs),
                    sig: sig::item_signature(item, &self.save_ctxt),
                    attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
                },
            );
        }

        for field in def.fields() {
            self.process_struct_field_def(field, item.id);
            self.visit_ty(&field.ty);
        }

        self.process_generic_params(ty_params, &qualname, item.id);
    }

    fn process_enum(
        &mut self,
        item: &'l ast::Item,
        enum_definition: &'l ast::EnumDef,
        ty_params: &'l ast::Generics,
    ) {
        let enum_data = self.save_ctxt.get_item_data(item);
        let enum_data = match enum_data {
            None => return,
            Some(data) => data,
        };
        down_cast_data!(enum_data, DefData, item.span);

        let hir_id = self.tcx.hir().node_to_hir_id(item.id);
        let access = access_from!(self.save_ctxt, item, hir_id);

        for variant in &enum_definition.variants {
            let name = variant.ident.name.to_string();
            let qualname = format!("{}::{}", enum_data.qualname, name);
            let name_span = variant.ident.span;

            match variant.data {
                ast::VariantData::Struct(ref fields, ..) => {
                    let fields_str = fields
                        .iter()
                        .enumerate()
                        .map(|(i, f)| {
                            f.ident.map(|i| i.to_string()).unwrap_or_else(|| i.to_string())
                        })
                        .collect::<Vec<_>>()
                        .join(", ");
                    let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
                    if !self.span.filter_generated(name_span) {
                        let span = self.span_from_span(name_span);
                        let id = id_from_node_id(variant.id, &self.save_ctxt);
                        let parent = Some(id_from_node_id(item.id, &self.save_ctxt));

                        self.dumper.dump_def(
                            &access,
                            Def {
                                kind: DefKind::StructVariant,
                                id,
                                span,
                                name,
                                qualname,
                                value,
                                parent,
                                children: vec![],
                                decl_id: None,
                                docs: self.save_ctxt.docs_for_attrs(&variant.attrs),
                                sig: sig::variant_signature(variant, &self.save_ctxt),
                                attributes: lower_attributes(
                                    variant.attrs.clone(),
                                    &self.save_ctxt,
                                ),
                            },
                        );
                    }
                }
                ref v => {
                    let mut value = format!("{}::{}", enum_data.name, name);
                    if let &ast::VariantData::Tuple(ref fields, _) = v {
                        value.push('(');
                        value.push_str(&fields
                            .iter()
                            .map(|f| ty_to_string(&f.ty))
                            .collect::<Vec<_>>()
                            .join(", "));
                        value.push(')');
                    }
                    if !self.span.filter_generated(name_span) {
                        let span = self.span_from_span(name_span);
                        let id = id_from_node_id(variant.id, &self.save_ctxt);
                        let parent = Some(id_from_node_id(item.id, &self.save_ctxt));

                        self.dumper.dump_def(
                            &access,
                            Def {
                                kind: DefKind::TupleVariant,
                                id,
                                span,
                                name,
                                qualname,
                                value,
                                parent,
                                children: vec![],
                                decl_id: None,
                                docs: self.save_ctxt.docs_for_attrs(&variant.attrs),
                                sig: sig::variant_signature(variant, &self.save_ctxt),
                                attributes: lower_attributes(
                                    variant.attrs.clone(),
                                    &self.save_ctxt,
                                ),
                            },
                        );
                    }
                }
            }


            for field in variant.data.fields() {
                self.process_struct_field_def(field, variant.id);
                self.visit_ty(&field.ty);
            }
        }
        self.process_generic_params(ty_params, &enum_data.qualname, item.id);
        self.dumper.dump_def(&access, enum_data);
    }

    fn process_impl(
        &mut self,
        item: &'l ast::Item,
        generics: &'l ast::Generics,
        trait_ref: &'l Option<ast::TraitRef>,
        typ: &'l ast::Ty,
        impl_items: &'l [ast::ImplItem],
    ) {
        if let Some(impl_data) = self.save_ctxt.get_item_data(item) {
            if !self.span.filter_generated(item.span) {
                if let super::Data::RelationData(rel, imp) = impl_data {
                    self.dumper.dump_relation(rel);
                    self.dumper.dump_impl(imp);
                } else {
                    span_bug!(item.span, "unexpected data kind: {:?}", impl_data);
                }
            }
        }
        self.visit_ty(&typ);
        if let &Some(ref trait_ref) = trait_ref {
            self.process_path(trait_ref.ref_id, &trait_ref.path);
        }
        self.process_generic_params(generics, "", item.id);
        for impl_item in impl_items {
            let map = &self.tcx.hir();
            self.process_impl_item(impl_item, map.local_def_id_from_node_id(item.id));
        }
    }

    fn process_trait(
        &mut self,
        item: &'l ast::Item,
        generics: &'l ast::Generics,
        trait_refs: &'l ast::GenericBounds,
        methods: &'l [ast::TraitItem],
    ) {
        let name = item.ident.to_string();
        let qualname = format!("::{}",
            self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
        let mut val = name.clone();
        if !generics.params.is_empty() {
            val.push_str(&generic_params_to_string(&generics.params));
        }
        if !trait_refs.is_empty() {
            val.push_str(": ");
            val.push_str(&bounds_to_string(trait_refs));
        }
        if !self.span.filter_generated(item.ident.span) {
            let id = id_from_node_id(item.id, &self.save_ctxt);
            let span = self.span_from_span(item.ident.span);
            let children = methods
                .iter()
                .map(|i| id_from_node_id(i.id, &self.save_ctxt))
                .collect();
            let hir_id = self.tcx.hir().node_to_hir_id(item.id);
            self.dumper.dump_def(
                &access_from!(self.save_ctxt, item, hir_id),
                Def {
                    kind: DefKind::Trait,
                    id,
                    span,
                    name,
                    qualname: qualname.clone(),
                    value: val,
                    parent: None,
                    children,
                    decl_id: None,
                    docs: self.save_ctxt.docs_for_attrs(&item.attrs),
                    sig: sig::item_signature(item, &self.save_ctxt),
                    attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
                },
            );
        }

        // super-traits
        for super_bound in trait_refs.iter() {
            let trait_ref = match *super_bound {
                ast::GenericBound::Trait(ref trait_ref, _) => trait_ref,
                ast::GenericBound::Outlives(..) => continue,
            };

            let trait_ref = &trait_ref.trait_ref;
            if let Some(id) = self.lookup_def_id(trait_ref.ref_id) {
                let sub_span = trait_ref.path.segments.last().unwrap().ident.span;
                if !self.span.filter_generated(sub_span) {
                    let span = self.span_from_span(sub_span);
                    self.dumper.dump_ref(Ref {
                        kind: RefKind::Type,
                        span: span.clone(),
                        ref_id: id_from_def_id(id),
                    });

                    self.dumper.dump_relation(Relation {
                        kind: RelationKind::SuperTrait,
                        span,
                        from: id_from_def_id(id),
                        to: id_from_node_id(item.id, &self.save_ctxt),
                    });
                }
            }
        }

        // walk generics and methods
        self.process_generic_params(generics, &qualname, item.id);
        for method in methods {
            let map = &self.tcx.hir();
            self.process_trait_item(method, map.local_def_id_from_node_id(item.id))
        }
    }

    // `item` is the module in question, represented as an item.
    fn process_mod(&mut self, item: &ast::Item) {
        if let Some(mod_data) = self.save_ctxt.get_item_data(item) {
            down_cast_data!(mod_data, DefData, item.span);
            let hir_id = self.tcx.hir().node_to_hir_id(item.id);
            self.dumper.dump_def(&access_from!(self.save_ctxt, item, hir_id), mod_data);
        }
    }

    fn dump_path_ref(&mut self, id: NodeId, path: &ast::Path) {
        let path_data = self.save_ctxt.get_path_data(id, path);
        if let Some(path_data) = path_data {
            self.dumper.dump_ref(path_data);
        }
    }

    fn process_path(&mut self, id: NodeId, path: &'l ast::Path) {
        if self.span.filter_generated(path.span) {
            return;
        }
        self.dump_path_ref(id, path);

        // Type arguments
        for seg in &path.segments {
            if let Some(ref generic_args) = seg.args {
                match **generic_args {
                    ast::GenericArgs::AngleBracketed(ref data) => {
                        for arg in &data.args {
                            match arg {
                                ast::GenericArg::Type(ty) => self.visit_ty(ty),
                                _ => {}
                            }
                        }
                    }
                    ast::GenericArgs::Parenthesized(ref data) => {
                        for t in &data.inputs {
                            self.visit_ty(t);
                        }
                        if let Some(ref t) = data.output {
                            self.visit_ty(t);
                        }
                    }
                }
            }
        }

        self.write_sub_paths_truncated(path);
    }

    fn process_struct_lit(
        &mut self,
        ex: &'l ast::Expr,
        path: &'l ast::Path,
        fields: &'l [ast::Field],
        variant: &'l ty::VariantDef,
        base: &'l Option<P<ast::Expr>>,
    ) {
        if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) {
            self.write_sub_paths_truncated(path);
            down_cast_data!(struct_lit_data, RefData, ex.span);
            if !generated_code(ex.span) {
                self.dumper.dump_ref(struct_lit_data);
            }

            for field in fields {
                if let Some(field_data) = self.save_ctxt.get_field_ref_data(field, variant) {
                    self.dumper.dump_ref(field_data);
                }

                self.visit_expr(&field.expr)
            }
        }

        walk_list!(self, visit_expr, base);
    }

    fn process_method_call(
        &mut self,
        ex: &'l ast::Expr,
        seg: &'l ast::PathSegment,
        args: &'l [P<ast::Expr>],
    ) {
        debug!("process_method_call {:?} {:?}", ex, ex.span);
        if let Some(mcd) = self.save_ctxt.get_expr_data(ex) {
            down_cast_data!(mcd, RefData, ex.span);
            if !generated_code(ex.span) {
                self.dumper.dump_ref(mcd);
            }
        }

        // Explicit types in the turbo-fish.
        if let Some(ref generic_args) = seg.args {
            if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args {
                for arg in &data.args {
                    match arg {
                        ast::GenericArg::Type(ty) => self.visit_ty(ty),
                        _ => {}
                    }
                }
            }
        }

        // walk receiver and args
        walk_list!(self, visit_expr, args);
    }

    fn process_pat(&mut self, p: &'l ast::Pat) {
        match p.node {
            PatKind::Struct(ref _path, ref fields, _) => {
                // FIXME do something with _path?
                let hir_id = self.tcx.hir().node_to_hir_id(p.id);
                let adt = match self.save_ctxt.tables.node_type_opt(hir_id) {
                    Some(ty) => ty.ty_adt_def().unwrap(),
                    None => {
                        visit::walk_pat(self, p);
                        return;
                    }
                };
                let variant = adt.variant_of_res(self.save_ctxt.get_path_res(p.id));

                for field in fields {
                    if let Some(index) = self.tcx.find_field_index(field.ident, variant) {
                        if !self.span.filter_generated(field.ident.span) {
                            let span = self.span_from_span(field.ident.span);
                            self.dumper.dump_ref(Ref {
                                kind: RefKind::Variable,
                                span,
                                ref_id: id_from_def_id(variant.fields[index].did),
                            });
                        }
                    }
                    self.visit_pat(&field.pat);
                }
            }
            _ => visit::walk_pat(self, p),
        }
    }

    fn process_var_decl(&mut self, pat: &'l ast::Pat) {
        // The pattern could declare multiple new vars,
        // we must walk the pattern and collect them all.
        let mut collector = PathCollector::new();
        collector.visit_pat(&pat);
        self.visit_pat(&pat);

        // Process collected paths.
        for (id, ident, _) in collector.collected_idents {
            match self.save_ctxt.get_path_res(id) {
                Res::Local(hir_id) => {
                    let id = self.tcx.hir().hir_to_node_id(hir_id);
                    let typ = self.save_ctxt.tables.node_type_opt(hir_id)
                        .map(|t| t.to_string())
                        .unwrap_or_default();

                    // Rust uses the id of the pattern for var lookups, so we'll use it too.
                    if !self.span.filter_generated(ident.span) {
                        let qualname = format!("{}${}", ident.to_string(), id);
                        let id = id_from_node_id(id, &self.save_ctxt);
                        let span = self.span_from_span(ident.span);

                        self.dumper.dump_def(
                            &Access {
                                public: false,
                                reachable: false,
                            },
                            Def {
                                kind: DefKind::Local,
                                id,
                                span,
                                name: ident.to_string(),
                                qualname,
                                value: typ,
                                parent: None,
                                children: vec![],
                                decl_id: None,
                                docs: String::new(),
                                sig: None,
                                attributes: vec![],
                            },
                        );
                    }
                }
                Res::Def(HirDefKind::Ctor(..), _) |
                Res::Def(HirDefKind::Const, _) |
                Res::Def(HirDefKind::AssocConst, _) |
                Res::Def(HirDefKind::Struct, _) |
                Res::Def(HirDefKind::Variant, _) |
                Res::Def(HirDefKind::TyAlias, _) |
                Res::Def(HirDefKind::AssocTy, _) |
                Res::SelfTy(..) => {
                    self.dump_path_ref(id, &ast::Path::from_ident(ident));
                }
                def => error!(
                    "unexpected definition kind when processing collected idents: {:?}",
                    def
                ),
            }
        }

        for (id, ref path) in collector.collected_paths {
            self.process_path(id, path);
        }
    }

    /// Extracts macro use and definition information from the AST node defined
    /// by the given NodeId, using the expansion information from the node's
    /// span.
    ///
    /// If the span is not macro-generated, do nothing, else use callee and
    /// callsite spans to record macro definition and use data, using the
    /// mac_uses and mac_defs sets to prevent multiples.
    fn process_macro_use(&mut self, _span: Span) {
        // FIXME if we're not dumping the defs (see below), there is no point
        // dumping refs either.
        // let source_span = span.source_callsite();
        // if !self.macro_calls.insert(source_span) {
        //     return;
        // }

        // let data = match self.save_ctxt.get_macro_use_data(span) {
        //     None => return,
        //     Some(data) => data,
        // };

        // self.dumper.macro_use(data);

        // FIXME write the macro def
        // let mut hasher = DefaultHasher::new();
        // data.callee_span.hash(&mut hasher);
        // let hash = hasher.finish();
        // let qualname = format!("{}::{}", data.name, hash);
        // Don't write macro definition for imported macros
        // if !self.mac_defs.contains(&data.callee_span)
        //     && !data.imported {
        //     self.mac_defs.insert(data.callee_span);
        //     if let Some(sub_span) = self.span.span_for_macro_def_name(data.callee_span) {
        //         self.dumper.macro_data(MacroData {
        //             span: sub_span,
        //             name: data.name.clone(),
        //             qualname: qualname.clone(),
        //             // FIXME where do macro docs come from?
        //             docs: String::new(),
        //         }.lower(self.tcx));
        //     }
        // }
    }

    fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId) {
        self.process_macro_use(trait_item.span);
        let vis_span = trait_item.span.shrink_to_lo();
        match trait_item.node {
            ast::TraitItemKind::Const(ref ty, ref expr) => {
                self.process_assoc_const(
                    trait_item.id,
                    trait_item.ident,
                    &ty,
                    expr.as_ref().map(|e| &**e),
                    trait_id,
                    respan(vis_span, ast::VisibilityKind::Public),
                    &trait_item.attrs,
                );
            }
            ast::TraitItemKind::Method(ref sig, ref body) => {
                self.process_method(
                    sig,
                    body.as_ref().map(|x| &**x),
                    trait_item.id,
                    trait_item.ident,
                    &trait_item.generics,
                    respan(vis_span, ast::VisibilityKind::Public),
                    trait_item.span,
                );
            }
            ast::TraitItemKind::Type(ref bounds, ref default_ty) => {
                // FIXME do something with _bounds (for type refs)
                let name = trait_item.ident.name.to_string();
                let qualname = format!("::{}",
                    self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(trait_item.id)));

                if !self.span.filter_generated(trait_item.ident.span) {
                    let span = self.span_from_span(trait_item.ident.span);
                    let id = id_from_node_id(trait_item.id, &self.save_ctxt);

                    self.dumper.dump_def(
                        &Access {
                            public: true,
                            reachable: true,
                        },
                        Def {
                            kind: DefKind::Type,
                            id,
                            span,
                            name,
                            qualname,
                            value: self.span.snippet(trait_item.span),
                            parent: Some(id_from_def_id(trait_id)),
                            children: vec![],
                            decl_id: None,
                            docs: self.save_ctxt.docs_for_attrs(&trait_item.attrs),
                            sig: sig::assoc_type_signature(
                                trait_item.id,
                                trait_item.ident,
                                Some(bounds),
                                default_ty.as_ref().map(|ty| &**ty),
                                &self.save_ctxt,
                            ),
                            attributes: lower_attributes(trait_item.attrs.clone(), &self.save_ctxt),
                        },
                    );
                }

                if let &Some(ref default_ty) = default_ty {
                    self.visit_ty(default_ty)
                }
            }
            ast::TraitItemKind::Macro(_) => {}
        }
    }

    fn process_impl_item(&mut self, impl_item: &'l ast::ImplItem, impl_id: DefId) {
        self.process_macro_use(impl_item.span);
        match impl_item.node {
            ast::ImplItemKind::Const(ref ty, ref expr) => {
                self.process_assoc_const(
                    impl_item.id,
                    impl_item.ident,
                    &ty,
                    Some(expr),
                    impl_id,
                    impl_item.vis.clone(),
                    &impl_item.attrs,
                );
            }
            ast::ImplItemKind::Method(ref sig, ref body) => {
                self.process_method(
                    sig,
                    Some(body),
                    impl_item.id,
                    impl_item.ident,
                    &impl_item.generics,
                    impl_item.vis.clone(),
                    impl_item.span,
                );
            }
            ast::ImplItemKind::TyAlias(ref ty) => {
                // FIXME: uses of the assoc type should ideally point to this
                // 'def' and the name here should be a ref to the def in the
                // trait.
                self.visit_ty(ty)
            }
            ast::ImplItemKind::OpaqueTy(ref bounds) => {
                // FIXME: uses of the assoc type should ideally point to this
                // 'def' and the name here should be a ref to the def in the
                // trait.
                self.process_bounds(&bounds);
            }
            ast::ImplItemKind::Macro(_) => {}
        }
    }

    /// Dumps imports in a use tree recursively.
    ///
    /// A use tree is an import that may contain nested braces (RFC 2128). The `use_tree` parameter
    /// is the current use tree under scrutiny, while `id` and `prefix` are its corresponding node
    /// ID and path. `root_item` is the topmost use tree in the hierarchy.
    ///
    /// If `use_tree` is a simple or glob import, it is dumped into the analysis data. Otherwise,
    /// each child use tree is dumped recursively.
    fn process_use_tree(&mut self,
                         use_tree: &'l ast::UseTree,
                         id: NodeId,
                         root_item: &'l ast::Item,
                         prefix: &ast::Path) {
        let path = &use_tree.prefix;

        // The access is calculated using the current tree ID, but with the root tree's visibility
        // (since nested trees don't have their own visibility).
        let hir_id = self.tcx.hir().node_to_hir_id(id);
        let access = access_from!(self.save_ctxt, root_item, hir_id);

        // The parent `DefId` of a given use tree is always the enclosing item.
        let parent = self.save_ctxt.tcx.hir().opt_local_def_id_from_node_id(id)
            .and_then(|id| self.save_ctxt.tcx.parent(id))
            .map(id_from_def_id);

        match use_tree.kind {
            ast::UseTreeKind::Simple(alias, ..) => {
                let ident = use_tree.ident();
                let path = ast::Path {
                    segments: prefix.segments
                        .iter()
                        .chain(path.segments.iter())
                        .cloned()
                        .collect(),
                    span: path.span,
                };

                let sub_span = path.segments.last().unwrap().ident.span;
                if !self.span.filter_generated(sub_span) {
                    let ref_id = self.lookup_def_id(id).map(|id| id_from_def_id(id));
                    let alias_span = alias.map(|i| self.span_from_span(i.span));
                    let span = self.span_from_span(sub_span);
                    self.dumper.import(&access, Import {
                        kind: ImportKind::Use,
                        ref_id,
                        span,
                        alias_span,
                        name: ident.to_string(),
                        value: String::new(),
                        parent,
                    });
                    self.write_sub_paths_truncated(&path);
                }
            }
            ast::UseTreeKind::Glob => {
                let path = ast::Path {
                    segments: prefix.segments
                        .iter()
                        .chain(path.segments.iter())
                        .cloned()
                        .collect(),
                    span: path.span,
                };

                // Make a comma-separated list of names of imported modules.
                let def_id = self.tcx.hir().local_def_id_from_node_id(id);
                let names = self.tcx.names_imported_by_glob_use(def_id);
                let names: Vec<_> = names.iter().map(|n| n.to_string()).collect();

                // Otherwise it's a span with wrong macro expansion info, which
                // we don't want to track anyway, since it's probably macro-internal `use`
                if let Some(sub_span) =
                    self.span.sub_span_of_token(use_tree.span, token::BinOp(token::Star))
                {
                    if !self.span.filter_generated(use_tree.span) {
                        let span = self.span_from_span(sub_span);

                        self.dumper.import(&access, Import {
                            kind: ImportKind::GlobUse,
                            ref_id: None,
                            span,
                            alias_span: None,
                            name: "*".to_owned(),
                            value: names.join(", "),
                            parent,
                        });
                        self.write_sub_paths(&path);
                    }
                }
            }
            ast::UseTreeKind::Nested(ref nested_items) => {
                let prefix = ast::Path {
                    segments: prefix.segments
                        .iter()
                        .chain(path.segments.iter())
                        .cloned()
                        .collect(),
                    span: path.span,
                };
                for &(ref tree, id) in nested_items {
                    self.process_use_tree(tree, id, root_item, &prefix);
                }
            }
        }
    }

    fn process_bounds(&mut self, bounds: &'l ast::GenericBounds) {
        for bound in bounds {
            if let ast::GenericBound::Trait(ref trait_ref, _) = *bound {
                self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
            }
        }
    }
}

impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
    fn visit_mod(&mut self, m: &'l ast::Mod, span: Span, attrs: &[ast::Attribute], id: NodeId) {
        // Since we handle explicit modules ourselves in visit_item, this should
        // only get called for the root module of a crate.
        assert_eq!(id, ast::CRATE_NODE_ID);

        let qualname = format!("::{}",
            self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(id)));

        let cm = self.tcx.sess.source_map();
        let filename = cm.span_to_filename(span);
        let data_id = id_from_node_id(id, &self.save_ctxt);
        let children = m.items
            .iter()
            .map(|i| id_from_node_id(i.id, &self.save_ctxt))
            .collect();
        let span = self.span_from_span(span);

        self.dumper.dump_def(
            &Access {
                public: true,
                reachable: true,
            },
            Def {
                kind: DefKind::Mod,
                id: data_id,
                name: String::new(),
                qualname,
                span,
                value: filename.to_string(),
                children,
                parent: None,
                decl_id: None,
                docs: self.save_ctxt.docs_for_attrs(attrs),
                sig: None,
                attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
            },
        );
        visit::walk_mod(self, m);
    }

    fn visit_item(&mut self, item: &'l ast::Item) {
        use syntax::ast::ItemKind::*;
        self.process_macro_use(item.span);
        match item.node {
            Use(ref use_tree) => {
                let prefix = ast::Path {
                    segments: vec![],
                    span: DUMMY_SP,
                };
                self.process_use_tree(use_tree, item.id, item, &prefix);
            }
            ExternCrate(_) => {
                let name_span = item.ident.span;
                if !self.span.filter_generated(name_span) {
                    let span = self.span_from_span(name_span);
                    let parent = self.save_ctxt.tcx.hir().opt_local_def_id_from_node_id(item.id)
                        .and_then(|id| self.save_ctxt.tcx.parent(id))
                        .map(id_from_def_id);
                    self.dumper.import(
                        &Access {
                            public: false,
                            reachable: false,
                        },
                        Import {
                            kind: ImportKind::ExternCrate,
                            ref_id: None,
                            span,
                            alias_span: None,
                            name: item.ident.to_string(),
                            value: String::new(),
                            parent,
                        },
                    );
                }
            }
            Fn(ref decl, .., ref ty_params, ref body) => {
                self.process_fn(item, &decl, ty_params, &body)
            }
            Static(ref typ, _, ref expr) => self.process_static_or_const_item(item, typ, expr),
            Const(ref typ, ref expr) => self.process_static_or_const_item(item, &typ, &expr),
            Struct(ref def, ref ty_params) | Union(ref def, ref ty_params) => {
                self.process_struct(item, def, ty_params)
            }
            Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
            Impl(.., ref ty_params, ref trait_ref, ref typ, ref impl_items) => {
                self.process_impl(item, ty_params, trait_ref, &typ, impl_items)
            }
            Trait(_, _, ref generics, ref trait_refs, ref methods) => {
                self.process_trait(item, generics, trait_refs, methods)
            }
            Mod(ref m) => {
                self.process_mod(item);
                visit::walk_mod(self, m);
            }
            TyAlias(ref ty, ref ty_params) => {
                let qualname = format!("::{}",
                    self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
                let value = ty_to_string(&ty);
                if !self.span.filter_generated(item.ident.span) {
                    let span = self.span_from_span(item.ident.span);
                    let id = id_from_node_id(item.id, &self.save_ctxt);
                    let hir_id = self.tcx.hir().node_to_hir_id(item.id);

                    self.dumper.dump_def(
                        &access_from!(self.save_ctxt, item, hir_id),
                        Def {
                            kind: DefKind::Type,
                            id,
                            span,
                            name: item.ident.to_string(),
                            qualname: qualname.clone(),
                            value,
                            parent: None,
                            children: vec![],
                            decl_id: None,
                            docs: self.save_ctxt.docs_for_attrs(&item.attrs),
                            sig: sig::item_signature(item, &self.save_ctxt),
                            attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
                        },
                    );
                }

                self.visit_ty(&ty);
                self.process_generic_params(ty_params, &qualname, item.id);
            }
            OpaqueTy(ref bounds, ref ty_params) => {
                let qualname = format!("::{}",
                    self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));

                let value = String::new();
                if !self.span.filter_generated(item.ident.span) {
                    let span = self.span_from_span(item.ident.span);
                    let id = id_from_node_id(item.id, &self.save_ctxt);
                    let hir_id = self.tcx.hir().node_to_hir_id(item.id);

                    self.dumper.dump_def(
                        &access_from!(self.save_ctxt, item, hir_id),
                        Def {
                            kind: DefKind::Type,
                            id,
                            span,
                            name: item.ident.to_string(),
                            qualname: qualname.clone(),
                            value,
                            parent: None,
                            children: vec![],
                            decl_id: None,
                            docs: self.save_ctxt.docs_for_attrs(&item.attrs),
                            sig: sig::item_signature(item, &self.save_ctxt),
                            attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
                        },
                    );
                }

                self.process_bounds(bounds);
                self.process_generic_params(ty_params, &qualname, item.id);
            }
            Mac(_) => (),
            _ => visit::walk_item(self, item),
        }
    }

    fn visit_generics(&mut self, generics: &'l ast::Generics) {
        for param in &generics.params {
            match param.kind {
                ast::GenericParamKind::Lifetime { .. } => {}
                ast::GenericParamKind::Type { ref default, .. } => {
                    self.process_bounds(&param.bounds);
                    if let Some(ref ty) = default {
                        self.visit_ty(&ty);
                    }
                }
                ast::GenericParamKind::Const { ref ty } => {
                    self.process_bounds(&param.bounds);
                    self.visit_ty(&ty);
                }
            }
        }
        for pred in &generics.where_clause.predicates {
            if let ast::WherePredicate::BoundPredicate(ref wbp) = *pred {
                self.process_bounds(&wbp.bounds);
                self.visit_ty(&wbp.bounded_ty);
            }
        }
    }

    fn visit_ty(&mut self, t: &'l ast::Ty) {
        self.process_macro_use(t.span);
        match t.node {
            ast::TyKind::Path(_, ref path) => {
                if generated_code(t.span) {
                    return;
                }

                if let Some(id) = self.lookup_def_id(t.id) {
                    let sub_span = path.segments.last().unwrap().ident.span;
                    let span = self.span_from_span(sub_span);
                    self.dumper.dump_ref(Ref {
                        kind: RefKind::Type,
                        span,
                        ref_id: id_from_def_id(id),
                    });
                }

                self.write_sub_paths_truncated(path);
                visit::walk_path(self, path);
            }
            ast::TyKind::Array(ref element, ref length) => {
                self.visit_ty(element);
                self.nest_tables(length.id, |v| v.visit_expr(&length.value));
            }
            ast::TyKind::ImplTrait(id, ref bounds) => {
                // FIXME: As of writing, the opaque type lowering introduces
                // another DefPath scope/segment (used to declare the resulting
                // opaque type item).
                // However, the synthetic scope does *not* have associated
                // typeck tables, which means we can't nest it and we fire an
                // assertion when resolving the qualified type paths in trait
                // bounds...
                // This will panic if called on return type `impl Trait`, which
                // we guard against in `process_fn`.
                self.nest_tables(id, |v| v.process_bounds(bounds));
            }
            _ => visit::walk_ty(self, t),
        }
    }

    fn visit_expr(&mut self, ex: &'l ast::Expr) {
        debug!("visit_expr {:?}", ex.node);
        self.process_macro_use(ex.span);
        match ex.node {
            ast::ExprKind::Struct(ref path, ref fields, ref base) => {
                let expr_hir_id = self.save_ctxt.tcx.hir().node_to_hir_id(ex.id);
                let hir_expr = self.save_ctxt.tcx.hir().expect_expr(expr_hir_id);
                let adt = match self.save_ctxt.tables.expr_ty_opt(&hir_expr) {
                    Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(),
                    _ => {
                        visit::walk_expr(self, ex);
                        return;
                    }
                };
                let node_id = self.save_ctxt.tcx.hir().hir_to_node_id(hir_expr.hir_id);
                let res = self.save_ctxt.get_path_res(node_id);
                self.process_struct_lit(ex, path, fields, adt.variant_of_res(res), base)
            }
            ast::ExprKind::MethodCall(ref seg, ref args) => self.process_method_call(ex, seg, args),
            ast::ExprKind::Field(ref sub_ex, _) => {
                self.visit_expr(&sub_ex);

                if let Some(field_data) = self.save_ctxt.get_expr_data(ex) {
                    down_cast_data!(field_data, RefData, ex.span);
                    if !generated_code(ex.span) {
                        self.dumper.dump_ref(field_data);
                    }
                }
            }
            ast::ExprKind::Closure(_, _, _, ref decl, ref body, _fn_decl_span) => {
                let id = format!("${}", ex.id);

                // walk arg and return types
                for arg in &decl.inputs {
                    self.visit_ty(&arg.ty);
                }

                if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
                    self.visit_ty(&ret_ty);
                }

                // walk the body
                self.nest_tables(ex.id, |v| {
                    v.process_formals(&decl.inputs, &id);
                    v.visit_expr(body)
                });
            }
            ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) => {
                self.process_var_decl(pattern);
                debug!("for loop, walk sub-expr: {:?}", subexpression.node);
                self.visit_expr(subexpression);
                visit::walk_block(self, block);
            }
            ast::ExprKind::Let(ref pat, ref scrutinee) => {
                self.process_var_decl(pat);
                self.visit_expr(scrutinee);
            }
            ast::ExprKind::Repeat(ref element, ref count) => {
                self.visit_expr(element);
                self.nest_tables(count.id, |v| v.visit_expr(&count.value));
            }
            // In particular, we take this branch for call and path expressions,
            // where we'll index the idents involved just by continuing to walk.
            _ => visit::walk_expr(self, ex),
        }
    }

    fn visit_mac(&mut self, mac: &'l ast::Mac) {
        // These shouldn't exist in the AST at this point, log a span bug.
        span_bug!(
            mac.span,
            "macro invocation should have been expanded out of AST"
        );
    }

    fn visit_pat(&mut self, p: &'l ast::Pat) {
        self.process_macro_use(p.span);
        self.process_pat(p);
    }

    fn visit_arm(&mut self, arm: &'l ast::Arm) {
        self.process_var_decl(&arm.pat);
        if let Some(expr) = &arm.guard {
            self.visit_expr(expr);
        }
        self.visit_expr(&arm.body);
    }

    fn visit_path(&mut self, p: &'l ast::Path, id: NodeId) {
        self.process_path(id, p);
    }

    fn visit_stmt(&mut self, s: &'l ast::Stmt) {
        self.process_macro_use(s.span);
        visit::walk_stmt(self, s)
    }

    fn visit_local(&mut self, l: &'l ast::Local) {
        self.process_macro_use(l.span);
        self.process_var_decl(&l.pat);

        // Just walk the initialiser and type (don't want to walk the pattern again).
        walk_list!(self, visit_ty, &l.ty);
        walk_list!(self, visit_expr, &l.init);
    }

    fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
        let hir_id = self.tcx.hir().node_to_hir_id(item.id);
        let access = access_from!(self.save_ctxt, item, hir_id);

        match item.node {
            ast::ForeignItemKind::Fn(ref decl, ref generics) => {
                if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) {
                    down_cast_data!(fn_data, DefData, item.span);

                    self.process_generic_params(generics, &fn_data.qualname, item.id);
                    self.dumper.dump_def(&access, fn_data);
                }

                for arg in &decl.inputs {
                    self.visit_ty(&arg.ty);
                }

                if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
                    self.visit_ty(&ret_ty);
                }
            }
            ast::ForeignItemKind::Static(ref ty, _) => {
                if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
                    down_cast_data!(var_data, DefData, item.span);
                    self.dumper.dump_def(&access, var_data);
                }

                self.visit_ty(ty);
            }
            ast::ForeignItemKind::Ty => {
                if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
                    down_cast_data!(var_data, DefData, item.span);
                    self.dumper.dump_def(&access, var_data);
                }
            }
            ast::ForeignItemKind::Macro(..) => {}
        }
    }
}
