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