]> git.lizzy.rs Git - rust.git/blob - src/librustc_save_analysis/json_dumper.rs
save-analysis: Use serde instead of libserialize to dump JSON data
[rust.git] / src / librustc_save_analysis / json_dumper.rs
1 use std::io::Write;
2
3 use rls_data::config::Config;
4 use rls_data::{self, Analysis, CompilationOptions, CratePreludeData, Def, DefKind, Impl, Import,
5                MacroRef, Ref, RefKind, Relation};
6 use rls_span::{Column, Row};
7
8 use log::error;
9
10 #[derive(Debug)]
11 pub struct Access {
12     pub reachable: bool,
13     pub public: bool,
14 }
15
16 pub struct JsonDumper<O: DumpOutput> {
17     result: Analysis,
18     config: Config,
19     output: O,
20 }
21
22 pub trait DumpOutput {
23     fn dump(&mut self, result: &Analysis);
24 }
25
26 pub struct WriteOutput<'b, W: Write> {
27     output: &'b mut W,
28 }
29
30 impl<'b, W: Write> DumpOutput for WriteOutput<'b, W> {
31     fn dump(&mut self, result: &Analysis) {
32         if let Err(e) = serde_json::to_writer(self.output.by_ref(), result) {
33             error!("Can't serialize save-analysis: {:?}", e);
34         }
35     }
36 }
37
38 pub struct CallbackOutput<'b> {
39     callback: &'b mut dyn FnMut(&Analysis),
40 }
41
42 impl<'b> DumpOutput for CallbackOutput<'b> {
43     fn dump(&mut self, result: &Analysis) {
44         (self.callback)(result)
45     }
46 }
47
48 impl<'b, W: Write> JsonDumper<WriteOutput<'b, W>> {
49     pub fn new(writer: &'b mut W, config: Config) -> JsonDumper<WriteOutput<'b, W>> {
50         JsonDumper {
51             output: WriteOutput { output: writer },
52             config: config.clone(),
53             result: Analysis::new(config),
54         }
55     }
56 }
57
58 impl<'b> JsonDumper<CallbackOutput<'b>> {
59     pub fn with_callback(
60         callback: &'b mut dyn FnMut(&Analysis),
61         config: Config,
62     ) -> JsonDumper<CallbackOutput<'b>> {
63         JsonDumper {
64             output: CallbackOutput { callback },
65             config: config.clone(),
66             result: Analysis::new(config),
67         }
68     }
69 }
70
71 impl<O: DumpOutput> Drop for JsonDumper<O> {
72     fn drop(&mut self) {
73         self.output.dump(&self.result);
74     }
75 }
76
77 impl<'b, O: DumpOutput + 'b> JsonDumper<O> {
78     pub fn crate_prelude(&mut self, data: CratePreludeData) {
79         self.result.prelude = Some(data)
80     }
81
82     pub fn compilation_opts(&mut self, data: CompilationOptions) {
83         self.result.compilation = Some(data);
84     }
85
86     pub fn _macro_use(&mut self, data: MacroRef) {
87         if self.config.pub_only || self.config.reachable_only {
88             return;
89         }
90         self.result.macro_refs.push(data);
91     }
92
93     pub fn import(&mut self, access: &Access, import: Import) {
94         if !access.public && self.config.pub_only
95             || !access.reachable && self.config.reachable_only {
96             return;
97         }
98         self.result.imports.push(import);
99     }
100
101     pub fn dump_ref(&mut self, data: Ref) {
102         if self.config.pub_only || self.config.reachable_only {
103             return;
104         }
105         self.result.refs.push(data);
106     }
107
108     pub fn dump_def(&mut self, access: &Access, mut data: Def) {
109         if !access.public && self.config.pub_only
110             || !access.reachable && self.config.reachable_only {
111             return;
112         }
113         if data.kind == DefKind::Mod && data.span.file_name.to_str().unwrap() != data.value {
114             // If the module is an out-of-line definition, then we'll make the
115             // definition the first character in the module's file and turn
116             // the declaration into a reference to it.
117             let rf = Ref {
118                 kind: RefKind::Mod,
119                 span: data.span,
120                 ref_id: data.id,
121             };
122             self.result.refs.push(rf);
123             data.span = rls_data::SpanData {
124                 file_name: data.value.clone().into(),
125                 byte_start: 0,
126                 byte_end: 0,
127                 line_start: Row::new_one_indexed(1),
128                 line_end: Row::new_one_indexed(1),
129                 column_start: Column::new_one_indexed(1),
130                 column_end: Column::new_one_indexed(1),
131             }
132         }
133         self.result.defs.push(data);
134     }
135
136     pub fn dump_relation(&mut self, data: Relation) {
137         self.result.relations.push(data);
138     }
139
140     pub fn dump_impl(&mut self, data: Impl) {
141         self.result.impls.push(data);
142     }
143 }