]> git.lizzy.rs Git - rust.git/blob - src/librustc_save_analysis/json_dumper.rs
Move the API json dumper to use rls-data too
[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 rls_data::{self, Id, Analysis, Import, ImportKind, Def, DefKind, Ref, RefKind, MacroRef,
17                Relation, RelationKind, Signature, SigElement, CratePreludeData};
18 use rls_span::{Column, Row};
19
20 use external_data;
21 use external_data::*;
22 use data::{self, VariableKind};
23 use dump::Dump;
24
25 pub struct JsonDumper<'b, W: Write + 'b> {
26     output: &'b mut W,
27     result: Analysis,
28 }
29
30 impl<'b, W: Write> JsonDumper<'b, W> {
31     pub fn new(writer: &'b mut W) -> JsonDumper<'b, W> {
32         JsonDumper { output: writer, result: Analysis::new() }
33     }
34 }
35
36 impl<'b, W: Write> Drop for JsonDumper<'b, W> {
37     fn drop(&mut self) {
38         if let Err(_) = write!(self.output, "{}", as_json(&self.result)) {
39             error!("Error writing output");
40         }
41     }
42 }
43
44 macro_rules! impl_fn {
45     ($fn_name: ident, $data_type: ident, $bucket: ident) => {
46         fn $fn_name(&mut self, data: $data_type) {
47             self.result.$bucket.push(data.into());
48         }
49     }
50 }
51
52 impl<'b, W: Write + 'b> Dump for JsonDumper<'b, W> {
53     fn crate_prelude(&mut self, data: CratePreludeData) {
54         self.result.prelude = Some(data)
55     }
56
57     impl_fn!(extern_crate, ExternCrateData, imports);
58     impl_fn!(use_data, UseData, imports);
59     impl_fn!(use_glob, UseGlobData, imports);
60
61     impl_fn!(enum_data, EnumData, defs);
62     impl_fn!(tuple_variant, TupleVariantData, defs);
63     impl_fn!(struct_variant, StructVariantData, defs);
64     impl_fn!(struct_data, StructData, defs);
65     impl_fn!(trait_data, TraitData, defs);
66     impl_fn!(function, FunctionData, defs);
67     impl_fn!(method, MethodData, defs);
68     impl_fn!(macro_data, MacroData, defs);
69     impl_fn!(typedef, TypeDefData, defs);
70     impl_fn!(variable, VariableData, defs);
71
72     impl_fn!(function_ref, FunctionRefData, refs);
73     impl_fn!(function_call, FunctionCallData, refs);
74     impl_fn!(method_call, MethodCallData, refs);
75     impl_fn!(mod_ref, ModRefData, refs);
76     impl_fn!(type_ref, TypeRefData, refs);
77     impl_fn!(variable_ref, VariableRefData, refs);
78
79     impl_fn!(macro_use, MacroUseData, macro_refs);
80
81     fn mod_data(&mut self, data: ModData) {
82         let id: Id = id_from_def_id(data.id);
83         let mut def = Def {
84             kind: DefKind::Mod,
85             id: id,
86             span: data.span.into(),
87             name: data.name,
88             qualname: data.qualname,
89             value: data.filename,
90             parent: None,
91             children: data.items.into_iter().map(|id| id_from_def_id(id)).collect(),
92             decl_id: None,
93             docs: data.docs,
94             sig: Some(data.sig.into()),
95             attributes: data.attributes.into_iter().map(|a| a.into()).collect(),
96         };
97         if def.span.file_name.to_str().unwrap() != def.value {
98             // If the module is an out-of-line defintion, then we'll make the
99             // defintion the first character in the module's file and turn the
100             // the declaration into a reference to it.
101             let rf = Ref {
102                 kind: RefKind::Mod,
103                 span: def.span,
104                 ref_id: id,
105             };
106             self.result.refs.push(rf);
107             def.span = rls_data::SpanData {
108                 file_name: def.value.clone().into(),
109                 byte_start: 0,
110                 byte_end: 0,
111                 line_start: Row::new_one_indexed(1),
112                 line_end: Row::new_one_indexed(1),
113                 column_start: Column::new_one_indexed(1),
114                 column_end: Column::new_one_indexed(1),
115             }
116         }
117
118         self.result.defs.push(def);
119     }
120
121     fn impl_data(&mut self, data: ImplData) {
122         if data.self_ref.is_some() {
123             self.result.relations.push(data.into());
124         }
125     }
126     fn inheritance(&mut self, data: InheritanceData) {
127         self.result.relations.push(data.into());
128     }
129 }
130
131 // FIXME do we want to change ExternalData to this mode? It will break DXR.
132 // FIXME methods. The defs have information about possible overriding and the
133 // refs have decl information (e.g., a trait method where we know the required
134 // method, but not the supplied method). In both cases, we are currently
135 // ignoring it.
136
137 // DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
138 // we use our own Id which is the same, but without the newtype.
139 pub fn id_from_def_id(id: DefId) -> Id {
140     Id {
141         krate: id.krate.as_u32(),
142         index: id.index.as_u32(),
143     }
144 }
145
146 impl Into<Import> for ExternCrateData {
147     fn into(self) -> Import {
148         Import {
149             kind: ImportKind::ExternCrate,
150             ref_id: None,
151             span: self.span,
152             name: self.name,
153             value: String::new(),
154         }
155     }
156 }
157 impl Into<Import> for UseData {
158     fn into(self) -> Import {
159         Import {
160             kind: ImportKind::Use,
161             ref_id: self.mod_id.map(|id| id_from_def_id(id)),
162             span: self.span,
163             name: self.name,
164             value: String::new(),
165         }
166     }
167 }
168 impl Into<Import> for UseGlobData {
169     fn into(self) -> Import {
170         Import {
171             kind: ImportKind::GlobUse,
172             ref_id: None,
173             span: self.span,
174             name: "*".to_owned(),
175             value: self.names.join(", "),
176         }
177     }
178 }
179
180 impl Into<Def> for EnumData {
181     fn into(self) -> Def {
182         Def {
183             kind: DefKind::Enum,
184             id: id_from_def_id(self.id),
185             span: self.span,
186             name: self.name,
187             qualname: self.qualname,
188             value: self.value,
189             parent: None,
190             children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(),
191             decl_id: None,
192             docs: self.docs,
193             sig: Some(self.sig.into()),
194             attributes: self.attributes,
195         }
196     }
197 }
198
199 impl Into<Def> for TupleVariantData {
200     fn into(self) -> Def {
201         Def {
202             kind: DefKind::Tuple,
203             id: id_from_def_id(self.id),
204             span: self.span,
205             name: self.name,
206             qualname: self.qualname,
207             value: self.value,
208             parent: None,
209             children: vec![],
210             decl_id: None,
211             docs: self.docs,
212             sig: Some(self.sig.into()),
213             attributes: self.attributes,
214         }
215     }
216 }
217 impl Into<Def> for StructVariantData {
218     fn into(self) -> Def {
219         Def {
220             kind: DefKind::Struct,
221             id: id_from_def_id(self.id),
222             span: self.span,
223             name: self.name,
224             qualname: self.qualname,
225             value: self.value,
226             parent: None,
227             children: vec![],
228             decl_id: None,
229             docs: self.docs,
230             sig: Some(self.sig.into()),
231             attributes: self.attributes,
232         }
233     }
234 }
235 impl Into<Def> for StructData {
236     fn into(self) -> Def {
237         Def {
238             kind: DefKind::Struct,
239             id: id_from_def_id(self.id),
240             span: self.span,
241             name: self.name,
242             qualname: self.qualname,
243             value: self.value,
244             parent: None,
245             children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(),
246             decl_id: None,
247             docs: self.docs,
248             sig: Some(self.sig.into()),
249             attributes: self.attributes,
250         }
251     }
252 }
253 impl Into<Def> for TraitData {
254     fn into(self) -> Def {
255         Def {
256             kind: DefKind::Trait,
257             id: id_from_def_id(self.id),
258             span: self.span,
259             name: self.name,
260             qualname: self.qualname,
261             value: self.value,
262             parent: None,
263             children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(),
264             decl_id: None,
265             docs: self.docs,
266             sig: Some(self.sig.into()),
267             attributes: self.attributes,
268         }
269     }
270 }
271 impl Into<Def> for FunctionData {
272     fn into(self) -> Def {
273         Def {
274             kind: DefKind::Function,
275             id: id_from_def_id(self.id),
276             span: self.span,
277             name: self.name,
278             qualname: self.qualname,
279             value: self.value,
280             parent: None,
281             children: vec![],
282             decl_id: None,
283             docs: self.docs,
284             sig: Some(self.sig.into()),
285             attributes: self.attributes,
286         }
287     }
288 }
289 impl Into<Def> for MethodData {
290     fn into(self) -> Def {
291         Def {
292             kind: DefKind::Method,
293             id: id_from_def_id(self.id),
294             span: self.span,
295             name: self.name,
296             qualname: self.qualname,
297             value: self.value,
298             parent: None,
299             children: vec![],
300             decl_id: self.decl_id.map(|id| id_from_def_id(id)),
301             docs: self.docs,
302             sig: Some(self.sig.into()),
303             attributes: self.attributes,
304         }
305     }
306 }
307 impl Into<Def> for MacroData {
308     fn into(self) -> Def {
309         Def {
310             kind: DefKind::Macro,
311             id: id_from_def_id(null_def_id()),
312             span: self.span,
313             name: self.name,
314             qualname: self.qualname,
315             value: String::new(),
316             parent: None,
317             children: vec![],
318             decl_id: None,
319             docs: self.docs,
320             sig: None,
321             attributes: vec![],
322         }
323     }
324 }
325 impl Into<Def> for TypeDefData {
326     fn into(self) -> Def {
327         Def {
328             kind: DefKind::Type,
329             id: id_from_def_id(self.id),
330             span: self.span,
331             name: self.name,
332             qualname: self.qualname,
333             value: self.value,
334             parent: None,
335             children: vec![],
336             decl_id: None,
337             docs: String::new(),
338             sig: self.sig.map(|s| s.into()),
339             attributes: self.attributes,
340         }
341     }
342 }
343 impl Into<Def> for VariableData {
344     fn into(self) -> Def {
345         Def {
346             kind: match self.kind {
347                 VariableKind::Static => DefKind::Static,
348                 VariableKind::Const => DefKind::Const,
349                 VariableKind::Local => DefKind::Local,
350                 VariableKind::Field => DefKind::Field,
351             },
352             id: id_from_def_id(self.id),
353             span: self.span,
354             name: self.name,
355             qualname: self.qualname,
356             value: self.type_value,
357             parent: None,
358             children: vec![],
359             decl_id: None,
360             docs: self.docs,
361             sig: None,
362             attributes: self.attributes,
363         }
364     }
365 }
366
367 impl Into<Ref> for FunctionRefData {
368     fn into(self) -> Ref {
369         Ref {
370             kind: RefKind::Function,
371             span: self.span,
372             ref_id: id_from_def_id(self.ref_id),
373         }
374     }
375 }
376 impl Into<Ref> for FunctionCallData {
377     fn into(self) -> Ref {
378         Ref {
379             kind: RefKind::Function,
380             span: self.span,
381             ref_id: id_from_def_id(self.ref_id),
382         }
383     }
384 }
385 impl Into<Ref> for MethodCallData {
386     fn into(self) -> Ref {
387         Ref {
388             kind: RefKind::Function,
389             span: self.span,
390             ref_id: id_from_def_id(self.ref_id.or(self.decl_id).unwrap_or(null_def_id())),
391         }
392     }
393 }
394 impl Into<Ref> for ModRefData {
395     fn into(self) -> Ref {
396         Ref {
397             kind: RefKind::Mod,
398             span: self.span,
399             ref_id: id_from_def_id(self.ref_id.unwrap_or(null_def_id())),
400         }
401     }
402 }
403 impl Into<Ref> for TypeRefData {
404     fn into(self) -> Ref {
405         Ref {
406             kind: RefKind::Type,
407             span: self.span,
408             ref_id: id_from_def_id(self.ref_id.unwrap_or(null_def_id())),
409         }
410     }
411 }
412 impl Into<Ref> for VariableRefData {
413     fn into(self) -> Ref {
414         Ref {
415             kind: RefKind::Variable,
416             span: self.span,
417             ref_id: id_from_def_id(self.ref_id),
418         }
419     }
420 }
421
422 impl Into<MacroRef> for MacroUseData {
423     fn into(self) -> MacroRef {
424         MacroRef {
425             span: self.span,
426             qualname: self.qualname,
427             callee_span: self.callee_span.into(),
428         }
429     }
430 }
431
432 impl Into<Relation> for ImplData {
433     fn into(self) -> Relation {
434         Relation {
435             span: self.span,
436             kind: RelationKind::Impl,
437             from: id_from_def_id(self.self_ref.unwrap_or(null_def_id())),
438             to: id_from_def_id(self.trait_ref.unwrap_or(null_def_id())),
439         }
440     }
441 }
442
443 impl Into<Relation> for InheritanceData {
444     fn into(self) -> Relation {
445         Relation {
446             span: self.span,
447             kind: RelationKind::SuperTrait,
448             from: id_from_def_id(self.base_id),
449             to: id_from_def_id(self.deriv_id),
450         }
451     }
452 }
453
454 impl Into<Signature> for external_data::Signature {
455     fn into(self) -> Signature {
456         Signature {
457             span: self.span,
458             text: self.text,
459             ident_start: self.ident_start,
460             ident_end: self.ident_end,
461             defs: self.defs.into_iter().map(|s| s.into()).collect(),
462             refs: self.refs.into_iter().map(|s| s.into()).collect(),
463         }
464     }
465 }
466
467 impl Into<SigElement> for data::SigElement {
468     fn into(self) -> SigElement {
469         SigElement {
470             id: id_from_def_id(self.id),
471             start: self.start,
472             end: self.end,
473         }
474     }
475 }