save-analysis-json: introduce a lowering step
...in which we make the spans nice.
This commit is contained in:
parent
e7b8c5e3ab
commit
91b5ed5ce3
2 changed files with 607 additions and 9 deletions
|
@ -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,
|
||||
|
|
|
@ -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<data::ExternalCrateData>,
|
||||
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<DefId>,
|
||||
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<DefId>,
|
||||
pub self_ref: Option<DefId>,
|
||||
}
|
||||
|
||||
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<DefId>,
|
||||
pub decl_id: Option<DefId>,
|
||||
}
|
||||
|
||||
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<DefId>,
|
||||
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<DefId>,
|
||||
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<DefId>,
|
||||
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<String>,
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue