]> git.lizzy.rs Git - rust.git/blob - src/librustc_save_analysis/json_dumper.rs
3abb19d53841419fbe00dc523347e5d4193f3a81
[rust.git] / src / librustc_save_analysis / json_dumper.rs
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.
4 //
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.
10
11 use std::io::Write;
12
13 use rustc::hir::def_id::DefId;
14 use rustc_serialize::json::as_json;
15
16 use external_data::*;
17 use data::VariableKind;
18 use dump::Dump;
19 use super::Format;
20
21 pub struct JsonDumper<'b, W: Write + 'b> {
22     output: &'b mut W,
23     result: Analysis,
24 }
25
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() }
29     }
30 }
31
32 impl<'b, W: Write> Drop for JsonDumper<'b, W> {
33     fn drop(&mut self) {
34         if let Err(_) = write!(self.output, "{}", as_json(&self.result)) {
35             error!("Error writing output");
36         }
37     }
38 }
39
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));
44         }
45     }
46 }
47
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)
51     }
52
53     impl_fn!(extern_crate, ExternCrateData, imports);
54     impl_fn!(use_data, UseData, imports);
55     impl_fn!(use_glob, UseGlobData, imports);
56
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);
67
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);
74
75     impl_fn!(macro_use, MacroUseData, macro_refs);
76
77     fn mod_data(&mut self, data: ModData) {
78         let id: Id = From::from(data.id);
79         let mut def = Def {
80             kind: DefKind::Mod,
81             id: id,
82             span: data.span,
83             name: data.name,
84             qualname: data.qualname,
85             value: data.filename,
86             children: data.items.into_iter().map(|id| From::from(id)).collect(),
87             decl_id: None,
88             docs: data.docs,
89             sig: None,
90         };
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.
95             let rf = Ref {
96                 kind: RefKind::Mod,
97                 span: def.span,
98                 ref_id: id,
99             };
100             self.result.refs.push(rf);
101             def.span = SpanData {
102                 file_name: def.value.clone(),
103                 byte_start: 0,
104                 byte_end: 0,
105                 line_start: 1,
106                 line_end: 1,
107                 column_start: 1,
108                 column_end: 1,
109             }
110         }
111
112         self.result.defs.push(def);
113     }
114
115     // FIXME store this instead of throwing it away.
116     fn impl_data(&mut self, _data: ImplData) {}
117     fn inheritance(&mut self, _data: InheritanceData) {}
118 }
119
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
124 // ignoring it.
125
126 #[derive(Debug, RustcEncodable)]
127 struct Analysis {
128     kind: Format,
129     prelude: Option<CratePreludeData>,
130     imports: Vec<Import>,
131     defs: Vec<Def>,
132     refs: Vec<Ref>,
133     macro_refs: Vec<MacroRef>,
134 }
135
136 impl Analysis {
137     fn new() -> Analysis {
138         Analysis {
139             kind: Format::Json,
140             prelude: None,
141             imports: vec![],
142             defs: vec![],
143             refs: vec![],
144             macro_refs: vec![],
145         }
146     }
147 }
148
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)]
152 struct Id {
153     krate: u32,
154     index: u32,
155 }
156
157 impl From<DefId> for Id {
158     fn from(id: DefId) -> Id {
159         Id {
160             krate: id.krate.as_u32(),
161             index: id.index.as_u32(),
162         }
163     }
164 }
165
166 #[derive(Debug, RustcEncodable)]
167 struct Import {
168     kind: ImportKind,
169     ref_id: Option<Id>,
170     span: SpanData,
171     name: String,
172     value: String,
173 }
174
175 #[derive(Debug, RustcEncodable)]
176 enum ImportKind {
177     ExternCrate,
178     Use,
179     GlobUse,
180 }
181
182 impl From<ExternCrateData> for Import {
183     fn from(data: ExternCrateData) -> Import {
184         Import {
185             kind: ImportKind::ExternCrate,
186             ref_id: None,
187             span: data.span,
188             name: data.name,
189             value: String::new(),
190         }
191     }
192 }
193 impl From<UseData> for Import {
194     fn from(data: UseData) -> Import {
195         Import {
196             kind: ImportKind::Use,
197             ref_id: data.mod_id.map(|id| From::from(id)),
198             span: data.span,
199             name: data.name,
200             value: String::new(),
201         }
202     }
203 }
204 impl From<UseGlobData> for Import {
205     fn from(data: UseGlobData) -> Import {
206         Import {
207             kind: ImportKind::GlobUse,
208             ref_id: None,
209             span: data.span,
210             name: "*".to_owned(),
211             value: data.names.join(", "),
212         }
213     }
214 }
215
216 #[derive(Debug, RustcEncodable)]
217 struct Def {
218     kind: DefKind,
219     id: Id,
220     span: SpanData,
221     name: String,
222     qualname: String,
223     value: String,
224     children: Vec<Id>,
225     decl_id: Option<Id>,
226     docs: String,
227     sig: Option<Signature>,
228 }
229
230 #[derive(Debug, RustcEncodable)]
231 enum DefKind {
232     // value = variant names
233     Enum,
234     // value = enum name + variant name + types
235     Tuple,
236     // value = [enum name +] name + fields
237     Struct,
238     // value = signature
239     Trait,
240     // value = type + generics
241     Function,
242     // value = type + generics
243     Method,
244     // No id, no value.
245     Macro,
246     // value = file_name
247     Mod,
248     // value = aliased type
249     Type,
250     // value = type and init expression (for all variable kinds).
251     Local,
252     Static,
253     Const,
254     Field,
255 }
256
257 impl From<EnumData> for Def {
258     fn from(data: EnumData) -> Def {
259         Def {
260             kind: DefKind::Enum,
261             id: From::from(data.id),
262             span: data.span,
263             name: data.name,
264             qualname: data.qualname,
265             value: data.value,
266             children: data.variants.into_iter().map(|id| From::from(id)).collect(),
267             decl_id: None,
268             docs: data.docs,
269             sig: None,
270         }
271     }
272 }
273
274 impl From<TupleVariantData> for Def {
275     fn from(data: TupleVariantData) -> Def {
276         Def {
277             kind: DefKind::Tuple,
278             id: From::from(data.id),
279             span: data.span,
280             name: data.name,
281             qualname: data.qualname,
282             value: data.value,
283             children: vec![],
284             decl_id: None,
285             docs: data.docs,
286             sig: None,
287         }
288     }
289 }
290 impl From<StructVariantData> for Def {
291     fn from(data: StructVariantData) -> Def {
292         Def {
293             kind: DefKind::Struct,
294             id: From::from(data.id),
295             span: data.span,
296             name: data.name,
297             qualname: data.qualname,
298             value: data.value,
299             children: vec![],
300             decl_id: None,
301             docs: data.docs,
302             sig: None,
303         }
304     }
305 }
306 impl From<StructData> for Def {
307     fn from(data: StructData) -> Def {
308         Def {
309             kind: DefKind::Struct,
310             id: From::from(data.id),
311             span: data.span,
312             name: data.name,
313             qualname: data.qualname,
314             value: data.value,
315             children: data.fields.into_iter().map(|id| From::from(id)).collect(),
316             decl_id: None,
317             docs: data.docs,
318             sig: Some(data.sig),
319         }
320     }
321 }
322 impl From<TraitData> for Def {
323     fn from(data: TraitData) -> Def {
324         Def {
325             kind: DefKind::Trait,
326             id: From::from(data.id),
327             span: data.span,
328             name: data.name,
329             qualname: data.qualname,
330             value: data.value,
331             children: data.items.into_iter().map(|id| From::from(id)).collect(),
332             decl_id: None,
333             docs: data.docs,
334             sig: None,
335         }
336     }
337 }
338 impl From<FunctionData> for Def {
339     fn from(data: FunctionData) -> Def {
340         Def {
341             kind: DefKind::Function,
342             id: From::from(data.id),
343             span: data.span,
344             name: data.name,
345             qualname: data.qualname,
346             value: data.value,
347             children: vec![],
348             decl_id: None,
349             docs: data.docs,
350             sig: None,
351         }
352     }
353 }
354 impl From<MethodData> for Def {
355     fn from(data: MethodData) -> Def {
356         Def {
357             kind: DefKind::Method,
358             id: From::from(data.id),
359             span: data.span,
360             name: data.name,
361             qualname: data.qualname,
362             value: data.value,
363             children: vec![],
364             decl_id: data.decl_id.map(|id| From::from(id)),
365             docs: data.docs,
366             sig: None,
367         }
368     }
369 }
370 impl From<MacroData> for Def {
371     fn from(data: MacroData) -> Def {
372         Def {
373             kind: DefKind::Macro,
374             id: From::from(null_def_id()),
375             span: data.span,
376             name: data.name,
377             qualname: data.qualname,
378             value: String::new(),
379             children: vec![],
380             decl_id: None,
381             docs: data.docs,
382             sig: None,
383         }
384     }
385 }
386 impl From<TypeDefData> for Def {
387     fn from(data: TypeDefData) -> Def {
388         Def {
389             kind: DefKind::Type,
390             id: From::from(data.id),
391             span: data.span,
392             name: data.name,
393             qualname: data.qualname,
394             value: data.value,
395             children: vec![],
396             decl_id: None,
397             docs: String::new(),
398             sig: None,
399         }
400     }
401 }
402 impl From<VariableData> for Def {
403     fn from(data: VariableData) -> Def {
404         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,
410             },
411             id: From::from(data.id),
412             span: data.span,
413             name: data.name,
414             qualname: data.qualname,
415             value: data.type_value,
416             children: vec![],
417             decl_id: None,
418             docs: data.docs,
419             sig: None,
420         }
421     }
422 }
423
424 #[derive(Debug, RustcEncodable)]
425 enum RefKind {
426     Function,
427     Mod,
428     Type,
429     Variable,
430 }
431
432 #[derive(Debug, RustcEncodable)]
433 struct Ref {
434     kind: RefKind,
435     span: SpanData,
436     ref_id: Id,
437 }
438
439 impl From<FunctionRefData> for Ref {
440     fn from(data: FunctionRefData) -> Ref {
441         Ref {
442             kind: RefKind::Function,
443             span: data.span,
444             ref_id: From::from(data.ref_id),
445         }
446     }
447 }
448 impl From<FunctionCallData> for Ref {
449     fn from(data: FunctionCallData) -> Ref {
450         Ref {
451             kind: RefKind::Function,
452             span: data.span,
453             ref_id: From::from(data.ref_id),
454         }
455     }
456 }
457 impl From<MethodCallData> for Ref {
458     fn from(data: MethodCallData) -> Ref {
459         Ref {
460             kind: RefKind::Function,
461             span: data.span,
462             ref_id: From::from(data.ref_id.or(data.decl_id).unwrap_or(null_def_id())),
463         }
464     }
465 }
466 impl From<ModRefData> for Ref {
467     fn from(data: ModRefData) -> Ref {
468         Ref {
469             kind: RefKind::Mod,
470             span: data.span,
471             ref_id: From::from(data.ref_id.unwrap_or(null_def_id())),
472         }
473     }
474 }
475 impl From<TypeRefData> for Ref {
476     fn from(data: TypeRefData) -> Ref {
477         Ref {
478             kind: RefKind::Type,
479             span: data.span,
480             ref_id: From::from(data.ref_id.unwrap_or(null_def_id())),
481         }
482     }
483 }
484 impl From<VariableRefData> for Ref {
485     fn from(data: VariableRefData) -> Ref {
486         Ref {
487             kind: RefKind::Variable,
488             span: data.span,
489             ref_id: From::from(data.ref_id),
490         }
491     }
492 }
493
494 #[derive(Debug, RustcEncodable)]
495 struct MacroRef {
496     span: SpanData,
497     qualname: String,
498     callee_span: SpanData,
499 }
500
501 impl From<MacroUseData> for MacroRef {
502     fn from(data: MacroUseData) -> MacroRef {
503         MacroRef {
504             span: data.span,
505             qualname: data.qualname,
506             callee_span: data.callee_span,
507         }
508     }
509 }