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.
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.
14 use super::span_utils::SpanUtils;
19 use syntax::ast::{NodeId,DefId};
20 use syntax::codemap::*;
24 pub out: Box<Writer+'static>,
29 pub fn record(&mut self, info: &str) {
30 match write!(self.out, "{}", info) {
31 Err(_) => error!("Error writing output '{}'", info),
36 pub fn dump_span(&mut self,
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.as_slice());
48 pub struct FmtStrs<'a> {
49 pub recorder: Box<Recorder>,
54 macro_rules! s { ($e:expr) => { format!("{}", $e) }}
57 // leading _ to allow empty construction without a warning.
58 let mut _temp = ::std::vec::Vec::new();
59 $(_temp.push(s!($e));)*
90 impl<'a> FmtStrs<'a> {
91 pub fn new(rec: Box<Recorder>, span: SpanUtils<'a>, krate: String) -> FmtStrs<'a> {
99 // A map from kind of item to a tuple of
100 // a string representation of the name
101 // a vector of field names
102 // whether this kind requires a span
103 // whether dump_spans should dump for this kind
104 fn lookup_row(r: Row) -> (&'static str, Vec<&'static str>, bool, bool) {
106 Variable => ("variable",
107 vec!("id","name","qualname","value","type","scopeid"),
109 Enum => ("enum", vec!("id","qualname","scopeid","value"), true, true),
110 Variant => ("variant",
111 vec!("id","name","qualname","type","value","scopeid"),
113 VariantStruct => ("variant_struct",
114 vec!("id","ctor_id","qualname","type","value","scopeid"),
116 Function => ("function",
117 vec!("id","qualname","declid","declidcrate","scopeid"),
119 MethodDecl => ("method_decl", vec!("id","qualname","scopeid"), true, true),
120 Struct => ("struct", vec!("id","ctor_id","qualname","scopeid","value"), true, true),
121 Trait => ("trait", vec!("id","qualname","scopeid","value"), true, true),
122 Impl => ("impl", vec!("id","refid","refidcrate","scopeid"), true, true),
123 Module => ("module", vec!("id","qualname","scopeid","def_file"), true, false),
124 UseAlias => ("use_alias",
125 vec!("id","refid","refidcrate","name","scopeid"),
127 ExternCrate => ("extern_crate",
128 vec!("id","name","location","crate","scopeid"),
130 Inheritance => ("inheritance",
131 vec!("base","basecrate","derived","derivedcrate"),
133 MethodCall => ("method_call",
134 vec!("refid","refidcrate","declid","declidcrate","scopeid"),
136 Typedef => ("typedef", vec!("id","qualname","value"), true, true),
137 ExternalCrate => ("external_crate", vec!("name","crate","file_name"), false, false),
138 Crate => ("crate", vec!("name"), true, false),
139 FnCall => ("fn_call", vec!("refid","refidcrate","qualname","scopeid"), true, true),
140 ModRef => ("mod_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
141 VarRef => ("var_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
142 TypeRef => ("type_ref",
143 vec!("refid","refidcrate","qualname","scopeid"),
145 StructRef => ("struct_ref",
146 vec!("refid","refidcrate","qualname","scopeid"),
148 FnRef => ("fn_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true)
152 pub fn make_values_str(&self,
154 fields: &Vec<&'static str>,
156 span: Span) -> Option<String> {
157 if values.len() != fields.len() {
158 self.span.sess.span_bug(span, format!(
159 "Mismatch between length of fields for '{}', expected '{}', found '{}'",
160 kind, fields.len(), values.len()).as_slice());
163 let values = values.iter().map(|s| {
164 // Never take more than 1020 chars
166 s.as_slice().slice_to(1020)
172 let pairs = fields.iter().zip(values);
173 let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(
174 if *f == "qualname" && v.len() > 0 {
175 let mut n = self.krate.clone();
183 Some(strs.fold(String::new(), |mut s, ss| {
184 s.push_str(ss.as_slice());
189 pub fn record_without_span(&mut self,
193 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
196 self.span.sess.span_bug(span, format!(
197 "Called record_without_span for '{}' which does requires a span",
200 assert!(!dump_spans);
202 if self.recorder.dump_spans {
206 let values_str = match self.make_values_str(label, fields, values, span) {
211 let mut result = String::from_str(label);
212 result.push_str(values_str.as_slice());
213 result.push_str("\n");
214 self.recorder.record(result.as_slice());
217 pub fn record_with_span(&mut self,
221 values: Vec<String>) {
222 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
224 if self.recorder.dump_spans {
226 self.recorder.dump_span(self.span, label, span, Some(sub_span));
232 self.span.sess.span_bug(span,
233 format!("Called record_with_span for '{}' \
234 which does not require a span", label).as_slice());
237 let values_str = match self.make_values_str(label, fields, values, span) {
241 let result = format!("{},{}{}\n", label, self.span.extent_str(sub_span), values_str);
242 self.recorder.record(result.as_slice());
245 pub fn check_and_record(&mut self,
248 sub_span: Option<Span>,
249 values: Vec<String>) {
251 Some(sub_span) => self.record_with_span(kind, span, sub_span, values),
253 let (label, _, _, _) = FmtStrs::lookup_row(kind);
254 self.span.report_span_err(label, span);
259 pub fn variable_str(&mut self,
261 sub_span: Option<Span>,
266 // Getting a fully qualified name for a variable is hard because in
267 // the local case they can be overridden in one block and there is no nice way
268 // to refer to such a scope in english, so we just hack it by appending the
269 // variable def's node id
270 let mut qualname = String::from_str(name);
271 qualname.push_str("$");
272 qualname.push_str(id.to_string().as_slice());
273 self.check_and_record(Variable,
276 svec!(id, name, qualname, value, typ, 0u));
280 pub fn formal_str(&mut self,
282 sub_span: Option<Span>,
287 let mut qualname = String::from_str(fn_name);
288 qualname.push_str("::");
289 qualname.push_str(name);
290 self.check_and_record(Variable,
293 svec!(id, name, qualname, "", typ, 0u));
296 // value is the initialising expression of the static if it is not mut, otherwise "".
297 pub fn static_str(&mut self,
299 sub_span: Option<Span>,
306 self.check_and_record(Variable,
309 svec!(id, name, qualname, value, typ, scope_id));
312 pub fn field_str(&mut self,
314 sub_span: Option<Span>,
320 self.check_and_record(Variable,
323 svec!(id, name, qualname, "", typ, scope_id));
326 pub fn enum_str(&mut self,
328 sub_span: Option<Span>,
333 self.check_and_record(Enum,
336 svec!(id, name, scope_id, value));
339 pub fn tuple_variant_str(&mut self,
341 sub_span: Option<Span>,
348 self.check_and_record(Variant,
351 svec!(id, name, qualname, typ, val, scope_id));
354 pub fn struct_variant_str(&mut self,
356 sub_span: Option<Span>,
363 self.check_and_record(VariantStruct,
366 svec!(id, ctor_id, name, typ, val, scope_id));
369 pub fn fn_str(&mut self,
371 sub_span: Option<Span>,
375 self.check_and_record(Function,
378 svec!(id, name, "", "", scope_id));
381 pub fn method_str(&mut self,
383 sub_span: Option<Span>,
386 decl_id: Option<DefId>,
388 let values = match decl_id {
389 Some(decl_id) => svec!(id, name, decl_id.node, decl_id.krate, scope_id),
390 None => svec!(id, name, "", "", scope_id)
392 self.check_and_record(Function,
398 pub fn method_decl_str(&mut self,
400 sub_span: Option<Span>,
404 self.check_and_record(MethodDecl,
407 svec!(id, name, scope_id));
410 pub fn struct_str(&mut self,
412 sub_span: Option<Span>,
418 self.check_and_record(Struct,
421 svec!(id, ctor_id, name, scope_id, value));
424 pub fn trait_str(&mut self,
426 sub_span: Option<Span>,
431 self.check_and_record(Trait,
434 svec!(id, name, scope_id, value));
437 pub fn impl_str(&mut self,
439 sub_span: Option<Span>,
443 self.check_and_record(Impl,
446 svec!(id, ref_id.node, ref_id.krate, scope_id));
449 pub fn mod_str(&mut self,
451 sub_span: Option<Span>,
456 self.check_and_record(Module,
459 svec!(id, name, parent, filename));
462 pub fn use_alias_str(&mut self,
464 sub_span: Option<Span>,
466 mod_id: Option<DefId>,
469 let (mod_node, mod_crate) = match mod_id {
470 Some(mod_id) => (mod_id.node, mod_id.krate),
473 self.check_and_record(UseAlias,
476 svec!(id, mod_node, mod_crate, name, parent));
479 pub fn extern_crate_str(&mut self,
481 sub_span: Option<Span>,
487 self.check_and_record(ExternCrate,
490 svec!(id, name, loc, cnum, parent));
493 pub fn inherit_str(&mut self,
495 sub_span: Option<Span>,
498 self.check_and_record(Inheritance,
507 pub fn fn_call_str(&mut self,
509 sub_span: Option<Span>,
512 self.check_and_record(FnCall,
515 svec!(id.node, id.krate, "", scope_id));
518 pub fn meth_call_str(&mut self,
520 sub_span: Option<Span>,
521 defid: Option<DefId>,
522 declid: Option<DefId>,
524 let (dfn, dfk) = match defid {
525 Some(defid) => (defid.node, defid.krate),
528 let (dcn, dck) = match declid {
529 Some(declid) => (s!(declid.node), s!(declid.krate)),
530 None => ("".to_string(), "".to_string())
532 self.check_and_record(MethodCall,
535 svec!(dfn, dfk, dcn, dck, scope_id));
538 pub fn sub_mod_ref_str(&mut self,
543 self.record_with_span(ModRef,
546 svec!(0u, 0u, qualname, parent));
549 pub fn typedef_str(&mut self,
551 sub_span: Option<Span>,
555 self.check_and_record(Typedef,
558 svec!(id, qualname, value));
561 pub fn crate_str(&mut self,
564 self.record_with_span(Crate,
570 pub fn external_crate_str(&mut self,
573 num: ast::CrateNum) {
574 let lo_loc = self.span.sess.codemap().lookup_char_pos(span.lo);
575 self.record_without_span(ExternalCrate,
576 svec!(name, num, lo_loc.file.name),
580 pub fn sub_type_ref_str(&mut self,
584 self.record_with_span(TypeRef,
587 svec!(0u, 0u, qualname, 0u));
590 // A slightly generic function for a reference to an item of any kind.
591 pub fn ref_str(&mut self,
594 sub_span: Option<Span>,
597 self.check_and_record(kind,
600 svec!(id.node, id.krate, "", scope_id));