]> git.proxmox.com Git - rustc.git/blob - src/librustc_trans/save/recorder.rs
193902d981d690b30cf3795d6f58af419818038e
[rustc.git] / src / librustc_trans / save / recorder.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 pub use self::Row::*;
12
13 use super::escape;
14 use super::span_utils::SpanUtils;
15
16 use std::io::Write;
17
18 use syntax::ast;
19 use syntax::ast::{NodeId,DefId};
20 use syntax::codemap::*;
21
22 const ZERO_DEF_ID: DefId = DefId { node: 0, krate: 0 };
23
24 pub struct Recorder {
25 // output file
26 pub out: Box<Write+'static>,
27 pub dump_spans: bool,
28 }
29
30 impl Recorder {
31 pub fn record(&mut self, info: &str) {
32 match write!(self.out, "{}", info) {
33 Err(_) => error!("Error writing output '{}'", info),
34 _ => (),
35 }
36 }
37
38 pub fn dump_span(&mut self,
39 su: SpanUtils,
40 kind: &str,
41 span: Span,
42 _sub_span: Option<Span>) {
43 assert!(self.dump_spans);
44 let result = format!("span,kind,{},{},text,\"{}\"\n",
45 kind, su.extent_str(span), escape(su.snippet(span)));
46 self.record(&result[..]);
47 }
48 }
49
50 pub struct FmtStrs<'a> {
51 pub recorder: Box<Recorder>,
52 span: SpanUtils<'a>,
53 }
54
55 macro_rules! s { ($e:expr) => { format!("{}", $e) }}
56 macro_rules! svec {
57 ($($e:expr),*) => ({
58 // leading _ to allow empty construction without a warning.
59 let mut _temp = ::std::vec::Vec::new();
60 $(_temp.push(s!($e));)*
61 _temp
62 })
63 }
64
65 // FIXME recorder should operate on super::Data, rather than lots of ad hoc
66 // data.
67
68 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
69 pub enum Row {
70 Variable,
71 Enum,
72 Variant,
73 VariantStruct,
74 Function,
75 MethodDecl,
76 Struct,
77 Trait,
78 Impl,
79 Module,
80 UseAlias,
81 UseGlob,
82 ExternCrate,
83 Inheritance,
84 MethodCall,
85 Typedef,
86 ExternalCrate,
87 Crate,
88 FnCall,
89 ModRef,
90 VarRef,
91 TypeRef,
92 StructRef,
93 FnRef,
94 }
95
96 impl<'a> FmtStrs<'a> {
97 pub fn new(rec: Box<Recorder>, span: SpanUtils<'a>) -> FmtStrs<'a> {
98 FmtStrs {
99 recorder: rec,
100 span: span,
101 }
102 }
103
104 // A map from kind of item to a tuple of
105 // a string representation of the name
106 // a vector of field names
107 // whether this kind requires a span
108 // whether dump_spans should dump for this kind
109 fn lookup_row(r: Row) -> (&'static str, Vec<&'static str>, bool, bool) {
110 match r {
111 Variable => ("variable",
112 vec!("id","name","qualname","value","type","scopeid"),
113 true, true),
114 Enum => ("enum", vec!("id","qualname","scopeid","value"), true, true),
115 Variant => ("variant",
116 vec!("id","name","qualname","type","value","scopeid"),
117 true, true),
118 VariantStruct => ("variant_struct",
119 vec!("id","ctor_id","qualname","type","value","scopeid"),
120 true, true),
121 Function => ("function",
122 vec!("id","qualname","declid","declidcrate","scopeid"),
123 true, true),
124 MethodDecl => ("method_decl", vec!("id","qualname","scopeid"), true, true),
125 Struct => ("struct", vec!("id","ctor_id","qualname","scopeid","value"), true, true),
126 Trait => ("trait", vec!("id","qualname","scopeid","value"), true, true),
127 Impl => ("impl",
128 vec!("id","refid","refidcrate","traitid","traitidcrate","scopeid"),
129 true, true),
130 Module => ("module", vec!("id","qualname","scopeid","def_file"), true, false),
131 UseAlias => ("use_alias",
132 vec!("id","refid","refidcrate","name","scopeid"),
133 true, true),
134 UseGlob => ("use_glob", vec!("id","value","scopeid"), true, true),
135 ExternCrate => ("extern_crate",
136 vec!("id","name","location","crate","scopeid"),
137 true, true),
138 Inheritance => ("inheritance",
139 vec!("base","basecrate","derived","derivedcrate"),
140 true, false),
141 MethodCall => ("method_call",
142 vec!("refid","refidcrate","declid","declidcrate","scopeid"),
143 true, true),
144 Typedef => ("typedef", vec!("id","qualname","value"), true, true),
145 ExternalCrate => ("external_crate", vec!("name","crate","file_name"), false, false),
146 Crate => ("crate", vec!("name"), true, false),
147 FnCall => ("fn_call", vec!("refid","refidcrate","qualname","scopeid"), true, true),
148 ModRef => ("mod_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
149 VarRef => ("var_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
150 TypeRef => ("type_ref",
151 vec!("refid","refidcrate","qualname","scopeid"),
152 true, true),
153 StructRef => ("struct_ref",
154 vec!("refid","refidcrate","qualname","scopeid"),
155 true, true),
156 FnRef => ("fn_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true)
157 }
158 }
159
160 pub fn make_values_str(&self,
161 kind: &'static str,
162 fields: &Vec<&'static str>,
163 values: Vec<String>,
164 span: Span) -> Option<String> {
165 if values.len() != fields.len() {
166 self.span.sess.span_bug(span, &format!(
167 "Mismatch between length of fields for '{}', expected '{}', found '{}'",
168 kind, fields.len(), values.len()));
169 }
170
171 let values = values.iter().map(|s| {
172 // Never take more than 1020 chars
173 if s.len() > 1020 {
174 &s[..1020]
175 } else {
176 &s[..]
177 }
178 });
179
180 let pairs = fields.iter().zip(values);
181 let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from_str(v))));
182 Some(strs.fold(String::new(), |mut s, ss| {
183 s.push_str(&ss[..]);
184 s
185 }))
186 }
187
188 pub fn record_without_span(&mut self,
189 kind: Row,
190 values: Vec<String>,
191 span: Span) {
192 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
193
194 if needs_span {
195 self.span.sess.span_bug(span, &format!(
196 "Called record_without_span for '{}' which does requires a span",
197 label));
198 }
199 assert!(!dump_spans);
200
201 if self.recorder.dump_spans {
202 return;
203 }
204
205 let values_str = match self.make_values_str(label, fields, values, span) {
206 Some(vs) => vs,
207 None => return,
208 };
209
210 let mut result = String::from_str(label);
211 result.push_str(&values_str[..]);
212 result.push_str("\n");
213 self.recorder.record(&result[..]);
214 }
215
216 pub fn record_with_span(&mut self,
217 kind: Row,
218 span: Span,
219 sub_span: Span,
220 values: Vec<String>) {
221 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
222
223 if self.recorder.dump_spans {
224 if dump_spans {
225 self.recorder.dump_span(self.span.clone(),
226 label,
227 span,
228 Some(sub_span));
229 }
230 return;
231 }
232
233 if !needs_span {
234 self.span.sess.span_bug(span,
235 &format!("Called record_with_span for '{}' \
236 which does not require a span", label));
237 }
238
239 let values_str = match self.make_values_str(label, fields, values, span) {
240 Some(vs) => vs,
241 None => return,
242 };
243 let result = format!("{},{}{}\n", label, self.span.extent_str(sub_span), values_str);
244 self.recorder.record(&result[..]);
245 }
246
247 pub fn check_and_record(&mut self,
248 kind: Row,
249 span: Span,
250 sub_span: Option<Span>,
251 values: Vec<String>) {
252 match sub_span {
253 Some(sub_span) => self.record_with_span(kind, span, sub_span, values),
254 None => {
255 let (label, _, _, _) = FmtStrs::lookup_row(kind);
256 self.span.report_span_err(label, span);
257 }
258 }
259 }
260
261 pub fn variable_str(&mut self,
262 span: Span,
263 sub_span: Option<Span>,
264 id: NodeId,
265 name: &str,
266 value: &str,
267 typ: &str) {
268 // Getting a fully qualified name for a variable is hard because in
269 // the local case they can be overridden in one block and there is no nice way
270 // to refer to such a scope in english, so we just hack it by appending the
271 // variable def's node id
272 let mut qualname = String::from_str(name);
273 qualname.push_str("$");
274 qualname.push_str(&id.to_string());
275 self.check_and_record(Variable,
276 span,
277 sub_span,
278 svec!(id, name, qualname, value, typ, 0));
279 }
280
281 // formal parameters
282 pub fn formal_str(&mut self,
283 span: Span,
284 sub_span: Option<Span>,
285 id: NodeId,
286 fn_name: &str,
287 name: &str,
288 typ: &str) {
289 let mut qualname = String::from_str(fn_name);
290 qualname.push_str("::");
291 qualname.push_str(name);
292 self.check_and_record(Variable,
293 span,
294 sub_span,
295 svec!(id, name, qualname, "", typ, 0));
296 }
297
298 // value is the initialising expression of the static if it is not mut, otherwise "".
299 pub fn static_str(&mut self,
300 span: Span,
301 sub_span: Option<Span>,
302 id: NodeId,
303 name: &str,
304 qualname: &str,
305 value: &str,
306 typ: &str,
307 scope_id: NodeId) {
308 self.check_and_record(Variable,
309 span,
310 sub_span,
311 svec!(id, name, qualname, value, typ, scope_id));
312 }
313
314 pub fn field_str(&mut self,
315 span: Span,
316 sub_span: Option<Span>,
317 id: NodeId,
318 name: &str,
319 qualname: &str,
320 typ: &str,
321 scope_id: NodeId) {
322 self.check_and_record(Variable,
323 span,
324 sub_span,
325 svec!(id, name, qualname, "", typ, scope_id));
326 }
327
328 pub fn enum_str(&mut self,
329 span: Span,
330 sub_span: Option<Span>,
331 id: NodeId,
332 name: &str,
333 scope_id: NodeId,
334 value: &str) {
335 self.check_and_record(Enum,
336 span,
337 sub_span,
338 svec!(id, name, scope_id, value));
339 }
340
341 pub fn tuple_variant_str(&mut self,
342 span: Span,
343 sub_span: Option<Span>,
344 id: NodeId,
345 name: &str,
346 qualname: &str,
347 typ: &str,
348 val: &str,
349 scope_id: NodeId) {
350 self.check_and_record(Variant,
351 span,
352 sub_span,
353 svec!(id, name, qualname, typ, val, scope_id));
354 }
355
356 pub fn struct_variant_str(&mut self,
357 span: Span,
358 sub_span: Option<Span>,
359 id: NodeId,
360 ctor_id: NodeId,
361 name: &str,
362 typ: &str,
363 val: &str,
364 scope_id: NodeId) {
365 self.check_and_record(VariantStruct,
366 span,
367 sub_span,
368 svec!(id, ctor_id, name, typ, val, scope_id));
369 }
370
371 pub fn fn_str(&mut self,
372 span: Span,
373 sub_span: Option<Span>,
374 id: NodeId,
375 name: &str,
376 scope_id: NodeId) {
377 self.check_and_record(Function,
378 span,
379 sub_span,
380 svec!(id, name, "", "", scope_id));
381 }
382
383 pub fn method_str(&mut self,
384 span: Span,
385 sub_span: Option<Span>,
386 id: NodeId,
387 name: &str,
388 decl_id: Option<DefId>,
389 scope_id: NodeId) {
390 let values = match decl_id {
391 Some(decl_id) => svec!(id, name, decl_id.node, decl_id.krate, scope_id),
392 None => svec!(id, name, "", "", scope_id)
393 };
394 self.check_and_record(Function,
395 span,
396 sub_span,
397 values);
398 }
399
400 pub fn method_decl_str(&mut self,
401 span: Span,
402 sub_span: Option<Span>,
403 id: NodeId,
404 name: &str,
405 scope_id: NodeId) {
406 self.check_and_record(MethodDecl,
407 span,
408 sub_span,
409 svec!(id, name, scope_id));
410 }
411
412 pub fn struct_str(&mut self,
413 span: Span,
414 sub_span: Option<Span>,
415 id: NodeId,
416 ctor_id: NodeId,
417 name: &str,
418 scope_id: NodeId,
419 value: &str) {
420 self.check_and_record(Struct,
421 span,
422 sub_span,
423 svec!(id, ctor_id, name, scope_id, value));
424 }
425
426 pub fn trait_str(&mut self,
427 span: Span,
428 sub_span: Option<Span>,
429 id: NodeId,
430 name: &str,
431 scope_id: NodeId,
432 value: &str) {
433 self.check_and_record(Trait,
434 span,
435 sub_span,
436 svec!(id, name, scope_id, value));
437 }
438
439 pub fn impl_str(&mut self,
440 span: Span,
441 sub_span: Option<Span>,
442 id: NodeId,
443 ref_id: Option<DefId>,
444 trait_id: Option<DefId>,
445 scope_id: NodeId) {
446 let ref_id = ref_id.unwrap_or(ZERO_DEF_ID);
447 let trait_id = trait_id.unwrap_or(ZERO_DEF_ID);
448 self.check_and_record(Impl,
449 span,
450 sub_span,
451 svec!(id,
452 ref_id.node,
453 ref_id.krate,
454 trait_id.node,
455 trait_id.krate,
456 scope_id));
457 }
458
459 pub fn mod_str(&mut self,
460 span: Span,
461 sub_span: Option<Span>,
462 id: NodeId,
463 name: &str,
464 parent: NodeId,
465 filename: &str) {
466 self.check_and_record(Module,
467 span,
468 sub_span,
469 svec!(id, name, parent, filename));
470 }
471
472 pub fn use_alias_str(&mut self,
473 span: Span,
474 sub_span: Option<Span>,
475 id: NodeId,
476 mod_id: Option<DefId>,
477 name: &str,
478 parent: NodeId) {
479 let (mod_node, mod_crate) = match mod_id {
480 Some(mod_id) => (mod_id.node, mod_id.krate),
481 None => (0, 0)
482 };
483 self.check_and_record(UseAlias,
484 span,
485 sub_span,
486 svec!(id, mod_node, mod_crate, name, parent));
487 }
488
489 pub fn use_glob_str(&mut self,
490 span: Span,
491 sub_span: Option<Span>,
492 id: NodeId,
493 values: &str,
494 parent: NodeId) {
495 self.check_and_record(UseGlob,
496 span,
497 sub_span,
498 svec!(id, values, parent));
499 }
500
501 pub fn extern_crate_str(&mut self,
502 span: Span,
503 sub_span: Option<Span>,
504 id: NodeId,
505 cnum: ast::CrateNum,
506 name: &str,
507 loc: &str,
508 parent: NodeId) {
509 self.check_and_record(ExternCrate,
510 span,
511 sub_span,
512 svec!(id, name, loc, cnum, parent));
513 }
514
515 pub fn inherit_str(&mut self,
516 span: Span,
517 sub_span: Option<Span>,
518 base_id: DefId,
519 deriv_id: NodeId) {
520 self.check_and_record(Inheritance,
521 span,
522 sub_span,
523 svec!(base_id.node,
524 base_id.krate,
525 deriv_id,
526 0));
527 }
528
529 pub fn fn_call_str(&mut self,
530 span: Span,
531 sub_span: Option<Span>,
532 id: DefId,
533 scope_id:NodeId) {
534 self.check_and_record(FnCall,
535 span,
536 sub_span,
537 svec!(id.node, id.krate, "", scope_id));
538 }
539
540 pub fn meth_call_str(&mut self,
541 span: Span,
542 sub_span: Option<Span>,
543 defid: Option<DefId>,
544 declid: Option<DefId>,
545 scope_id: NodeId) {
546 let (dfn, dfk) = match defid {
547 Some(defid) => (defid.node, defid.krate),
548 None => (0, 0)
549 };
550 let (dcn, dck) = match declid {
551 Some(declid) => (s!(declid.node), s!(declid.krate)),
552 None => ("".to_string(), "".to_string())
553 };
554 self.check_and_record(MethodCall,
555 span,
556 sub_span,
557 svec!(dfn, dfk, dcn, dck, scope_id));
558 }
559
560 pub fn sub_mod_ref_str(&mut self,
561 span: Span,
562 sub_span: Span,
563 qualname: &str,
564 parent:NodeId) {
565 self.record_with_span(ModRef,
566 span,
567 sub_span,
568 svec!(0, 0, qualname, parent));
569 }
570
571 pub fn typedef_str(&mut self,
572 span: Span,
573 sub_span: Option<Span>,
574 id: NodeId,
575 qualname: &str,
576 value: &str) {
577 self.check_and_record(Typedef,
578 span,
579 sub_span,
580 svec!(id, qualname, value));
581 }
582
583 pub fn crate_str(&mut self,
584 span: Span,
585 name: &str) {
586 self.record_with_span(Crate,
587 span,
588 span,
589 svec!(name));
590 }
591
592 pub fn external_crate_str(&mut self,
593 span: Span,
594 name: &str,
595 num: ast::CrateNum) {
596 let lo_loc = self.span.sess.codemap().lookup_char_pos(span.lo);
597 self.record_without_span(ExternalCrate,
598 svec!(name, num, lo_loc.file.name),
599 span);
600 }
601
602 pub fn sub_type_ref_str(&mut self,
603 span: Span,
604 sub_span: Span,
605 qualname: &str) {
606 self.record_with_span(TypeRef,
607 span,
608 sub_span,
609 svec!(0, 0, qualname, 0));
610 }
611
612 // A slightly generic function for a reference to an item of any kind.
613 pub fn ref_str(&mut self,
614 kind: Row,
615 span: Span,
616 sub_span: Option<Span>,
617 id: DefId,
618 scope_id: NodeId) {
619 self.check_and_record(kind,
620 span,
621 sub_span,
622 svec!(id.node, id.krate, "", scope_id));
623 }
624 }