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