diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs index 2fbeac8be83..b79c459920a 100644 --- a/src/librustc_save_analysis/data.rs +++ b/src/librustc_save_analysis/data.rs @@ -18,7 +18,37 @@ use std::hash::Hasher; use rustc::hir::def_id::DefId; use rustc::ty; use syntax::ast::{CrateNum, NodeId}; -use syntax::codemap::Span; +use syntax::codemap::{Span, CodeMap}; + +#[derive(Debug, Clone, RustcEncodable)] +pub struct SpanData { + file_name: String, + byte_start: u32, + byte_end: u32, + /// 1-based. + line_start: usize, + line_end: usize, + /// 1-based, character offset. + column_start: usize, + column_end: usize, +} + +impl SpanData { + pub fn 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(), + byte_start: span.lo.0, + byte_end: span.hi.0, + line_start: start.line, + line_end: end.line, + column_start: start.col.0 + 1, + column_end: end.col.0 + 1, + } + } +} pub struct CrateData { pub name: String, diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index 8a631ad8b32..e040b392ae7 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -11,31 +11,37 @@ use std::io::Write; use rustc_serialize::json::as_json; +use syntax::codemap::CodeMap; -use super::data::*; +use rustc::hir::def_id::DefId; +use syntax::ast::{CrateNum, NodeId}; + +use super::data::{self, SpanData}; use super::dump::Dump; -pub struct JsonDumper<'b, W: 'b> { +pub struct JsonDumper<'a, 'b, W: 'b> { output: &'b mut W, + codemap: &'a CodeMap, } -impl<'b, W: Write> JsonDumper<'b, W> { - pub fn new(writer: &'b mut W) -> JsonDumper<'b, W> { - JsonDumper { output: writer } +impl<'a, 'b, W: Write> JsonDumper<'a, 'b, W> { + pub fn new(writer: &'b mut W, codemap: &'a CodeMap) -> JsonDumper<'a, 'b, W> { + JsonDumper { output: writer, codemap:codemap } } } macro_rules! impl_fn { ($fn_name: ident, $data_type: ident) => { - fn $fn_name(&mut self, data: $data_type) { + fn $fn_name(&mut self, data: data::$data_type) { + let data = data.lower(self.codemap); if let Err(_) = write!(self.output, "{}", as_json(&data)) { error!("Error writing output '{}'", as_json(&data)); } - } + } } } -impl<'b, W: Write + 'b> Dump for JsonDumper<'b, W> { +impl<'a, 'b, W: Write + 'b> Dump for JsonDumper<'a, 'b, W> { impl_fn!(crate_prelude, CratePreludeData); impl_fn!(enum_data, EnumData); impl_fn!(extern_crate, ExternCrateData); @@ -61,3 +67,565 @@ impl<'b, W: Write + 'b> Dump for JsonDumper<'b, W> { impl_fn!(variable, VariableData); impl_fn!(variable_ref, VariableRefData); } + +trait Lower { + type Target; + fn lower(self, cm: &CodeMap) -> Self::Target; +} + +#[derive(Debug, RustcEncodable)] +pub struct CratePreludeData { + pub crate_name: String, + pub crate_root: String, + pub external_crates: Vec, + pub span: SpanData, +} + +impl Lower for data::CratePreludeData { + type Target = CratePreludeData; + + fn lower(self, cm: &CodeMap) -> CratePreludeData { + CratePreludeData { + crate_name: self.crate_name, + crate_root: self.crate_root, + external_crates: self.external_crates, + span: SpanData::from_span(self.span, cm), + } + } +} + +/// Data for enum declarations. +#[derive(Clone, Debug, RustcEncodable)] +pub struct EnumData { + pub id: NodeId, + pub value: String, + pub qualname: String, + pub span: SpanData, + pub scope: NodeId, +} + +impl Lower for data::EnumData { + type Target = EnumData; + + fn lower(self, cm: &CodeMap) -> EnumData { + EnumData { + id: self.id, + value: self.value, + qualname: self.qualname, + span: SpanData::from_span(self.span, cm), + scope: self.scope, + } + } +} + +/// Data for extern crates. +#[derive(Debug, RustcEncodable)] +pub struct ExternCrateData { + pub id: NodeId, + pub name: String, + pub crate_num: CrateNum, + pub location: String, + pub span: SpanData, + pub scope: NodeId, +} + +impl Lower for data::ExternCrateData { + type Target = ExternCrateData; + + fn lower(self, cm: &CodeMap) -> ExternCrateData { + ExternCrateData { + id: self.id, + name: self.name, + crate_num: self.crate_num, + location: self.location, + span: SpanData::from_span(self.span, cm), + scope: self.scope, + } + } +} + +/// Data about a function call. +#[derive(Debug, RustcEncodable)] +pub struct FunctionCallData { + pub span: SpanData, + pub scope: NodeId, + pub ref_id: DefId, +} + +impl Lower for data::FunctionCallData { + type Target = FunctionCallData; + + fn lower(self, cm: &CodeMap) -> FunctionCallData { + FunctionCallData { + span: SpanData::from_span(self.span, cm), + scope: self.scope, + ref_id: self.ref_id, + } + } +} + +/// Data for all kinds of functions and methods. +#[derive(Clone, Debug, RustcEncodable)] +pub struct FunctionData { + pub id: NodeId, + pub name: String, + pub qualname: String, + pub declaration: Option, + pub span: SpanData, + pub scope: NodeId, +} + +impl Lower for data::FunctionData { + type Target = FunctionData; + + fn lower(self, cm: &CodeMap) -> FunctionData { + FunctionData { + id: self.id, + name: self.name, + qualname: self.qualname, + declaration: self.declaration, + span: SpanData::from_span(self.span, cm), + scope: self.scope, + } + } +} + +/// Data about a function call. +#[derive(Debug, RustcEncodable)] +pub struct FunctionRefData { + pub span: SpanData, + pub scope: NodeId, + pub ref_id: DefId, +} + +impl Lower for data::FunctionRefData { + type Target = FunctionRefData; + + fn lower(self, cm: &CodeMap) -> FunctionRefData { + FunctionRefData { + span: SpanData::from_span(self.span, cm), + scope: self.scope, + ref_id: self.ref_id, + } + } +} +#[derive(Debug, RustcEncodable)] +pub struct ImplData { + pub id: NodeId, + pub span: SpanData, + pub scope: NodeId, + pub trait_ref: Option, + pub self_ref: Option, +} + +impl Lower for data::ImplData { + type Target = ImplData; + + fn lower(self, cm: &CodeMap) -> ImplData { + ImplData { + id: self.id, + span: SpanData::from_span(self.span, cm), + scope: self.scope, + trait_ref: self.trait_ref, + self_ref: self.self_ref, + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct InheritanceData { + pub span: SpanData, + pub base_id: DefId, + pub deriv_id: NodeId +} + +impl Lower for data::InheritanceData { + type Target = InheritanceData; + + fn lower(self, cm: &CodeMap) -> InheritanceData { + InheritanceData { + span: SpanData::from_span(self.span, cm), + base_id: self.base_id, + deriv_id: self.deriv_id + } + } +} + +/// Data about a macro declaration. +#[derive(Debug, RustcEncodable)] +pub struct MacroData { + pub span: SpanData, + pub name: String, + pub qualname: String, +} + +impl Lower for data::MacroData { + type Target = MacroData; + + fn lower(self, cm: &CodeMap) -> MacroData { + MacroData { + span: SpanData::from_span(self.span, cm), + name: self.name, + qualname: self.qualname, + } + } +} + +/// Data about a macro use. +#[derive(Debug, RustcEncodable)] +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: NodeId, + pub imported: bool, +} + +impl Lower for data::MacroUseData { + type Target = MacroUseData; + + fn lower(self, cm: &CodeMap) -> MacroUseData { + MacroUseData { + span: SpanData::from_span(self.span, cm), + name: self.name, + qualname: self.qualname, + callee_span: SpanData::from_span(self.callee_span, cm), + scope: self.scope, + imported: self.imported, + } + } +} + +/// Data about a method call. +#[derive(Debug, RustcEncodable)] +pub struct MethodCallData { + pub span: SpanData, + pub scope: NodeId, + pub ref_id: Option, + pub decl_id: Option, +} + +impl Lower for data::MethodCallData { + type Target = MethodCallData; + + fn lower(self, cm: &CodeMap) -> MethodCallData { + MethodCallData { + span: SpanData::from_span(self.span, cm), + scope: self.scope, + 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, RustcEncodable)] +pub struct MethodData { + pub id: NodeId, + pub qualname: String, + pub span: SpanData, + pub scope: NodeId, +} + +impl Lower for data::MethodData { + type Target = MethodData; + + fn lower(self, cm: &CodeMap) -> MethodData { + MethodData { + span: SpanData::from_span(self.span, cm), + scope: self.scope, + id: self.id, + qualname: self.qualname, + } + } +} + +/// Data for modules. +#[derive(Debug, RustcEncodable)] +pub struct ModData { + pub id: NodeId, + pub name: String, + pub qualname: String, + pub span: SpanData, + pub scope: NodeId, + pub filename: String, +} + +impl Lower for data::ModData { + type Target = ModData; + + fn lower(self, cm: &CodeMap) -> ModData { + ModData { + id: self.id, + name: self.name, + qualname: self.qualname, + span: SpanData::from_span(self.span, cm), + scope: self.scope, + filename: self.filename, + } + } +} + +/// Data for a reference to a module. +#[derive(Debug, RustcEncodable)] +pub struct ModRefData { + pub span: SpanData, + pub scope: NodeId, + pub ref_id: Option, + pub qualname: String +} + +impl Lower for data::ModRefData { + type Target = ModRefData; + + fn lower(self, cm: &CodeMap) -> ModRefData { + ModRefData { + span: SpanData::from_span(self.span, cm), + scope: self.scope, + ref_id: self.ref_id, + qualname: self.qualname, + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct StructData { + pub span: SpanData, + pub id: NodeId, + pub ctor_id: NodeId, + pub qualname: String, + pub scope: NodeId, + pub value: String +} + +impl Lower for data::StructData { + type Target = StructData; + + fn lower(self, cm: &CodeMap) -> StructData { + StructData { + span: SpanData::from_span(self.span, cm), + id: self.id, + ctor_id: self.ctor_id, + qualname: self.qualname, + scope: self.scope, + value: self.value + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct StructVariantData { + pub span: SpanData, + pub id: NodeId, + pub qualname: String, + pub type_value: String, + pub value: String, + pub scope: NodeId +} + +impl Lower for data::StructVariantData { + type Target = StructVariantData; + + fn lower(self, cm: &CodeMap) -> StructVariantData { + StructVariantData { + span: SpanData::from_span(self.span, cm), + id: self.id, + qualname: self.qualname, + type_value: self.type_value, + value: self.value, + scope: self.scope, + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct TraitData { + pub span: SpanData, + pub id: NodeId, + pub qualname: String, + pub scope: NodeId, + pub value: String +} + +impl Lower for data::TraitData { + type Target = TraitData; + + fn lower(self, cm: &CodeMap) -> TraitData { + TraitData { + span: SpanData::from_span(self.span, cm), + id: self.id, + qualname: self.qualname, + scope: self.scope, + value: self.value, + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct TupleVariantData { + pub span: SpanData, + pub id: NodeId, + pub name: String, + pub qualname: String, + pub type_value: String, + pub value: String, + pub scope: NodeId, +} + +impl Lower for data::TupleVariantData { + type Target = TupleVariantData; + + fn lower(self, cm: &CodeMap) -> TupleVariantData { + TupleVariantData { + span: SpanData::from_span(self.span, cm), + id: self.id, + name: self.name, + qualname: self.qualname, + type_value: self.type_value, + value: self.value, + scope: self.scope, + } + } +} + +/// Data for a typedef. +#[derive(Debug, RustcEncodable)] +pub struct TypedefData { + pub id: NodeId, + pub span: SpanData, + pub qualname: String, + pub value: String, +} + +impl Lower for data::TypedefData { + type Target = TypedefData; + + fn lower(self, cm: &CodeMap) -> TypedefData { + TypedefData { + id: self.id, + span: SpanData::from_span(self.span, cm), + qualname: self.qualname, + value: self.value, + } + } +} + +/// Data for a reference to a type or trait. +#[derive(Clone, Debug, RustcEncodable)] +pub struct TypeRefData { + pub span: SpanData, + pub scope: NodeId, + pub ref_id: Option, + pub qualname: String, +} + +impl Lower for data::TypeRefData { + type Target = TypeRefData; + + fn lower(self, cm: &CodeMap) -> TypeRefData { + TypeRefData { + span: SpanData::from_span(self.span, cm), + scope: self.scope, + ref_id: self.ref_id, + qualname: self.qualname, + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct UseData { + pub id: NodeId, + pub span: SpanData, + pub name: String, + pub mod_id: Option, + pub scope: NodeId +} + +impl Lower for data::UseData { + type Target = UseData; + + fn lower(self, cm: &CodeMap) -> UseData { + UseData { + id: self.id, + span: SpanData::from_span(self.span, cm), + name: self.name, + mod_id: self.mod_id, + scope: self.scope, + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct UseGlobData { + pub id: NodeId, + pub span: SpanData, + pub names: Vec, + pub scope: NodeId +} + +impl Lower for data::UseGlobData { + type Target = UseGlobData; + + fn lower(self, cm: &CodeMap) -> UseGlobData { + UseGlobData { + id: self.id, + span: SpanData::from_span(self.span, cm), + names: self.names, + scope: self.scope, + } + } +} + +/// Data for local and global variables (consts and statics). +#[derive(Debug, RustcEncodable)] +pub struct VariableData { + pub id: NodeId, + pub name: String, + pub qualname: String, + pub span: SpanData, + pub scope: NodeId, + pub value: String, + pub type_value: String, +} + +impl Lower for data::VariableData { + type Target = VariableData; + + fn lower(self, cm: &CodeMap) -> VariableData { + VariableData { + id: self.id, + name: self.name, + qualname: self.qualname, + span: SpanData::from_span(self.span, cm), + scope: self.scope, + value: self.value, + type_value: self.type_value, + } + } +} + +/// 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, RustcEncodable)] +pub struct VariableRefData { + pub name: String, + pub span: SpanData, + pub scope: NodeId, + pub ref_id: DefId, +} + +impl Lower for data::VariableRefData { + type Target = VariableRefData; + + fn lower(self, cm: &CodeMap) -> VariableRefData { + VariableRefData { + name: self.name, + span: SpanData::from_span(self.span, cm), + scope: self.scope, + ref_id: self.ref_id, + } + } +}