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::*;
22 const ZERO_DEF_ID: DefId = DefId { node: 0, krate: 0 };
26 pub out: Box<Writer+'static>,
31 pub fn record(&mut self, info: &str) {
32 match write!(self.out, "{}", info) {
33 Err(_) => error!("Error writing output '{}'", info),
38 pub fn dump_span(&mut self,
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[]);
50 pub struct FmtStrs<'a> {
51 pub recorder: Box<Recorder>,
55 macro_rules! s { ($e:expr) => { format!("{}", $e) }}
58 // leading _ to allow empty construction without a warning.
59 let mut _temp = ::std::vec::Vec::new();
60 $(_temp.push(s!($e));)*
65 #[derive(Copy, Debug, Eq, PartialEq)]
93 impl<'a> FmtStrs<'a> {
94 pub fn new(rec: Box<Recorder>, span: SpanUtils<'a>) -> FmtStrs<'a> {
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) {
108 Variable => ("variable",
109 vec!("id","name","qualname","value","type","scopeid"),
111 Enum => ("enum", vec!("id","qualname","scopeid","value"), true, true),
112 Variant => ("variant",
113 vec!("id","name","qualname","type","value","scopeid"),
115 VariantStruct => ("variant_struct",
116 vec!("id","ctor_id","qualname","type","value","scopeid"),
118 Function => ("function",
119 vec!("id","qualname","declid","declidcrate","scopeid"),
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),
125 vec!("id","refid","refidcrate","traitid","traitidcrate","scopeid"),
127 Module => ("module", vec!("id","qualname","scopeid","def_file"), true, false),
128 UseAlias => ("use_alias",
129 vec!("id","refid","refidcrate","name","scopeid"),
131 UseGlob => ("use_glob", vec!("id","value","scopeid"), true, true),
132 ExternCrate => ("extern_crate",
133 vec!("id","name","location","crate","scopeid"),
135 Inheritance => ("inheritance",
136 vec!("base","basecrate","derived","derivedcrate"),
138 MethodCall => ("method_call",
139 vec!("refid","refidcrate","declid","declidcrate","scopeid"),
141 Typedef => ("typedef", vec!("id","qualname","value"), true, true),
142 ExternalCrate => ("external_crate", vec!("name","crate","file_name"), false, false),
143 Crate => ("crate", vec!("name"), true, false),
144 FnCall => ("fn_call", vec!("refid","refidcrate","qualname","scopeid"), true, true),
145 ModRef => ("mod_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
146 VarRef => ("var_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
147 TypeRef => ("type_ref",
148 vec!("refid","refidcrate","qualname","scopeid"),
150 StructRef => ("struct_ref",
151 vec!("refid","refidcrate","qualname","scopeid"),
153 FnRef => ("fn_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true)
157 pub fn make_values_str(&self,
159 fields: &Vec<&'static str>,
161 span: Span) -> Option<String> {
162 if values.len() != fields.len() {
163 self.span.sess.span_bug(span, &format!(
164 "Mismatch between length of fields for '{}', expected '{}', found '{}'",
165 kind, fields.len(), values.len())[]);
168 let values = values.iter().map(|s| {
169 // Never take more than 1020 chars
177 let pairs = fields.iter().zip(values);
178 let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from_str(v))));
179 Some(strs.fold(String::new(), |mut s, ss| {
185 pub fn record_without_span(&mut self,
189 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
192 self.span.sess.span_bug(span, &format!(
193 "Called record_without_span for '{}' which does requires a span",
196 assert!(!dump_spans);
198 if self.recorder.dump_spans {
202 let values_str = match self.make_values_str(label, fields, values, span) {
207 let mut result = String::from_str(label);
208 result.push_str(&values_str[]);
209 result.push_str("\n");
210 self.recorder.record(&result[]);
213 pub fn record_with_span(&mut self,
217 values: Vec<String>) {
218 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
220 if self.recorder.dump_spans {
222 self.recorder.dump_span(self.span.clone(),
231 self.span.sess.span_bug(span,
232 &format!("Called record_with_span for '{}' \
233 which does not require a span", label));
236 let values_str = match self.make_values_str(label, fields, values, span) {
240 let result = format!("{},{}{}\n", label, self.span.extent_str(sub_span), values_str);
241 self.recorder.record(&result[]);
244 pub fn check_and_record(&mut self,
247 sub_span: Option<Span>,
248 values: Vec<String>) {
250 Some(sub_span) => self.record_with_span(kind, span, sub_span, values),
252 let (label, _, _, _) = FmtStrs::lookup_row(kind);
253 self.span.report_span_err(label, span);
258 pub fn variable_str(&mut self,
260 sub_span: Option<Span>,
265 // Getting a fully qualified name for a variable is hard because in
266 // the local case they can be overridden in one block and there is no nice way
267 // to refer to such a scope in english, so we just hack it by appending the
268 // variable def's node id
269 let mut qualname = String::from_str(name);
270 qualname.push_str("$");
271 qualname.push_str(&id.to_string()[]);
272 self.check_and_record(Variable,
275 svec!(id, name, qualname, value, typ, 0));
279 pub fn formal_str(&mut self,
281 sub_span: Option<Span>,
286 let mut qualname = String::from_str(fn_name);
287 qualname.push_str("::");
288 qualname.push_str(name);
289 self.check_and_record(Variable,
292 svec!(id, name, qualname, "", typ, 0));
295 // value is the initialising expression of the static if it is not mut, otherwise "".
296 pub fn static_str(&mut self,
298 sub_span: Option<Span>,
305 self.check_and_record(Variable,
308 svec!(id, name, qualname, value, typ, scope_id));
311 pub fn field_str(&mut self,
313 sub_span: Option<Span>,
319 self.check_and_record(Variable,
322 svec!(id, name, qualname, "", typ, scope_id));
325 pub fn enum_str(&mut self,
327 sub_span: Option<Span>,
332 self.check_and_record(Enum,
335 svec!(id, name, scope_id, value));
338 pub fn tuple_variant_str(&mut self,
340 sub_span: Option<Span>,
347 self.check_and_record(Variant,
350 svec!(id, name, qualname, typ, val, scope_id));
353 pub fn struct_variant_str(&mut self,
355 sub_span: Option<Span>,
362 self.check_and_record(VariantStruct,
365 svec!(id, ctor_id, name, typ, val, scope_id));
368 pub fn fn_str(&mut self,
370 sub_span: Option<Span>,
374 self.check_and_record(Function,
377 svec!(id, name, "", "", scope_id));
380 pub fn method_str(&mut self,
382 sub_span: Option<Span>,
385 decl_id: Option<DefId>,
387 let values = match decl_id {
388 Some(decl_id) => svec!(id, name, decl_id.node, decl_id.krate, scope_id),
389 None => svec!(id, name, "", "", scope_id)
391 self.check_and_record(Function,
397 pub fn method_decl_str(&mut self,
399 sub_span: Option<Span>,
403 self.check_and_record(MethodDecl,
406 svec!(id, name, scope_id));
409 pub fn struct_str(&mut self,
411 sub_span: Option<Span>,
417 self.check_and_record(Struct,
420 svec!(id, ctor_id, name, scope_id, value));
423 pub fn trait_str(&mut self,
425 sub_span: Option<Span>,
430 self.check_and_record(Trait,
433 svec!(id, name, scope_id, value));
436 pub fn impl_str(&mut self,
438 sub_span: Option<Span>,
440 ref_id: Option<DefId>,
441 trait_id: Option<DefId>,
443 let ref_id = ref_id.unwrap_or(ZERO_DEF_ID);
444 let trait_id = trait_id.unwrap_or(ZERO_DEF_ID);
445 self.check_and_record(Impl,
456 pub fn mod_str(&mut self,
458 sub_span: Option<Span>,
463 self.check_and_record(Module,
466 svec!(id, name, parent, filename));
469 pub fn use_alias_str(&mut self,
471 sub_span: Option<Span>,
473 mod_id: Option<DefId>,
476 let (mod_node, mod_crate) = match mod_id {
477 Some(mod_id) => (mod_id.node, mod_id.krate),
480 self.check_and_record(UseAlias,
483 svec!(id, mod_node, mod_crate, name, parent));
486 pub fn use_glob_str(&mut self,
488 sub_span: Option<Span>,
492 self.check_and_record(UseGlob,
495 svec!(id, values, parent));
498 pub fn extern_crate_str(&mut self,
500 sub_span: Option<Span>,
506 self.check_and_record(ExternCrate,
509 svec!(id, name, loc, cnum, parent));
512 pub fn inherit_str(&mut self,
514 sub_span: Option<Span>,
517 self.check_and_record(Inheritance,
526 pub fn fn_call_str(&mut self,
528 sub_span: Option<Span>,
531 self.check_and_record(FnCall,
534 svec!(id.node, id.krate, "", scope_id));
537 pub fn meth_call_str(&mut self,
539 sub_span: Option<Span>,
540 defid: Option<DefId>,
541 declid: Option<DefId>,
543 let (dfn, dfk) = match defid {
544 Some(defid) => (defid.node, defid.krate),
547 let (dcn, dck) = match declid {
548 Some(declid) => (s!(declid.node), s!(declid.krate)),
549 None => ("".to_string(), "".to_string())
551 self.check_and_record(MethodCall,
554 svec!(dfn, dfk, dcn, dck, scope_id));
557 pub fn sub_mod_ref_str(&mut self,
562 self.record_with_span(ModRef,
565 svec!(0, 0, qualname, parent));
568 pub fn typedef_str(&mut self,
570 sub_span: Option<Span>,
574 self.check_and_record(Typedef,
577 svec!(id, qualname, value));
580 pub fn crate_str(&mut self,
583 self.record_with_span(Crate,
589 pub fn external_crate_str(&mut self,
592 num: ast::CrateNum) {
593 let lo_loc = self.span.sess.codemap().lookup_char_pos(span.lo);
594 self.record_without_span(ExternalCrate,
595 svec!(name, num, lo_loc.file.name),
599 pub fn sub_type_ref_str(&mut self,
603 self.record_with_span(TypeRef,
606 svec!(0, 0, qualname, 0));
609 // A slightly generic function for a reference to an item of any kind.
610 pub fn ref_str(&mut self,
613 sub_span: Option<Span>,
616 self.check_and_record(kind,
619 svec!(id.node, id.krate, "", scope_id));