]> git.lizzy.rs Git - rust.git/blob - src/librustc_save_analysis/csv_dumper.rs
0fd95500422ff193af8a29aa1f8ea615657eb775
[rust.git] / src / librustc_save_analysis / csv_dumper.rs
1 // Copyright 2012-2014 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 super::external_data::*;
14 use super::dump::Dump;
15
16 pub struct CsvDumper<'b, W: 'b> {
17     output: &'b mut W
18 }
19
20 impl<'b, W: Write> CsvDumper<'b, W> {
21     pub fn new(writer: &'b mut W) -> CsvDumper<'b, W> {
22         CsvDumper { output: writer }
23     }
24
25     fn record(&mut self, kind: &str, span: SpanData, values: String) {
26         let span_str = span_extent_str(span);
27         if let Err(_) = write!(self.output, "{},{}{}\n", kind, span_str, values) {
28             error!("Error writing output");
29         }
30     }
31
32     fn record_raw(&mut self, info: &str) {
33         if let Err(_) = write!(self.output, "{}", info) {
34             error!("Error writing output '{}'", info);
35         }
36     }
37 }
38
39 impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> {
40     fn crate_prelude(&mut self, data: CratePreludeData) {
41         let values = make_values_str(&[
42             ("name", &data.crate_name),
43             ("crate_root", &data.crate_root)
44         ]);
45
46         self.record("crate", data.span, values);
47
48         for c in data.external_crates {
49             let num = c.num.to_string();
50             let values = make_values_str(&[
51                 ("name", &c.name),
52                 ("crate", &num),
53                 ("file_name", &c.file_name)
54             ]);
55
56             self.record_raw(&format!("external_crate{}\n", values));
57         }
58
59         self.record_raw("end_external_crates\n");
60     }
61
62     fn enum_data(&mut self, data: EnumData) {
63         let id = data.id.index.as_u32().to_string();
64         let scope = data.scope.index.as_u32().to_string();
65         let values = make_values_str(&[
66             ("id", &id),
67             ("qualname", &data.qualname),
68             ("scopeid", &scope),
69             ("value", &data.value)
70         ]);
71
72         self.record("enum", data.span, values);
73     }
74
75     fn extern_crate(&mut self, data: ExternCrateData) {
76         let id = data.id.index.as_u32().to_string();
77         let crate_num = data.crate_num.to_string();
78         let scope = data.scope.index.as_u32().to_string();
79         let values = make_values_str(&[
80             ("id", &id),
81             ("name", &data.name),
82             ("location", &data.location),
83             ("crate", &crate_num),
84             ("scopeid", &scope)
85         ]);
86
87         self.record("extern_crate", data.span, values);
88     }
89
90     fn impl_data(&mut self, data: ImplData) {
91         let self_ref = data.self_ref.unwrap_or(null_def_id());
92         let trait_ref = data.trait_ref.unwrap_or(null_def_id());
93
94         let id = data.id.index.as_u32().to_string();
95         let ref_id = self_ref.index.as_usize().to_string();
96         let ref_id_crate = self_ref.krate.to_string();
97         let trait_id = trait_ref.index.as_usize().to_string();
98         let trait_id_crate = trait_ref.krate.to_string();
99         let scope = data.scope.index.as_u32().to_string();
100         let values = make_values_str(&[
101             ("id", &id),
102             ("refid", &ref_id),
103             ("refidcrate", &ref_id_crate),
104             ("traitid", &trait_id),
105             ("traitidcrate", &trait_id_crate),
106             ("scopeid", &scope)
107         ]);
108
109         self.record("impl", data.span, values);
110     }
111
112     fn inheritance(&mut self, data: InheritanceData) {
113        let base_id = data.base_id.index.as_usize().to_string();
114        let base_crate = data.base_id.krate.to_string();
115        let deriv_id = data.deriv_id.index.as_u32().to_string();
116        let deriv_crate = data.deriv_id.krate.to_string();
117        let values = make_values_str(&[
118            ("base", &base_id),
119            ("basecrate", &base_crate),
120            ("derived", &deriv_id),
121            ("derivedcrate", &deriv_crate)
122        ]);
123
124        self.record("inheritance", data.span, values);
125     }
126
127     fn function(&mut self, data: FunctionData) {
128         let (decl_id, decl_crate) = match data.declaration {
129             Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()),
130             None => (String::new(), String::new())
131         };
132
133         let id = data.id.index.as_u32().to_string();
134         let scope = data.scope.index.as_u32().to_string();
135         let values = make_values_str(&[
136             ("id", &id),
137             ("qualname", &data.qualname),
138             ("declid", &decl_id),
139             ("declidcrate", &decl_crate),
140             ("scopeid", &scope)
141         ]);
142
143         self.record("function", data.span, values);
144     }
145
146     fn function_ref(&mut self, data: FunctionRefData) {
147         let ref_id = data.ref_id.index.as_usize().to_string();
148         let ref_crate = data.ref_id.krate.to_string();
149         let scope = data.scope.index.as_u32().to_string();
150         let values = make_values_str(&[
151             ("refid", &ref_id),
152             ("refidcrate", &ref_crate),
153             ("qualname", ""),
154             ("scopeid", &scope)
155         ]);
156
157         self.record("fn_ref", data.span, values);
158     }
159
160     fn function_call(&mut self, data: FunctionCallData) {
161         let ref_id = data.ref_id.index.as_usize().to_string();
162         let ref_crate = data.ref_id.krate.to_string();
163         let qualname = String::new();
164         let scope = data.scope.index.as_u32().to_string();
165         let values = make_values_str(&[
166             ("refid", &ref_id),
167             ("refidcrate", &ref_crate),
168             ("qualname", &qualname),
169             ("scopeid", &scope)
170         ]);
171
172         self.record("fn_call", data.span, values);
173     }
174
175     fn method(&mut self, data: MethodData) {
176         let id = data.id.index.as_u32().to_string();
177         let scope = data.scope.index.as_u32().to_string();
178         let values = make_values_str(&[
179             ("id", &id),
180             ("qualname", &data.qualname),
181             ("scopeid", &scope)
182         ]);
183
184         self.record("method_decl", data.span, values);
185     }
186
187     fn method_call(&mut self, data: MethodCallData) {
188         let (dcn, dck) = match data.decl_id {
189             Some(declid) => (declid.index.as_usize().to_string(), declid.krate.to_string()),
190             None => (String::new(), String::new()),
191         };
192
193         let ref_id = data.ref_id.unwrap_or(null_def_id());
194
195         let def_id = ref_id.index.as_usize().to_string();
196         let def_crate = ref_id.krate.to_string();
197         let scope = data.scope.index.as_u32().to_string();
198         let values = make_values_str(&[
199             ("refid", &def_id),
200             ("refidcrate", &def_crate),
201             ("declid", &dcn),
202             ("declidcrate", &dck),
203             ("scopeid", &scope)
204         ]);
205
206         self.record("method_call", data.span, values);
207     }
208
209     fn macro_data(&mut self, data: MacroData) {
210         let values = make_values_str(&[
211             ("name", &data.name),
212             ("qualname", &data.qualname)
213         ]);
214
215         self.record("macro", data.span, values);
216     }
217
218     fn macro_use(&mut self, data: MacroUseData) {
219         let scope = data.scope.index.as_u32().to_string();
220         let values = make_values_str(&[
221             ("callee_name", &data.name),
222             ("qualname", &data.qualname),
223             ("scopeid", &scope)
224         ]);
225
226         self.record("macro_use", data.span, values);
227     }
228
229     fn mod_data(&mut self, data: ModData) {
230         let id = data.id.index.as_u32().to_string();
231         let scope = data.scope.index.as_u32().to_string();
232         let values = make_values_str(&[
233             ("id", &id),
234             ("qualname", &data.qualname),
235             ("scopeid", &scope),
236             ("def_file", &data.filename)
237         ]);
238
239         self.record("module", data.span, values);
240     }
241
242     fn mod_ref(&mut self, data: ModRefData) {
243         let (ref_id, ref_crate) = match data.ref_id {
244             Some(rid) => (rid.index.as_usize().to_string(), rid.krate.to_string()),
245             None => (0.to_string(), 0.to_string())
246         };
247
248         let scope = data.scope.index.as_u32().to_string();
249         let values = make_values_str(&[
250             ("refid", &ref_id),
251             ("refidcrate", &ref_crate),
252             ("qualname", &data.qualname),
253             ("scopeid", &scope)
254         ]);
255
256         self.record("mod_ref", data.span, values);
257     }
258
259     fn struct_data(&mut self, data: StructData) {
260         let id = data.id.index.as_u32().to_string();
261         let ctor_id = data.ctor_id.index.as_u32().to_string();
262         let scope = data.scope.index.as_u32().to_string();
263         let values = make_values_str(&[
264             ("id", &id),
265             ("ctor_id", &ctor_id),
266             ("qualname", &data.qualname),
267             ("scopeid", &scope),
268             ("value", &data.value)
269         ]);
270
271         self.record("struct", data.span, values);
272     }
273
274     fn struct_variant(&mut self, data: StructVariantData) {
275         let id = data.id.index.as_u32().to_string();
276         let scope = data.scope.index.as_u32().to_string();
277         let values = make_values_str(&[
278             ("id", &id),
279             ("ctor_id", &id),
280             ("qualname", &data.qualname),
281             ("type", &data.type_value),
282             ("value", &data.value),
283             ("scopeid", &scope)
284         ]);
285
286         self.record("variant_struct", data.span, values);
287     }
288
289     fn trait_data(&mut self, data: TraitData) {
290         let id = data.id.index.as_u32().to_string();
291         let scope = data.scope.index.as_u32().to_string();
292         let values = make_values_str(&[
293             ("id", &id),
294             ("qualname", &data.qualname),
295             ("scopeid", &scope),
296             ("value", &data.value)
297         ]);
298
299         self.record("trait", data.span, values);
300     }
301
302     fn tuple_variant(&mut self, data: TupleVariantData) {
303         let id = data.id.index.as_u32().to_string();
304         let scope = data.scope.index.as_u32().to_string();
305         let values = make_values_str(&[
306             ("id", &id),
307             ("name", &data.name),
308             ("qualname", &data.qualname),
309             ("type", &data.type_value),
310             ("value", &data.value),
311             ("scopeid", &scope)
312         ]);
313
314         self.record("variant", data.span, values);
315     }
316
317     fn type_ref(&mut self, data: TypeRefData) {
318         let (ref_id, ref_crate) = match data.ref_id {
319             Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()),
320             None => (0.to_string(), 0.to_string())
321         };
322
323         let scope = data.scope.index.as_u32().to_string();
324         let values = make_values_str(&[
325             ("refid", &ref_id),
326             ("refidcrate", &ref_crate),
327             ("qualname", &data.qualname),
328             ("scopeid", &scope)
329         ]);
330
331         self.record("type_ref", data.span, values);
332     }
333
334     fn typedef(&mut self, data: TypeDefData) {
335         let id = data.id.index.as_u32().to_string();
336         let values = make_values_str(&[
337             ("id", &id),
338             ("qualname", &data.qualname),
339             ("value", &data.value)
340         ]);
341
342         self.record("typedef", data.span, values);
343     }
344
345     fn use_data(&mut self, data: UseData) {
346         let mod_id = data.mod_id.unwrap_or(null_def_id());
347
348         let id = data.id.index.as_u32().to_string();
349         let ref_id = mod_id.index.as_usize().to_string();
350         let ref_crate = mod_id.krate.to_string();
351         let scope = data.scope.index.as_u32().to_string();
352         let values = make_values_str(&[
353             ("id", &id),
354             ("refid", &ref_id),
355             ("refidcrate", &ref_crate),
356             ("name", &data.name),
357             ("scopeid", &scope)
358         ]);
359
360         self.record("use_alias", data.span, values);
361     }
362
363     fn use_glob(&mut self, data: UseGlobData) {
364         let names = data.names.join(", ");
365
366         let id = data.id.index.as_u32().to_string();
367         let scope = data.scope.index.as_u32().to_string();
368         let values = make_values_str(&[
369             ("id", &id),
370             ("value", &names),
371             ("scopeid", &scope)
372         ]);
373
374         self.record("use_glob", data.span, values);
375     }
376
377     fn variable(&mut self, data: VariableData) {
378         let id = data.id.index.as_u32().to_string();
379         let scope = data.scope.index.as_u32().to_string();
380         let values = make_values_str(&[
381             ("id", &id),
382             ("name", &data.name),
383             ("qualname", &data.qualname),
384             ("value", &data.value),
385             ("type", &data.type_value),
386             ("scopeid", &scope)
387         ]);
388
389         self.record("variable", data.span, values);
390     }
391
392     fn variable_ref(&mut self, data: VariableRefData) {
393         let ref_id = data.ref_id.index.as_usize().to_string();
394         let ref_crate = data.ref_id.krate.to_string();
395         let scope = data.scope.index.as_u32().to_string();
396         let values = make_values_str(&[
397             ("refid", &ref_id),
398             ("refidcrate", &ref_crate),
399             ("qualname", ""),
400             ("scopeid", &scope)
401         ]);
402
403         self.record("var_ref", data.span, values)
404     }
405 }
406
407 // Helper function to escape quotes in a string
408 fn escape(s: String) -> String {
409     s.replace("\"", "\"\"")
410 }
411
412 fn make_values_str(pairs: &[(&'static str, &str)]) -> String {
413     let pairs = pairs.into_iter().map(|&(f, v)| {
414         // Never take more than 1020 chars
415         if v.len() > 1020 {
416             (f, &v[..1020])
417         } else {
418             (f, v)
419         }
420     });
421
422     let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from(v))));
423     strs.fold(String::new(), |mut s, ss| {
424         s.push_str(&ss[..]);
425         s
426     })
427 }
428
429 fn span_extent_str(span: SpanData) -> String {
430     format!("file_name,\"{}\",file_line,{},file_col,{},byte_start,{},\
431              file_line_end,{},file_col_end,{},byte_end,{}",
432              span.file_name, span.line_start, span.column_start, span.byte_start,
433              span.line_end, span.column_end, span.byte_end)
434 }