]> git.lizzy.rs Git - rust.git/blob - src/librustc_save_analysis/json_dumper.rs
f97272ad5440960a7d112fa3b4f8f4138ee89245
[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         };
90         if def.span.file_name != def.value {
91             // If the module is an out-of-line defintion, then we'll make the
92             // defintion the first character in the module's file and turn the
93             // the declaration into a reference to it.
94             let rf = Ref {
95                 kind: RefKind::Mod,
96                 span: def.span,
97                 ref_id: id,
98             };
99             self.result.refs.push(rf);
100             def.span = SpanData {
101                 file_name: def.value.clone(),
102                 byte_start: 0,
103                 byte_end: 0,
104                 line_start: 1,
105                 line_end: 1,
106                 column_start: 1,
107                 column_end: 1,
108             }
109         }
110
111         self.result.defs.push(def);
112     }
113
114     // FIXME store this instead of throwing it away.
115     fn impl_data(&mut self, _data: ImplData) {}
116     fn inheritance(&mut self, _data: InheritanceData) {}
117 }
118
119 // FIXME do we want to change ExternalData to this mode? It will break DXR.
120 // FIXME methods. The defs have information about possible overriding and the
121 // refs have decl information (e.g., a trait method where we know the required
122 // method, but not the supplied method). In both cases, we are currently
123 // ignoring it.
124
125 #[derive(Debug, RustcEncodable)]
126 struct Analysis {
127     kind: Format,
128     prelude: Option<CratePreludeData>,
129     imports: Vec<Import>,
130     defs: Vec<Def>,
131     refs: Vec<Ref>,
132     macro_refs: Vec<MacroRef>,
133 }
134
135 impl Analysis {
136     fn new() -> Analysis {
137         Analysis {
138             kind: Format::Json,
139             prelude: None,
140             imports: vec![],
141             defs: vec![],
142             refs: vec![],
143             macro_refs: vec![],
144         }
145     }
146 }
147
148 // DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
149 // we use our own Id which is the same, but without the newtype.
150 #[derive(Clone, Copy, Debug, RustcEncodable)]
151 struct Id {
152     krate: u32,
153     index: u32,
154 }
155
156 impl From<DefId> for Id {
157     fn from(id: DefId) -> Id {
158         Id {
159             krate: id.krate.as_u32(),
160             index: id.index.as_u32(),
161         }
162     }
163 }
164
165 #[derive(Debug, RustcEncodable)]
166 struct Import {
167     kind: ImportKind,
168     ref_id: Option<Id>,
169     span: SpanData,
170     name: String,
171     value: String,
172 }
173
174 #[derive(Debug, RustcEncodable)]
175 enum ImportKind {
176     ExternCrate,
177     Use,
178     GlobUse,
179 }
180
181 impl From<ExternCrateData> for Import {
182     fn from(data: ExternCrateData) -> Import {
183         Import {
184             kind: ImportKind::ExternCrate,
185             ref_id: None,
186             span: data.span,
187             name: data.name,
188             value: String::new(),
189         }
190     }
191 }
192 impl From<UseData> for Import {
193     fn from(data: UseData) -> Import {
194         Import {
195             kind: ImportKind::Use,
196             ref_id: data.mod_id.map(|id| From::from(id)),
197             span: data.span,
198             name: data.name,
199             value: String::new(),
200         }
201     }
202 }
203 impl From<UseGlobData> for Import {
204     fn from(data: UseGlobData) -> Import {
205         Import {
206             kind: ImportKind::GlobUse,
207             ref_id: None,
208             span: data.span,
209             name: "*".to_owned(),
210             value: data.names.join(", "),
211         }
212     }
213 }
214
215 #[derive(Debug, RustcEncodable)]
216 struct Def {
217     kind: DefKind,
218     id: Id,
219     span: SpanData,
220     name: String,
221     qualname: String,
222     value: String,
223     children: Vec<Id>,
224     decl_id: Option<Id>,
225     docs: String,
226 }
227
228 #[derive(Debug, RustcEncodable)]
229 enum DefKind {
230     // value = variant names
231     Enum,
232     // value = enum name + variant name + types
233     Tuple,
234     // value = [enum name +] name + fields
235     Struct,
236     // value = signature
237     Trait,
238     // value = type + generics
239     Function,
240     // value = type + generics
241     Method,
242     // No id, no value.
243     Macro,
244     // value = file_name
245     Mod,
246     // value = aliased type
247     Type,
248     // value = type and init expression (for all variable kinds).
249     Local,
250     Static,
251     Const,
252     Field,
253 }
254
255 impl From<EnumData> for Def {
256     fn from(data: EnumData) -> Def {
257         Def {
258             kind: DefKind::Enum,
259             id: From::from(data.id),
260             span: data.span,
261             name: data.name,
262             qualname: data.qualname,
263             value: data.value,
264             children: data.variants.into_iter().map(|id| From::from(id)).collect(),
265             decl_id: None,
266             docs: data.docs,
267         }
268     }
269 }
270
271 impl From<TupleVariantData> for Def {
272     fn from(data: TupleVariantData) -> Def {
273         Def {
274             kind: DefKind::Tuple,
275             id: From::from(data.id),
276             span: data.span,
277             name: data.name,
278             qualname: data.qualname,
279             value: data.value,
280             children: vec![],
281             decl_id: None,
282             docs: data.docs,
283         }
284     }
285 }
286 impl From<StructVariantData> for Def {
287     fn from(data: StructVariantData) -> Def {
288         Def {
289             kind: DefKind::Struct,
290             id: From::from(data.id),
291             span: data.span,
292             name: data.name,
293             qualname: data.qualname,
294             value: data.value,
295             children: vec![],
296             decl_id: None,
297             docs: data.docs,
298         }
299     }
300 }
301 impl From<StructData> for Def {
302     fn from(data: StructData) -> Def {
303         Def {
304             kind: DefKind::Struct,
305             id: From::from(data.id),
306             span: data.span,
307             name: data.name,
308             qualname: data.qualname,
309             value: data.value,
310             children: data.fields.into_iter().map(|id| From::from(id)).collect(),
311             decl_id: None,
312             docs: data.docs,
313         }
314     }
315 }
316 impl From<TraitData> for Def {
317     fn from(data: TraitData) -> Def {
318         Def {
319             kind: DefKind::Trait,
320             id: From::from(data.id),
321             span: data.span,
322             name: data.name,
323             qualname: data.qualname,
324             value: data.value,
325             children: data.items.into_iter().map(|id| From::from(id)).collect(),
326             decl_id: None,
327             docs: data.docs,
328         }
329     }
330 }
331 impl From<FunctionData> for Def {
332     fn from(data: FunctionData) -> Def {
333         Def {
334             kind: DefKind::Function,
335             id: From::from(data.id),
336             span: data.span,
337             name: data.name,
338             qualname: data.qualname,
339             value: data.value,
340             children: vec![],
341             decl_id: None,
342             docs: data.docs,
343         }
344     }
345 }
346 impl From<MethodData> for Def {
347     fn from(data: MethodData) -> Def {
348         Def {
349             kind: DefKind::Method,
350             id: From::from(data.id),
351             span: data.span,
352             name: data.name,
353             qualname: data.qualname,
354             value: data.value,
355             children: vec![],
356             decl_id: data.decl_id.map(|id| From::from(id)),
357             docs: data.docs,
358         }
359     }
360 }
361 impl From<MacroData> for Def {
362     fn from(data: MacroData) -> Def {
363         Def {
364             kind: DefKind::Macro,
365             id: From::from(null_def_id()),
366             span: data.span,
367             name: data.name,
368             qualname: data.qualname,
369             value: String::new(),
370             children: vec![],
371             decl_id: None,
372             docs: data.docs,
373         }
374     }
375 }
376
377 impl From<TypeDefData> for Def {
378     fn from(data: TypeDefData) -> Def {
379         Def {
380             kind: DefKind::Type,
381             id: From::from(data.id),
382             span: data.span,
383             name: data.name,
384             qualname: data.qualname,
385             value: data.value,
386             children: vec![],
387             decl_id: None,
388             docs: String::new(),
389         }
390     }
391 }
392 impl From<VariableData> for Def {
393     fn from(data: VariableData) -> Def {
394         Def {
395             kind: match data.kind {
396                 VariableKind::Static => DefKind::Static,
397                 VariableKind::Const => DefKind::Const,
398                 VariableKind::Local => DefKind::Local,
399                 VariableKind::Field => DefKind::Field,
400             },
401             id: From::from(data.id),
402             span: data.span,
403             name: data.name,
404             qualname: data.qualname,
405             value: data.type_value,
406             children: vec![],
407             decl_id: None,
408             docs: data.docs,
409         }
410     }
411 }
412
413 #[derive(Debug, RustcEncodable)]
414 enum RefKind {
415     Function,
416     Mod,
417     Type,
418     Variable,
419 }
420
421 #[derive(Debug, RustcEncodable)]
422 struct Ref {
423     kind: RefKind,
424     span: SpanData,
425     ref_id: Id,
426 }
427
428 impl From<FunctionRefData> for Ref {
429     fn from(data: FunctionRefData) -> Ref {
430         Ref {
431             kind: RefKind::Function,
432             span: data.span,
433             ref_id: From::from(data.ref_id),
434         }
435     }
436 }
437 impl From<FunctionCallData> for Ref {
438     fn from(data: FunctionCallData) -> Ref {
439         Ref {
440             kind: RefKind::Function,
441             span: data.span,
442             ref_id: From::from(data.ref_id),
443         }
444     }
445 }
446 impl From<MethodCallData> for Ref {
447     fn from(data: MethodCallData) -> Ref {
448         Ref {
449             kind: RefKind::Function,
450             span: data.span,
451             ref_id: From::from(data.ref_id.or(data.decl_id).unwrap_or(null_def_id())),
452         }
453     }
454 }
455 impl From<ModRefData> for Ref {
456     fn from(data: ModRefData) -> Ref {
457         Ref {
458             kind: RefKind::Mod,
459             span: data.span,
460             ref_id: From::from(data.ref_id.unwrap_or(null_def_id())),
461         }
462     }
463 }
464 impl From<TypeRefData> for Ref {
465     fn from(data: TypeRefData) -> Ref {
466         Ref {
467             kind: RefKind::Type,
468             span: data.span,
469             ref_id: From::from(data.ref_id.unwrap_or(null_def_id())),
470         }
471     }
472 }
473 impl From<VariableRefData> for Ref {
474     fn from(data: VariableRefData) -> Ref {
475         Ref {
476             kind: RefKind::Variable,
477             span: data.span,
478             ref_id: From::from(data.ref_id),
479         }
480     }
481 }
482
483 #[derive(Debug, RustcEncodable)]
484 struct MacroRef {
485     span: SpanData,
486     qualname: String,
487     callee_span: SpanData,
488 }
489
490 impl From<MacroUseData> for MacroRef {
491     fn from(data: MacroUseData) -> MacroRef {
492         MacroRef {
493             span: data.span,
494             qualname: data.qualname,
495             callee_span: data.callee_span,
496         }
497     }
498 }