]> git.proxmox.com Git - rustc.git/blob - src/librustc_save_analysis/csv_dumper.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.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 rustc::hir::def_id::{DefId, DefIndex};
14 use syntax::codemap::Span;
15
16 use super::data::*;
17 use super::dump::Dump;
18 use super::span_utils::SpanUtils;
19
20 pub struct CsvDumper<'a, 'b, W: 'b> {
21 output: &'b mut W,
22 dump_spans: bool,
23 span: SpanUtils<'a>
24 }
25
26 impl<'a, 'b, W: Write> CsvDumper<'a, 'b, W> {
27 pub fn new(writer: &'b mut W, span: SpanUtils<'a>) -> CsvDumper<'a, 'b, W> {
28 CsvDumper { output: writer, dump_spans: false, span: span }
29 }
30
31 fn record(&mut self, kind: &str, span: Span, values: String) {
32 let span_str = self.span.extent_str(span);
33 if let Err(_) = write!(self.output, "{},{}{}\n", kind, span_str, values) {
34 error!("Error writing output");
35 }
36 }
37
38 fn record_raw(&mut self, info: &str) {
39 if let Err(_) = write!(self.output, "{}", info) {
40 error!("Error writing output '{}'", info);
41 }
42 }
43
44 pub fn dump_span(&mut self, kind: &str, span: Span) {
45 assert!(self.dump_spans);
46 let result = format!("span,kind,{},{},text,\"{}\"\n",
47 kind,
48 self.span.extent_str(span),
49 escape(self.span.snippet(span)));
50 self.record_raw(&result);
51 }
52 }
53
54 impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
55 fn crate_prelude(&mut self, span: Span, data: CratePreludeData) {
56 let crate_root = data.crate_root.unwrap_or("<no source>".to_owned());
57
58 let values = make_values_str(&[
59 ("name", &data.crate_name),
60 ("crate_root", &crate_root)
61 ]);
62
63 self.record("crate", span, values);
64
65 for c in data.external_crates {
66 let num = c.num.to_string();
67 let lo_loc = self.span.sess.codemap().lookup_char_pos(span.lo);
68 let file_name = SpanUtils::make_path_string(&lo_loc.file.name);
69 let values = make_values_str(&[
70 ("name", &c.name),
71 ("crate", &num),
72 ("file_name", &file_name)
73 ]);
74
75 self.record_raw(&format!("external_crate{}\n", values));
76 }
77
78 self.record_raw("end_external_crates\n");
79 }
80
81 fn enum_data(&mut self, span: Span, data: EnumData) {
82 if self.dump_spans {
83 self.dump_span("enum", span);
84 return;
85 }
86
87 let id = data.id.to_string();
88 let scope = data.scope.to_string();
89 let values = make_values_str(&[
90 ("id", &id),
91 ("qualname", &data.qualname),
92 ("scopeid", &scope),
93 ("value", &data.value)
94 ]);
95
96 self.record("enum", data.span, values);
97 }
98
99 fn extern_crate(&mut self, span: Span, data: ExternCrateData) {
100 if self.dump_spans {
101 self.dump_span("extern_crate", span);
102 return;
103 }
104
105 let id = data.id.to_string();
106 let crate_num = data.crate_num.to_string();
107 let scope = data.scope.to_string();
108 let values = make_values_str(&[
109 ("id", &id),
110 ("name", &data.name),
111 ("location", &data.location),
112 ("crate", &crate_num),
113 ("scopeid", &scope)
114 ]);
115
116 self.record("extern_crate", data.span, values);
117 }
118
119 fn impl_data(&mut self, span: Span, data: ImplData) {
120 if self.dump_spans {
121 self.dump_span("impl", span);
122 return;
123 }
124
125 let self_ref = data.self_ref.unwrap_or(null_def_id());
126 let trait_ref = data.trait_ref.unwrap_or(null_def_id());
127
128 let id = data.id.to_string();
129 let ref_id = self_ref.index.as_usize().to_string();
130 let ref_id_crate = self_ref.krate.to_string();
131 let trait_id = trait_ref.index.as_usize().to_string();
132 let trait_id_crate = trait_ref.krate.to_string();
133 let scope = data.scope.to_string();
134 let values = make_values_str(&[
135 ("id", &id),
136 ("refid", &ref_id),
137 ("refidcrate", &ref_id_crate),
138 ("traitid", &trait_id),
139 ("traitidcrate", &trait_id_crate),
140 ("scopeid", &scope)
141 ]);
142
143 self.record("impl", data.span, values);
144 }
145
146 fn inheritance(&mut self, data: InheritanceData) {
147 if self.dump_spans {
148 return;
149 }
150
151 let base_id = data.base_id.index.as_usize().to_string();
152 let base_crate = data.base_id.krate.to_string();
153 let deriv_id = data.deriv_id.to_string();
154 let deriv_crate = 0.to_string();
155 let values = make_values_str(&[
156 ("base", &base_id),
157 ("basecrate", &base_crate),
158 ("derived", &deriv_id),
159 ("derivedcrate", &deriv_crate)
160 ]);
161
162 self.record("inheritance", data.span, values);
163 }
164
165 fn function(&mut self, span: Span, data: FunctionData) {
166 if self.dump_spans {
167 self.dump_span("function", span);
168 return;
169 }
170
171 let (decl_id, decl_crate) = match data.declaration {
172 Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()),
173 None => (String::new(), String::new())
174 };
175
176 let id = data.id.to_string();
177 let scope = data.scope.to_string();
178 let values = make_values_str(&[
179 ("id", &id),
180 ("qualname", &data.qualname),
181 ("declid", &decl_id),
182 ("declidcrate", &decl_crate),
183 ("scopeid", &scope)
184 ]);
185
186 self.record("function", data.span, values);
187 }
188
189 fn function_ref(&mut self, span: Span, data: FunctionRefData) {
190 if self.dump_spans {
191 self.dump_span("fn_ref", span);
192 return;
193 }
194
195 let ref_id = data.ref_id.index.as_usize().to_string();
196 let ref_crate = data.ref_id.krate.to_string();
197 let scope = data.scope.to_string();
198 let values = make_values_str(&[
199 ("refid", &ref_id),
200 ("refidcrate", &ref_crate),
201 ("qualname", ""),
202 ("scopeid", &scope)
203 ]);
204
205 self.record("fn_ref", data.span, values);
206 }
207
208 fn function_call(&mut self, span: Span, data: FunctionCallData) {
209 if self.dump_spans {
210 self.dump_span("fn_call", span);
211 return;
212 }
213
214 let ref_id = data.ref_id.index.as_usize().to_string();
215 let ref_crate = data.ref_id.krate.to_string();
216 let qualname = String::new();
217 let scope = data.scope.to_string();
218 let values = make_values_str(&[
219 ("refid", &ref_id),
220 ("refidcrate", &ref_crate),
221 ("qualname", &qualname),
222 ("scopeid", &scope)
223 ]);
224
225 self.record("fn_call", data.span, values);
226 }
227
228 fn method(&mut self, span: Span, data: MethodData) {
229 if self.dump_spans {
230 self.dump_span("method_decl", span);
231 return;
232 }
233
234 let id = data.id.to_string();
235 let scope = data.scope.to_string();
236 let values = make_values_str(&[
237 ("id", &id),
238 ("qualname", &data.qualname),
239 ("scopeid", &scope)
240 ]);
241
242 self.record("method_decl", span, values);
243 }
244
245 fn method_call(&mut self, span: Span, data: MethodCallData) {
246 if self.dump_spans {
247 self.dump_span("method_call", span);
248 return;
249 }
250
251 let (dcn, dck) = match data.decl_id {
252 Some(declid) => (declid.index.as_usize().to_string(), declid.krate.to_string()),
253 None => (String::new(), String::new()),
254 };
255
256 let ref_id = data.ref_id.unwrap_or(null_def_id());
257
258 let def_id = ref_id.index.as_usize().to_string();
259 let def_crate = ref_id.krate.to_string();
260 let scope = data.scope.to_string();
261 let values = make_values_str(&[
262 ("refid", &def_id),
263 ("refidcrate", &def_crate),
264 ("declid", &dcn),
265 ("declidcrate", &dck),
266 ("scopeid", &scope)
267 ]);
268
269 self.record("method_call", data.span, values);
270 }
271
272 fn macro_data(&mut self, span: Span, data: MacroData) {
273 if self.dump_spans {
274 self.dump_span("macro", span);
275 return;
276 }
277
278 let values = make_values_str(&[
279 ("name", &data.name),
280 ("qualname", &data.qualname)
281 ]);
282
283 self.record("macro", data.span, values);
284 }
285
286 fn macro_use(&mut self, span: Span, data: MacroUseData) {
287 if self.dump_spans {
288 self.dump_span("macro_use", span);
289 return;
290 }
291
292 let scope = data.scope.to_string();
293 let values = make_values_str(&[
294 ("callee_name", &data.name),
295 ("qualname", &data.qualname),
296 ("scopeid", &scope)
297 ]);
298
299 self.record("macro_use", data.span, values);
300 }
301
302 fn mod_data(&mut self, data: ModData) {
303 if self.dump_spans {
304 return;
305 }
306
307 let id = data.id.to_string();
308 let scope = data.scope.to_string();
309 let values = make_values_str(&[
310 ("id", &id),
311 ("qualname", &data.qualname),
312 ("scopeid", &scope),
313 ("def_file", &data.filename)
314 ]);
315
316 self.record("module", data.span, values);
317 }
318
319 fn mod_ref(&mut self, span: Span, data: ModRefData) {
320 if self.dump_spans {
321 self.dump_span("mod_ref", span);
322 return;
323 }
324
325 let (ref_id, ref_crate) = match data.ref_id {
326 Some(rid) => (rid.index.as_usize().to_string(), rid.krate.to_string()),
327 None => (0.to_string(), 0.to_string())
328 };
329
330 let scope = data.scope.to_string();
331 let values = make_values_str(&[
332 ("refid", &ref_id),
333 ("refidcrate", &ref_crate),
334 ("qualname", &data.qualname),
335 ("scopeid", &scope)
336 ]);
337
338 self.record("mod_ref", data.span, values);
339 }
340
341 fn struct_data(&mut self, span: Span, data: StructData) {
342 if self.dump_spans {
343 self.dump_span("struct", span);
344 return;
345 }
346
347 let id = data.id.to_string();
348 let ctor_id = data.ctor_id.to_string();
349 let scope = data.scope.to_string();
350 let values = make_values_str(&[
351 ("id", &id),
352 ("ctor_id", &ctor_id),
353 ("qualname", &data.qualname),
354 ("scopeid", &scope),
355 ("value", &data.value)
356 ]);
357
358 self.record("struct", data.span, values);
359 }
360
361 fn struct_variant(&mut self, span: Span, data: StructVariantData) {
362 if self.dump_spans {
363 self.dump_span("variant_struct", span);
364 return;
365 }
366
367 let id = data.id.to_string();
368 let scope = data.scope.to_string();
369 let values = make_values_str(&[
370 ("id", &id),
371 ("ctor_id", &id),
372 ("qualname", &data.qualname),
373 ("type", &data.type_value),
374 ("value", &data.value),
375 ("scopeid", &scope)
376 ]);
377
378 self.record("variant_struct", data.span, values);
379 }
380
381 fn trait_data(&mut self, span: Span, data: TraitData) {
382 if self.dump_spans {
383 self.dump_span("trait", span);
384 return;
385 }
386
387 let id = data.id.to_string();
388 let scope = data.scope.to_string();
389 let values = make_values_str(&[
390 ("id", &id),
391 ("qualname", &data.qualname),
392 ("scopeid", &scope),
393 ("value", &data.value)
394 ]);
395
396 self.record("trait", data.span, values);
397 }
398
399 fn tuple_variant(&mut self, span: Span, data: TupleVariantData) {
400 if self.dump_spans {
401 self.dump_span("variant", span);
402 return;
403 }
404
405 let id = data.id.to_string();
406 let scope = data.scope.to_string();
407 let values = make_values_str(&[
408 ("id", &id),
409 ("name", &data.name),
410 ("qualname", &data.qualname),
411 ("type", &data.type_value),
412 ("value", &data.value),
413 ("scopeid", &scope)
414 ]);
415
416 self.record("variant", data.span, values);
417 }
418
419 fn type_ref(&mut self, span: Span, data: TypeRefData) {
420 if self.dump_spans {
421 self.dump_span("type_ref", span);
422 return;
423 }
424
425 let (ref_id, ref_crate) = match data.ref_id {
426 Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()),
427 None => (0.to_string(), 0.to_string())
428 };
429
430 let scope = data.scope.to_string();
431 let values = make_values_str(&[
432 ("refid", &ref_id),
433 ("refidcrate", &ref_crate),
434 ("qualname", &data.qualname),
435 ("scopeid", &scope)
436 ]);
437
438 self.record("type_ref", data.span, values);
439 }
440
441 fn typedef(&mut self, span: Span, data: TypedefData) {
442 if self.dump_spans {
443 self.dump_span("typedef", span);
444 return;
445 }
446
447 let id = data.id.to_string();
448 let values = make_values_str(&[
449 ("id", &id),
450 ("qualname", &data.qualname),
451 ("value", &data.value)
452 ]);
453
454 self.record("typedef", data.span, values);
455 }
456
457 fn use_data(&mut self, span: Span, data: UseData) {
458 if self.dump_spans {
459 self.dump_span("use_alias", span);
460 return;
461 }
462
463 let mod_id = data.mod_id.unwrap_or(null_def_id());
464
465 let id = data.id.to_string();
466 let ref_id = mod_id.index.as_usize().to_string();
467 let ref_crate = mod_id.krate.to_string();
468 let scope = data.scope.to_string();
469 let values = make_values_str(&[
470 ("id", &id),
471 ("refid", &ref_id),
472 ("refidcrate", &ref_crate),
473 ("name", &data.name),
474 ("scopeid", &scope)
475 ]);
476
477 self.record("use_alias", data.span, values);
478 }
479
480 fn use_glob(&mut self, span: Span, data: UseGlobData) {
481 if self.dump_spans {
482 self.dump_span("use_glob", span);
483 return;
484 }
485
486 let names = data.names.join(", ");
487
488 let id = data.id.to_string();
489 let scope = data.scope.to_string();
490 let values = make_values_str(&[
491 ("id", &id),
492 ("value", &names),
493 ("scopeid", &scope)
494 ]);
495
496 self.record("use_glob", data.span, values);
497 }
498
499 fn variable(&mut self, span: Span, data: VariableData) {
500 if self.dump_spans {
501 self.dump_span("variable", span);
502 return;
503 }
504
505 let id = data.id.to_string();
506 let scope = data.scope.to_string();
507 let values = make_values_str(&[
508 ("id", &id),
509 ("name", &data.name),
510 ("qualname", &data.qualname),
511 ("value", &data.value),
512 ("type", &data.type_value),
513 ("scopeid", &scope)
514 ]);
515
516 self.record("variable", data.span, values);
517 }
518
519 fn variable_ref(&mut self, span: Span, data: VariableRefData) {
520 if self.dump_spans {
521 self.dump_span("var_ref", span);
522 return;
523 }
524
525 let ref_id = data.ref_id.index.as_usize().to_string();
526 let ref_crate = data.ref_id.krate.to_string();
527 let scope = data.scope.to_string();
528 let values = make_values_str(&[
529 ("refid", &ref_id),
530 ("refidcrate", &ref_crate),
531 ("qualname", ""),
532 ("scopeid", &scope)
533 ]);
534
535 self.record("var_ref", data.span, values)
536 }
537 }
538
539 // Helper function to escape quotes in a string
540 fn escape(s: String) -> String {
541 s.replace("\"", "\"\"")
542 }
543
544 fn make_values_str(pairs: &[(&'static str, &str)]) -> String {
545 let pairs = pairs.into_iter().map(|&(f, v)| {
546 // Never take more than 1020 chars
547 if v.len() > 1020 {
548 (f, &v[..1020])
549 } else {
550 (f, v)
551 }
552 });
553
554 let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from(v))));
555 strs.fold(String::new(), |mut s, ss| {
556 s.push_str(&ss[..]);
557 s
558 })
559 }
560
561 fn null_def_id() -> DefId {
562 DefId {
563 krate: 0,
564 index: DefIndex::new(0),
565 }
566 }