]> git.lizzy.rs Git - rust.git/blob - src/librustc_save_analysis/json_api_dumper.rs
add -Z pre-link-arg{,s} to rustc
[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 json_dumper::id_from_def_id;
19
20 use rls_data::{Analysis, Import, ImportKind, Def, DefKind, CratePreludeData};
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         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) = data.into() {
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     fn impl_data(&mut self, data: ImplData) {
79         if data.self_ref.is_some() {
80             self.result.relations.push(data.into());
81         }
82     }
83     fn inheritance(&mut self, data: InheritanceData) {
84         self.result.relations.push(data.into());
85     }
86 }
87
88 // FIXME methods. The defs have information about possible overriding and the
89 // refs have decl information (e.g., a trait method where we know the required
90 // method, but not the supplied method). In both cases, we are currently
91 // ignoring it.
92
93 impl Into<Option<Import>> for UseData {
94     fn into(self) -> Option<Import> {
95         match self.visibility {
96             Visibility::Public => Some(Import {
97                 kind: ImportKind::Use,
98                 ref_id: self.mod_id.map(|id| id_from_def_id(id)),
99                 span: self.span,
100                 name: self.name,
101                 value: String::new(),
102             }),
103             _ => None,
104         }
105     }
106 }
107 impl Into<Option<Import>> for UseGlobData {
108     fn into(self) -> Option<Import> {
109         match self.visibility {
110             Visibility::Public => Some(Import {
111                 kind: ImportKind::GlobUse,
112                 ref_id: None,
113                 span: self.span,
114                 name: "*".to_owned(),
115                 value: self.names.join(", "),
116             }),
117             _ => None,
118         }
119     }
120 }
121
122 impl Into<Option<Def>> for EnumData {
123     fn into(self) -> Option<Def> {
124         match self.visibility {
125             Visibility::Public => Some(Def {
126                 kind: DefKind::Enum,
127                 id: id_from_def_id(self.id),
128                 span: self.span,
129                 name: self.name,
130                 qualname: self.qualname,
131                 value: self.value,
132                 parent: None,
133                 children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(),
134                 decl_id: None,
135                 docs: self.docs,
136                 sig: Some(self.sig.into()),
137                 attributes: vec![],
138             }),
139             _ => None,
140         }
141     }
142 }
143
144 impl Into<Option<Def>> for TupleVariantData {
145     fn into(self) -> Option<Def> {
146         Some(Def {
147             kind: DefKind::Tuple,
148             id: id_from_def_id(self.id),
149             span: self.span,
150             name: self.name,
151             qualname: self.qualname,
152             value: self.value,
153             parent: self.parent.map(|id| id_from_def_id(id)),
154             children: vec![],
155             decl_id: None,
156             docs: self.docs,
157             sig: Some(self.sig.into()),
158             attributes: vec![],
159         })
160     }
161 }
162 impl Into<Option<Def>> for StructVariantData {
163     fn into(self) -> Option<Def> {
164         Some(Def {
165             kind: DefKind::Struct,
166             id: id_from_def_id(self.id),
167             span: self.span,
168             name: self.name,
169             qualname: self.qualname,
170             value: self.value,
171             parent: self.parent.map(|id| id_from_def_id(id)),
172             children: vec![],
173             decl_id: None,
174             docs: self.docs,
175             sig: Some(self.sig.into()),
176             attributes: vec![],
177         })
178     }
179 }
180 impl Into<Option<Def>> for StructData {
181     fn into(self) -> Option<Def> {
182         match self.visibility {
183             Visibility::Public => Some(Def {
184             kind: DefKind::Struct,
185             id: id_from_def_id(self.id),
186             span: self.span,
187             name: self.name,
188             qualname: self.qualname,
189             value: self.value,
190             parent: None,
191             children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(),
192             decl_id: None,
193             docs: self.docs,
194             sig: Some(self.sig.into()),
195             attributes: vec![],
196         }),
197             _ => None,
198         }
199     }
200 }
201 impl Into<Option<Def>> for TraitData {
202     fn into(self) -> Option<Def> {
203         match self.visibility {
204             Visibility::Public => Some(Def {
205                 kind: DefKind::Trait,
206                 id: id_from_def_id(self.id),
207                 span: self.span,
208                 name: self.name,
209                 qualname: self.qualname,
210                 value: self.value,
211                 children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(),
212                 parent: None,
213                 decl_id: None,
214                 docs: self.docs,
215                 sig: Some(self.sig.into()),
216                 attributes: vec![],
217             }),
218             _ => None,
219         }
220     }
221 }
222 impl Into<Option<Def>> for FunctionData {
223     fn into(self) -> Option<Def> {
224         match self.visibility {
225             Visibility::Public => Some(Def {
226                 kind: DefKind::Function,
227                 id: id_from_def_id(self.id),
228                 span: self.span,
229                 name: self.name,
230                 qualname: self.qualname,
231                 value: self.value,
232                 children: vec![],
233                 parent: self.parent.map(|id| id_from_def_id(id)),
234                 decl_id: None,
235                 docs: self.docs,
236                 sig: Some(self.sig.into()),
237                 attributes: vec![],
238             }),
239             _ => None,
240         }
241     }
242 }
243 impl Into<Option<Def>> for MethodData {
244     fn into(self) -> Option<Def> {
245         match self.visibility {
246             Visibility::Public => Some(Def {
247                 kind: DefKind::Method,
248                 id: id_from_def_id(self.id),
249                 span: self.span,
250                 name: self.name,
251                 qualname: self.qualname,
252                 value: self.value,
253                 children: vec![],
254                 parent: self.parent.map(|id| id_from_def_id(id)),
255                 decl_id: self.decl_id.map(|id| id_from_def_id(id)),
256                 docs: self.docs,
257                 sig: Some(self.sig.into()),
258                 attributes: vec![],
259             }),
260             _ => None,
261         }
262     }
263 }
264 impl Into<Option<Def>> for MacroData {
265     fn into(self) -> Option<Def> {
266         Some(Def {
267             kind: DefKind::Macro,
268             id: id_from_def_id(null_def_id()),
269             span: self.span,
270             name: self.name,
271             qualname: self.qualname,
272             value: String::new(),
273             children: vec![],
274             parent: None,
275             decl_id: None,
276             docs: self.docs,
277             sig: None,
278             attributes: vec![],
279         })
280     }
281 }
282 impl Into<Option<Def>> for ModData {
283     fn into(self) -> Option<Def> {
284         match self.visibility {
285             Visibility::Public => Some(Def {
286                 kind: DefKind::Mod,
287                 id: id_from_def_id(self.id),
288                 span: self.span,
289                 name: self.name,
290                 qualname: self.qualname,
291                 value: self.filename,
292                 children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(),
293                 parent: None,
294                 decl_id: None,
295                 docs: self.docs,
296                 sig: Some(self.sig.into()),
297                 attributes: vec![],
298             }),
299             _ => None,
300         }
301     }
302 }
303 impl Into<Option<Def>> for TypeDefData {
304     fn into(self) -> Option<Def> {
305         match self.visibility {
306             Visibility::Public => Some(Def {
307                 kind: DefKind::Type,
308                 id: id_from_def_id(self.id),
309                 span: self.span,
310                 name: self.name,
311                 qualname: self.qualname,
312                 value: self.value,
313                 children: vec![],
314                 parent: self.parent.map(|id| id_from_def_id(id)),
315                 decl_id: None,
316                 docs: String::new(),
317                 sig: self.sig.map(|s| s.into()),
318                 attributes: vec![],
319             }),
320             _ => None,
321         }
322     }
323 }
324
325 impl Into<Option<Def>> for VariableData {
326     fn into(self) -> Option<Def> {
327         match self.visibility {
328             Visibility::Public => Some(Def {
329                 kind: match self.kind {
330                     VariableKind::Static => DefKind::Static,
331                     VariableKind::Const => DefKind::Const,
332                     VariableKind::Local => { return None }
333                     VariableKind::Field => DefKind::Field,
334                 },
335                 id: id_from_def_id(self.id),
336                 span: self.span,
337                 name: self.name,
338                 qualname: self.qualname,
339                 value: self.value,
340                 children: vec![],
341                 parent: self.parent.map(|id| id_from_def_id(id)),
342                 decl_id: None,
343                 docs: self.docs,
344                 sig: self.sig.map(|s| s.into()),
345                 attributes: vec![],
346             }),
347             _ => None,
348         }
349     }
350 }