]> git.lizzy.rs Git - rust.git/blob - src/librustc_save_analysis/json_api_dumper.rs
bddee6460ff9ceff438f1f38da0a2333e463481a
[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_serialize::json::as_json;
14
15 use external_data::*;
16 use data::{VariableKind, Visibility};
17 use dump::Dump;
18 use id_from_def_id;
19
20 use rls_data::{Analysis, Import, ImportKind, Def, DefKind, CratePreludeData, Format};
21
22
23 // A dumper to dump a restricted set of JSON information, designed for use with
24 // libraries distributed without their source. Clients are likely to use type
25 // information here, and (for example) generate Rustdoc URLs, but don't need
26 // information for navigating the source of the crate.
27 // Relative to the regular JSON save-analysis info, this form is filtered to
28 // remove non-visible items.
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         let mut result = Analysis::new();
37         result.kind = Format::JsonApi;
38         JsonApiDumper { output: writer, result }
39     }
40 }
41
42 impl<'b, W: Write> Drop for JsonApiDumper<'b, W> {
43     fn drop(&mut self) {
44         if let Err(_) = write!(self.output, "{}", as_json(&self.result)) {
45             error!("Error writing output");
46         }
47     }
48 }
49
50 macro_rules! impl_fn {
51     ($fn_name: ident, $data_type: ident, $bucket: ident) => {
52         fn $fn_name(&mut self, data: $data_type) {
53             if let Some(datum) = data.into() {
54                 self.result.$bucket.push(datum);
55             }
56         }
57     }
58 }
59
60 impl<'b, W: Write + 'b> Dump for JsonApiDumper<'b, W> {
61     fn crate_prelude(&mut self, data: CratePreludeData) {
62         self.result.prelude = Some(data)
63     }
64
65     impl_fn!(use_data, UseData, imports);
66     impl_fn!(use_glob, UseGlobData, imports);
67
68     impl_fn!(enum_data, EnumData, defs);
69     impl_fn!(tuple_variant, TupleVariantData, defs);
70     impl_fn!(struct_variant, StructVariantData, defs);
71     impl_fn!(struct_data, StructData, defs);
72     impl_fn!(trait_data, TraitData, defs);
73     impl_fn!(function, FunctionData, defs);
74     impl_fn!(method, MethodData, defs);
75     impl_fn!(macro_data, MacroData, defs);
76     impl_fn!(mod_data, ModData, defs);
77     impl_fn!(typedef, TypeDefData, defs);
78     impl_fn!(variable, VariableData, defs);
79
80     fn impl_data(&mut self, data: ImplData) {
81         if data.self_ref.is_some() {
82             self.result.relations.push(data.into());
83         }
84     }
85     fn inheritance(&mut self, data: InheritanceData) {
86         self.result.relations.push(data.into());
87     }
88 }
89
90 // FIXME methods. The defs have information about possible overriding and the
91 // refs have decl information (e.g., a trait method where we know the required
92 // method, but not the supplied method). In both cases, we are currently
93 // ignoring it.
94
95 impl Into<Option<Import>> for UseData {
96     fn into(self) -> Option<Import> {
97         match self.visibility {
98             Visibility::Public => Some(Import {
99                 kind: ImportKind::Use,
100                 ref_id: self.mod_id.map(|id| id_from_def_id(id)),
101                 span: self.span,
102                 name: self.name,
103                 value: String::new(),
104             }),
105             _ => None,
106         }
107     }
108 }
109 impl Into<Option<Import>> for UseGlobData {
110     fn into(self) -> Option<Import> {
111         match self.visibility {
112             Visibility::Public => Some(Import {
113                 kind: ImportKind::GlobUse,
114                 ref_id: None,
115                 span: self.span,
116                 name: "*".to_owned(),
117                 value: self.names.join(", "),
118             }),
119             _ => None,
120         }
121     }
122 }
123
124 impl Into<Option<Def>> for EnumData {
125     fn into(self) -> Option<Def> {
126         match self.visibility {
127             Visibility::Public => Some(Def {
128                 kind: DefKind::Enum,
129                 id: id_from_def_id(self.id),
130                 span: self.span,
131                 name: self.name,
132                 qualname: self.qualname,
133                 value: self.value,
134                 parent: None,
135                 children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(),
136                 decl_id: None,
137                 docs: self.docs,
138                 sig: self.sig,
139                 attributes: vec![],
140             }),
141             _ => None,
142         }
143     }
144 }
145
146 impl Into<Option<Def>> for TupleVariantData {
147     fn into(self) -> Option<Def> {
148         Some(Def {
149             kind: DefKind::Tuple,
150             id: id_from_def_id(self.id),
151             span: self.span,
152             name: self.name,
153             qualname: self.qualname,
154             value: self.value,
155             parent: self.parent.map(|id| id_from_def_id(id)),
156             children: vec![],
157             decl_id: None,
158             docs: self.docs,
159             sig: self.sig,
160             attributes: vec![],
161         })
162     }
163 }
164 impl Into<Option<Def>> for StructVariantData {
165     fn into(self) -> Option<Def> {
166         Some(Def {
167             kind: DefKind::Struct,
168             id: id_from_def_id(self.id),
169             span: self.span,
170             name: self.name,
171             qualname: self.qualname,
172             value: self.value,
173             parent: self.parent.map(|id| id_from_def_id(id)),
174             children: vec![],
175             decl_id: None,
176             docs: self.docs,
177             sig: self.sig,
178             attributes: vec![],
179         })
180     }
181 }
182 impl Into<Option<Def>> for StructData {
183     fn into(self) -> Option<Def> {
184         match self.visibility {
185             Visibility::Public => Some(Def {
186             kind: DefKind::Struct,
187             id: id_from_def_id(self.id),
188             span: self.span,
189             name: self.name,
190             qualname: self.qualname,
191             value: self.value,
192             parent: None,
193             children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(),
194             decl_id: None,
195             docs: self.docs,
196             sig: self.sig,
197             attributes: vec![],
198         }),
199             _ => None,
200         }
201     }
202 }
203 impl Into<Option<Def>> for TraitData {
204     fn into(self) -> Option<Def> {
205         match self.visibility {
206             Visibility::Public => Some(Def {
207                 kind: DefKind::Trait,
208                 id: id_from_def_id(self.id),
209                 span: self.span,
210                 name: self.name,
211                 qualname: self.qualname,
212                 value: self.value,
213                 children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(),
214                 parent: None,
215                 decl_id: None,
216                 docs: self.docs,
217                 sig: self.sig,
218                 attributes: vec![],
219             }),
220             _ => None,
221         }
222     }
223 }
224 impl Into<Option<Def>> for FunctionData {
225     fn into(self) -> Option<Def> {
226         match self.visibility {
227             Visibility::Public => Some(Def {
228                 kind: DefKind::Function,
229                 id: id_from_def_id(self.id),
230                 span: self.span,
231                 name: self.name,
232                 qualname: self.qualname,
233                 value: self.value,
234                 children: vec![],
235                 parent: self.parent.map(|id| id_from_def_id(id)),
236                 decl_id: None,
237                 docs: self.docs,
238                 sig: self.sig,
239                 attributes: vec![],
240             }),
241             _ => None,
242         }
243     }
244 }
245 impl Into<Option<Def>> for MethodData {
246     fn into(self) -> Option<Def> {
247         match self.visibility {
248             Visibility::Public => Some(Def {
249                 kind: DefKind::Method,
250                 id: id_from_def_id(self.id),
251                 span: self.span,
252                 name: self.name,
253                 qualname: self.qualname,
254                 value: self.value,
255                 children: vec![],
256                 parent: self.parent.map(|id| id_from_def_id(id)),
257                 decl_id: self.decl_id.map(|id| id_from_def_id(id)),
258                 docs: self.docs,
259                 sig: self.sig,
260                 attributes: vec![],
261             }),
262             _ => None,
263         }
264     }
265 }
266 impl Into<Option<Def>> for MacroData {
267     fn into(self) -> Option<Def> {
268         Some(Def {
269             kind: DefKind::Macro,
270             id: id_from_def_id(null_def_id()),
271             span: self.span,
272             name: self.name,
273             qualname: self.qualname,
274             value: String::new(),
275             children: vec![],
276             parent: None,
277             decl_id: None,
278             docs: self.docs,
279             sig: None,
280             attributes: vec![],
281         })
282     }
283 }
284 impl Into<Option<Def>> for ModData {
285     fn into(self) -> Option<Def> {
286         match self.visibility {
287             Visibility::Public => Some(Def {
288                 kind: DefKind::Mod,
289                 id: id_from_def_id(self.id),
290                 span: self.span,
291                 name: self.name,
292                 qualname: self.qualname,
293                 value: self.filename,
294                 children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(),
295                 parent: None,
296                 decl_id: None,
297                 docs: self.docs,
298                 sig: self.sig.map(|s| s.into()),
299                 attributes: vec![],
300             }),
301             _ => None,
302         }
303     }
304 }
305 impl Into<Option<Def>> for TypeDefData {
306     fn into(self) -> Option<Def> {
307         match self.visibility {
308             Visibility::Public => Some(Def {
309                 kind: DefKind::Type,
310                 id: id_from_def_id(self.id),
311                 span: self.span,
312                 name: self.name,
313                 qualname: self.qualname,
314                 value: self.value,
315                 children: vec![],
316                 parent: self.parent.map(|id| id_from_def_id(id)),
317                 decl_id: None,
318                 docs: String::new(),
319                 sig: self.sig.map(|s| s.into()),
320                 attributes: vec![],
321             }),
322             _ => None,
323         }
324     }
325 }
326
327 impl Into<Option<Def>> for VariableData {
328     fn into(self) -> Option<Def> {
329         match self.visibility {
330             Visibility::Public => Some(Def {
331                 kind: match self.kind {
332                     VariableKind::Static => DefKind::Static,
333                     VariableKind::Const => DefKind::Const,
334                     VariableKind::Local => { return None }
335                     VariableKind::Field => DefKind::Field,
336                 },
337                 id: id_from_def_id(self.id),
338                 span: self.span,
339                 name: self.name,
340                 qualname: self.qualname,
341                 value: self.value,
342                 children: vec![],
343                 parent: self.parent.map(|id| id_from_def_id(id)),
344                 decl_id: None,
345                 docs: self.docs,
346                 sig: self.sig.map(|s| s.into()),
347                 attributes: vec![],
348             }),
349             _ => None,
350         }
351     }
352 }