1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 use rustc::hir::def_id::DefId;
14 use rustc_serialize::json::as_json;
17 use data::VariableKind;
21 pub struct JsonDumper<'b, W: Write + 'b> {
26 impl<'b, W: Write> JsonDumper<'b, W> {
27 pub fn new(writer: &'b mut W) -> JsonDumper<'b, W> {
28 JsonDumper { output: writer, result: Analysis::new() }
32 impl<'b, W: Write> Drop for JsonDumper<'b, W> {
34 if let Err(_) = write!(self.output, "{}", as_json(&self.result)) {
35 error!("Error writing output");
40 macro_rules! impl_fn {
41 ($fn_name: ident, $data_type: ident, $bucket: ident) => {
42 fn $fn_name(&mut self, data: $data_type) {
43 self.result.$bucket.push(From::from(data));
48 impl<'b, W: Write + 'b> Dump for JsonDumper<'b, W> {
49 fn crate_prelude(&mut self, data: CratePreludeData) {
50 self.result.prelude = Some(data)
53 impl_fn!(extern_crate, ExternCrateData, imports);
54 impl_fn!(use_data, UseData, imports);
55 impl_fn!(use_glob, UseGlobData, imports);
57 impl_fn!(enum_data, EnumData, defs);
58 impl_fn!(tuple_variant, TupleVariantData, defs);
59 impl_fn!(struct_variant, StructVariantData, defs);
60 impl_fn!(struct_data, StructData, defs);
61 impl_fn!(trait_data, TraitData, defs);
62 impl_fn!(function, FunctionData, defs);
63 impl_fn!(method, MethodData, defs);
64 impl_fn!(macro_data, MacroData, defs);
65 impl_fn!(typedef, TypeDefData, defs);
66 impl_fn!(variable, VariableData, defs);
68 impl_fn!(function_ref, FunctionRefData, refs);
69 impl_fn!(function_call, FunctionCallData, refs);
70 impl_fn!(method_call, MethodCallData, refs);
71 impl_fn!(mod_ref, ModRefData, refs);
72 impl_fn!(type_ref, TypeRefData, refs);
73 impl_fn!(variable_ref, VariableRefData, refs);
75 impl_fn!(macro_use, MacroUseData, macro_refs);
77 fn mod_data(&mut self, data: ModData) {
78 let id: Id = From::from(data.id);
84 qualname: data.qualname,
86 children: data.items.into_iter().map(|id| From::from(id)).collect(),
91 if def.span.file_name != def.value {
92 // If the module is an out-of-line defintion, then we'll make the
93 // defintion the first character in the module's file and turn the
94 // the declaration into a reference to it.
100 self.result.refs.push(rf);
101 def.span = SpanData {
102 file_name: def.value.clone(),
112 self.result.defs.push(def);
115 // FIXME store this instead of throwing it away.
116 fn impl_data(&mut self, _data: ImplData) {}
117 fn inheritance(&mut self, _data: InheritanceData) {}
120 // FIXME do we want to change ExternalData to this mode? It will break DXR.
121 // FIXME methods. The defs have information about possible overriding and the
122 // refs have decl information (e.g., a trait method where we know the required
123 // method, but not the supplied method). In both cases, we are currently
126 #[derive(Debug, RustcEncodable)]
129 prelude: Option<CratePreludeData>,
130 imports: Vec<Import>,
133 macro_refs: Vec<MacroRef>,
137 fn new() -> Analysis {
149 // DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
150 // we use our own Id which is the same, but without the newtype.
151 #[derive(Clone, Copy, Debug, RustcEncodable)]
157 impl From<DefId> for Id {
158 fn from(id: DefId) -> Id {
160 krate: id.krate.as_u32(),
161 index: id.index.as_u32(),
166 #[derive(Debug, RustcEncodable)]
175 #[derive(Debug, RustcEncodable)]
182 impl From<ExternCrateData> for Import {
183 fn from(data: ExternCrateData) -> Import {
185 kind: ImportKind::ExternCrate,
189 value: String::new(),
193 impl From<UseData> for Import {
194 fn from(data: UseData) -> Import {
196 kind: ImportKind::Use,
197 ref_id: data.mod_id.map(|id| From::from(id)),
200 value: String::new(),
204 impl From<UseGlobData> for Import {
205 fn from(data: UseGlobData) -> Import {
207 kind: ImportKind::GlobUse,
210 name: "*".to_owned(),
211 value: data.names.join(", "),
216 #[derive(Debug, RustcEncodable)]
227 sig: Option<Signature>,
230 #[derive(Debug, RustcEncodable)]
232 // value = variant names
234 // value = enum name + variant name + types
236 // value = [enum name +] name + fields
240 // value = type + generics
242 // value = type + generics
248 // value = aliased type
250 // value = type and init expression (for all variable kinds).
257 impl From<EnumData> for Def {
258 fn from(data: EnumData) -> Def {
261 id: From::from(data.id),
264 qualname: data.qualname,
266 children: data.variants.into_iter().map(|id| From::from(id)).collect(),
274 impl From<TupleVariantData> for Def {
275 fn from(data: TupleVariantData) -> Def {
277 kind: DefKind::Tuple,
278 id: From::from(data.id),
281 qualname: data.qualname,
290 impl From<StructVariantData> for Def {
291 fn from(data: StructVariantData) -> Def {
293 kind: DefKind::Struct,
294 id: From::from(data.id),
297 qualname: data.qualname,
306 impl From<StructData> for Def {
307 fn from(data: StructData) -> Def {
309 kind: DefKind::Struct,
310 id: From::from(data.id),
313 qualname: data.qualname,
315 children: data.fields.into_iter().map(|id| From::from(id)).collect(),
322 impl From<TraitData> for Def {
323 fn from(data: TraitData) -> Def {
325 kind: DefKind::Trait,
326 id: From::from(data.id),
329 qualname: data.qualname,
331 children: data.items.into_iter().map(|id| From::from(id)).collect(),
338 impl From<FunctionData> for Def {
339 fn from(data: FunctionData) -> Def {
341 kind: DefKind::Function,
342 id: From::from(data.id),
345 qualname: data.qualname,
354 impl From<MethodData> for Def {
355 fn from(data: MethodData) -> Def {
357 kind: DefKind::Method,
358 id: From::from(data.id),
361 qualname: data.qualname,
364 decl_id: data.decl_id.map(|id| From::from(id)),
370 impl From<MacroData> for Def {
371 fn from(data: MacroData) -> Def {
373 kind: DefKind::Macro,
374 id: From::from(null_def_id()),
377 qualname: data.qualname,
378 value: String::new(),
386 impl From<TypeDefData> for Def {
387 fn from(data: TypeDefData) -> Def {
390 id: From::from(data.id),
393 qualname: data.qualname,
402 impl From<VariableData> for Def {
403 fn from(data: VariableData) -> Def {
405 kind: match data.kind {
406 VariableKind::Static => DefKind::Static,
407 VariableKind::Const => DefKind::Const,
408 VariableKind::Local => DefKind::Local,
409 VariableKind::Field => DefKind::Field,
411 id: From::from(data.id),
414 qualname: data.qualname,
415 value: data.type_value,
424 #[derive(Debug, RustcEncodable)]
432 #[derive(Debug, RustcEncodable)]
439 impl From<FunctionRefData> for Ref {
440 fn from(data: FunctionRefData) -> Ref {
442 kind: RefKind::Function,
444 ref_id: From::from(data.ref_id),
448 impl From<FunctionCallData> for Ref {
449 fn from(data: FunctionCallData) -> Ref {
451 kind: RefKind::Function,
453 ref_id: From::from(data.ref_id),
457 impl From<MethodCallData> for Ref {
458 fn from(data: MethodCallData) -> Ref {
460 kind: RefKind::Function,
462 ref_id: From::from(data.ref_id.or(data.decl_id).unwrap_or(null_def_id())),
466 impl From<ModRefData> for Ref {
467 fn from(data: ModRefData) -> Ref {
471 ref_id: From::from(data.ref_id.unwrap_or(null_def_id())),
475 impl From<TypeRefData> for Ref {
476 fn from(data: TypeRefData) -> Ref {
480 ref_id: From::from(data.ref_id.unwrap_or(null_def_id())),
484 impl From<VariableRefData> for Ref {
485 fn from(data: VariableRefData) -> Ref {
487 kind: RefKind::Variable,
489 ref_id: From::from(data.ref_id),
494 #[derive(Debug, RustcEncodable)]
498 callee_span: SpanData,
501 impl From<MacroUseData> for MacroRef {
502 fn from(data: MacroUseData) -> MacroRef {
505 qualname: data.qualname,
506 callee_span: data.callee_span,