]> git.lizzy.rs Git - rust.git/blob - src/librustc_save_analysis/json_api_dumper.rs
777e64fe77f8b85623373b23b973560933233432
[rust.git] / src / librustc_save_analysis / json_api_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, Visibility, SigElement};
18 use dump::Dump;
19 use super::Format;
20
21
22 // A dumper to dump a restricted set of JSON information, designed for use with
23 // libraries distributed without their source. Clients are likely to use type
24 // information here, and (for example) generate Rustdoc URLs, but don't need
25 // information for navigating the source of the crate.
26 // Relative to the regular JSON save-analysis info, this form is filtered to
27 // remove non-visible items, but includes some extra info for items (e.g., the
28 // parent field for finding the struct to which a field belongs).
29 pub struct JsonApiDumper<'b, W: Write + 'b> {
30     output: &'b mut W,
31     result: Analysis,
32 }
33
34 impl<'b, W: Write> JsonApiDumper<'b, W> {
35     pub fn new(writer: &'b mut W) -> JsonApiDumper<'b, W> {
36         JsonApiDumper { output: writer, result: Analysis::new() }
37     }
38 }
39
40 impl<'b, W: Write> Drop for JsonApiDumper<'b, W> {
41     fn drop(&mut self) {
42         if let Err(_) = write!(self.output, "{}", as_json(&self.result)) {
43             error!("Error writing output");
44         }
45     }
46 }
47
48 macro_rules! impl_fn {
49     ($fn_name: ident, $data_type: ident, $bucket: ident) => {
50         fn $fn_name(&mut self, data: $data_type) {
51             if let Some(datum) = From::from(data) {
52                 self.result.$bucket.push(datum);
53             }
54         }
55     }
56 }
57
58 impl<'b, W: Write + 'b> Dump for JsonApiDumper<'b, W> {
59     fn crate_prelude(&mut self, data: CratePreludeData) {
60         self.result.prelude = Some(data)
61     }
62
63     impl_fn!(use_data, UseData, imports);
64     impl_fn!(use_glob, UseGlobData, imports);
65
66     impl_fn!(enum_data, EnumData, defs);
67     impl_fn!(tuple_variant, TupleVariantData, defs);
68     impl_fn!(struct_variant, StructVariantData, defs);
69     impl_fn!(struct_data, StructData, defs);
70     impl_fn!(trait_data, TraitData, defs);
71     impl_fn!(function, FunctionData, defs);
72     impl_fn!(method, MethodData, defs);
73     impl_fn!(macro_data, MacroData, defs);
74     impl_fn!(mod_data, ModData, defs);
75     impl_fn!(typedef, TypeDefData, defs);
76     impl_fn!(variable, VariableData, defs);
77 }
78
79 // FIXME methods. The defs have information about possible overriding and the
80 // refs have decl information (e.g., a trait method where we know the required
81 // method, but not the supplied method). In both cases, we are currently
82 // ignoring it.
83
84 #[derive(Debug, RustcEncodable)]
85 struct Analysis {
86     kind: Format,
87     prelude: Option<CratePreludeData>,
88     imports: Vec<Import>,
89     defs: Vec<Def>,
90     // These two fields are dummies so that clients can parse the two kinds of
91     // JSON data in the same way.
92     refs: Vec<()>,
93     macro_refs: Vec<()>,
94 }
95
96 impl Analysis {
97     fn new() -> Analysis {
98         Analysis {
99             kind: Format::JsonApi,
100             prelude: None,
101             imports: vec![],
102             defs: vec![],
103             refs: vec![],
104             macro_refs: vec![],
105         }
106     }
107 }
108
109 // DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
110 // we use our own Id which is the same, but without the newtype.
111 #[derive(Debug, RustcEncodable)]
112 struct Id {
113     krate: u32,
114     index: u32,
115 }
116
117 impl From<DefId> for Id {
118     fn from(id: DefId) -> Id {
119         Id {
120             krate: id.krate.as_u32(),
121             index: id.index.as_u32(),
122         }
123     }
124 }
125
126 #[derive(Debug, RustcEncodable)]
127 struct Import {
128     kind: ImportKind,
129     id: Id,
130     span: SpanData,
131     name: String,
132     value: String,
133 }
134
135 #[derive(Debug, RustcEncodable)]
136 enum ImportKind {
137     Use,
138     GlobUse,
139 }
140
141 impl From<UseData> for Option<Import> {
142     fn from(data: UseData) -> Option<Import> {
143         match data.visibility {
144             Visibility::Public => Some(Import {
145                 kind: ImportKind::Use,
146                 id: From::from(data.id),
147                 span: data.span,
148                 name: data.name,
149                 value: String::new(),
150             }),
151             _ => None,
152         }
153     }
154 }
155 impl From<UseGlobData> for Option<Import> {
156     fn from(data: UseGlobData) -> Option<Import> {
157         match data.visibility {
158             Visibility::Public => Some(Import {
159                 kind: ImportKind::GlobUse,
160                 id: From::from(data.id),
161                 span: data.span,
162                 name: "*".to_owned(),
163                 value: data.names.join(", "),
164             }),
165             _ => None,
166         }
167     }
168 }
169
170 #[derive(Debug, RustcEncodable)]
171 struct Def {
172     kind: DefKind,
173     id: Id,
174     span: SpanData,
175     name: String,
176     qualname: String,
177     value: String,
178     parent: Option<Id>,
179     children: Vec<Id>,
180     decl_id: Option<Id>,
181     docs: String,
182     sig: Option<JsonSignature>,
183 }
184
185 #[derive(Debug, RustcEncodable)]
186 enum DefKind {
187     // value = variant names
188     Enum,
189     // value = enum name + variant name + types
190     Tuple,
191     // value = [enum name +] name + fields
192     Struct,
193     // value = signature
194     Trait,
195     // value = type + generics
196     Function,
197     // value = type + generics
198     Method,
199     // No id, no value.
200     Macro,
201     // value = file_name
202     Mod,
203     // value = aliased type
204     Type,
205     // value = type and init expression (for all variable kinds).
206     Static,
207     Const,
208     Field,
209 }
210
211 impl From<EnumData> for Option<Def> {
212     fn from(data: EnumData) -> Option<Def> {
213         match data.visibility {
214             Visibility::Public => Some(Def {
215                 kind: DefKind::Enum,
216                 id: From::from(data.id),
217                 span: data.span,
218                 name: data.name,
219                 qualname: data.qualname,
220                 value: data.value,
221                 parent: None,
222                 children: data.variants.into_iter().map(|id| From::from(id)).collect(),
223                 decl_id: None,
224                 docs: data.docs,
225                 sig: None,
226             }),
227             _ => None,
228         }
229     }
230 }
231
232 impl From<TupleVariantData> for Option<Def> {
233     fn from(data: TupleVariantData) -> Option<Def> {
234         Some(Def {
235             kind: DefKind::Tuple,
236             id: From::from(data.id),
237             span: data.span,
238             name: data.name,
239             qualname: data.qualname,
240             value: data.value,
241             parent: data.parent.map(|id| From::from(id)),
242             children: vec![],
243             decl_id: None,
244             docs: data.docs,
245             sig: None,
246         })
247     }
248 }
249 impl From<StructVariantData> for Option<Def> {
250     fn from(data: StructVariantData) -> Option<Def> {
251         Some(Def {
252             kind: DefKind::Struct,
253             id: From::from(data.id),
254             span: data.span,
255             name: data.name,
256             qualname: data.qualname,
257             value: data.value,
258             parent: data.parent.map(|id| From::from(id)),
259             children: vec![],
260             decl_id: None,
261             docs: data.docs,
262             sig: None,
263         })
264     }
265 }
266 impl From<StructData> for Option<Def> {
267     fn from(data: StructData) -> Option<Def> {
268         match data.visibility {
269             Visibility::Public => Some(Def {
270             kind: DefKind::Struct,
271             id: From::from(data.id),
272             span: data.span,
273             name: data.name,
274             qualname: data.qualname,
275             value: data.value,
276             parent: None,
277             children: data.fields.into_iter().map(|id| From::from(id)).collect(),
278             decl_id: None,
279             docs: data.docs,
280             sig: Some(From::from(data.sig)),
281         }),
282             _ => None,
283         }
284     }
285 }
286 impl From<TraitData> for Option<Def> {
287     fn from(data: TraitData) -> Option<Def> {
288         match data.visibility {
289             Visibility::Public => Some(Def {
290                 kind: DefKind::Trait,
291                 id: From::from(data.id),
292                 span: data.span,
293                 name: data.name,
294                 qualname: data.qualname,
295                 value: data.value,
296                 children: data.items.into_iter().map(|id| From::from(id)).collect(),
297                 parent: None,
298                 decl_id: None,
299                 docs: data.docs,
300                 sig: None,
301             }),
302             _ => None,
303         }
304     }
305 }
306 impl From<FunctionData> for Option<Def> {
307     fn from(data: FunctionData) -> Option<Def> {
308         match data.visibility {
309             Visibility::Public => Some(Def {
310                 kind: DefKind::Function,
311                 id: From::from(data.id),
312                 span: data.span,
313                 name: data.name,
314                 qualname: data.qualname,
315                 value: data.value,
316                 children: vec![],
317                 parent: data.parent.map(|id| From::from(id)),
318                 decl_id: None,
319                 docs: data.docs,
320                 sig: None,
321             }),
322             _ => None,
323         }
324     }
325 }
326 impl From<MethodData> for Option<Def> {
327     fn from(data: MethodData) -> Option<Def> {
328         match data.visibility {
329             Visibility::Public => Some(Def {
330                 kind: DefKind::Method,
331                 id: From::from(data.id),
332                 span: data.span,
333                 name: data.name,
334                 qualname: data.qualname,
335                 value: data.value,
336                 children: vec![],
337                 parent: data.parent.map(|id| From::from(id)),
338                 decl_id: data.decl_id.map(|id| From::from(id)),
339                 docs: data.docs,
340                 sig: None,
341             }),
342             _ => None,
343         }
344     }
345 }
346 impl From<MacroData> for Option<Def> {
347     fn from(data: MacroData) -> Option<Def> {
348         Some(Def {
349             kind: DefKind::Macro,
350             id: From::from(null_def_id()),
351             span: data.span,
352             name: data.name,
353             qualname: data.qualname,
354             value: String::new(),
355             children: vec![],
356             parent: None,
357             decl_id: None,
358             docs: data.docs,
359             sig: None,
360         })
361     }
362 }
363 impl From<ModData> for Option<Def> {
364     fn from(data:ModData) -> Option<Def> {
365         match data.visibility {
366             Visibility::Public => Some(Def {
367                 kind: DefKind::Mod,
368                 id: From::from(data.id),
369                 span: data.span,
370                 name: data.name,
371                 qualname: data.qualname,
372                 value: data.filename,
373                 children: data.items.into_iter().map(|id| From::from(id)).collect(),
374                 parent: None,
375                 decl_id: None,
376                 docs: data.docs,
377                 sig: None,
378             }),
379             _ => None,
380         }
381     }
382 }
383 impl From<TypeDefData> for Option<Def> {
384     fn from(data: TypeDefData) -> Option<Def> {
385         match data.visibility {
386             Visibility::Public => Some(Def {
387                 kind: DefKind::Type,
388                 id: From::from(data.id),
389                 span: data.span,
390                 name: data.name,
391                 qualname: data.qualname,
392                 value: data.value,
393                 children: vec![],
394                 parent: data.parent.map(|id| From::from(id)),
395                 decl_id: None,
396                 docs: String::new(),
397                 sig: None,
398             }),
399             _ => None,
400         }
401     }
402 }
403
404 impl From<VariableData> for Option<Def> {
405     fn from(data: VariableData) -> Option<Def> {
406         match data.visibility {
407             Visibility::Public => Some(Def {
408                 kind: match data.kind {
409                     VariableKind::Static => DefKind::Static,
410                     VariableKind::Const => DefKind::Const,
411                     VariableKind::Local => { return None }
412                     VariableKind::Field => DefKind::Field,
413                 },
414                 id: From::from(data.id),
415                 span: data.span,
416                 name: data.name,
417                 qualname: data.qualname,
418                 value: data.value,
419                 children: vec![],
420                 parent: data.parent.map(|id| From::from(id)),
421                 decl_id: None,
422                 docs: data.docs,
423                 sig: data.sig.map(|s| From::from(s)),
424             }),
425             _ => None,
426         }
427     }
428 }
429
430 #[derive(Debug, RustcEncodable)]
431 pub struct JsonSignature {
432     span: SpanData,
433     text: String,
434     ident_start: usize,
435     ident_end: usize,
436     defs: Vec<JsonSigElement>,
437     refs: Vec<JsonSigElement>,
438 }
439
440 impl From<Signature> for JsonSignature {
441     fn from(data: Signature) -> JsonSignature {
442         JsonSignature {
443             span: data.span,
444             text: data.text,
445             ident_start: data.ident_start,
446             ident_end: data.ident_end,
447             defs: data.defs.into_iter().map(|s| From::from(s)).collect(),
448             refs: data.refs.into_iter().map(|s| From::from(s)).collect(),
449         }
450     }
451 }
452
453 #[derive(Debug, RustcEncodable)]
454 pub struct JsonSigElement {
455     id: Id,
456     start: usize,
457     end: usize,
458 }
459
460 impl From<SigElement> for JsonSigElement {
461     fn from(data: SigElement) -> JsonSigElement {
462         JsonSigElement {
463             id: From::from(data.id),
464             start: data.start,
465             end: data.end,
466         }
467     }
468 }