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;
16 use middle::def_id::DefId;
21 use syntax::ast::NodeId;
22 use syntax::codemap::*;
24 const ZERO_DEF_ID: DefId = DefId { xxx_node: 0, krate: 0 };
28 pub out: Box<Write + 'static>,
33 pub fn record(&mut self, info: &str) {
34 match write!(self.out, "{}", info) {
35 Err(_) => error!("Error writing output '{}'", info),
40 pub fn dump_span(&mut self, su: SpanUtils, kind: &str, span: Span, _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[..]);
48 pub struct FmtStrs<'a> {
49 pub recorder: Box<Recorder>,
53 macro_rules! s { ($e:expr) => { format!("{}", $e) }}
56 // leading _ to allow empty construction without a warning.
57 let mut _temp = ::std::vec::Vec::new();
58 $(_temp.push(s!($e));)*
63 // FIXME recorder should operate on super::Data, rather than lots of ad hoc
66 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
93 impl<'a> FmtStrs<'a> {
94 pub fn new(rec: Box<Recorder>, span: SpanUtils<'a>) -> FmtStrs<'a> {
95 FmtStrs { recorder: rec, span: span }
98 // A map from kind of item to a tuple of
99 // a string representation of the name
100 // a vector of field names
101 // whether this kind requires a span
102 // whether dump_spans should dump for this kind
103 fn lookup_row(r: Row) -> (&'static str, Vec<&'static str>, bool, bool) {
105 Variable => ("variable",
106 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"),
114 VariantStruct => ("variant_struct",
115 vec!("id","ctor_id","qualname","type","value","scopeid"),
118 Function => ("function",
119 vec!("id","qualname","declid","declidcrate","scopeid"),
122 MethodDecl => ("method_decl", vec!("id","qualname","scopeid"), true, true),
123 Struct => ("struct", vec!("id","ctor_id","qualname","scopeid","value"), true, true),
124 Trait => ("trait", vec!("id","qualname","scopeid","value"), true, true),
126 vec!("id","refid","refidcrate","traitid","traitidcrate","scopeid"),
129 Module => ("module", vec!("id","qualname","scopeid","def_file"), true, false),
130 UseAlias => ("use_alias", vec!("id","refid","refidcrate","name","scopeid"), true, true),
131 UseGlob => ("use_glob", vec!("id","value","scopeid"), true, true),
132 ExternCrate => ("extern_crate",
133 vec!("id","name","location","crate","scopeid"),
136 Inheritance => ("inheritance",
137 vec!("base","basecrate","derived","derivedcrate"),
140 MethodCall => ("method_call",
141 vec!("refid","refidcrate","declid","declidcrate","scopeid"),
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", vec!("refid","refidcrate","qualname","scopeid"), true, true),
151 FnRef => ("fn_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
155 pub fn make_values_str(&self,
157 fields: &Vec<&'static str>,
161 if values.len() != fields.len() {
162 self.span.sess.span_bug(span, &format!(
163 "Mismatch between length of fields for '{}', expected '{}', found '{}'",
164 kind, fields.len(), values.len()));
167 let values = values.iter().map(|s| {
168 // Never take more than 1020 chars
176 let pairs = fields.iter().zip(values);
177 let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from(v))));
178 Some(strs.fold(String::new(), |mut s, ss| {
184 pub fn record_without_span(&mut self, kind: Row, values: Vec<String>, span: Span) {
185 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
188 self.span.sess.span_bug(span, &format!(
189 "Called record_without_span for '{}' which does requires a span",
192 assert!(!dump_spans);
194 if self.recorder.dump_spans {
198 let values_str = match self.make_values_str(label, fields, values, span) {
203 let mut result = String::from(label);
204 result.push_str(&values_str[..]);
205 result.push_str("\n");
206 self.recorder.record(&result[..]);
209 pub fn record_with_span(&mut self,
213 values: Vec<String>) {
214 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
216 if self.recorder.dump_spans {
218 self.recorder.dump_span(self.span.clone(),
227 self.span.sess.span_bug(span,
228 &format!("Called record_with_span for '{}' \
229 which does not require a span", label));
232 let values_str = match self.make_values_str(label, fields, values, span) {
236 let result = format!("{},{}{}\n", label, self.span.extent_str(sub_span), values_str);
237 self.recorder.record(&result[..]);
240 pub fn check_and_record(&mut self,
243 sub_span: Option<Span>,
244 values: Vec<String>) {
246 Some(sub_span) => self.record_with_span(kind, span, sub_span, values),
248 let (label, _, _, _) = FmtStrs::lookup_row(kind);
249 self.span.report_span_err(label, span);
254 pub fn variable_str(&mut self,
256 sub_span: Option<Span>,
261 // Getting a fully qualified name for a variable is hard because in
262 // the local case they can be overridden in one block and there is no nice way
263 // to refer to such a scope in english, so we just hack it by appending the
264 // variable def's node id
265 let mut qualname = String::from(name);
266 qualname.push_str("$");
267 qualname.push_str(&id.to_string());
268 self.check_and_record(Variable,
271 svec!(id, name, qualname, value, typ, 0));
275 pub fn formal_str(&mut self,
277 sub_span: Option<Span>,
282 let mut qualname = String::from(fn_name);
283 qualname.push_str("::");
284 qualname.push_str(name);
285 self.check_and_record(Variable,
288 svec!(id, name, qualname, "", typ, 0));
291 // value is the initialising expression of the static if it is not mut, otherwise "".
292 pub fn static_str(&mut self,
294 sub_span: Option<Span>,
301 self.check_and_record(Variable,
304 svec!(id, name, qualname, value, typ, scope_id));
307 pub fn field_str(&mut self,
309 sub_span: Option<Span>,
315 self.check_and_record(Variable,
318 svec!(id, name, qualname, "", typ, scope_id));
321 pub fn enum_str(&mut self,
323 sub_span: Option<Span>,
328 self.check_and_record(Enum,
331 svec!(id, name, scope_id, value));
334 pub fn tuple_variant_str(&mut self,
336 sub_span: Option<Span>,
343 self.check_and_record(Variant,
346 svec!(id, name, qualname, typ, val, scope_id));
349 pub fn struct_variant_str(&mut self,
351 sub_span: Option<Span>,
358 self.check_and_record(VariantStruct,
361 svec!(id, ctor_id, name, typ, val, scope_id));
364 pub fn fn_str(&mut self,
366 sub_span: Option<Span>,
370 self.check_and_record(Function,
373 svec!(id, name, "", "", scope_id));
376 pub fn method_str(&mut self,
378 sub_span: Option<Span>,
381 decl_id: Option<DefId>,
383 let values = match decl_id {
384 Some(decl_id) => svec!(id, name, decl_id.xxx_node, decl_id.krate, scope_id),
385 None => svec!(id, name, "", "", scope_id),
387 self.check_and_record(Function,
393 pub fn method_decl_str(&mut self,
395 sub_span: Option<Span>,
399 self.check_and_record(MethodDecl,
402 svec!(id, name, scope_id));
405 pub fn struct_str(&mut self,
407 sub_span: Option<Span>,
413 self.check_and_record(Struct,
416 svec!(id, ctor_id, name, scope_id, value));
419 pub fn trait_str(&mut self,
421 sub_span: Option<Span>,
426 self.check_and_record(Trait,
429 svec!(id, name, scope_id, value));
432 pub fn impl_str(&mut self,
434 sub_span: Option<Span>,
436 ref_id: Option<DefId>,
437 trait_id: Option<DefId>,
439 let ref_id = ref_id.unwrap_or(ZERO_DEF_ID);
440 let trait_id = trait_id.unwrap_or(ZERO_DEF_ID);
441 self.check_and_record(Impl,
452 pub fn mod_str(&mut self,
454 sub_span: Option<Span>,
459 self.check_and_record(Module,
462 svec!(id, name, parent, filename));
465 pub fn use_alias_str(&mut self,
467 sub_span: Option<Span>,
469 mod_id: Option<DefId>,
472 let (mod_node, mod_crate) = match mod_id {
473 Some(mod_id) => (mod_id.xxx_node, mod_id.krate),
476 self.check_and_record(UseAlias,
479 svec!(id, mod_node, mod_crate, name, parent));
482 pub fn use_glob_str(&mut self,
484 sub_span: Option<Span>,
488 self.check_and_record(UseGlob,
491 svec!(id, values, parent));
494 pub fn extern_crate_str(&mut self,
496 sub_span: Option<Span>,
502 self.check_and_record(ExternCrate,
505 svec!(id, name, loc, cnum, parent));
508 pub fn inherit_str(&mut self,
510 sub_span: Option<Span>,
513 self.check_and_record(Inheritance,
516 svec!(base_id.xxx_node,
522 pub fn fn_call_str(&mut self,
524 sub_span: Option<Span>,
527 self.check_and_record(FnCall,
530 svec!(id.xxx_node, id.krate, "", scope_id));
533 pub fn meth_call_str(&mut self,
535 sub_span: Option<Span>,
536 defid: Option<DefId>,
537 declid: Option<DefId>,
539 let (dfn, dfk) = match defid {
540 Some(defid) => (defid.xxx_node, defid.krate),
543 let (dcn, dck) = match declid {
544 Some(declid) => (s!(declid.xxx_node), s!(declid.krate)),
545 None => ("".to_string(), "".to_string()),
547 self.check_and_record(MethodCall,
550 svec!(dfn, dfk, dcn, dck, scope_id));
553 pub fn sub_mod_ref_str(&mut self, span: Span, sub_span: Span, qualname: &str, parent: NodeId) {
554 self.record_with_span(ModRef,
557 svec!(0, 0, qualname, parent));
560 pub fn typedef_str(&mut self,
562 sub_span: Option<Span>,
566 self.check_and_record(Typedef,
569 svec!(id, qualname, value));
572 pub fn crate_str(&mut self, span: Span, name: &str) {
573 self.record_with_span(Crate,
579 pub fn external_crate_str(&mut self, span: Span, name: &str, num: ast::CrateNum) {
580 let lo_loc = self.span.sess.codemap().lookup_char_pos(span.lo);
581 self.record_without_span(ExternalCrate,
582 svec!(name, num, lo_loc.file.name),
586 pub fn sub_type_ref_str(&mut self, span: Span, sub_span: Span, qualname: &str) {
587 self.record_with_span(TypeRef,
590 svec!(0, 0, qualname, 0));
593 // A slightly generic function for a reference to an item of any kind.
594 pub fn ref_str(&mut self,
597 sub_span: Option<Span>,
600 self.check_and_record(kind,
603 svec!(id.xxx_node, id.krate, "", scope_id));