]> git.lizzy.rs Git - rust.git/commitdiff
Remove intermediate forms and some other refactoring
authorNick Cameron <ncameron@mozilla.com>
Thu, 8 Jun 2017 02:45:15 +0000 (14:45 +1200)
committerNick Cameron <ncameron@mozilla.com>
Fri, 16 Jun 2017 00:52:37 +0000 (12:52 +1200)
src/librustc_save_analysis/data.rs [deleted file]
src/librustc_save_analysis/dump.rs [deleted file]
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/external_data.rs [deleted file]
src/librustc_save_analysis/json_api_dumper.rs
src/librustc_save_analysis/json_dumper.rs
src/librustc_save_analysis/lib.rs
src/librustc_save_analysis/span_utils.rs

diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs
deleted file mode 100644 (file)
index e15e3f6..0000000
+++ /dev/null
@@ -1,421 +0,0 @@
-// Copyright 2012-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.
-
-//! Structs representing the analysis data from a crate.
-//!
-//! The `Dump` trait can be used together with `DumpVisitor` in order to
-//! retrieve the data from a crate.
-
-use rustc::hir;
-use rustc::hir::def_id::{CrateNum, DefId};
-use syntax::ast::{self, Attribute, NodeId};
-use syntax_pos::Span;
-
-use rls_data::{ExternalCrateData, Signature};
-
-pub struct CrateData {
-    pub name: String,
-    pub number: u32,
-    pub span: Span,
-}
-
-/// Data for any entity in the Rust language. The actual data contained varies
-/// with the kind of entity being queried. See the nested structs for details.
-#[derive(Debug)]
-pub enum Data {
-    /// Data for Enums.
-    EnumData(EnumData),
-    /// Data for extern crates.
-    ExternCrateData(ExternCrateData),
-    /// Data about a function call.
-    FunctionCallData(FunctionCallData),
-    /// Data for all kinds of functions and methods.
-    FunctionData(FunctionData),
-    /// Data about a function ref.
-    FunctionRefData(FunctionRefData),
-    /// Data for impls.
-    ImplData(ImplData2),
-    /// Data for trait inheritance.
-    InheritanceData(InheritanceData),
-    /// Data about a macro declaration.
-    MacroData(MacroData),
-    /// Data about a macro use.
-    MacroUseData(MacroUseData),
-    /// Data about a method call.
-    MethodCallData(MethodCallData),
-    /// Data for method declarations (methods with a body are treated as functions).
-    MethodData(MethodData),
-    /// Data for modules.
-    ModData(ModData),
-    /// Data for a reference to a module.
-    ModRefData(ModRefData),
-    /// Data for a struct declaration.
-    StructData(StructData),
-    /// Data for a struct variant.
-    StructVariantDat(StructVariantData),
-    /// Data for a trait declaration.
-    TraitData(TraitData),
-    /// Data for a tuple variant.
-    TupleVariantData(TupleVariantData),
-    /// Data for a typedef.
-    TypeDefData(TypeDefData),
-    /// Data for a reference to a type or trait.
-    TypeRefData(TypeRefData),
-    /// Data for a use statement.
-    UseData(UseData),
-    /// Data for a global use statement.
-    UseGlobData(UseGlobData),
-    /// Data for local and global variables (consts and statics), and fields.
-    VariableData(VariableData),
-    /// Data for the use of some variable (e.g., the use of a local variable, which
-    /// will refere to that variables declaration).
-    VariableRefData(VariableRefData),
-}
-
-#[derive(Eq, PartialEq, Clone, Copy, Debug)]
-pub enum Visibility {
-    Public,
-    Restricted,
-    Inherited,
-}
-
-impl<'a> From<&'a ast::Visibility> for Visibility {
-    fn from(v: &'a ast::Visibility) -> Visibility {
-        match *v {
-            ast::Visibility::Public => Visibility::Public,
-            ast::Visibility::Crate(_) => Visibility::Restricted,
-            ast::Visibility::Restricted { .. } => Visibility::Restricted,
-            ast::Visibility::Inherited => Visibility::Inherited,
-        }
-    }
-}
-
-impl<'a> From<&'a hir::Visibility> for Visibility {
-    fn from(v: &'a hir::Visibility) -> Visibility {
-        match *v {
-            hir::Visibility::Public => Visibility::Public,
-            hir::Visibility::Crate => Visibility::Restricted,
-            hir::Visibility::Restricted { .. } => Visibility::Restricted,
-            hir::Visibility::Inherited => Visibility::Inherited,
-        }
-    }
-}
-
-/// Data for the prelude of a crate.
-#[derive(Debug)]
-pub struct CratePreludeData {
-    pub crate_name: String,
-    pub crate_root: String,
-    pub external_crates: Vec<ExternalCrateData>,
-    pub span: Span,
-}
-
-/// Data for enum declarations.
-#[derive(Clone, Debug)]
-pub struct EnumData {
-    pub id: NodeId,
-    pub name: String,
-    pub value: String,
-    pub qualname: String,
-    pub span: Span,
-    pub scope: NodeId,
-    pub variants: Vec<NodeId>,
-    pub visibility: Visibility,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-/// Data for extern crates.
-#[derive(Debug)]
-pub struct ExternCrateData {
-    pub id: NodeId,
-    pub name: String,
-    pub crate_num: CrateNum,
-    pub location: String,
-    pub span: Span,
-    pub scope: NodeId,
-}
-
-/// Data about a function call.
-#[derive(Debug)]
-pub struct FunctionCallData {
-    pub span: Span,
-    pub scope: NodeId,
-    pub ref_id: DefId,
-}
-
-/// Data for all kinds of functions and methods.
-#[derive(Clone, Debug)]
-pub struct FunctionData {
-    pub id: NodeId,
-    pub name: String,
-    pub qualname: String,
-    pub declaration: Option<DefId>,
-    pub span: Span,
-    pub scope: NodeId,
-    pub value: String,
-    pub visibility: Visibility,
-    pub parent: Option<DefId>,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-/// Data about a function call.
-#[derive(Debug)]
-pub struct FunctionRefData {
-    pub span: Span,
-    pub scope: NodeId,
-    pub ref_id: DefId,
-}
-
-#[derive(Debug)]
-pub struct ImplData {
-    pub id: NodeId,
-    pub span: Span,
-    pub scope: NodeId,
-    pub trait_ref: Option<DefId>,
-    pub self_ref: Option<DefId>,
-}
-
-#[derive(Debug)]
-// FIXME: this struct should not exist. However, removing it requires heavy
-// refactoring of dump_visitor.rs. See PR 31838 for more info.
-pub struct ImplData2 {
-    pub id: NodeId,
-    pub span: Span,
-    pub scope: NodeId,
-    // FIXME: I'm not really sure inline data is the best way to do this. Seems
-    // OK in this case, but generalising leads to returning chunks of AST, which
-    // feels wrong.
-    pub trait_ref: Option<TypeRefData>,
-    pub self_ref: Option<TypeRefData>,
-}
-
-#[derive(Debug)]
-pub struct InheritanceData {
-    pub span: Span,
-    pub base_id: DefId,
-    pub deriv_id: NodeId
-}
-
-/// Data about a macro declaration.
-#[derive(Debug)]
-pub struct MacroData {
-    pub span: Span,
-    pub name: String,
-    pub qualname: String,
-    pub docs: String,
-}
-
-/// Data about a macro use.
-#[derive(Debug)]
-pub struct MacroUseData {
-    pub span: Span,
-    pub name: String,
-    pub qualname: String,
-    // Because macro expansion happens before ref-ids are determined,
-    // we use the callee span to reference the associated macro definition.
-    pub callee_span: Span,
-    pub scope: NodeId,
-    pub imported: bool,
-}
-
-/// Data about a method call.
-#[derive(Debug)]
-pub struct MethodCallData {
-    pub span: Span,
-    pub scope: NodeId,
-    pub ref_id: Option<DefId>,
-    pub decl_id: Option<DefId>,
-}
-
-/// Data for method declarations (methods with a body are treated as functions).
-#[derive(Clone, Debug)]
-pub struct MethodData {
-    pub id: NodeId,
-    pub name: String,
-    pub qualname: String,
-    pub span: Span,
-    pub scope: NodeId,
-    pub value: String,
-    pub decl_id: Option<DefId>,
-    pub parent: Option<DefId>,
-    pub visibility: Visibility,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-/// Data for modules.
-#[derive(Debug)]
-pub struct ModData {
-    pub id: NodeId,
-    pub name: String,
-    pub qualname: String,
-    pub span: Span,
-    pub scope: NodeId,
-    pub filename: String,
-    pub items: Vec<NodeId>,
-    pub visibility: Visibility,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-/// Data for a reference to a module.
-#[derive(Debug)]
-pub struct ModRefData {
-    pub span: Span,
-    pub scope: NodeId,
-    pub ref_id: Option<DefId>,
-    pub qualname: String
-}
-
-#[derive(Debug)]
-pub struct StructData {
-    pub span: Span,
-    pub name: String,
-    pub id: NodeId,
-    pub ctor_id: NodeId,
-    pub qualname: String,
-    pub scope: NodeId,
-    pub value: String,
-    pub fields: Vec<NodeId>,
-    pub visibility: Visibility,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-#[derive(Debug)]
-pub struct StructVariantData {
-    pub span: Span,
-    pub name: String,
-    pub id: NodeId,
-    pub qualname: String,
-    pub type_value: String,
-    pub value: String,
-    pub scope: NodeId,
-    pub parent: Option<DefId>,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-#[derive(Debug)]
-pub struct TraitData {
-    pub span: Span,
-    pub id: NodeId,
-    pub name: String,
-    pub qualname: String,
-    pub scope: NodeId,
-    pub value: String,
-    pub items: Vec<NodeId>,
-    pub visibility: Visibility,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-#[derive(Debug)]
-pub struct TupleVariantData {
-    pub span: Span,
-    pub id: NodeId,
-    pub name: String,
-    pub qualname: String,
-    pub type_value: String,
-    pub value: String,
-    pub scope: NodeId,
-    pub parent: Option<DefId>,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-/// Data for a typedef.
-#[derive(Debug)]
-pub struct TypeDefData {
-    pub id: NodeId,
-    pub name: String,
-    pub span: Span,
-    pub qualname: String,
-    pub value: String,
-    pub visibility: Visibility,
-    pub parent: Option<DefId>,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-/// Data for a reference to a type or trait.
-#[derive(Clone, Debug)]
-pub struct TypeRefData {
-    pub span: Span,
-    pub scope: NodeId,
-    pub ref_id: Option<DefId>,
-    pub qualname: String,
-}
-
-#[derive(Debug)]
-pub struct UseData {
-    pub id: NodeId,
-    pub span: Span,
-    pub name: String,
-    pub mod_id: Option<DefId>,
-    pub scope: NodeId,
-    pub visibility: Visibility,
-}
-
-#[derive(Debug)]
-pub struct UseGlobData {
-    pub id: NodeId,
-    pub span: Span,
-    pub names: Vec<String>,
-    pub scope: NodeId,
-    pub visibility: Visibility,
-}
-
-/// Data for local and global variables (consts and statics).
-#[derive(Debug)]
-pub struct VariableData {
-    pub id: NodeId,
-    pub kind: VariableKind,
-    pub name: String,
-    pub qualname: String,
-    pub span: Span,
-    pub scope: NodeId,
-    pub parent: Option<DefId>,
-    pub value: String,
-    pub type_value: String,
-    pub visibility: Visibility,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-#[derive(Debug)]
-pub enum VariableKind {
-    Static,
-    Const,
-    Local,
-    Field,
-}
-
-/// Data for the use of some item (e.g., the use of a local variable, which
-/// will refer to that variables declaration (by ref_id)).
-#[derive(Debug)]
-pub struct VariableRefData {
-    pub name: String,
-    pub span: Span,
-    pub scope: NodeId,
-    pub ref_id: DefId,
-}
diff --git a/src/librustc_save_analysis/dump.rs b/src/librustc_save_analysis/dump.rs
deleted file mode 100644 (file)
index 795ff58..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2012-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.
-
-use super::external_data::*;
-
-use rls_data::CratePreludeData;
-
-pub trait Dump {
-    fn crate_prelude(&mut self, _: CratePreludeData) {}
-    fn enum_data(&mut self, _: EnumData) {}
-    fn extern_crate(&mut self, _: ExternCrateData) {}
-    fn impl_data(&mut self, _: ImplData) {}
-    fn inheritance(&mut self, _: InheritanceData) {}
-    fn function(&mut self, _: FunctionData) {}
-    fn function_ref(&mut self, _: FunctionRefData) {}
-    fn function_call(&mut self, _: FunctionCallData) {}
-    fn method(&mut self, _: MethodData) {}
-    fn method_call(&mut self, _: MethodCallData) {}
-    fn macro_data(&mut self, _: MacroData) {}
-    fn macro_use(&mut self, _: MacroUseData) {}
-    fn mod_data(&mut self, _: ModData) {}
-    fn mod_ref(&mut self, _: ModRefData) {}
-    fn struct_data(&mut self, _: StructData) {}
-    fn struct_variant(&mut self, _: StructVariantData) {}
-    fn trait_data(&mut self, _: TraitData) {}
-    fn tuple_variant(&mut self, _: TupleVariantData) {}
-    fn type_ref(&mut self, _: TypeRefData) {}
-    fn typedef(&mut self, _: TypeDefData) {}
-    fn use_data(&mut self, _: UseData) {}
-    fn use_glob(&mut self, _: UseGlobData) {}
-    fn variable(&mut self, _: VariableData) {}
-    fn variable_ref(&mut self, _: VariableRefData) {}
-}
index ea346d99e31b5a4ed47be3725d9a1cfb71001204..cc33d3db8eba70a92abe31895ac4ddb1aced0c67 100644 (file)
@@ -8,10 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Write the output of rustc's analysis to an implementor of Dump. The data is
-//! primarily designed to be used as input to the DXR tool, specifically its
-//! Rust plugin. It could also be used by IDEs or other code browsing, search, or
-//! cross-referencing tools.
+//! 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 Def IDs to identify objects. The
 //! is used for recording the output in a format-agnostic way (see CsvDumper
 //! for an example).
 
-use rustc::hir;
-use rustc::hir::def::Def;
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::hir::map::{Node, NodeItem};
+use rustc::hir::def::Def as HirDef;
+use rustc::hir::def_id::DefId;
+use rustc::hir::map::Node;
 use rustc::session::Session;
-use rustc::ty::{self, TyCtxt, AssociatedItemContainer};
+use rustc::ty::{self, TyCtxt};
 
-use std::collections::HashSet;
-use std::collections::hash_map::DefaultHasher;
-use std::hash::*;
 use std::path::Path;
 
 use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID};
 use syntax::codemap::Spanned;
 use syntax_pos::*;
 
-use {escape, generated_code, SaveContext, PathCollector, docs_for_attrs};
-use data::*;
-use dump::Dump;
-use external_data::{Lower, make_def_id};
-use recorder;
+use {escape, generated_code, SaveContext, PathCollector, docs_for_attrs, lower_attributes, Dump};
 use span_utils::SpanUtils;
 use sig;
 
-use rls_data::ExternalCrateData;
+use rls_data::{CratePreludeData, Import, ImportKind, SpanData, Ref, RefKind,
+               Def, DefKind, Relation, RelationKind};
 
 macro_rules! down_cast_data {
     ($id:ident, $kind:ident, $sp:expr) => {
@@ -82,8 +72,7 @@ pub struct DumpVisitor<'l, 'tcx: 'l, 'll, D: 'll> {
     // 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: HashSet<Span>,
-    mac_uses: HashSet<Span>,
+    // mac_defs: HashSet<Span>,
 }
 
 impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
@@ -98,8 +87,7 @@ pub fn new(save_ctxt: SaveContext<'l, 'tcx>,
             dumper: dumper,
             span: span_utils.clone(),
             cur_scope: CRATE_NODE_ID,
-            mac_defs: HashSet::new(),
-            mac_uses: HashSet::new(),
+            // mac_defs: HashSet::new(),
         }
     }
 
@@ -127,6 +115,10 @@ fn nest_tables<F>(&mut self, item_id: NodeId, f: F)
         }
     }
 
+    fn span_from_span(&self, span: Span) -> SpanData {
+        self.save_ctxt.span_from_span(span)
+    }
+
     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| {
@@ -137,25 +129,14 @@ pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
             }
         });
 
-        // Info about all the external crates referenced from this crate.
-        let external_crates = self.save_ctxt.get_external_crates().into_iter().map(|c| {
-            let lo_loc = self.span.sess.codemap().lookup_char_pos(c.span.lo);
-            ExternalCrateData {
-                name: c.name,
-                num: c.number,
-                file_name: SpanUtils::make_path_string(&lo_loc.file.name),
-            }
-        }).collect();
-
-        // The current crate.
         let data = CratePreludeData {
             crate_name: name.into(),
             crate_root: crate_root.unwrap_or("<no source>".to_owned()),
-            external_crates: external_crates,
-            span: krate.span,
+            external_crates: self.save_ctxt.get_external_crates(),
+            span: self.span_from_span(krate.span),
         };
 
-        self.dumper.crate_prelude(data.lower(self.tcx));
+        self.dumper.crate_prelude(data);
     }
 
     // Return all non-empty prefixes of a path.
@@ -211,13 +192,13 @@ fn process_path_prefixes(&self, path: &ast::Path) -> Vec<(Span, String)> {
 
     fn write_sub_paths(&mut self, path: &ast::Path) {
         let sub_paths = self.process_path_prefixes(path);
-        for (span, qualname) in sub_paths {
-            self.dumper.mod_ref(ModRefData {
-                span: span,
-                qualname: qualname,
-                scope: self.cur_scope,
-                ref_id: None
-            }.lower(self.tcx));
+        for (span, _) in sub_paths {
+            let span = self.span_from_span(span);
+            self.dumper.dump_ref(Ref {
+                kind: RefKind::Mod,
+                span,
+                ref_id: ::null_id(),
+            });
         }
     }
 
@@ -230,13 +211,13 @@ fn write_sub_paths_truncated(&mut self, path: &ast::Path) {
             return;
         }
 
-        for (span, qualname) in sub_paths.into_iter().take(len - 1) {
-            self.dumper.mod_ref(ModRefData {
-                span: span,
-                qualname: qualname,
-                scope: self.cur_scope,
-                ref_id: None
-            }.lower(self.tcx));
+        for (span, _) in sub_paths.into_iter().take(len - 1) {
+            let span = self.span_from_span(span);
+            self.dumper.dump_ref(Ref {
+                kind: RefKind::Mod,
+                span,
+                ref_id: ::null_id(),
+            });
         }
     }
 
@@ -251,32 +232,32 @@ fn write_sub_path_trait_truncated(&mut self, path: &ast::Path) {
         let sub_paths = &sub_paths[.. (len-1)];
 
         // write the trait part of the sub-path
-        let (ref span, ref qualname) = sub_paths[len-2];
-        self.dumper.type_ref(TypeRefData {
-            ref_id: None,
-            span: *span,
-            qualname: qualname.to_owned(),
-            scope: CRATE_NODE_ID
-        }.lower(self.tcx));
+        let (ref span, _) = sub_paths[len-2];
+        let span = self.span_from_span(*span);
+        self.dumper.dump_ref(Ref {
+            kind: RefKind::Type,
+            ref_id: ::null_id(),
+            span,
+        });
 
         // write the other sub-paths
         if len <= 2 {
             return;
         }
         let sub_paths = &sub_paths[..len-2];
-        for &(ref span, ref qualname) in sub_paths {
-            self.dumper.mod_ref(ModRefData {
-                span: *span,
-                qualname: qualname.to_owned(),
-                scope: self.cur_scope,
-                ref_id: None
-            }.lower(self.tcx));
+        for &(ref span, _) in sub_paths {
+            let span = self.span_from_span(*span);
+            self.dumper.dump_ref(Ref {
+                kind: RefKind::Mod,
+                span,
+                ref_id: ::null_id(),
+            });
         }
     }
 
     fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
         match self.save_ctxt.get_path_def(ref_id) {
-            Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None,
+            HirDef::PrimTy(..) | HirDef::SelfTy(..) | HirDef::Err => None,
             def => Some(def.def_id()),
         }
     }
@@ -285,67 +266,67 @@ fn process_def_kind(&mut self,
                         ref_id: NodeId,
                         span: Span,
                         sub_span: Option<Span>,
-                        def_id: DefId,
-                        scope: NodeId) {
+                        def_id: DefId) {
         if self.span.filter_generated(sub_span, span) {
             return;
         }
 
         let def = self.save_ctxt.get_path_def(ref_id);
         match def {
-            Def::Mod(_) => {
-                self.dumper.mod_ref(ModRefData {
-                    span: sub_span.expect("No span found for mod ref"),
-                    ref_id: Some(def_id),
-                    scope: scope,
-                    qualname: String::new()
-                }.lower(self.tcx));
+            HirDef::Mod(_) => {
+                let span = self.span_from_span(sub_span.expect("No span found for mod ref"));
+                self.dumper.dump_ref(Ref {
+                    kind: RefKind::Mod,
+                    span,
+                    ref_id: ::id_from_def_id(def_id),
+                });
             }
-            Def::Struct(..) |
-            Def::Variant(..) |
-            Def::Union(..) |
-            Def::Enum(..) |
-            Def::TyAlias(..) |
-            Def::Trait(_) => {
-                self.dumper.type_ref(TypeRefData {
-                    span: sub_span.expect("No span found for type ref"),
-                    ref_id: Some(def_id),
-                    scope: scope,
-                    qualname: String::new()
-                }.lower(self.tcx));
+            HirDef::Struct(..) |
+            HirDef::Variant(..) |
+            HirDef::Union(..) |
+            HirDef::Enum(..) |
+            HirDef::TyAlias(..) |
+            HirDef::Trait(_) => {
+                let span = self.span_from_span(sub_span.expect("No span found for type ref"));
+                self.dumper.dump_ref(Ref {
+                    kind: RefKind::Type,
+                    span,
+                    ref_id: ::id_from_def_id(def_id),
+                });
             }
-            Def::Static(..) |
-            Def::Const(..) |
-            Def::StructCtor(..) |
-            Def::VariantCtor(..) => {
-                self.dumper.variable_ref(VariableRefData {
-                    span: sub_span.expect("No span found for var ref"),
-                    ref_id: def_id,
-                    scope: scope,
-                    name: String::new()
-                }.lower(self.tcx));
+            HirDef::Static(..) |
+            HirDef::Const(..) |
+            HirDef::StructCtor(..) |
+            HirDef::VariantCtor(..) => {
+                let span = self.span_from_span(sub_span.expect("No span found for var ref"));
+                self.dumper.dump_ref(Ref {
+                    kind: RefKind::Variable,
+                    span,
+                    ref_id: ::id_from_def_id(def_id),
+                });
             }
-            Def::Fn(..) => {
-                self.dumper.function_ref(FunctionRefData {
-                    span: sub_span.expect("No span found for fn ref"),
-                    ref_id: def_id,
-                    scope: scope
-                }.lower(self.tcx));
+            HirDef::Fn(..) => {
+                let span = self.span_from_span(sub_span.expect("No span found for fn ref"));
+                self.dumper.dump_ref(Ref {
+                    kind: RefKind::Function,
+                    span,
+                    ref_id: ::id_from_def_id(def_id),
+                });
             }
             // With macros 2.0, we can legitimately get a ref to a macro, but
             // we don't handle it properly for now (FIXME).
-            Def::Macro(..) => {}
-            Def::Local(..) |
-            Def::Upvar(..) |
-            Def::SelfTy(..) |
-            Def::Label(_) |
-            Def::TyParam(..) |
-            Def::Method(..) |
-            Def::AssociatedTy(..) |
-            Def::AssociatedConst(..) |
-            Def::PrimTy(_) |
-            Def::GlobalAsm(_) |
-            Def::Err => {
+            HirDef::Macro(..) => {}
+            HirDef::Local(..) |
+            HirDef::Upvar(..) |
+            HirDef::SelfTy(..) |
+            HirDef::Label(_) |
+            HirDef::TyParam(..) |
+            HirDef::Method(..) |
+            HirDef::AssociatedTy(..) |
+            HirDef::AssociatedConst(..) |
+            HirDef::PrimTy(_) |
+            HirDef::GlobalAsm(_) |
+            HirDef::Err => {
                span_bug!(span,
                          "process_def_kind for unexpected item: {:?}",
                          def);
@@ -368,21 +349,23 @@ fn process_formals(&mut self, formals: &'l [ast::Arg], qualname: &str) {
                 // variable name, but who knows?)
                 let sub_span = span_utils.span_for_last_ident(p.span);
                 if !self.span.filter_generated(sub_span, p.span) {
-                    self.dumper.variable(VariableData {
-                        id: id,
-                        kind: VariableKind::Local,
-                        span: sub_span.expect("No span found for variable"),
+                    let id = ::id_from_node_id(id, &self.save_ctxt);
+                    let span = self.span_from_span(sub_span.expect("No span found for variable"));
+
+                    self.dumper.dump_def(false, Def {
+                        kind: DefKind::Local,
+                        id,
+                        span,
                         name: path_to_string(p),
                         qualname: format!("{}::{}", qualname, path_to_string(p)),
-                        type_value: typ,
-                        value: String::new(),
-                        scope: CRATE_NODE_ID,
+                        value: typ,
                         parent: None,
-                        visibility: Visibility::Inherited,
+                        children: vec![],
+                        decl_id: None,
                         docs: String::new(),
                         sig: None,
-                        attributes: vec![],
-                    }.lower(self.tcx));
+                        attributes:vec![],
+                    });
                 }
             }
         }
@@ -393,12 +376,11 @@ fn process_method(&mut self,
                       body: Option<&'l ast::Block>,
                       id: ast::NodeId,
                       name: ast::Ident,
-                      vis: Visibility,
-                      attrs: &'l [Attribute],
+                      vis: ast::Visibility,
                       span: Span) {
         debug!("process_method: {}:{}", id, name);
 
-        if let Some(method_data) = self.save_ctxt.get_method_data(id, name.name, span) {
+        if let Some(mut method_data) = self.save_ctxt.get_method_data(id, name.name, span) {
 
             let sig_str = ::make_signature(&sig.decl, &sig.generics);
             if body.is_some() {
@@ -407,61 +389,11 @@ fn process_method(&mut self,
                 });
             }
 
-            // If the method is defined in an impl, then try and find the corresponding
-            // method decl in a trait, and if there is one, make a decl_id for it. This
-            // requires looking up the impl, then the trait, then searching for a method
-            // with the right name.
-            if !self.span.filter_generated(Some(method_data.span), span) {
-                let container =
-                    self.tcx.associated_item(self.tcx.hir.local_def_id(id)).container;
-                let mut trait_id;
-                let mut decl_id = None;
-                match container {
-                    AssociatedItemContainer::ImplContainer(id) => {
-                        trait_id = self.tcx.trait_id_of_impl(id);
-
-                        match trait_id {
-                            Some(id) => {
-                                for item in self.tcx.associated_items(id) {
-                                    if item.kind == ty::AssociatedKind::Method {
-                                        if item.name == name.name {
-                                            decl_id = Some(item.def_id);
-                                            break;
-                                        }
-                                    }
-                                }
-                            }
-                            None => {
-                                if let Some(NodeItem(item)) = self.tcx.hir.get_if_local(id) {
-                                    if let hir::ItemImpl(_, _, _, _, _, ref ty, _) = item.node {
-                                        trait_id = self.lookup_def_id(ty.id);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    AssociatedItemContainer::TraitContainer(id) => {
-                        trait_id = Some(id);
-                    }
-                }
-
-                self.dumper.method(MethodData {
-                    id: method_data.id,
-                    name: method_data.name,
-                    span: method_data.span,
-                    scope: method_data.scope,
-                    qualname: method_data.qualname.clone(),
-                    value: sig_str,
-                    decl_id: decl_id,
-                    parent: trait_id,
-                    visibility: vis,
-                    docs: docs_for_attrs(attrs),
-                    sig: sig::method_signature(id, name, sig, &self.save_ctxt),
-                    attributes: attrs.to_vec(),
-                }.lower(self.tcx));
-            }
-
             self.process_generic_params(&sig.generics, span, &method_data.qualname, id);
+
+            method_data.value = sig_str;
+            method_data.sig = sig::method_signature(id, name, sig, &self.save_ctxt);
+            self.dumper.dump_def(vis == ast::Visibility::Public, method_data);
         }
 
         // walk arg and return types
@@ -480,22 +412,17 @@ fn process_method(&mut self,
     }
 
     fn process_trait_ref(&mut self, trait_ref: &'l ast::TraitRef) {
-        let trait_ref_data = self.save_ctxt.get_trait_ref_data(trait_ref, self.cur_scope);
+        let trait_ref_data = self.save_ctxt.get_trait_ref_data(trait_ref);
         if let Some(trait_ref_data) = trait_ref_data {
-            if !self.span.filter_generated(Some(trait_ref_data.span), trait_ref.path.span) {
-                self.dumper.type_ref(trait_ref_data.lower(self.tcx));
-            }
+            self.dumper.dump_ref(trait_ref_data);
         }
-        self.process_path(trait_ref.ref_id, &trait_ref.path, Some(recorder::TypeRef));
+        self.process_path(trait_ref.ref_id, &trait_ref.path);
     }
 
     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(mut field_data) = field_data {
-            if !self.span.filter_generated(Some(field_data.span), field.span) {
-                field_data.value = String::new();
-                self.dumper.variable(field_data.lower(self.tcx));
-            }
+        if let Some(field_data) = field_data {
+            self.dumper.dump_def(field.vis == ast::Visibility::Public, field_data);
         }
     }
 
@@ -519,18 +446,23 @@ fn process_generic_params(&mut self,
                                    name,
                                    id);
             if !self.span.filter_generated(Some(param_ss), full_span) {
-                self.dumper.typedef(TypeDefData {
-                    span: param_ss,
-                    name: name,
-                    id: param.id,
-                    qualname: qualname,
+                let id = ::id_from_node_id(param.id, &self.save_ctxt);
+                let span = self.span_from_span(param_ss);
+
+                self.dumper.dump_def(false, Def {
+                    kind: DefKind::Type,
+                    id,
+                    span,
+                    name,
+                    qualname,
                     value: String::new(),
-                    visibility: Visibility::Inherited,
                     parent: None,
+                    children: vec![],
+                    decl_id: None,
                     docs: String::new(),
                     sig: None,
                     attributes: vec![],
-                }.lower(self.tcx));
+                });
             }
         }
         self.visit_generics(generics);
@@ -542,13 +474,10 @@ fn process_fn(&mut self,
                   ty_params: &'l ast::Generics,
                   body: &'l ast::Block) {
         if let Some(fn_data) = self.save_ctxt.get_item_data(item) {
-            down_cast_data!(fn_data, FunctionData, item.span);
-            if !self.span.filter_generated(Some(fn_data.span), item.span) {
-                self.dumper.function(fn_data.clone().lower(self.tcx));
-            }
-
+            down_cast_data!(fn_data, DefData, item.span);
             self.nest_tables(item.id, |v| v.process_formals(&decl.inputs, &fn_data.qualname));
             self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id);
+            self.dumper.dump_def(item.vis == ast::Visibility::Public, fn_data);
         }
 
         for arg in &decl.inputs {
@@ -567,10 +496,8 @@ fn process_static_or_const_item(&mut self,
                                     typ: &'l ast::Ty,
                                     expr: &'l ast::Expr) {
         if let Some(var_data) = self.save_ctxt.get_item_data(item) {
-            down_cast_data!(var_data, VariableData, item.span);
-            if !self.span.filter_generated(Some(var_data.span), item.span) {
-                self.dumper.variable(var_data.lower(self.tcx));
-            }
+            down_cast_data!(var_data, DefData, item.span);
+            self.dumper.dump_def(item.vis == ast::Visibility::Public, var_data);
         }
         self.visit_ty(&typ);
         self.visit_expr(expr);
@@ -583,29 +510,31 @@ fn process_assoc_const(&mut self,
                            typ: &'l ast::Ty,
                            expr: Option<&'l ast::Expr>,
                            parent_id: DefId,
-                           vis: Visibility,
+                           vis: ast::Visibility,
                            attrs: &'l [Attribute]) {
         let qualname = format!("::{}", self.tcx.node_path_str(id));
 
         let sub_span = self.span.sub_span_after_keyword(span, keywords::Const);
-        let value = expr.map(|e| self.span.snippet(e.span)).unwrap_or(String::new());
 
         if !self.span.filter_generated(sub_span, span) {
-            self.dumper.variable(VariableData {
-                span: sub_span.expect("No span found for variable"),
-                kind: VariableKind::Const,
-                id: id,
+            let sig = sig::assoc_const_signature(id, name, typ, expr, &self.save_ctxt);
+            let id = ::id_from_node_id(id, &self.save_ctxt);
+            let span = self.span_from_span(sub_span.expect("No span found for variable"));
+
+            self.dumper.dump_def(vis == ast::Visibility::Public, Def {
+                kind: DefKind::Const,
+                id,
+                span,
                 name: name.to_string(),
-                qualname: qualname,
-                value: value,
-                type_value: ty_to_string(&typ),
-                scope: self.cur_scope,
-                parent: Some(parent_id),
-                visibility: vis,
+                qualname,
+                value: ty_to_string(&typ),
+                parent: Some(::id_from_def_id(parent_id)),
+                children: vec![],
+                decl_id: None,
                 docs: docs_for_attrs(attrs),
-                sig: sig::assoc_const_signature(id, name, typ, expr, &self.save_ctxt),
-                attributes: attrs.to_vec(),
-            }.lower(self.tcx));
+                sig,
+                attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
+            });
         }
 
         // walk type and init value
@@ -624,7 +553,7 @@ fn process_struct(&mut self,
         let qualname = format!("::{}", self.tcx.node_path_str(item.id));
 
         let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct);
-        let (val, fields) =
+        let (value, fields) =
             if let ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) = item.node
         {
             let fields_str = fields.iter()
@@ -633,26 +562,28 @@ fn process_struct(&mut self,
                                                   .unwrap_or(i.to_string()))
                                    .collect::<Vec<_>>()
                                    .join(", ");
-            (format!("{} {{ {} }}", name, fields_str), fields.iter().map(|f| f.id).collect())
+            (format!("{} {{ {} }}", name, fields_str),
+             fields.iter().map(|f| ::id_from_node_id(f.id, &self.save_ctxt)).collect())
         } else {
             (String::new(), vec![])
         };
 
         if !self.span.filter_generated(sub_span, item.span) {
-            self.dumper.struct_data(StructData {
-                span: sub_span.expect("No span found for struct"),
-                id: item.id,
-                name: name,
-                ctor_id: def.id(),
+            let span = self.span_from_span(sub_span.expect("No span found for struct"));
+            self.dumper.dump_def(item.vis == ast::Visibility::Public, Def {
+                kind: DefKind::Struct,
+                id: ::id_from_node_id(item.id, &self.save_ctxt),
+                span,
+                name,
                 qualname: qualname.clone(),
-                scope: self.cur_scope,
-                value: val,
-                fields: fields,
-                visibility: From::from(&item.vis),
+                value,
+                parent: None,
+                children: fields,
+                decl_id: None,
                 docs: docs_for_attrs(&item.attrs),
                 sig: sig::item_signature(item, &self.save_ctxt),
-                attributes: item.attrs.clone(),
-            }.lower(self.tcx));
+                attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
+            });
         }
 
         for field in def.fields() {
@@ -672,10 +603,7 @@ fn process_enum(&mut self,
             None => return,
             Some(data) => data,
         };
-        down_cast_data!(enum_data, EnumData, item.span);
-        if !self.span.filter_generated(Some(enum_data.span), item.span) {
-            self.dumper.enum_data(enum_data.clone().lower(self.tcx));
-        }
+        down_cast_data!(enum_data, DefData, item.span);
 
         for variant in &enum_definition.variants {
             let name = variant.node.name.name.to_string();
@@ -692,48 +620,62 @@ fn process_enum(&mut self,
                                                           .unwrap_or(i.to_string()))
                                            .collect::<Vec<_>>()
                                            .join(", ");
-                    let val = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
+                    let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
                     if !self.span.filter_generated(sub_span, variant.span) {
-                        self.dumper.struct_variant(StructVariantData {
-                            span: sub_span.expect("No span found for struct variant"),
-                            id: variant.node.data.id(),
-                            name: name,
-                            qualname: qualname,
-                            type_value: enum_data.qualname.clone(),
-                            value: val,
-                            scope: enum_data.scope,
-                            parent: Some(make_def_id(item.id, &self.tcx.hir)),
+                        let span = self.span_from_span(
+                            sub_span.expect("No span found for struct variant"));
+                        let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt);
+                        let parent = Some(::id_from_node_id(item.id, &self.save_ctxt));
+
+                        self.dumper.dump_def(item.vis == ast::Visibility::Public, Def {
+                            kind: DefKind::Struct,
+                            id,
+                            span,
+                            name,
+                            qualname,
+                            value,
+                            parent,
+                            children: vec![],
+                            decl_id: None,
                             docs: docs_for_attrs(&variant.node.attrs),
                             sig: sig::variant_signature(variant, &self.save_ctxt),
-                            attributes: variant.node.attrs.clone(),
-                        }.lower(self.tcx));
+                            attributes: lower_attributes(variant.node.attrs.clone(),
+                                                         &self.save_ctxt),
+                        });
                     }
                 }
                 ref v => {
                     let sub_span = self.span.span_for_first_ident(variant.span);
-                    let mut val = format!("{}::{}", enum_data.name, name);
+                    let mut value = format!("{}::{}", enum_data.name, name);
                     if let &ast::VariantData::Tuple(ref fields, _) = v {
-                        val.push('(');
-                        val.push_str(&fields.iter()
-                                            .map(|f| ty_to_string(&f.ty))
-                                            .collect::<Vec<_>>()
-                                            .join(", "));
-                        val.push(')');
+                        value.push('(');
+                        value.push_str(&fields.iter()
+                                              .map(|f| ty_to_string(&f.ty))
+                                              .collect::<Vec<_>>()
+                                              .join(", "));
+                        value.push(')');
                     }
                     if !self.span.filter_generated(sub_span, variant.span) {
-                        self.dumper.tuple_variant(TupleVariantData {
-                            span: sub_span.expect("No span found for tuple variant"),
-                            id: variant.node.data.id(),
-                            name: name,
-                            qualname: qualname,
-                            type_value: enum_data.qualname.clone(),
-                            value: val,
-                            scope: enum_data.scope,
-                            parent: Some(make_def_id(item.id, &self.tcx.hir)),
+                        let span =
+                            self.span_from_span(sub_span.expect("No span found for tuple variant"));
+                        let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt);
+                        let parent = Some(::id_from_node_id(item.id, &self.save_ctxt));
+
+                        self.dumper.dump_def(item.vis == ast::Visibility::Public, Def {
+                            kind: DefKind::Tuple,
+                            id,
+                            span,
+                            name,
+                            qualname,
+                            value,
+                            parent,
+                            children: vec![],
+                            decl_id: None,
                             docs: docs_for_attrs(&variant.node.attrs),
                             sig: sig::variant_signature(variant, &self.save_ctxt),
-                            attributes: variant.node.attrs.clone(),
-                        }.lower(self.tcx));
+                            attributes: lower_attributes(variant.node.attrs.clone(),
+                                                         &self.save_ctxt),
+                        });
                     }
                 }
             }
@@ -744,7 +686,8 @@ fn process_enum(&mut self,
                 self.visit_ty(&field.ty);
             }
         }
-        self.process_generic_params(ty_params, item.span, &enum_data.qualname, enum_data.id);
+        self.process_generic_params(ty_params, item.span, &enum_data.qualname, item.id);
+        self.dumper.dump_def(item.vis == ast::Visibility::Public, enum_data);
     }
 
     fn process_impl(&mut self,
@@ -754,25 +697,17 @@ fn process_impl(&mut self,
                     typ: &'l ast::Ty,
                     impl_items: &'l [ast::ImplItem]) {
         if let Some(impl_data) = self.save_ctxt.get_item_data(item) {
-            down_cast_data!(impl_data, ImplData, item.span);
-            if !self.span.filter_generated(Some(impl_data.span), item.span) {
-                self.dumper.impl_data(ImplData {
-                    id: impl_data.id,
-                    span: impl_data.span,
-                    scope: impl_data.scope,
-                    trait_ref: impl_data.trait_ref.map(|d| d.ref_id.unwrap()),
-                    self_ref: impl_data.self_ref.map(|d| d.ref_id.unwrap())
-                }.lower(self.tcx));
-            }
+            down_cast_data!(impl_data, RelationData, item.span);
+            self.dumper.dump_relation(impl_data);
         }
         self.visit_ty(&typ);
         if let &Some(ref trait_ref) = trait_ref {
-            self.process_path(trait_ref.ref_id, &trait_ref.path, Some(recorder::TypeRef));
+            self.process_path(trait_ref.ref_id, &trait_ref.path);
         }
         self.process_generic_params(type_parameters, item.span, "", item.id);
         for impl_item in impl_items {
             let map = &self.tcx.hir;
-            self.process_impl_item(impl_item, make_def_id(item.id, map));
+            self.process_impl_item(impl_item, map.local_def_id(item.id));
         }
     }
 
@@ -793,19 +728,24 @@ fn process_trait(&mut self,
         }
         let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait);
         if !self.span.filter_generated(sub_span, item.span) {
-            self.dumper.trait_data(TraitData {
-                span: sub_span.expect("No span found for trait"),
-                id: item.id,
-                name: name,
+            let id = ::id_from_node_id(item.id, &self.save_ctxt);
+            let span = self.span_from_span(sub_span.expect("No span found for trait"));
+            let children =
+                methods.iter().map(|i| ::id_from_node_id(i.id, &self.save_ctxt)).collect();
+            self.dumper.dump_def(item.vis == ast::Visibility::Public, Def {
+                kind: DefKind::Trait,
+                id,
+                span,
+                name,
                 qualname: qualname.clone(),
-                scope: self.cur_scope,
                 value: val,
-                items: methods.iter().map(|i| i.id).collect(),
-                visibility: From::from(&item.vis),
+                parent: None,
+                children,
+                decl_id: None,
                 docs: docs_for_attrs(&item.attrs),
                 sig: sig::item_signature(item, &self.save_ctxt),
-                attributes: item.attrs.clone(),
-            }.lower(self.tcx));
+                attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
+            });
         }
 
         // super-traits
@@ -823,21 +763,22 @@ fn process_trait(&mut self,
             if let Some(id) = self.lookup_def_id(trait_ref.ref_id) {
                 let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span);
                 if !self.span.filter_generated(sub_span, trait_ref.path.span) {
-                    self.dumper.type_ref(TypeRefData {
-                        span: sub_span.expect("No span found for trait ref"),
-                        ref_id: Some(id),
-                        scope: self.cur_scope,
-                        qualname: String::new()
-                    }.lower(self.tcx));
+                    let span = self.span_from_span(sub_span.expect("No span found for trait ref"));
+                    self.dumper.dump_ref(Ref {
+                        kind: RefKind::Type,
+                        span,
+                        ref_id: ::id_from_def_id(id),
+                    });
                 }
 
                 if !self.span.filter_generated(sub_span, trait_ref.path.span) {
-                    let sub_span = sub_span.expect("No span for inheritance");
-                    self.dumper.inheritance(InheritanceData {
+                    let sub_span = self.span_from_span(sub_span.expect("No span for inheritance"));
+                    self.dumper.dump_relation(Relation {
+                        kind: RelationKind::SuperTrait,
                         span: sub_span,
-                        base_id: id,
-                        deriv_id: item.id
-                    }.lower(self.tcx));
+                        from: ::id_from_def_id(id),
+                        to: ::id_from_node_id(item.id, &self.save_ctxt),
+                    });
                 }
             }
         }
@@ -846,21 +787,19 @@ fn process_trait(&mut self,
         self.process_generic_params(generics, item.span, &qualname, item.id);
         for method in methods {
             let map = &self.tcx.hir;
-            self.process_trait_item(method, make_def_id(item.id, map))
+            self.process_trait_item(method, map.local_def_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, ModData, item.span);
-            if !self.span.filter_generated(Some(mod_data.span), item.span) {
-                self.dumper.mod_data(mod_data.lower(self.tcx));
-            }
+            down_cast_data!(mod_data, DefData, item.span);
+            self.dumper.dump_def(item.vis == ast::Visibility::Public, mod_data);
         }
     }
 
-    fn process_path(&mut self, id: NodeId, path: &ast::Path, ref_kind: Option<recorder::Row>) {
+    fn process_path(&mut self, id: NodeId, path: &ast::Path) {
         let path_data = self.save_ctxt.get_path_data(id, path);
         if generated_code(path.span) && path_data.is_none() {
             return;
@@ -873,81 +812,29 @@ fn process_path(&mut self, id: NodeId, path: &ast::Path, ref_kind: Option<record
             }
         };
 
-        match path_data {
-            Data::VariableRefData(vrd) => {
-                // FIXME: this whole block duplicates the code in process_def_kind
-                if !self.span.filter_generated(Some(vrd.span), path.span) {
-                    match ref_kind {
-                        Some(recorder::TypeRef) => {
-                            self.dumper.type_ref(TypeRefData {
-                                span: vrd.span,
-                                ref_id: Some(vrd.ref_id),
-                                scope: vrd.scope,
-                                qualname: String::new()
-                            }.lower(self.tcx));
-                        }
-                        Some(recorder::FnRef) => {
-                            self.dumper.function_ref(FunctionRefData {
-                                span: vrd.span,
-                                ref_id: vrd.ref_id,
-                                scope: vrd.scope
-                            }.lower(self.tcx));
-                        }
-                        Some(recorder::ModRef) => {
-                            self.dumper.mod_ref( ModRefData {
-                                span: vrd.span,
-                                ref_id: Some(vrd.ref_id),
-                                scope: vrd.scope,
-                                qualname: String::new()
-                            }.lower(self.tcx));
-                        }
-                        Some(recorder::VarRef) | None
-                            => self.dumper.variable_ref(vrd.lower(self.tcx))
-                    }
-                }
-
-            }
-            Data::TypeRefData(trd) => {
-                if !self.span.filter_generated(Some(trd.span), path.span) {
-                    self.dumper.type_ref(trd.lower(self.tcx));
-                }
-            }
-            Data::MethodCallData(mcd) => {
-                if !self.span.filter_generated(Some(mcd.span), path.span) {
-                    self.dumper.method_call(mcd.lower(self.tcx));
-                }
-            }
-            Data::FunctionCallData(fcd) => {
-                if !self.span.filter_generated(Some(fcd.span), path.span) {
-                    self.dumper.function_call(fcd.lower(self.tcx));
-                }
-            }
-            _ => {
-               span_bug!(path.span, "Unexpected data: {:?}", path_data);
-            }
-        }
+        self.dumper.dump_ref(path_data);
 
         // Modules or types in the path prefix.
         match self.save_ctxt.get_path_def(id) {
-            Def::Method(did) => {
+            HirDef::Method(did) => {
                 let ti = self.tcx.associated_item(did);
                 if ti.kind == ty::AssociatedKind::Method && ti.method_has_self_argument {
                     self.write_sub_path_trait_truncated(path);
                 }
             }
-            Def::Fn(..) |
-            Def::Const(..) |
-            Def::Static(..) |
-            Def::StructCtor(..) |
-            Def::VariantCtor(..) |
-            Def::AssociatedConst(..) |
-            Def::Local(..) |
-            Def::Upvar(..) |
-            Def::Struct(..) |
-            Def::Union(..) |
-            Def::Variant(..) |
-            Def::TyAlias(..) |
-            Def::AssociatedTy(..) => self.write_sub_paths_truncated(path),
+            HirDef::Fn(..) |
+            HirDef::Const(..) |
+            HirDef::Static(..) |
+            HirDef::StructCtor(..) |
+            HirDef::VariantCtor(..) |
+            HirDef::AssociatedConst(..) |
+            HirDef::Local(..) |
+            HirDef::Upvar(..) |
+            HirDef::Struct(..) |
+            HirDef::Union(..) |
+            HirDef::Variant(..) |
+            HirDef::TyAlias(..) |
+            HirDef::AssociatedTy(..) => self.write_sub_paths_truncated(path),
             _ => {}
         }
     }
@@ -961,20 +848,15 @@ fn process_struct_lit(&mut self,
         self.write_sub_paths_truncated(path);
 
         if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) {
-            down_cast_data!(struct_lit_data, TypeRefData, ex.span);
-            if !self.span.filter_generated(Some(struct_lit_data.span), ex.span) {
-                self.dumper.type_ref(struct_lit_data.lower(self.tcx));
+            down_cast_data!(struct_lit_data, RefData, ex.span);
+            if !generated_code(ex.span) {
+                self.dumper.dump_ref(struct_lit_data);
             }
 
-            let scope = self.save_ctxt.enclosing_scope(ex.id);
-
             for field in fields {
                 if let Some(field_data) = self.save_ctxt
-                                              .get_field_ref_data(field, variant, scope) {
-
-                    if !self.span.filter_generated(Some(field_data.span), field.ident.span) {
-                        self.dumper.variable_ref(field_data.lower(self.tcx));
-                    }
+                                              .get_field_ref_data(field, variant) {
+                    self.dumper.dump_ref(field_data);
                 }
 
                 self.visit_expr(&field.expr)
@@ -986,9 +868,9 @@ fn process_struct_lit(&mut self,
 
     fn process_method_call(&mut self, ex: &'l ast::Expr, args: &'l [P<ast::Expr>]) {
         if let Some(mcd) = self.save_ctxt.get_expr_data(ex) {
-            down_cast_data!(mcd, MethodCallData, ex.span);
-            if !self.span.filter_generated(Some(mcd.span), ex.span) {
-                self.dumper.method_call(mcd.lower(self.tcx));
+            down_cast_data!(mcd, RefData, ex.span);
+            if !generated_code(ex.span) {
+                self.dumper.dump_ref(mcd);
             }
         }
 
@@ -1013,12 +895,13 @@ fn process_pat(&mut self, p: &'l ast::Pat) {
                     let sub_span = self.span.span_for_first_ident(span);
                     if let Some(f) = variant.find_field_named(field.ident.name) {
                         if !self.span.filter_generated(sub_span, span) {
-                            self.dumper.variable_ref(VariableRefData {
-                                span: sub_span.expect("No span fund for var ref"),
-                                ref_id: f.did,
-                                scope: self.cur_scope,
-                                name: String::new()
-                            }.lower(self.tcx));
+                            let span =
+                                self.span_from_span(sub_span.expect("No span fund for var ref"));
+                            self.dumper.dump_ref(Ref {
+                                kind: RefKind::Variable,
+                                span,
+                                ref_id: ::id_from_def_id(f.did),
+                            });
                         }
                     }
                     self.visit_pat(&field.pat);
@@ -1036,7 +919,7 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
         collector.visit_pat(&p);
         self.visit_pat(&p);
 
-        for &(id, ref p, immut, _) in &collector.collected_paths {
+        for &(id, ref p, immut) in &collector.collected_paths {
             let mut value = match immut {
                 ast::Mutability::Immutable => value.to_string(),
                 _ => String::new(),
@@ -1058,21 +941,24 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
             let sub_span = self.span.span_for_last_ident(p.span);
             // Rust uses the id of the pattern for var lookups, so we'll use it too.
             if !self.span.filter_generated(sub_span, p.span) {
-                self.dumper.variable(VariableData {
-                    span: sub_span.expect("No span found for variable"),
-                    kind: VariableKind::Local,
-                    id: id,
+                let qualname = format!("{}${}", path_to_string(p), id);
+                let id = ::id_from_node_id(id, &self.save_ctxt);
+                let span = self.span_from_span(sub_span.expect("No span found for variable"));
+
+                self.dumper.dump_def(false, Def {
+                    kind: DefKind::Local,
+                    id,
+                    span,
                     name: path_to_string(p),
-                    qualname: format!("{}${}", path_to_string(p), id),
-                    value: value,
-                    type_value: typ,
-                    scope: CRATE_NODE_ID,
+                    qualname,
+                    value: typ,
                     parent: None,
-                    visibility: Visibility::Inherited,
+                    children: vec![],
+                    decl_id: None,
                     docs: String::new(),
                     sig: None,
-                    attributes: vec![],
-                }.lower(self.tcx));
+                    attributes:vec![],
+                });
             }
         }
     }
@@ -1084,46 +970,36 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
     /// 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, id: NodeId) {
-        let data = match self.save_ctxt.get_macro_use_data(span, id) {
+    fn process_macro_use(&mut self, span: Span) {
+        let data = match self.save_ctxt.get_macro_use_data(span) {
             None => return,
             Some(data) => data,
         };
-        let mut hasher = DefaultHasher::new();
-        data.callee_span.hash(&mut hasher);
-        let hash = hasher.finish();
-        let qualname = format!("{}::{}", data.name, hash);
+
+        // 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));
-            }
-        }
-        if !self.mac_uses.contains(&data.span) {
-            self.mac_uses.insert(data.span);
-            if let Some(sub_span) = self.span.span_for_macro_use_name(data.span) {
-                self.dumper.macro_use(MacroUseData {
-                    span: sub_span,
-                    name: data.name,
-                    qualname: qualname,
-                    scope: data.scope,
-                    callee_span: data.callee_span,
-                    imported: data.imported,
-                }.lower(self.tcx));
-            }
-        }
+        // 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));
+        //     }
+        // }
+        self.dumper.macro_use(data);
     }
 
     fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId) {
-        self.process_macro_use(trait_item.span, trait_item.id);
+        self.process_macro_use(trait_item.span);
         match trait_item.node {
             ast::TraitItemKind::Const(ref ty, ref expr) => {
                 self.process_assoc_const(trait_item.id,
@@ -1132,7 +1008,7 @@ fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId
                                          &ty,
                                          expr.as_ref().map(|e| &**e),
                                          trait_id,
-                                         Visibility::Public,
+                                         ast::Visibility::Public,
                                          &trait_item.attrs);
             }
             ast::TraitItemKind::Method(ref sig, ref body) => {
@@ -1140,8 +1016,7 @@ fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId
                                     body.as_ref().map(|x| &**x),
                                     trait_item.id,
                                     trait_item.ident,
-                                    Visibility::Public,
-                                    &trait_item.attrs,
+                                    ast::Visibility::Public,
                                     trait_item.span);
             }
             ast::TraitItemKind::Type(ref bounds, ref default_ty) => {
@@ -1151,22 +1026,27 @@ fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId
                 let sub_span = self.span.sub_span_after_keyword(trait_item.span, keywords::Type);
 
                 if !self.span.filter_generated(sub_span, trait_item.span) {
-                    self.dumper.typedef(TypeDefData {
-                        span: sub_span.expect("No span found for assoc type"),
-                        name: name,
-                        id: trait_item.id,
-                        qualname: qualname,
+                    let span = self.span_from_span(sub_span.expect("No span found for assoc type"));
+                    let id = ::id_from_node_id(trait_item.id, &self.save_ctxt);
+
+                    self.dumper.dump_def(true, Def {
+                        kind: DefKind::Type,
+                        id,
+                        span,
+                        name,
+                        qualname,
                         value: self.span.snippet(trait_item.span),
-                        visibility: Visibility::Public,
-                        parent: Some(trait_id),
+                        parent: Some(::id_from_def_id(trait_id)),
+                        children: vec![],
+                        decl_id: None,
                         docs: 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: trait_item.attrs.clone(),
-                    }.lower(self.tcx));
+                        attributes: lower_attributes(trait_item.attrs.clone(), &self.save_ctxt),
+                    });
                 }
 
                 if let &Some(ref default_ty) = default_ty {
@@ -1178,7 +1058,7 @@ fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId
     }
 
     fn process_impl_item(&mut self, impl_item: &'l ast::ImplItem, impl_id: DefId) {
-        self.process_macro_use(impl_item.span, impl_item.id);
+        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,
@@ -1187,7 +1067,7 @@ fn process_impl_item(&mut self, impl_item: &'l ast::ImplItem, impl_id: DefId) {
                                          &ty,
                                          Some(expr),
                                          impl_id,
-                                         From::from(&impl_item.vis),
+                                         impl_item.vis.clone(),
                                          &impl_item.attrs);
             }
             ast::ImplItemKind::Method(ref sig, ref body) => {
@@ -1195,8 +1075,7 @@ fn process_impl_item(&mut self, impl_item: &'l ast::ImplItem, impl_id: DefId) {
                                     Some(body),
                                     impl_item.id,
                                     impl_item.ident,
-                                    From::from(&impl_item.vis),
-                                    &impl_item.attrs,
+                                    impl_item.vis.clone(),
                                     impl_item.span);
             }
             ast::ImplItemKind::Type(ref ty) => {
@@ -1220,25 +1099,30 @@ fn visit_mod(&mut self, m: &'l ast::Mod, span: Span, attrs: &[ast::Attribute], i
 
         let cm = self.tcx.sess.codemap();
         let filename = cm.span_to_filename(span);
-        self.dumper.mod_data(ModData {
-            id: id,
+        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(true, Def {
+            kind: DefKind::Mod,
+            id: data_id,
             name: String::new(),
-            qualname: qualname,
-            span: span,
-            scope: id,
-            filename: filename,
-            items: m.items.iter().map(|i| i.id).collect(),
-            visibility: Visibility::Public,
+            qualname,
+            span,
+            value: filename,
+            children,
+            parent: None,
+            decl_id: None,
             docs: docs_for_attrs(attrs),
             sig: None,
-            attributes: attrs.to_owned(),
-        }.lower(self.tcx));
+            attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
+        });
         self.nest_scope(id, |v| visit::walk_mod(v, m));
     }
 
     fn visit_item(&mut self, item: &'l ast::Item) {
         use syntax::ast::ItemKind::*;
-        self.process_macro_use(item.span, item.id);
+        self.process_macro_use(item.span);
         match item.node {
             Use(ref use_item) => {
                 match use_item.node {
@@ -1246,9 +1130,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                         let sub_span = self.span.span_for_last_ident(path.span);
                         let mod_id = match self.lookup_def_id(item.id) {
                             Some(def_id) => {
-                                let scope = self.cur_scope;
-                                self.process_def_kind(item.id, path.span, sub_span, def_id, scope);
-
+                                self.process_def_kind(item.id, path.span, sub_span, def_id);
                                 Some(def_id)
                             }
                             None => None,
@@ -1263,14 +1145,15 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                         };
 
                         if !self.span.filter_generated(sub_span, path.span) {
-                            self.dumper.use_data(UseData {
-                                span: sub_span.expect("No span found for use"),
-                                id: item.id,
-                                mod_id: mod_id,
+                            let span =
+                                self.span_from_span(sub_span.expect("No span found for use"));
+                            self.dumper.import(item.vis == ast::Visibility::Public, Import {
+                                kind: ImportKind::Use,
+                                ref_id: mod_id.map(|id| ::id_from_def_id(id)),
+                                span,
                                 name: ident.to_string(),
-                                scope: self.cur_scope,
-                                visibility: From::from(&item.vis),
-                            }.lower(self.tcx));
+                                value: String::new(),
+                            });
                         }
                         self.write_sub_paths_truncated(path);
                     }
@@ -1288,23 +1171,24 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                         let sub_span = self.span
                                            .sub_span_of_token(item.span, token::BinOp(token::Star));
                         if !self.span.filter_generated(sub_span, item.span) {
-                            self.dumper.use_glob(UseGlobData {
-                                span: sub_span.expect("No span found for use glob"),
-                                id: item.id,
-                                names: names,
-                                scope: self.cur_scope,
-                                visibility: From::from(&item.vis),
-                            }.lower(self.tcx));
+                            let span =
+                                self.span_from_span(sub_span.expect("No span found for use glob"));
+                            self.dumper.import(item.vis == ast::Visibility::Public, Import {
+                                kind: ImportKind::GlobUse,
+                                ref_id: None,
+                                span,
+                                name: "*".to_owned(),
+                                value: names.join(", "),
+                            });
                         }
                         self.write_sub_paths(path);
                     }
                     ast::ViewPathList(ref path, ref list) => {
                         for plid in list {
-                            let scope = self.cur_scope;
                             let id = plid.node.id;
                             if let Some(def_id) = self.lookup_def_id(id) {
                                 let span = plid.span;
-                                self.process_def_kind(id, span, Some(span), def_id, scope);
+                                self.process_def_kind(id, span, Some(span), def_id);
                             }
                         }
 
@@ -1312,26 +1196,19 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                     }
                 }
             }
-            ExternCrate(ref s) => {
-                let location = match *s {
-                    Some(s) => s.to_string(),
-                    None => item.ident.to_string(),
-                };
+            ExternCrate(_) => {
                 let alias_span = self.span.span_for_last_ident(item.span);
-                let cnum = match self.sess.cstore.extern_mod_stmt_cnum(item.id) {
-                    Some(cnum) => cnum,
-                    None => LOCAL_CRATE,
-                };
 
                 if !self.span.filter_generated(alias_span, item.span) {
-                    self.dumper.extern_crate(ExternCrateData {
-                        id: item.id,
+                    let span =
+                        self.span_from_span(alias_span.expect("No span found for extern crate"));
+                    self.dumper.import(false, Import {
+                        kind: ImportKind::ExternCrate,
+                        ref_id: None,
+                        span,
                         name: item.ident.to_string(),
-                        crate_num: cnum,
-                        location: location,
-                        span: alias_span.expect("No span found for extern crate"),
-                        scope: self.cur_scope,
-                    }.lower(self.tcx));
+                        value: String::new(),
+                    });
                 }
             }
             Fn(ref decl, .., ref ty_params, ref body) =>
@@ -1360,18 +1237,23 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                 let value = ty_to_string(&ty);
                 let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type);
                 if !self.span.filter_generated(sub_span, item.span) {
-                    self.dumper.typedef(TypeDefData {
-                        span: sub_span.expect("No span found for typedef"),
+                    let span = self.span_from_span(sub_span.expect("No span found for typedef"));
+                    let id = ::id_from_node_id(item.id, &self.save_ctxt);
+
+                    self.dumper.dump_def(item.vis == ast::Visibility::Public, Def {
+                        kind: DefKind::Type,
+                        id,
+                        span,
                         name: item.ident.to_string(),
-                        id: item.id,
                         qualname: qualname.clone(),
-                        value: value,
-                        visibility: From::from(&item.vis),
+                        value,
                         parent: None,
+                        children: vec![],
+                        decl_id: None,
                         docs: docs_for_attrs(&item.attrs),
                         sig: sig::item_signature(item, &self.save_ctxt),
-                        attributes: item.attrs.clone(),
-                    }.lower(self.tcx));
+                        attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
+                    });
                 }
 
                 self.visit_ty(&ty);
@@ -1396,7 +1278,7 @@ fn visit_generics(&mut self, generics: &'l ast::Generics) {
     }
 
     fn visit_ty(&mut self, t: &'l ast::Ty) {
-        self.process_macro_use(t.span, t.id);
+        self.process_macro_use(t.span);
         match t.node {
             ast::TyKind::Path(_, ref path) => {
                 if generated_code(t.span) {
@@ -1405,12 +1287,12 @@ fn visit_ty(&mut self, t: &'l ast::Ty) {
 
                 if let Some(id) = self.lookup_def_id(t.id) {
                     if let Some(sub_span) = self.span.sub_span_for_type_name(t.span) {
-                        self.dumper.type_ref(TypeRefData {
-                            span: sub_span,
-                            ref_id: Some(id),
-                            scope: self.cur_scope,
-                            qualname: String::new()
-                        }.lower(self.tcx));
+                        let span = self.span_from_span(sub_span);
+                        self.dumper.dump_ref(Ref {
+                            kind: RefKind::Type,
+                            span,
+                            ref_id: ::id_from_def_id(id),
+                        });
                     }
                 }
 
@@ -1427,7 +1309,7 @@ fn visit_ty(&mut self, t: &'l ast::Ty) {
 
     fn visit_expr(&mut self, ex: &'l ast::Expr) {
         debug!("visit_expr {:?}", ex.node);
-        self.process_macro_use(ex.span, ex.id);
+        self.process_macro_use(ex.span);
         match ex.node {
             ast::ExprKind::Struct(ref path, ref fields, ref base) => {
                 let hir_expr = self.save_ctxt.tcx.hir.expect_expr(ex.id);
@@ -1446,9 +1328,9 @@ fn visit_expr(&mut self, ex: &'l ast::Expr) {
                 self.visit_expr(&sub_ex);
 
                 if let Some(field_data) = self.save_ctxt.get_expr_data(ex) {
-                    down_cast_data!(field_data, VariableRefData, ex.span);
-                    if !self.span.filter_generated(Some(field_data.span), ex.span) {
-                        self.dumper.variable_ref(field_data.lower(self.tcx));
+                    down_cast_data!(field_data, RefData, ex.span);
+                    if !generated_code(ex.span) {
+                        self.dumper.dump_ref(field_data);
                     }
                 }
             }
@@ -1474,12 +1356,13 @@ fn visit_expr(&mut self, ex: &'l ast::Expr) {
                     ty::TyAdt(def, _) => {
                         let sub_span = self.span.sub_span_after_token(ex.span, token::Dot);
                         if !self.span.filter_generated(sub_span, ex.span) {
-                            self.dumper.variable_ref(VariableRefData {
-                                span: sub_span.expect("No span found for var ref"),
-                                ref_id: def.struct_variant().fields[idx.node].did,
-                                scope: self.cur_scope,
-                                name: String::new()
-                            }.lower(self.tcx));
+                            let span =
+                                self.span_from_span(sub_span.expect("No span found for var ref"));
+                            self.dumper.dump_ref(Ref {
+                                kind: RefKind::Variable,
+                                span: span,
+                                ref_id: ::id_from_def_id(def.struct_variant().fields[idx.node].did),
+                            });
                         }
                     }
                     ty::TyTuple(..) => {}
@@ -1540,7 +1423,7 @@ fn visit_mac(&mut self, mac: &'l ast::Mac) {
     }
 
     fn visit_pat(&mut self, p: &'l ast::Pat) {
-        self.process_macro_use(p.span, p.id);
+        self.process_macro_use(p.span);
         self.process_pat(p);
     }
 
@@ -1556,9 +1439,9 @@ fn visit_arm(&mut self, arm: &'l ast::Arm) {
         let mut paths_to_process = vec![];
 
         // process collected paths
-        for &(id, ref p, immut, ref_kind) in &collector.collected_paths {
+        for &(id, ref p, immut) in &collector.collected_paths {
             match self.save_ctxt.get_path_def(id) {
-                Def::Local(def_id) => {
+                HirDef::Local(def_id) => {
                     let id = self.tcx.hir.as_local_node_id(def_id).unwrap();
                     let mut value = if immut == ast::Mutability::Immutable {
                         self.span.snippet(p.span).to_string()
@@ -1573,53 +1456,56 @@ fn visit_arm(&mut self, arm: &'l ast::Arm) {
                     assert!(p.segments.len() == 1,
                             "qualified path for local variable def in arm");
                     if !self.span.filter_generated(Some(p.span), p.span) {
-                        self.dumper.variable(VariableData {
-                            span: p.span,
-                            kind: VariableKind::Local,
-                            id: id,
+                        let qualname = format!("{}${}", path_to_string(p), id);
+                        let id = ::id_from_node_id(id, &self.save_ctxt);
+                        let span = self.span_from_span(p.span);
+
+                        self.dumper.dump_def(false, Def {
+                            kind: DefKind::Local,
+                            id,
+                            span,
                             name: path_to_string(p),
-                            qualname: format!("{}${}", path_to_string(p), id),
-                            value: value,
-                            type_value: typ,
-                            scope: CRATE_NODE_ID,
+                            qualname,
+                            value: typ,
                             parent: None,
-                            visibility: Visibility::Inherited,
+                            children: vec![],
+                            decl_id: None,
                             docs: String::new(),
                             sig: None,
-                            attributes: vec![],
-                        }.lower(self.tcx));
+                            attributes:vec![],
+                        });
                     }
                 }
-                Def::StructCtor(..) | Def::VariantCtor(..) |
-                Def::Const(..) | Def::AssociatedConst(..) |
-                Def::Struct(..) | Def::Variant(..) |
-                Def::TyAlias(..) | Def::AssociatedTy(..) |
-                Def::SelfTy(..) => {
-                    paths_to_process.push((id, p.clone(), Some(ref_kind)))
+                HirDef::StructCtor(..) | HirDef::VariantCtor(..) |
+                HirDef::Const(..) | HirDef::AssociatedConst(..) |
+                HirDef::Struct(..) | HirDef::Variant(..) |
+                HirDef::TyAlias(..) | HirDef::AssociatedTy(..) |
+                HirDef::SelfTy(..) => {
+                    paths_to_process.push((id, p.clone()))
                 }
                 def => error!("unexpected definition kind when processing collected paths: {:?}",
                               def),
             }
         }
 
-        for &(id, ref path, ref_kind) in &paths_to_process {
-            self.process_path(id, path, ref_kind);
+        for &(id, ref path) in &paths_to_process {
+            self.process_path(id, path);
         }
         walk_list!(self, visit_expr, &arm.guard);
         self.visit_expr(&arm.body);
     }
 
     fn visit_path(&mut self, p: &'l ast::Path, id: NodeId) {
-        self.process_path(id, p, None);
+        self.process_path(id, p);
     }
 
     fn visit_stmt(&mut self, s: &'l ast::Stmt) {
-        self.process_macro_use(s.span, s.id);
+        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, l.id);
+        self.process_macro_use(l.span);
         let value = l.init.as_ref().map(|i| self.span.snippet(i.span)).unwrap_or(String::new());
         self.process_var_decl(&l.pat, value);
 
@@ -1632,14 +1518,12 @@ fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
         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, FunctionData, item.span);
-                    if !self.span.filter_generated(Some(fn_data.span), item.span) {
-                        self.dumper.function(fn_data.clone().lower(self.tcx));
-                    }
+                    down_cast_data!(fn_data, DefData, item.span);
 
                     self.nest_tables(item.id, |v| v.process_formals(&decl.inputs,
                                                                     &fn_data.qualname));
                     self.process_generic_params(generics, item.span, &fn_data.qualname, item.id);
+                    self.dumper.dump_def(item.vis == ast::Visibility::Public, fn_data);
                 }
 
                 for arg in &decl.inputs {
@@ -1652,10 +1536,8 @@ fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
             }
             ast::ForeignItemKind::Static(ref ty, _) => {
                 if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
-                    down_cast_data!(var_data, VariableData, item.span);
-                    if !self.span.filter_generated(Some(var_data.span), item.span) {
-                        self.dumper.variable(var_data.lower(self.tcx));
-                    }
+                    down_cast_data!(var_data, DefData, item.span);
+                    self.dumper.dump_def(item.vis == ast::Visibility::Public, var_data);
                 }
 
                 self.visit_ty(ty);
diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs
deleted file mode 100644 (file)
index 245a3bc..0000000
+++ /dev/null
@@ -1,748 +0,0 @@
-// Copyright 2016 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.
-
-use rustc::hir::def_id::{CrateNum, DefId, DefIndex};
-use rustc::hir::map::Map;
-use rustc::ty::TyCtxt;
-use syntax::ast::{self, NodeId};
-use syntax::codemap::CodeMap;
-use syntax::print::pprust;
-use syntax_pos::Span;
-
-use data::{self, Visibility};
-
-use rls_data::{SpanData, CratePreludeData, Attribute, Signature};
-use rls_span::{Column, Row};
-
-// FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet
-pub trait Lower {
-    type Target;
-    fn lower(self, tcx: TyCtxt) -> Self::Target;
-}
-
-pub fn make_def_id(id: NodeId, map: &Map) -> DefId {
-    map.opt_local_def_id(id).unwrap_or(null_def_id())
-}
-
-pub fn null_def_id() -> DefId {
-    DefId {
-        krate: CrateNum::from_u32(u32::max_value()),
-        index: DefIndex::from_u32(u32::max_value())
-    }
-}
-
-pub fn span_from_span(span: Span, cm: &CodeMap) -> SpanData {
-    let start = cm.lookup_char_pos(span.lo);
-    let end = cm.lookup_char_pos(span.hi);
-
-    SpanData {
-        file_name: start.file.name.clone().into(),
-        byte_start: span.lo.0,
-        byte_end: span.hi.0,
-        line_start: Row::new_one_indexed(start.line as u32),
-        line_end: Row::new_one_indexed(end.line as u32),
-        column_start: Column::new_one_indexed(start.col.0 as u32 + 1),
-        column_end: Column::new_one_indexed(end.col.0 as u32 + 1),
-    }
-}
-
-impl Lower for Vec<ast::Attribute> {
-    type Target = Vec<Attribute>;
-
-    fn lower(self, tcx: TyCtxt) -> Vec<Attribute> {
-        self.into_iter()
-        // Only retain real attributes. Doc comments are lowered separately.
-        .filter(|attr| attr.path != "doc")
-        .map(|mut attr| {
-            // Remove the surrounding '#[..]' or '#![..]' of the pretty printed
-            // attribute. First normalize all inner attribute (#![..]) to outer
-            // ones (#[..]), then remove the two leading and the one trailing character.
-            attr.style = ast::AttrStyle::Outer;
-            let value = pprust::attribute_to_string(&attr);
-            // This str slicing works correctly, because the leading and trailing characters
-            // are in the ASCII range and thus exactly one byte each.
-            let value = value[2..value.len()-1].to_string();
-
-            Attribute {
-                value: value,
-                span: span_from_span(attr.span, tcx.sess.codemap()),
-            }
-        }).collect()
-    }
-}
-
-impl Lower for data::CratePreludeData {
-    type Target = CratePreludeData;
-
-    fn lower(self, tcx: TyCtxt) -> CratePreludeData {
-        CratePreludeData {
-            crate_name: self.crate_name,
-            crate_root: self.crate_root,
-            external_crates: self.external_crates,
-            span: span_from_span(self.span, tcx.sess.codemap()),
-        }
-    }
-}
-
-/// Data for enum declarations.
-#[derive(Clone, Debug)]
-pub struct EnumData {
-    pub id: DefId,
-    pub value: String,
-    pub name: String,
-    pub qualname: String,
-    pub span: SpanData,
-    pub scope: DefId,
-    pub variants: Vec<DefId>,
-    pub visibility: Visibility,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-impl Lower for data::EnumData {
-    type Target = EnumData;
-
-    fn lower(self, tcx: TyCtxt) -> EnumData {
-        EnumData {
-            id: make_def_id(self.id, &tcx.hir),
-            name: self.name,
-            value: self.value,
-            qualname: self.qualname,
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            scope: make_def_id(self.scope, &tcx.hir),
-            variants: self.variants.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(),
-            visibility: self.visibility,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes.lower(tcx),
-        }
-    }
-}
-
-/// Data for extern crates.
-#[derive(Debug)]
-pub struct ExternCrateData {
-    pub id: DefId,
-    pub name: String,
-    pub crate_num: CrateNum,
-    pub location: String,
-    pub span: SpanData,
-    pub scope: DefId,
-}
-
-impl Lower for data::ExternCrateData {
-    type Target = ExternCrateData;
-
-    fn lower(self, tcx: TyCtxt) -> ExternCrateData {
-        ExternCrateData {
-            id: make_def_id(self.id, &tcx.hir),
-            name: self.name,
-            crate_num: self.crate_num,
-            location: self.location,
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            scope: make_def_id(self.scope, &tcx.hir),
-        }
-    }
-}
-
-/// Data about a function call.
-#[derive(Debug)]
-pub struct FunctionCallData {
-    pub span: SpanData,
-    pub scope: DefId,
-    pub ref_id: DefId,
-}
-
-impl Lower for data::FunctionCallData {
-    type Target = FunctionCallData;
-
-    fn lower(self, tcx: TyCtxt) -> FunctionCallData {
-        FunctionCallData {
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            scope: make_def_id(self.scope, &tcx.hir),
-            ref_id: self.ref_id,
-        }
-    }
-}
-
-/// Data for all kinds of functions and methods.
-#[derive(Clone, Debug)]
-pub struct FunctionData {
-    pub id: DefId,
-    pub name: String,
-    pub qualname: String,
-    pub declaration: Option<DefId>,
-    pub span: SpanData,
-    pub scope: DefId,
-    pub value: String,
-    pub visibility: Visibility,
-    pub parent: Option<DefId>,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-impl Lower for data::FunctionData {
-    type Target = FunctionData;
-
-    fn lower(self, tcx: TyCtxt) -> FunctionData {
-        FunctionData {
-            id: make_def_id(self.id, &tcx.hir),
-            name: self.name,
-            qualname: self.qualname,
-            declaration: self.declaration,
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            scope: make_def_id(self.scope, &tcx.hir),
-            value: self.value,
-            visibility: self.visibility,
-            parent: self.parent,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes.lower(tcx),
-        }
-    }
-}
-
-/// Data about a function call.
-#[derive(Debug)]
-pub struct FunctionRefData {
-    pub span: SpanData,
-    pub scope: DefId,
-    pub ref_id: DefId,
-}
-
-impl Lower for data::FunctionRefData {
-    type Target = FunctionRefData;
-
-    fn lower(self, tcx: TyCtxt) -> FunctionRefData {
-        FunctionRefData {
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            scope: make_def_id(self.scope, &tcx.hir),
-            ref_id: self.ref_id,
-        }
-    }
-}
-#[derive(Debug)]
-pub struct ImplData {
-    pub id: DefId,
-    pub span: SpanData,
-    pub scope: DefId,
-    pub trait_ref: Option<DefId>,
-    pub self_ref: Option<DefId>,
-}
-
-impl Lower for data::ImplData {
-    type Target = ImplData;
-
-    fn lower(self, tcx: TyCtxt) -> ImplData {
-        ImplData {
-            id: make_def_id(self.id, &tcx.hir),
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            scope: make_def_id(self.scope, &tcx.hir),
-            trait_ref: self.trait_ref,
-            self_ref: self.self_ref,
-        }
-    }
-}
-
-#[derive(Debug)]
-pub struct InheritanceData {
-    pub span: SpanData,
-    pub base_id: DefId,
-    pub deriv_id: DefId
-}
-
-impl Lower for data::InheritanceData {
-    type Target = InheritanceData;
-
-    fn lower(self, tcx: TyCtxt) -> InheritanceData {
-        InheritanceData {
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            base_id: self.base_id,
-            deriv_id: make_def_id(self.deriv_id, &tcx.hir)
-        }
-    }
-}
-
-/// Data about a macro declaration.
-#[derive(Debug)]
-pub struct MacroData {
-    pub span: SpanData,
-    pub name: String,
-    pub qualname: String,
-    pub docs: String,
-}
-
-impl Lower for data::MacroData {
-    type Target = MacroData;
-
-    fn lower(self, tcx: TyCtxt) -> MacroData {
-        MacroData {
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            name: self.name,
-            qualname: self.qualname,
-            docs: self.docs,
-        }
-    }
-}
-
-/// Data about a macro use.
-#[derive(Debug)]
-pub struct MacroUseData {
-    pub span: SpanData,
-    pub name: String,
-    pub qualname: String,
-    // Because macro expansion happens before ref-ids are determined,
-    // we use the callee span to reference the associated macro definition.
-    pub callee_span: SpanData,
-    pub scope: DefId,
-}
-
-impl Lower for data::MacroUseData {
-    type Target = MacroUseData;
-
-    fn lower(self, tcx: TyCtxt) -> MacroUseData {
-        MacroUseData {
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            name: self.name,
-            qualname: self.qualname,
-            callee_span: span_from_span(self.callee_span, tcx.sess.codemap()),
-            scope: make_def_id(self.scope, &tcx.hir),
-        }
-    }
-}
-
-/// Data about a method call.
-#[derive(Debug)]
-pub struct MethodCallData {
-    pub span: SpanData,
-    pub scope: DefId,
-    pub ref_id: Option<DefId>,
-    pub decl_id: Option<DefId>,
-}
-
-impl Lower for data::MethodCallData {
-    type Target = MethodCallData;
-
-    fn lower(self, tcx: TyCtxt) -> MethodCallData {
-        MethodCallData {
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            scope: make_def_id(self.scope, &tcx.hir),
-            ref_id: self.ref_id,
-            decl_id: self.decl_id,
-        }
-    }
-}
-
-/// Data for method declarations (methods with a body are treated as functions).
-#[derive(Clone, Debug)]
-pub struct MethodData {
-    pub id: DefId,
-    pub name: String,
-    pub qualname: String,
-    pub span: SpanData,
-    pub scope: DefId,
-    pub value: String,
-    pub decl_id: Option<DefId>,
-    pub visibility: Visibility,
-    pub parent: Option<DefId>,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-impl Lower for data::MethodData {
-    type Target = MethodData;
-
-    fn lower(self, tcx: TyCtxt) -> MethodData {
-        MethodData {
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            name: self.name,
-            scope: make_def_id(self.scope, &tcx.hir),
-            id: make_def_id(self.id, &tcx.hir),
-            qualname: self.qualname,
-            value: self.value,
-            decl_id: self.decl_id,
-            visibility: self.visibility,
-            parent: self.parent,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes.lower(tcx),
-        }
-    }
-}
-
-/// Data for modules.
-#[derive(Debug)]
-pub struct ModData {
-    pub id: DefId,
-    pub name: String,
-    pub qualname: String,
-    pub span: SpanData,
-    pub scope: DefId,
-    pub filename: String,
-    pub items: Vec<DefId>,
-    pub visibility: Visibility,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-impl Lower for data::ModData {
-    type Target = ModData;
-
-    fn lower(self, tcx: TyCtxt) -> ModData {
-        ModData {
-            id: make_def_id(self.id, &tcx.hir),
-            name: self.name,
-            qualname: self.qualname,
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            scope: make_def_id(self.scope, &tcx.hir),
-            filename: self.filename,
-            items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(),
-            visibility: self.visibility,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes.lower(tcx),
-        }
-    }
-}
-
-/// Data for a reference to a module.
-#[derive(Debug)]
-pub struct ModRefData {
-    pub span: SpanData,
-    pub scope: DefId,
-    pub ref_id: Option<DefId>,
-    pub qualname: String
-}
-
-impl Lower for data::ModRefData {
-    type Target = ModRefData;
-
-    fn lower(self, tcx: TyCtxt) -> ModRefData {
-        ModRefData {
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            scope: make_def_id(self.scope, &tcx.hir),
-            ref_id: self.ref_id,
-            qualname: self.qualname,
-        }
-    }
-}
-
-#[derive(Debug)]
-pub struct StructData {
-    pub span: SpanData,
-    pub name: String,
-    pub id: DefId,
-    pub ctor_id: DefId,
-    pub qualname: String,
-    pub scope: DefId,
-    pub value: String,
-    pub fields: Vec<DefId>,
-    pub visibility: Visibility,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-impl Lower for data::StructData {
-    type Target = StructData;
-
-    fn lower(self, tcx: TyCtxt) -> StructData {
-        StructData {
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            name: self.name,
-            id: make_def_id(self.id, &tcx.hir),
-            ctor_id: make_def_id(self.ctor_id, &tcx.hir),
-            qualname: self.qualname,
-            scope: make_def_id(self.scope, &tcx.hir),
-            value: self.value,
-            fields: self.fields.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(),
-            visibility: self.visibility,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes.lower(tcx),
-        }
-    }
-}
-
-#[derive(Debug)]
-pub struct StructVariantData {
-    pub span: SpanData,
-    pub name: String,
-    pub id: DefId,
-    pub qualname: String,
-    pub type_value: String,
-    pub value: String,
-    pub scope: DefId,
-    pub parent: Option<DefId>,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-impl Lower for data::StructVariantData {
-    type Target = StructVariantData;
-
-    fn lower(self, tcx: TyCtxt) -> StructVariantData {
-        StructVariantData {
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            name: self.name,
-            id: make_def_id(self.id, &tcx.hir),
-            qualname: self.qualname,
-            type_value: self.type_value,
-            value: self.value,
-            scope: make_def_id(self.scope, &tcx.hir),
-            parent: self.parent,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes.lower(tcx),
-        }
-    }
-}
-
-#[derive(Debug)]
-pub struct TraitData {
-    pub span: SpanData,
-    pub name: String,
-    pub id: DefId,
-    pub qualname: String,
-    pub scope: DefId,
-    pub value: String,
-    pub items: Vec<DefId>,
-    pub visibility: Visibility,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-impl Lower for data::TraitData {
-    type Target = TraitData;
-
-    fn lower(self, tcx: TyCtxt) -> TraitData {
-        TraitData {
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            name: self.name,
-            id: make_def_id(self.id, &tcx.hir),
-            qualname: self.qualname,
-            scope: make_def_id(self.scope, &tcx.hir),
-            value: self.value,
-            items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(),
-            visibility: self.visibility,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes.lower(tcx),
-        }
-    }
-}
-
-#[derive(Debug)]
-pub struct TupleVariantData {
-    pub span: SpanData,
-    pub id: DefId,
-    pub name: String,
-    pub qualname: String,
-    pub type_value: String,
-    pub value: String,
-    pub scope: DefId,
-    pub parent: Option<DefId>,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-impl Lower for data::TupleVariantData {
-    type Target = TupleVariantData;
-
-    fn lower(self, tcx: TyCtxt) -> TupleVariantData {
-        TupleVariantData {
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            id: make_def_id(self.id, &tcx.hir),
-            name: self.name,
-            qualname: self.qualname,
-            type_value: self.type_value,
-            value: self.value,
-            scope: make_def_id(self.scope, &tcx.hir),
-            parent: self.parent,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes.lower(tcx),
-        }
-    }
-}
-
-/// Data for a typedef.
-#[derive(Debug)]
-pub struct TypeDefData {
-    pub id: DefId,
-    pub name: String,
-    pub span: SpanData,
-    pub qualname: String,
-    pub value: String,
-    pub visibility: Visibility,
-    pub parent: Option<DefId>,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-impl Lower for data::TypeDefData {
-    type Target = TypeDefData;
-
-    fn lower(self, tcx: TyCtxt) -> TypeDefData {
-        TypeDefData {
-            id: make_def_id(self.id, &tcx.hir),
-            name: self.name,
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            qualname: self.qualname,
-            value: self.value,
-            visibility: self.visibility,
-            parent: self.parent,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes.lower(tcx),
-        }
-    }
-}
-
-/// Data for a reference to a type or trait.
-#[derive(Clone, Debug)]
-pub struct TypeRefData {
-    pub span: SpanData,
-    pub scope: DefId,
-    pub ref_id: Option<DefId>,
-    pub qualname: String,
-}
-
-impl Lower for data::TypeRefData {
-    type Target = TypeRefData;
-
-    fn lower(self, tcx: TyCtxt) -> TypeRefData {
-        TypeRefData {
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            scope: make_def_id(self.scope, &tcx.hir),
-            ref_id: self.ref_id,
-            qualname: self.qualname,
-        }
-    }
-}
-
-#[derive(Debug)]
-pub struct UseData {
-    pub id: DefId,
-    pub span: SpanData,
-    pub name: String,
-    pub mod_id: Option<DefId>,
-    pub scope: DefId,
-    pub visibility: Visibility,
-}
-
-impl Lower for data::UseData {
-    type Target = UseData;
-
-    fn lower(self, tcx: TyCtxt) -> UseData {
-        UseData {
-            id: make_def_id(self.id, &tcx.hir),
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            name: self.name,
-            mod_id: self.mod_id,
-            scope: make_def_id(self.scope, &tcx.hir),
-            visibility: self.visibility,
-        }
-    }
-}
-
-#[derive(Debug)]
-pub struct UseGlobData {
-    pub id: DefId,
-    pub span: SpanData,
-    pub names: Vec<String>,
-    pub scope: DefId,
-    pub visibility: Visibility,
-}
-
-impl Lower for data::UseGlobData {
-    type Target = UseGlobData;
-
-    fn lower(self, tcx: TyCtxt) -> UseGlobData {
-        UseGlobData {
-            id: make_def_id(self.id, &tcx.hir),
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            names: self.names,
-            scope: make_def_id(self.scope, &tcx.hir),
-            visibility: self.visibility,
-        }
-    }
-}
-
-/// Data for local and global variables (consts and statics).
-#[derive(Debug)]
-pub struct VariableData {
-    pub id: DefId,
-    pub name: String,
-    pub kind: data::VariableKind,
-    pub qualname: String,
-    pub span: SpanData,
-    pub scope: DefId,
-    pub value: String,
-    pub type_value: String,
-    pub parent: Option<DefId>,
-    pub visibility: Visibility,
-    pub docs: String,
-    pub sig: Option<Signature>,
-    pub attributes: Vec<Attribute>,
-}
-
-impl Lower for data::VariableData {
-    type Target = VariableData;
-
-    fn lower(self, tcx: TyCtxt) -> VariableData {
-        VariableData {
-            id: make_def_id(self.id, &tcx.hir),
-            kind: self.kind,
-            name: self.name,
-            qualname: self.qualname,
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            scope: make_def_id(self.scope, &tcx.hir),
-            value: self.value,
-            type_value: self.type_value,
-            parent: self.parent,
-            visibility: self.visibility,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes.lower(tcx),
-        }
-    }
-}
-
-/// Data for the use of some item (e.g., the use of a local variable, which
-/// will refer to that variables declaration (by ref_id)).
-#[derive(Debug)]
-pub struct VariableRefData {
-    pub name: String,
-    pub span: SpanData,
-    pub scope: DefId,
-    pub ref_id: DefId,
-}
-
-impl Lower for data::VariableRefData {
-    type Target = VariableRefData;
-
-    fn lower(self, tcx: TyCtxt) -> VariableRefData {
-        VariableRefData {
-            name: self.name,
-            span: span_from_span(self.span, tcx.sess.codemap()),
-            scope: make_def_id(self.scope, &tcx.hir),
-            ref_id: self.ref_id,
-        }
-    }
-}
index bddee6460ff9ceff438f1f38da0a2333e463481a..4b2301fd7f804dcf22f2042a994e5b5dea0df5de 100644 (file)
 
 use rustc_serialize::json::as_json;
 
-use external_data::*;
-use data::{VariableKind, Visibility};
-use dump::Dump;
-use id_from_def_id;
+use Dump;
 
-use rls_data::{Analysis, Import, ImportKind, Def, DefKind, CratePreludeData, Format};
+use rls_data::{Analysis, Import, Def, CratePreludeData, Format, Relation};
 
 
 // A dumper to dump a restricted set of JSON information, designed for use with
@@ -47,306 +44,23 @@ fn drop(&mut self) {
     }
 }
 
-macro_rules! impl_fn {
-    ($fn_name: ident, $data_type: ident, $bucket: ident) => {
-        fn $fn_name(&mut self, data: $data_type) {
-            if let Some(datum) = data.into() {
-                self.result.$bucket.push(datum);
-            }
-        }
-    }
-}
-
 impl<'b, W: Write + 'b> Dump for JsonApiDumper<'b, W> {
     fn crate_prelude(&mut self, data: CratePreludeData) {
         self.result.prelude = Some(data)
     }
 
-    impl_fn!(use_data, UseData, imports);
-    impl_fn!(use_glob, UseGlobData, imports);
-
-    impl_fn!(enum_data, EnumData, defs);
-    impl_fn!(tuple_variant, TupleVariantData, defs);
-    impl_fn!(struct_variant, StructVariantData, defs);
-    impl_fn!(struct_data, StructData, defs);
-    impl_fn!(trait_data, TraitData, defs);
-    impl_fn!(function, FunctionData, defs);
-    impl_fn!(method, MethodData, defs);
-    impl_fn!(macro_data, MacroData, defs);
-    impl_fn!(mod_data, ModData, defs);
-    impl_fn!(typedef, TypeDefData, defs);
-    impl_fn!(variable, VariableData, defs);
-
-    fn impl_data(&mut self, data: ImplData) {
-        if data.self_ref.is_some() {
-            self.result.relations.push(data.into());
-        }
-    }
-    fn inheritance(&mut self, data: InheritanceData) {
-        self.result.relations.push(data.into());
+    fn dump_relation(&mut self, data: Relation) {
+        self.result.relations.push(data);
     }
-}
-
-// FIXME methods. The defs have information about possible overriding and the
-// refs have decl information (e.g., a trait method where we know the required
-// method, but not the supplied method). In both cases, we are currently
-// ignoring it.
-
-impl Into<Option<Import>> for UseData {
-    fn into(self) -> Option<Import> {
-        match self.visibility {
-            Visibility::Public => Some(Import {
-                kind: ImportKind::Use,
-                ref_id: self.mod_id.map(|id| id_from_def_id(id)),
-                span: self.span,
-                name: self.name,
-                value: String::new(),
-            }),
-            _ => None,
+    fn import(&mut self, public: bool, import: Import) {
+        if public {
+            self.result.imports.push(import);
         }
     }
-}
-impl Into<Option<Import>> for UseGlobData {
-    fn into(self) -> Option<Import> {
-        match self.visibility {
-            Visibility::Public => Some(Import {
-                kind: ImportKind::GlobUse,
-                ref_id: None,
-                span: self.span,
-                name: "*".to_owned(),
-                value: self.names.join(", "),
-            }),
-            _ => None,
-        }
-    }
-}
-
-impl Into<Option<Def>> for EnumData {
-    fn into(self) -> Option<Def> {
-        match self.visibility {
-            Visibility::Public => Some(Def {
-                kind: DefKind::Enum,
-                id: id_from_def_id(self.id),
-                span: self.span,
-                name: self.name,
-                qualname: self.qualname,
-                value: self.value,
-                parent: None,
-                children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(),
-                decl_id: None,
-                docs: self.docs,
-                sig: self.sig,
-                attributes: vec![],
-            }),
-            _ => None,
-        }
-    }
-}
-
-impl Into<Option<Def>> for TupleVariantData {
-    fn into(self) -> Option<Def> {
-        Some(Def {
-            kind: DefKind::Tuple,
-            id: id_from_def_id(self.id),
-            span: self.span,
-            name: self.name,
-            qualname: self.qualname,
-            value: self.value,
-            parent: self.parent.map(|id| id_from_def_id(id)),
-            children: vec![],
-            decl_id: None,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: vec![],
-        })
-    }
-}
-impl Into<Option<Def>> for StructVariantData {
-    fn into(self) -> Option<Def> {
-        Some(Def {
-            kind: DefKind::Struct,
-            id: id_from_def_id(self.id),
-            span: self.span,
-            name: self.name,
-            qualname: self.qualname,
-            value: self.value,
-            parent: self.parent.map(|id| id_from_def_id(id)),
-            children: vec![],
-            decl_id: None,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: vec![],
-        })
-    }
-}
-impl Into<Option<Def>> for StructData {
-    fn into(self) -> Option<Def> {
-        match self.visibility {
-            Visibility::Public => Some(Def {
-            kind: DefKind::Struct,
-            id: id_from_def_id(self.id),
-            span: self.span,
-            name: self.name,
-            qualname: self.qualname,
-            value: self.value,
-            parent: None,
-            children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(),
-            decl_id: None,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: vec![],
-        }),
-            _ => None,
-        }
-    }
-}
-impl Into<Option<Def>> for TraitData {
-    fn into(self) -> Option<Def> {
-        match self.visibility {
-            Visibility::Public => Some(Def {
-                kind: DefKind::Trait,
-                id: id_from_def_id(self.id),
-                span: self.span,
-                name: self.name,
-                qualname: self.qualname,
-                value: self.value,
-                children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(),
-                parent: None,
-                decl_id: None,
-                docs: self.docs,
-                sig: self.sig,
-                attributes: vec![],
-            }),
-            _ => None,
-        }
-    }
-}
-impl Into<Option<Def>> for FunctionData {
-    fn into(self) -> Option<Def> {
-        match self.visibility {
-            Visibility::Public => Some(Def {
-                kind: DefKind::Function,
-                id: id_from_def_id(self.id),
-                span: self.span,
-                name: self.name,
-                qualname: self.qualname,
-                value: self.value,
-                children: vec![],
-                parent: self.parent.map(|id| id_from_def_id(id)),
-                decl_id: None,
-                docs: self.docs,
-                sig: self.sig,
-                attributes: vec![],
-            }),
-            _ => None,
-        }
-    }
-}
-impl Into<Option<Def>> for MethodData {
-    fn into(self) -> Option<Def> {
-        match self.visibility {
-            Visibility::Public => Some(Def {
-                kind: DefKind::Method,
-                id: id_from_def_id(self.id),
-                span: self.span,
-                name: self.name,
-                qualname: self.qualname,
-                value: self.value,
-                children: vec![],
-                parent: self.parent.map(|id| id_from_def_id(id)),
-                decl_id: self.decl_id.map(|id| id_from_def_id(id)),
-                docs: self.docs,
-                sig: self.sig,
-                attributes: vec![],
-            }),
-            _ => None,
-        }
-    }
-}
-impl Into<Option<Def>> for MacroData {
-    fn into(self) -> Option<Def> {
-        Some(Def {
-            kind: DefKind::Macro,
-            id: id_from_def_id(null_def_id()),
-            span: self.span,
-            name: self.name,
-            qualname: self.qualname,
-            value: String::new(),
-            children: vec![],
-            parent: None,
-            decl_id: None,
-            docs: self.docs,
-            sig: None,
-            attributes: vec![],
-        })
-    }
-}
-impl Into<Option<Def>> for ModData {
-    fn into(self) -> Option<Def> {
-        match self.visibility {
-            Visibility::Public => Some(Def {
-                kind: DefKind::Mod,
-                id: id_from_def_id(self.id),
-                span: self.span,
-                name: self.name,
-                qualname: self.qualname,
-                value: self.filename,
-                children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(),
-                parent: None,
-                decl_id: None,
-                docs: self.docs,
-                sig: self.sig.map(|s| s.into()),
-                attributes: vec![],
-            }),
-            _ => None,
-        }
-    }
-}
-impl Into<Option<Def>> for TypeDefData {
-    fn into(self) -> Option<Def> {
-        match self.visibility {
-            Visibility::Public => Some(Def {
-                kind: DefKind::Type,
-                id: id_from_def_id(self.id),
-                span: self.span,
-                name: self.name,
-                qualname: self.qualname,
-                value: self.value,
-                children: vec![],
-                parent: self.parent.map(|id| id_from_def_id(id)),
-                decl_id: None,
-                docs: String::new(),
-                sig: self.sig.map(|s| s.into()),
-                attributes: vec![],
-            }),
-            _ => None,
-        }
-    }
-}
-
-impl Into<Option<Def>> for VariableData {
-    fn into(self) -> Option<Def> {
-        match self.visibility {
-            Visibility::Public => Some(Def {
-                kind: match self.kind {
-                    VariableKind::Static => DefKind::Static,
-                    VariableKind::Const => DefKind::Const,
-                    VariableKind::Local => { return None }
-                    VariableKind::Field => DefKind::Field,
-                },
-                id: id_from_def_id(self.id),
-                span: self.span,
-                name: self.name,
-                qualname: self.qualname,
-                value: self.value,
-                children: vec![],
-                parent: self.parent.map(|id| id_from_def_id(id)),
-                decl_id: None,
-                docs: self.docs,
-                sig: self.sig.map(|s| s.into()),
-                attributes: vec![],
-            }),
-            _ => None,
+    fn dump_def(&mut self, public: bool, mut data: Def) {
+        if public {
+            data.attributes = vec![];
+            self.result.defs.push(data);
         }
     }
 }
index 58df612c687c3afdd8eeaa10bc53ae18ce08d11c..9cd375e98558ad3e8005e832d519cf98f84f3ee5 100644 (file)
 
 use rustc_serialize::json::as_json;
 
-use rls_data::{self, Id, Analysis, Import, ImportKind, Def, DefKind, Ref, RefKind, MacroRef,
-               Relation, RelationKind, CratePreludeData};
+use rls_data::{self, Analysis, Import, Def, DefKind, Ref, RefKind, MacroRef,
+               Relation, CratePreludeData};
 use rls_span::{Column, Row};
 
-use external_data::*;
-use data::VariableKind;
-use dump::Dump;
-use id_from_def_id;
+use Dump;
 
 pub struct JsonDumper<O: DumpOutput> {
     result: Analysis,
@@ -70,71 +67,35 @@ fn drop(&mut self) {
     }
 }
 
-macro_rules! impl_fn {
-    ($fn_name: ident, $data_type: ident, $bucket: ident) => {
-        fn $fn_name(&mut self, data: $data_type) {
-            self.result.$bucket.push(data.into());
-        }
-    }
-}
-
 impl<'b, O: DumpOutput + 'b> Dump for JsonDumper<O> {
     fn crate_prelude(&mut self, data: CratePreludeData) {
         self.result.prelude = Some(data)
     }
 
-    impl_fn!(extern_crate, ExternCrateData, imports);
-    impl_fn!(use_data, UseData, imports);
-    impl_fn!(use_glob, UseGlobData, imports);
-
-    impl_fn!(enum_data, EnumData, defs);
-    impl_fn!(tuple_variant, TupleVariantData, defs);
-    impl_fn!(struct_variant, StructVariantData, defs);
-    impl_fn!(struct_data, StructData, defs);
-    impl_fn!(trait_data, TraitData, defs);
-    impl_fn!(function, FunctionData, defs);
-    impl_fn!(method, MethodData, defs);
-    impl_fn!(macro_data, MacroData, defs);
-    impl_fn!(typedef, TypeDefData, defs);
-    impl_fn!(variable, VariableData, defs);
-
-    impl_fn!(function_ref, FunctionRefData, refs);
-    impl_fn!(function_call, FunctionCallData, refs);
-    impl_fn!(method_call, MethodCallData, refs);
-    impl_fn!(mod_ref, ModRefData, refs);
-    impl_fn!(type_ref, TypeRefData, refs);
-    impl_fn!(variable_ref, VariableRefData, refs);
+    fn macro_use(&mut self, data: MacroRef) {
+        self.result.macro_refs.push(data);
+    }
 
-    impl_fn!(macro_use, MacroUseData, macro_refs);
+    fn import(&mut self, _: bool, import: Import) {
+        self.result.imports.push(import);
+    }
 
-    fn mod_data(&mut self, data: ModData) {
-        let id: Id = id_from_def_id(data.id);
-        let mut def = Def {
-            kind: DefKind::Mod,
-            id: id,
-            span: data.span.into(),
-            name: data.name,
-            qualname: data.qualname,
-            value: data.filename,
-            parent: None,
-            children: data.items.into_iter().map(|id| id_from_def_id(id)).collect(),
-            decl_id: None,
-            docs: data.docs,
-            sig: data.sig,
-            attributes: data.attributes.into_iter().map(|a| a.into()).collect(),
-        };
-        if def.span.file_name.to_str().unwrap() != def.value {
+    fn dump_ref(&mut self, data: Ref) {
+        self.result.refs.push(data);
+    }
+    fn dump_def(&mut self, _: bool, mut data: Def) {
+        if data.kind == DefKind::Mod && data.span.file_name.to_str().unwrap() != data.value {
             // If the module is an out-of-line defintion, then we'll make the
             // defintion the first character in the module's file and turn the
             // the declaration into a reference to it.
             let rf = Ref {
                 kind: RefKind::Mod,
-                span: def.span,
-                ref_id: id,
+                span: data.span,
+                ref_id: data.id,
             };
             self.result.refs.push(rf);
-            def.span = rls_data::SpanData {
-                file_name: def.value.clone().into(),
+            data.span = rls_data::SpanData {
+                file_name: data.value.clone().into(),
                 byte_start: 0,
                 byte_end: 0,
                 line_start: Row::new_one_indexed(1),
@@ -143,330 +104,10 @@ fn mod_data(&mut self, data: ModData) {
                 column_end: Column::new_one_indexed(1),
             }
         }
-
-        self.result.defs.push(def);
-    }
-
-    fn impl_data(&mut self, data: ImplData) {
-        if data.self_ref.is_some() {
-            self.result.relations.push(data.into());
-        }
-    }
-    fn inheritance(&mut self, data: InheritanceData) {
-        self.result.relations.push(data.into());
-    }
-}
-
-// FIXME do we want to change ExternalData to this mode? It will break DXR.
-// FIXME methods. The defs have information about possible overriding and the
-// refs have decl information (e.g., a trait method where we know the required
-// method, but not the supplied method). In both cases, we are currently
-// ignoring it.
-
-impl Into<Import> for ExternCrateData {
-    fn into(self) -> Import {
-        Import {
-            kind: ImportKind::ExternCrate,
-            ref_id: None,
-            span: self.span,
-            name: self.name,
-            value: String::new(),
-        }
-    }
-}
-impl Into<Import> for UseData {
-    fn into(self) -> Import {
-        Import {
-            kind: ImportKind::Use,
-            ref_id: self.mod_id.map(|id| id_from_def_id(id)),
-            span: self.span,
-            name: self.name,
-            value: String::new(),
-        }
-    }
-}
-impl Into<Import> for UseGlobData {
-    fn into(self) -> Import {
-        Import {
-            kind: ImportKind::GlobUse,
-            ref_id: None,
-            span: self.span,
-            name: "*".to_owned(),
-            value: self.names.join(", "),
-        }
-    }
-}
-
-impl Into<Def> for EnumData {
-    fn into(self) -> Def {
-        Def {
-            kind: DefKind::Enum,
-            id: id_from_def_id(self.id),
-            span: self.span,
-            name: self.name,
-            qualname: self.qualname,
-            value: self.value,
-            parent: None,
-            children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(),
-            decl_id: None,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes,
-        }
-    }
-}
-
-impl Into<Def> for TupleVariantData {
-    fn into(self) -> Def {
-        Def {
-            kind: DefKind::Tuple,
-            id: id_from_def_id(self.id),
-            span: self.span,
-            name: self.name,
-            qualname: self.qualname,
-            value: self.value,
-            parent: None,
-            children: vec![],
-            decl_id: None,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes,
-        }
-    }
-}
-impl Into<Def> for StructVariantData {
-    fn into(self) -> Def {
-        Def {
-            kind: DefKind::Struct,
-            id: id_from_def_id(self.id),
-            span: self.span,
-            name: self.name,
-            qualname: self.qualname,
-            value: self.value,
-            parent: None,
-            children: vec![],
-            decl_id: None,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes,
-        }
-    }
-}
-impl Into<Def> for StructData {
-    fn into(self) -> Def {
-        Def {
-            kind: DefKind::Struct,
-            id: id_from_def_id(self.id),
-            span: self.span,
-            name: self.name,
-            qualname: self.qualname,
-            value: self.value,
-            parent: None,
-            children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(),
-            decl_id: None,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes,
-        }
-    }
-}
-impl Into<Def> for TraitData {
-    fn into(self) -> Def {
-        Def {
-            kind: DefKind::Trait,
-            id: id_from_def_id(self.id),
-            span: self.span,
-            name: self.name,
-            qualname: self.qualname,
-            value: self.value,
-            parent: None,
-            children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(),
-            decl_id: None,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes,
-        }
-    }
-}
-impl Into<Def> for FunctionData {
-    fn into(self) -> Def {
-        Def {
-            kind: DefKind::Function,
-            id: id_from_def_id(self.id),
-            span: self.span,
-            name: self.name,
-            qualname: self.qualname,
-            value: self.value,
-            parent: None,
-            children: vec![],
-            decl_id: None,
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes,
-        }
-    }
-}
-impl Into<Def> for MethodData {
-    fn into(self) -> Def {
-        Def {
-            kind: DefKind::Method,
-            id: id_from_def_id(self.id),
-            span: self.span,
-            name: self.name,
-            qualname: self.qualname,
-            value: self.value,
-            parent: None,
-            children: vec![],
-            decl_id: self.decl_id.map(|id| id_from_def_id(id)),
-            docs: self.docs,
-            sig: self.sig,
-            attributes: self.attributes,
-        }
-    }
-}
-impl Into<Def> for MacroData {
-    fn into(self) -> Def {
-        Def {
-            kind: DefKind::Macro,
-            id: id_from_def_id(null_def_id()),
-            span: self.span,
-            name: self.name,
-            qualname: self.qualname,
-            value: String::new(),
-            parent: None,
-            children: vec![],
-            decl_id: None,
-            docs: self.docs,
-            sig: None,
-            attributes: vec![],
-        }
-    }
-}
-impl Into<Def> for TypeDefData {
-    fn into(self) -> Def {
-        Def {
-            kind: DefKind::Type,
-            id: id_from_def_id(self.id),
-            span: self.span,
-            name: self.name,
-            qualname: self.qualname,
-            value: self.value,
-            parent: None,
-            children: vec![],
-            decl_id: None,
-            docs: String::new(),
-            sig: self.sig,
-            attributes: self.attributes,
-        }
+        self.result.defs.push(data);
     }
-}
-impl Into<Def> for VariableData {
-    fn into(self) -> Def {
-        Def {
-            kind: match self.kind {
-                VariableKind::Static => DefKind::Static,
-                VariableKind::Const => DefKind::Const,
-                VariableKind::Local => DefKind::Local,
-                VariableKind::Field => DefKind::Field,
-            },
-            id: id_from_def_id(self.id),
-            span: self.span,
-            name: self.name,
-            qualname: self.qualname,
-            value: self.type_value,
-            parent: None,
-            children: vec![],
-            decl_id: None,
-            docs: self.docs,
-            sig: None,
-            attributes: self.attributes,
-        }
-    }
-}
 
-impl Into<Ref> for FunctionRefData {
-    fn into(self) -> Ref {
-        Ref {
-            kind: RefKind::Function,
-            span: self.span,
-            ref_id: id_from_def_id(self.ref_id),
-        }
-    }
-}
-impl Into<Ref> for FunctionCallData {
-    fn into(self) -> Ref {
-        Ref {
-            kind: RefKind::Function,
-            span: self.span,
-            ref_id: id_from_def_id(self.ref_id),
-        }
-    }
-}
-impl Into<Ref> for MethodCallData {
-    fn into(self) -> Ref {
-        Ref {
-            kind: RefKind::Function,
-            span: self.span,
-            ref_id: id_from_def_id(self.ref_id.or(self.decl_id).unwrap_or(null_def_id())),
-        }
-    }
-}
-impl Into<Ref> for ModRefData {
-    fn into(self) -> Ref {
-        Ref {
-            kind: RefKind::Mod,
-            span: self.span,
-            ref_id: id_from_def_id(self.ref_id.unwrap_or(null_def_id())),
-        }
-    }
-}
-impl Into<Ref> for TypeRefData {
-    fn into(self) -> Ref {
-        Ref {
-            kind: RefKind::Type,
-            span: self.span,
-            ref_id: id_from_def_id(self.ref_id.unwrap_or(null_def_id())),
-        }
-    }
-}
-impl Into<Ref> for VariableRefData {
-    fn into(self) -> Ref {
-        Ref {
-            kind: RefKind::Variable,
-            span: self.span,
-            ref_id: id_from_def_id(self.ref_id),
-        }
-    }
-}
-
-impl Into<MacroRef> for MacroUseData {
-    fn into(self) -> MacroRef {
-        MacroRef {
-            span: self.span,
-            qualname: self.qualname,
-            callee_span: self.callee_span.into(),
-        }
-    }
-}
-
-impl Into<Relation> for ImplData {
-    fn into(self) -> Relation {
-        Relation {
-            span: self.span,
-            kind: RelationKind::Impl,
-            from: id_from_def_id(self.self_ref.unwrap_or(null_def_id())),
-            to: id_from_def_id(self.trait_ref.unwrap_or(null_def_id())),
-        }
-    }
-}
-
-impl Into<Relation> for InheritanceData {
-    fn into(self) -> Relation {
-        Relation {
-            span: self.span,
-            kind: RelationKind::SuperTrait,
-            from: id_from_def_id(self.base_id),
-            to: id_from_def_id(self.deriv_id),
-        }
+    fn dump_relation(&mut self, data: Relation) {
+        self.result.relations.push(data);
     }
 }
index be879a01fb8fb97b93137798beb5cb386df32660..0b2614ee83ca2003b64be33010991db8be406e06 100644 (file)
 
 mod json_api_dumper;
 mod json_dumper;
-mod data;
-mod dump;
 mod dump_visitor;
-pub mod external_data;
 #[macro_use]
-pub mod span_utils;
+mod span_utils;
 mod sig;
 
 use rustc::hir;
-use rustc::hir::def::Def;
-use rustc::hir::map::Node;
+use rustc::hir::def::Def as HirDef;
+use rustc::hir::map::{Node, NodeItem};
 use rustc::hir::def_id::DefId;
 use rustc::session::config::CrateType::CrateTypeExecutable;
 use rustc::session::Session;
 use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID};
 use syntax::parse::lexer::comments::strip_doc_comment_decoration;
 use syntax::parse::token;
+use syntax::print::pprust;
 use syntax::symbol::keywords;
 use syntax::visit::{self, Visitor};
 use syntax::print::pprust::{ty_to_string, arg_to_string};
 use syntax::codemap::MacroAttribute;
 use syntax_pos::*;
 
-pub use self::json_api_dumper::JsonApiDumper;
-pub use self::json_dumper::JsonDumper;
-pub use self::data::*;
-pub use self::external_data::make_def_id;
-pub use self::dump::Dump;
-pub use self::dump_visitor::DumpVisitor;
-use self::span_utils::SpanUtils;
-
-// FIXME this is legacy code and should be removed
-pub mod recorder {
-    pub use self::Row::*;
-
-    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
-    pub enum Row {
-        TypeRef,
-        ModRef,
-        VarRef,
-        FnRef,
-    }
-}
+pub use json_api_dumper::JsonApiDumper;
+pub use json_dumper::JsonDumper;
+use dump_visitor::DumpVisitor;
+use span_utils::SpanUtils;
+
+use rls_data::{Ref, RefKind, SpanData, MacroRef, Def, DefKind, Relation, RelationKind,
+               ExternalCrateData, Import, CratePreludeData};
+
 
 pub struct SaveContext<'l, 'tcx: 'l> {
     tcx: TyCtxt<'l, 'tcx, 'tcx>,
@@ -95,13 +81,49 @@ pub struct SaveContext<'l, 'tcx: 'l> {
     span_utils: SpanUtils<'tcx>,
 }
 
+#[derive(Debug)]
+pub enum Data {
+    /// Data about a macro use.
+    MacroUseData(MacroRef),
+    RefData(Ref),
+    DefData(Def),
+    RelationData(Relation),
+}
+
+pub trait Dump {
+    fn crate_prelude(&mut self, _: CratePreludeData);
+    fn macro_use(&mut self, _: MacroRef) {}
+    fn import(&mut self, _: bool, _: Import);
+    fn dump_ref(&mut self, _: Ref) {}
+    fn dump_def(&mut self, _: bool, _: Def);
+    fn dump_relation(&mut self, data: Relation);
+}
+
 macro_rules! option_try(
     ($e:expr) => (match $e { Some(e) => e, None => return None })
 );
 
 impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
+    fn span_from_span(&self, span: Span) -> SpanData {
+        use rls_span::{Row, Column};
+
+        let cm = self.tcx.sess.codemap();
+        let start = cm.lookup_char_pos(span.lo);
+        let end = cm.lookup_char_pos(span.hi);
+
+        SpanData {
+            file_name: start.file.name.clone().into(),
+            byte_start: span.lo.0,
+            byte_end: span.hi.0,
+            line_start: Row::new_one_indexed(start.line as u32),
+            line_end: Row::new_one_indexed(end.line as u32),
+            column_start: Column::new_one_indexed(start.col.0 as u32 + 1),
+            column_end: Column::new_one_indexed(end.col.0 as u32 + 1),
+        }
+    }
+
     // List external crates used by the current crate.
-    pub fn get_external_crates(&self) -> Vec<CrateData> {
+    pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
         let mut result = Vec::new();
 
         for n in self.tcx.sess.cstore.crates() {
@@ -112,10 +134,11 @@ pub fn get_external_crates(&self) -> Vec<CrateData> {
                     continue;
                 }
             };
-            result.push(CrateData {
+            let lo_loc = self.span_utils.sess.codemap().lookup_char_pos(span.lo);
+            result.push(ExternalCrateData {
                 name: self.tcx.sess.cstore.crate_name(n).to_string(),
-                number: n.as_u32(),
-                span: span,
+                num: n.as_u32(),
+                file_name: SpanUtils::make_path_string(&lo_loc.file.name),
             });
         }
 
@@ -128,39 +151,43 @@ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
             ast::ForeignItemKind::Fn(ref decl, ref generics) => {
                 let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn);
                 filter!(self.span_utils, sub_span, item.span, None);
-                Some(Data::FunctionData(FunctionData {
-                    id: item.id,
+
+                Some(Data::DefData(Def {
+                    kind: DefKind::Function,
+                    id: id_from_node_id(item.id, self),
+                    span: self.span_from_span(sub_span.unwrap()),
                     name: item.ident.to_string(),
-                    qualname: qualname,
-                    declaration: None,
-                    span: sub_span.unwrap(),
-                    scope: self.enclosing_scope(item.id),
+                    qualname,
                     value: make_signature(decl, generics),
-                    visibility: From::from(&item.vis),
                     parent: None,
+                    children: vec![],
+                    decl_id: None,
                     docs: docs_for_attrs(&item.attrs),
                     sig: sig::foreign_item_signature(item, self),
-                    attributes: item.attrs.clone(),
+                    attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
             ast::ForeignItemKind::Static(ref ty, m) => {
                 let keyword = if m { keywords::Mut } else { keywords::Static };
                 let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword);
                 filter!(self.span_utils, sub_span, item.span, None);
-                Some(Data::VariableData(VariableData {
-                    id: item.id,
-                    kind: VariableKind::Static,
+
+                let id = ::id_from_node_id(item.id, self);
+                let span = self.span_from_span(sub_span.unwrap());
+
+                Some(Data::DefData(Def {
+                    kind: DefKind::Static,
+                    id,
+                    span,
                     name: item.ident.to_string(),
-                    qualname: qualname,
-                    span: sub_span.unwrap(),
-                    scope: self.enclosing_scope(item.id),
+                    qualname,
+                    value: ty_to_string(ty),
                     parent: None,
-                    value: String::new(),
-                    type_value: ty_to_string(ty),
-                    visibility: From::from(&item.vis),
+                    children: vec![],
+                    decl_id: None,
                     docs: docs_for_attrs(&item.attrs),
                     sig: sig::foreign_item_signature(item, self),
-                    attributes: item.attrs.clone(),
+                    attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
         }
@@ -172,70 +199,71 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
                 let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn);
                 filter!(self.span_utils, sub_span, item.span, None);
-
-
-                Some(Data::FunctionData(FunctionData {
-                    id: item.id,
+                Some(Data::DefData(Def {
+                    kind: DefKind::Function,
+                    id: id_from_node_id(item.id, self),
+                    span: self.span_from_span(sub_span.unwrap()),
                     name: item.ident.to_string(),
-                    qualname: qualname,
-                    declaration: None,
-                    span: sub_span.unwrap(),
-                    scope: self.enclosing_scope(item.id),
+                    qualname,
                     value: make_signature(decl, generics),
-                    visibility: From::from(&item.vis),
                     parent: None,
+                    children: vec![],
+                    decl_id: None,
                     docs: docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, self),
-                    attributes: item.attrs.clone(),
+                    attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
-            ast::ItemKind::Static(ref typ, mt, ref expr) => {
+            ast::ItemKind::Static(ref typ, mt, _) => {
                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
 
-                // If the variable is immutable, save the initialising expression.
-                let (value, keyword) = match mt {
-                    ast::Mutability::Mutable => (String::from("<mutable>"), keywords::Mut),
-                    ast::Mutability::Immutable => {
-                        (self.span_utils.snippet(expr.span), keywords::Static)
-                    },
+                let keyword = match mt {
+                    ast::Mutability::Mutable => keywords::Mut,
+                    ast::Mutability::Immutable => keywords::Static,
                 };
 
                 let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword);
                 filter!(self.span_utils, sub_span, item.span, None);
-                Some(Data::VariableData(VariableData {
-                    id: item.id,
-                    kind: VariableKind::Static,
+
+                let id = id_from_node_id(item.id, self);
+                let span = self.span_from_span(sub_span.unwrap());
+
+                Some(Data::DefData(Def {
+                    kind: DefKind::Static,
+                    id,
+                    span,
                     name: item.ident.to_string(),
-                    qualname: qualname,
-                    span: sub_span.unwrap(),
-                    scope: self.enclosing_scope(item.id),
+                    qualname,
+                    value: ty_to_string(&typ),
                     parent: None,
-                    value: value,
-                    type_value: ty_to_string(&typ),
-                    visibility: From::from(&item.vis),
+                    children: vec![],
+                    decl_id: None,
                     docs: docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, self),
-                    attributes: item.attrs.clone(),
+                    attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
-            ast::ItemKind::Const(ref typ, ref expr) => {
+            ast::ItemKind::Const(ref typ, _) => {
                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
                 let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Const);
                 filter!(self.span_utils, sub_span, item.span, None);
-                Some(Data::VariableData(VariableData {
-                    id: item.id,
-                    kind: VariableKind::Const,
+
+                let id = id_from_node_id(item.id, self);
+                let span = self.span_from_span(sub_span.unwrap());
+
+                Some(Data::DefData(Def {
+                    kind: DefKind::Const,
+                    id,
+                    span,
                     name: item.ident.to_string(),
-                    qualname: qualname,
-                    span: sub_span.unwrap(),
-                    scope: self.enclosing_scope(item.id),
+                    qualname,
+                    value: ty_to_string(typ),
                     parent: None,
-                    value: self.span_utils.snippet(expr.span),
-                    type_value: ty_to_string(&typ),
-                    visibility: From::from(&item.vis),
+                    children: vec![],
+                    decl_id: None,
                     docs: docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, self),
-                    attributes: item.attrs.clone(),
+                    attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
             ast::ItemKind::Mod(ref m) => {
@@ -247,18 +275,19 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                 let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Mod);
                 filter!(self.span_utils, sub_span, item.span, None);
 
-                Some(Data::ModData(ModData {
-                    id: item.id,
+                Some(Data::DefData(Def {
+                    kind: DefKind::Mod,
+                    id: id_from_node_id(item.id, self),
                     name: item.ident.to_string(),
-                    qualname: qualname,
-                    span: sub_span.unwrap(),
-                    scope: self.enclosing_scope(item.id),
-                    filename: filename,
-                    items: m.items.iter().map(|i| i.id).collect(),
-                    visibility: From::from(&item.vis),
+                    qualname,
+                    span: self.span_from_span(sub_span.unwrap()),
+                    value: filename,
+                    parent: None,
+                    children: m.items.iter().map(|i| id_from_node_id(i.id, self)).collect(),
+                    decl_id: None,
                     docs: docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, self),
-                    attributes: item.attrs.clone(),
+                    attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
             ast::ItemKind::Enum(ref def, _) => {
@@ -270,61 +299,47 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                                       .map(|v| v.node.name.to_string())
                                       .collect::<Vec<_>>()
                                       .join(", ");
-                let val = format!("{}::{{{}}}", name, variants_str);
-                Some(Data::EnumData(EnumData {
-                    id: item.id,
-                    name: name,
-                    value: val,
-                    span: sub_span.unwrap(),
-                    qualname: qualname,
-                    scope: self.enclosing_scope(item.id),
-                    variants: def.variants.iter().map(|v| v.node.data.id()).collect(),
-                    visibility: From::from(&item.vis),
+                let value = format!("{}::{{{}}}", name, variants_str);
+                Some(Data::DefData(Def {
+                    kind: DefKind::Enum,
+                    id: id_from_node_id(item.id, self),
+                    span: self.span_from_span(sub_span.unwrap()),
+                    name,
+                    qualname,
+                    value,
+                    parent: None,
+                    children: def.variants
+                                 .iter()
+                                 .map(|v| id_from_node_id(v.node.data.id(), self))
+                                 .collect(),
+                    decl_id: None,
                     docs: docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, self),
-                    attributes: item.attrs.clone(),
+                    attributes: lower_attributes(item.attrs.to_owned(), self),
                 }))
             }
             ast::ItemKind::Impl(.., ref trait_ref, ref typ, _) => {
-                let mut type_data = None;
-                let sub_span;
-
-                let parent = self.enclosing_scope(item.id);
-
-                match typ.node {
+                if let ast::TyKind::Path(None, ref path) = typ.node {
                     // Common case impl for a struct or something basic.
-                    ast::TyKind::Path(None, ref path) => {
-                        if generated_code(path.span) {
-                            return None;
-                        }
-                        sub_span = self.span_utils.sub_span_for_type_name(path.span);
-                        type_data = self.lookup_ref_id(typ.id).map(|id| {
-                            TypeRefData {
-                                span: sub_span.unwrap(),
-                                scope: parent,
-                                ref_id: Some(id),
-                                qualname: String::new() // FIXME: generate the real qualname
-                            }
-                        });
-                    }
-                    _ => {
-                        // Less useful case, impl for a compound type.
-                        let span = typ.span;
-                        sub_span = self.span_utils.sub_span_for_type_name(span).or(Some(span));
+                    if generated_code(path.span) {
+                        return None;
                     }
+                    let sub_span = self.span_utils.sub_span_for_type_name(path.span);
+                    filter!(self.span_utils, sub_span, typ.span, None);
+
+                    let type_data = self.lookup_ref_id(typ.id);
+                    type_data.map(|type_data| Data::RelationData(Relation {
+                        kind: RelationKind::Impl,
+                        span: self.span_from_span(sub_span.unwrap()),
+                        from: id_from_def_id(type_data),
+                        to: trait_ref.as_ref()
+                                     .and_then(|t| self.lookup_ref_id(t.ref_id))
+                                     .map(id_from_def_id)
+                                     .unwrap_or(null_id()),
+                    }))
+                } else {
+                    None
                 }
-
-                let trait_data = trait_ref.as_ref()
-                                          .and_then(|tr| self.get_trait_ref_data(tr, parent));
-
-                filter!(self.span_utils, sub_span, typ.span, None);
-                Some(Data::ImplData(ImplData2 {
-                    id: item.id,
-                    span: sub_span.unwrap(),
-                    scope: parent,
-                    trait_ref: trait_data,
-                    self_ref: type_data,
-                }))
             }
             _ => {
                 // FIXME
@@ -336,7 +351,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
     pub fn get_field_data(&self,
                           field: &ast::StructField,
                           scope: NodeId)
-                          -> Option<VariableData> {
+                          -> Option<Def> {
         if let Some(ident) = field.ident {
             let name = ident.to_string();
             let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident);
@@ -345,20 +360,23 @@ pub fn get_field_data(&self,
             let def_id = self.tcx.hir.local_def_id(field.id);
             let typ = self.tcx.type_of(def_id).to_string();
 
-            Some(VariableData {
-                id: field.id,
-                kind: VariableKind::Field,
-                name: name,
-                qualname: qualname,
-                span: sub_span.unwrap(),
-                scope: scope,
-                parent: Some(make_def_id(scope, &self.tcx.hir)),
-                value: "".to_owned(),
-                type_value: typ,
-                visibility: From::from(&field.vis),
+
+            let id = id_from_node_id(field.id, self);
+            let span = self.span_from_span(sub_span.unwrap());
+
+            Some(Def {
+                kind: DefKind::Field,
+                id,
+                span,
+                name,
+                qualname,
+                value: typ,
+                parent: Some(id_from_node_id(scope, self)),
+                children: vec![],
+                decl_id: None,
                 docs: docs_for_attrs(&field.attrs),
                 sig: sig::field_signature(field, self),
-                attributes: field.attrs.clone(),
+                attributes: lower_attributes(field.attrs.clone(), self),
             })
         } else {
             None
@@ -371,10 +389,10 @@ pub fn get_method_data(&self,
                            id: ast::NodeId,
                            name: ast::Name,
                            span: Span)
-                           -> Option<FunctionData> {
+                           -> Option<Def> {
         // The qualname for a method is the trait name or name of the struct in an impl in
         // which the method is declared in, followed by the method's name.
-        let (qualname, parent_scope, decl_id, vis, docs, attributes) =
+        let (qualname, parent_scope, decl_id, docs, attributes) =
           match self.tcx.impl_of_method(self.tcx.hir.local_def_id(id)) {
             Some(impl_id) => match self.tcx.hir.get_if_local(impl_id) {
                 Some(Node::NodeItem(item)) => {
@@ -383,7 +401,7 @@ pub fn get_method_data(&self,
                             let mut result = String::from("<");
                             result.push_str(&self.tcx.hir.node_to_pretty_string(ty.id));
 
-                            let trait_id = self.tcx.trait_id_of_impl(impl_id);
+                            let mut trait_id = self.tcx.trait_id_of_impl(impl_id);
                             let mut decl_id = None;
                             if let Some(def_id) = trait_id {
                                 result.push_str(" as ");
@@ -391,11 +409,16 @@ pub fn get_method_data(&self,
                                 self.tcx.associated_items(def_id)
                                     .find(|item| item.name == name)
                                     .map(|item| decl_id = Some(item.def_id));
+                            } else {
+                                if let Some(NodeItem(item)) = self.tcx.hir.find(id) {
+                                    if let hir::ItemImpl(_, _, _, _, _, ref ty, _) = item.node {
+                                        trait_id = self.lookup_ref_id(ty.id);
+                                    }
+                                }
                             }
                             result.push_str(">");
 
                             (result, trait_id, decl_id,
-                             From::from(&item.vis),
                              docs_for_attrs(&item.attrs),
                              item.attrs.to_vec())
                         }
@@ -421,7 +444,6 @@ pub fn get_method_data(&self,
                         Some(Node::NodeItem(item)) => {
                             (format!("::{}", self.tcx.item_path_str(def_id)),
                              Some(def_id), None,
-                             From::from(&item.vis),
                              docs_for_attrs(&item.attrs),
                              item.attrs.to_vec())
                         }
@@ -449,27 +471,26 @@ pub fn get_method_data(&self,
         let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn);
         filter!(self.span_utils, sub_span, span, None);
 
-        Some(FunctionData {
-            id: id,
+        Some(Def {
+            kind: DefKind::Method,
+            id: id_from_node_id(id, self),
+            span: self.span_from_span(sub_span.unwrap()),
             name: name.to_string(),
-            qualname: qualname,
-            declaration: decl_id,
-            span: sub_span.unwrap(),
-            scope: self.enclosing_scope(id),
+            qualname,
             // FIXME you get better data here by using the visitor.
             value: String::new(),
-            visibility: vis,
-            parent: parent_scope,
-            docs: docs,
+            parent: parent_scope.map(|id| id_from_def_id(id)),
+            children: vec![],
+            decl_id: decl_id.map(|id| id_from_def_id(id)),
+            docs,
             sig: None,
-            attributes: attributes,
+            attributes: lower_attributes(attributes, self),
         })
     }
 
     pub fn get_trait_ref_data(&self,
-                              trait_ref: &ast::TraitRef,
-                              parent: NodeId)
-                              -> Option<TypeRefData> {
+                              trait_ref: &ast::TraitRef)
+                              -> Option<Ref> {
         self.lookup_ref_id(trait_ref.ref_id).and_then(|def_id| {
             let span = trait_ref.path.span;
             if generated_code(span) {
@@ -477,11 +498,11 @@ pub fn get_trait_ref_data(&self,
             }
             let sub_span = self.span_utils.sub_span_for_type_name(span).or(Some(span));
             filter!(self.span_utils, sub_span, span, None);
-            Some(TypeRefData {
-                span: sub_span.unwrap(),
-                scope: parent,
-                ref_id: Some(def_id),
-                qualname: String::new() // FIXME: generate the real qualname
+            let span = self.span_from_span(sub_span.unwrap());
+            Some(Ref {
+                kind: RefKind::Type,
+                span,
+                ref_id: id_from_def_id(def_id),
             })
         })
     }
@@ -507,11 +528,11 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
                         let f = def.struct_variant().field_named(ident.node.name);
                         let sub_span = self.span_utils.span_for_last_ident(expr.span);
                         filter!(self.span_utils, sub_span, expr.span, None);
-                        return Some(Data::VariableRefData(VariableRefData {
-                            name: ident.node.to_string(),
-                            span: sub_span.unwrap(),
-                            scope: self.enclosing_scope(expr.id),
-                            ref_id: f.did,
+                        let span = self.span_from_span(sub_span.unwrap());
+                        return Some(Data::RefData(Ref {
+                            kind: RefKind::Variable,
+                            span,
+                            ref_id: id_from_def_id(f.did),
                         }));
                     }
                     _ => {
@@ -525,11 +546,11 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
                     ty::TyAdt(def, _) if !def.is_enum() => {
                         let sub_span = self.span_utils.span_for_last_ident(path.span);
                         filter!(self.span_utils, sub_span, path.span, None);
-                        Some(Data::TypeRefData(TypeRefData {
-                            span: sub_span.unwrap(),
-                            scope: self.enclosing_scope(expr.id),
-                            ref_id: Some(def.did),
-                            qualname: String::new() // FIXME: generate the real qualname
+                        let span = self.span_from_span(sub_span.unwrap());
+                        Some(Data::RefData(Ref {
+                            kind: RefKind::Type,
+                            span,
+                            ref_id: id_from_def_id(def.did),
                         }))
                     }
                     _ => {
@@ -548,16 +569,15 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
                 };
                 let sub_span = self.span_utils.sub_span_for_meth_name(expr.span);
                 filter!(self.span_utils, sub_span, expr.span, None);
-                let parent = self.enclosing_scope(expr.id);
-                Some(Data::MethodCallData(MethodCallData {
-                    span: sub_span.unwrap(),
-                    scope: parent,
-                    ref_id: def_id,
-                    decl_id: decl_id,
+                let span = self.span_from_span(sub_span.unwrap());
+                Some(Data::RefData(Ref {
+                    kind: RefKind::Function,
+                    span,
+                    ref_id: def_id.or(decl_id).map(|id| id_from_def_id(id)).unwrap_or(null_id()),
                 }))
             }
             ast::ExprKind::Path(_, ref path) => {
-                self.get_path_data(expr.id, path)
+                self.get_path_data(expr.id, path).map(|d| Data::RefData(d))
             }
             _ => {
                 // FIXME
@@ -566,7 +586,7 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
         }
     }
 
-    pub fn get_path_def(&self, id: NodeId) -> Def {
+    pub fn get_path_def(&self, id: NodeId) -> HirDef {
         match self.tcx.hir.get(id) {
             Node::NodeTraitRef(tr) => tr.path.def,
 
@@ -582,7 +602,7 @@ pub fn get_path_def(&self, id: NodeId) -> Def {
             }
 
             Node::NodeLocal(&hir::Pat { node: hir::PatKind::Binding(_, def_id, ..), .. }) => {
-                Def::Local(def_id)
+                HirDef::Local(def_id)
             }
 
             Node::NodeTy(ty) => {
@@ -595,58 +615,58 @@ pub fn get_path_def(&self, id: NodeId) -> Def {
                                 for item in self.tcx.associated_items(proj.trait_ref.def_id) {
                                     if item.kind == ty::AssociatedKind::Type {
                                         if item.name == proj.item_name(self.tcx) {
-                                            return Def::AssociatedTy(item.def_id);
+                                            return HirDef::AssociatedTy(item.def_id);
                                         }
                                     }
                                 }
                             }
-                            Def::Err
+                            HirDef::Err
                         }
                     }
                 } else {
-                    Def::Err
+                    HirDef::Err
                 }
             }
 
-            _ => Def::Err
+            _ => HirDef::Err
         }
     }
 
-    pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
+    pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Ref> {
         let def = self.get_path_def(id);
         let sub_span = self.span_utils.span_for_last_ident(path.span);
         filter!(self.span_utils, sub_span, path.span, None);
         match def {
-            Def::Upvar(..) |
-            Def::Local(..) |
-            Def::Static(..) |
-            Def::Const(..) |
-            Def::AssociatedConst(..) |
-            Def::StructCtor(..) |
-            Def::VariantCtor(..) => {
-                Some(Data::VariableRefData(VariableRefData {
-                    name: self.span_utils.snippet(sub_span.unwrap()),
-                    span: sub_span.unwrap(),
-                    scope: self.enclosing_scope(id),
-                    ref_id: def.def_id(),
-                }))
+            HirDef::Upvar(..) |
+            HirDef::Local(..) |
+            HirDef::Static(..) |
+            HirDef::Const(..) |
+            HirDef::AssociatedConst(..) |
+            HirDef::StructCtor(..) |
+            HirDef::VariantCtor(..) => {
+                let span = self.span_from_span(sub_span.unwrap());
+                Some(Ref {
+                    kind: RefKind::Variable,
+                    span,
+                    ref_id: id_from_def_id(def.def_id()),
+                })
             }
-            Def::Struct(def_id) |
-            Def::Variant(def_id, ..) |
-            Def::Union(def_id) |
-            Def::Enum(def_id) |
-            Def::TyAlias(def_id) |
-            Def::AssociatedTy(def_id) |
-            Def::Trait(def_id) |
-            Def::TyParam(def_id) => {
-                Some(Data::TypeRefData(TypeRefData {
-                    span: sub_span.unwrap(),
-                    ref_id: Some(def_id),
-                    scope: self.enclosing_scope(id),
-                    qualname: String::new() // FIXME: generate the real qualname
-                }))
+            HirDef::Struct(def_id) |
+            HirDef::Variant(def_id, ..) |
+            HirDef::Union(def_id) |
+            HirDef::Enum(def_id) |
+            HirDef::TyAlias(def_id) |
+            HirDef::AssociatedTy(def_id) |
+            HirDef::Trait(def_id) |
+            HirDef::TyParam(def_id) => {
+                let span = self.span_from_span(sub_span.unwrap());
+                Some(Ref {
+                    kind: RefKind::Type,
+                    span,
+                    ref_id: id_from_def_id(def_id),
+                })
             }
-            Def::Method(decl_id) => {
+            HirDef::Method(decl_id) => {
                 let sub_span = self.span_utils.sub_span_for_meth_name(path.span);
                 filter!(self.span_utils, sub_span, path.span, None);
                 let def_id = if decl_id.is_local() {
@@ -657,60 +677,60 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
                 } else {
                     None
                 };
-                Some(Data::MethodCallData(MethodCallData {
-                    span: sub_span.unwrap(),
-                    scope: self.enclosing_scope(id),
-                    ref_id: def_id,
-                    decl_id: Some(decl_id),
-                }))
+                let span = self.span_from_span(sub_span.unwrap());
+                Some(Ref {
+                    kind: RefKind::Function,
+                    span,
+                    ref_id: id_from_def_id(def_id.unwrap_or(decl_id)),
+                })
             }
-            Def::Fn(def_id) => {
-                Some(Data::FunctionCallData(FunctionCallData {
-                    ref_id: def_id,
-                    span: sub_span.unwrap(),
-                    scope: self.enclosing_scope(id),
-                }))
+            HirDef::Fn(def_id) => {
+                let span = self.span_from_span(sub_span.unwrap());
+                Some(Ref {
+                    kind: RefKind::Function,
+                    span,
+                    ref_id: id_from_def_id(def_id),
+                })
             }
-            Def::Mod(def_id) => {
-                Some(Data::ModRefData(ModRefData {
-                    ref_id: Some(def_id),
-                    span: sub_span.unwrap(),
-                    scope: self.enclosing_scope(id),
-                    qualname: String::new() // FIXME: generate the real qualname
-                }))
+            HirDef::Mod(def_id) => {
+                let span = self.span_from_span(sub_span.unwrap());
+                Some(Ref {
+                    kind: RefKind::Mod,
+                    span,
+                    ref_id: id_from_def_id(def_id),
+                })
             }
-            Def::PrimTy(..) |
-            Def::SelfTy(..) |
-            Def::Label(..) |
-            Def::Macro(..) |
-            Def::GlobalAsm(..) |
-            Def::Err => None,
+            HirDef::PrimTy(..) |
+            HirDef::SelfTy(..) |
+            HirDef::Label(..) |
+            HirDef::Macro(..) |
+            HirDef::GlobalAsm(..) |
+            HirDef::Err => None,
         }
     }
 
     pub fn get_field_ref_data(&self,
                               field_ref: &ast::Field,
-                              variant: &ty::VariantDef,
-                              parent: NodeId)
-                              -> Option<VariableRefData> {
+                              variant: &ty::VariantDef)
+                              -> Option<Ref> {
         let f = variant.field_named(field_ref.ident.node.name);
         // We don't really need a sub-span here, but no harm done
         let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span);
         filter!(self.span_utils, sub_span, field_ref.ident.span, None);
-        Some(VariableRefData {
-            name: field_ref.ident.node.to_string(),
-            span: sub_span.unwrap(),
-            scope: parent,
-            ref_id: f.did,
+        let span = self.span_from_span(sub_span.unwrap());
+        Some(Ref {
+            kind: RefKind::Variable,
+            span,
+            ref_id: id_from_def_id(f.did),
         })
     }
 
-    /// Attempt to return MacroUseData for any AST node.
+    /// Attempt to return MacroRef for any AST node.
     ///
     /// For a given piece of AST defined by the supplied Span and NodeId,
     /// returns None if the node is not macro-generated or the span is malformed,
-    /// else uses the expansion callsite and callee to return some MacroUseData.
-    pub fn get_macro_use_data(&self, span: Span, id: NodeId) -> Option<MacroUseData> {
+    /// else uses the expansion callsite and callee to return some MacroRef.
+    pub fn get_macro_use_data(&self, span: Span) -> Option<MacroRef> {
         if !generated_code(span) {
             return None;
         }
@@ -718,6 +738,7 @@ pub fn get_macro_use_data(&self, span: Span, id: NodeId) -> Option<MacroUseData>
         // nested expansions and ensure we only generate data for source-visible
         // macro uses.
         let callsite = span.source_callsite();
+        let callsite_span = self.span_from_span(callsite);
         let callee = option_try!(span.source_callee());
         let callee_span = option_try!(callee.span);
 
@@ -731,34 +752,25 @@ pub fn get_macro_use_data(&self, span: Span, id: NodeId) -> Option<MacroUseData>
         // when read in, and no longer correspond to the source.
         if let Some(mac) = self.tcx.sess.imported_macro_spans.borrow().get(&callee_span) {
             let &(ref mac_name, mac_span) = mac;
-            return Some(MacroUseData {
-                                        span: callsite,
-                                        name: mac_name.clone(),
-                                        callee_span: mac_span,
-                                        scope: self.enclosing_scope(id),
-                                        imported: true,
-                                        qualname: String::new()// FIXME: generate the real qualname
-                                    });
+            let mac_span = self.span_from_span(mac_span);
+            return Some(MacroRef {
+                span: callsite_span,
+                qualname: mac_name.clone(), // FIXME: generate the real qualname
+                callee_span: mac_span,
+            });
         }
 
-        Some(MacroUseData {
-            span: callsite,
-            name: callee.name().to_string(),
-            callee_span: callee_span,
-            scope: self.enclosing_scope(id),
-            imported: false,
-            qualname: String::new() // FIXME: generate the real qualname
+        let callee_span = self.span_from_span(callee_span);
+        Some(MacroRef {
+            span: callsite_span,
+            qualname: callee.name().to_string(), // FIXME: generate the real qualname
+            callee_span,
         })
     }
 
-    pub fn get_data_for_id(&self, _id: &NodeId) -> Data {
-        // FIXME
-        bug!();
-    }
-
     fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
         match self.get_path_def(ref_id) {
-            Def::PrimTy(_) | Def::SelfTy(..) | Def::Err => None,
+            HirDef::PrimTy(_) | HirDef::SelfTy(..) | HirDef::Err => None,
             def => Some(def.def_id()),
         }
     }
@@ -800,7 +812,7 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
 // An AST visitor for collecting paths from patterns.
 struct PathCollector {
     // The Row field identifies the kind of pattern.
-    collected_paths: Vec<(NodeId, ast::Path, ast::Mutability, recorder::Row)>,
+    collected_paths: Vec<(NodeId, ast::Path, ast::Mutability)>,
 }
 
 impl PathCollector {
@@ -814,12 +826,12 @@ fn visit_pat(&mut self, p: &ast::Pat) {
         match p.node {
             PatKind::Struct(ref path, ..) => {
                 self.collected_paths.push((p.id, path.clone(),
-                                           ast::Mutability::Mutable, recorder::TypeRef));
+                                           ast::Mutability::Mutable));
             }
             PatKind::TupleStruct(ref path, ..) |
             PatKind::Path(_, ref path) => {
                 self.collected_paths.push((p.id, path.clone(),
-                                           ast::Mutability::Mutable, recorder::VarRef));
+                                           ast::Mutability::Mutable));
             }
             PatKind::Ident(bm, ref path1, _) => {
                 debug!("PathCollector, visit ident in pat {}: {:?} {:?}",
@@ -835,7 +847,7 @@ fn visit_pat(&mut self, p: &ast::Pat) {
                 };
                 // collect path for either visit_local or visit_arm
                 let path = ast::Path::from_ident(path1.span, path1.node);
-                self.collected_paths.push((p.id, path, immut, recorder::VarRef));
+                self.collected_paths.push((p.id, path, immut));
             }
             _ => {}
         }
@@ -1032,6 +1044,34 @@ fn id_from_def_id(id: DefId) -> rls_data::Id {
 }
 
 fn id_from_node_id(id: NodeId, scx: &SaveContext) -> rls_data::Id {
-    let def_id = scx.tcx.hir.local_def_id(id);
-    id_from_def_id(def_id)
+    let def_id = scx.tcx.hir.opt_local_def_id(id);
+    def_id.map(|id| id_from_def_id(id)).unwrap_or_else(null_id)
+}
+
+fn null_id() -> rls_data::Id {
+    rls_data::Id {
+        krate: u32::max_value(),
+        index: u32::max_value(),
+    }
+}
+
+fn lower_attributes(attrs: Vec<Attribute>, scx: &SaveContext) -> Vec<rls_data::Attribute> {
+    attrs.into_iter()
+    // Only retain real attributes. Doc comments are lowered separately.
+    .filter(|attr| attr.path != "doc")
+    .map(|mut attr| {
+        // Remove the surrounding '#[..]' or '#![..]' of the pretty printed
+        // attribute. First normalize all inner attribute (#![..]) to outer
+        // ones (#[..]), then remove the two leading and the one trailing character.
+        attr.style = ast::AttrStyle::Outer;
+        let value = pprust::attribute_to_string(&attr);
+        // This str slicing works correctly, because the leading and trailing characters
+        // are in the ASCII range and thus exactly one byte each.
+        let value = value[2..value.len()-1].to_string();
+
+        rls_data::Attribute {
+            value: value,
+            span: scx.span_from_span(attr.span),
+        }
+    }).collect()
 }
index af3efb48090810a602e53a51b6f634de54fa8744..77cde33e9620575e5e8acafe755557a2a73e3386 100644 (file)
@@ -20,7 +20,6 @@
 use syntax::parse::lexer::{self, StringReader};
 use syntax::parse::token::{self, Token};
 use syntax::symbol::keywords;
-use syntax::tokenstream::TokenTree;
 use syntax_pos::*;
 
 #[derive(Clone)]
@@ -277,45 +276,6 @@ pub fn spans_with_brackets(&self, span: Span, nesting: isize, limit: isize) -> V
         }
     }
 
-    /// `span` must be the span for an item such as a function or struct. This
-    /// function returns the program text from the start of the span until the
-    /// end of the 'signature' part, that is up to, but not including an opening
-    /// brace or semicolon.
-    pub fn signature_string_for_span(&self, span: Span) -> String {
-        let mut toks = self.retokenise_span(span);
-        toks.real_token();
-        let mut toks = toks.parse_all_token_trees().unwrap().trees();
-        let mut prev = toks.next().unwrap();
-
-        let first_span = prev.span();
-        let mut angle_count = 0;
-        for tok in toks {
-            if let TokenTree::Token(_, ref tok) = prev {
-                angle_count += match *tok {
-                    token::Eof => { break; }
-                    token::Lt => 1,
-                    token::Gt => -1,
-                    token::BinOp(token::Shl) => 2,
-                    token::BinOp(token::Shr) => -2,
-                    _ => 0,
-                };
-            }
-            if angle_count > 0 {
-                prev = tok;
-                continue;
-            }
-            if let TokenTree::Token(_, token::Semi) = tok {
-                return self.snippet(first_span.to(prev.span()));
-            } else if let TokenTree::Delimited(_, ref d) = tok {
-                if d.delim == token::Brace {
-                    return self.snippet(first_span.to(prev.span()));
-                }
-            }
-            prev = tok;
-        }
-        self.snippet(span)
-    }
-
     pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option<Span> {
         let mut toks = self.retokenise_span(span);
         let mut prev = toks.real_token();
@@ -385,57 +345,44 @@ pub fn spans_for_ty_params(&self, span: Span, number: isize) -> Vec<Span> {
         self.spans_with_brackets(span, 1, number)
     }
 
-    pub fn report_span_err(&self, kind: &str, span: Span) {
-        let loc = self.sess.codemap().lookup_char_pos(span.lo);
-        info!("({}) Could not find sub_span in `{}` in {}, line {}",
-              kind,
-              self.snippet(span),
-              loc.file.name,
-              loc.line);
-        self.err_count.set(self.err_count.get() + 1);
-        if self.err_count.get() > 1000 {
-            bug!("span errors reached 1000, giving up");
-        }
-    }
-
-    // Return the name for a macro definition (identifier after first `!`)
-    pub fn span_for_macro_def_name(&self, span: Span) -> Option<Span> {
-        let mut toks = self.retokenise_span(span);
-        loop {
-            let ts = toks.real_token();
-            if ts.tok == token::Eof {
-                return None;
-            }
-            if ts.tok == token::Not {
-                let ts = toks.real_token();
-                if ts.tok.is_ident() {
-                    return Some(ts.sp);
-                } else {
-                    return None;
-                }
-            }
-        }
-    }
-
-    // Return the name for a macro use (identifier before first `!`).
-    pub fn span_for_macro_use_name(&self, span:Span) -> Option<Span> {
-        let mut toks = self.retokenise_span(span);
-        let mut prev = toks.real_token();
-        loop {
-            if prev.tok == token::Eof {
-                return None;
-            }
-            let ts = toks.real_token();
-            if ts.tok == token::Not {
-                if prev.tok.is_ident() {
-                    return Some(prev.sp);
-                } else {
-                    return None;
-                }
-            }
-            prev = ts;
-        }
-    }
+    // // Return the name for a macro definition (identifier after first `!`)
+    // pub fn span_for_macro_def_name(&self, span: Span) -> Option<Span> {
+    //     let mut toks = self.retokenise_span(span);
+    //     loop {
+    //         let ts = toks.real_token();
+    //         if ts.tok == token::Eof {
+    //             return None;
+    //         }
+    //         if ts.tok == token::Not {
+    //             let ts = toks.real_token();
+    //             if ts.tok.is_ident() {
+    //                 return Some(ts.sp);
+    //             } else {
+    //                 return None;
+    //             }
+    //         }
+    //     }
+    // }
+
+    // // Return the name for a macro use (identifier before first `!`).
+    // pub fn span_for_macro_use_name(&self, span:Span) -> Option<Span> {
+    //     let mut toks = self.retokenise_span(span);
+    //     let mut prev = toks.real_token();
+    //     loop {
+    //         if prev.tok == token::Eof {
+    //             return None;
+    //         }
+    //         let ts = toks.real_token();
+    //         if ts.tok == token::Not {
+    //             if prev.tok.is_ident() {
+    //                 return Some(prev.sp);
+    //             } else {
+    //                 return None;
+    //             }
+    //         }
+    //         prev = ts;
+    //     }
+    // }
 
     /// Return true if the span is generated code, and
     /// it is not a subspan of the root callsite.