提交 8a2857e6 编写于 作者: N Nick Cameron

Remove intermediate forms and some other refactoring

上级 9a471606
// 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,
}
// 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) {}
}
......@@ -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
......@@ -27,16 +24,12 @@
//! 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};
......@@ -48,15 +41,12 @@
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);
......
// 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,
}
}
}
......@@ -12,12 +12,9 @@
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);
}
}
}
......@@ -12,14 +12,11 @@
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);
}
}
......@@ -37,17 +37,14 @@
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;
......@@ -61,32 +58,21 @@
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()
}
......@@ -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.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册