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.
11 use middle::save::escape;
12 use middle::save::span_utils::SpanUtils;
17 use syntax::ast::{NodeId,DefId};
18 use syntax::codemap::*;
27 pub fn record(&mut self, info: &str) {
28 match write!(self.out, "{}", info) {
29 Err(_) => error!("Error writing output '{}'", info),
34 pub fn dump_span(&mut self,
38 _sub_span: Option<Span>) {
39 assert!(self.dump_spans);
40 let result = format!("span,kind,{},{},text,\"{}\"\n",
41 kind, su.extent_str(span), escape(su.snippet(span)));
42 self.record(result.as_slice());
46 pub struct FmtStrs<'a> {
47 pub recorder: Box<Recorder>,
52 macro_rules! s { ($e:expr) => { format!("{}", $e) }}
55 // leading _ to allow empty construction without a warning.
56 let mut _temp = ::std::vec::Vec::new();
57 $(_temp.push(s!($e));)*
88 impl<'a> FmtStrs<'a> {
89 pub fn new(rec: Box<Recorder>, span: SpanUtils<'a>, krate: String) -> FmtStrs<'a> {
97 // A map from kind of item to a tuple of
98 // a string representation of the name
99 // a vector of field names
100 // whether this kind requires a span
101 // whether dump_spans should dump for this kind
102 fn lookup_row(r: Row) -> (&'static str, Vec<&'static str>, bool, bool) {
104 Variable => ("variable",
105 vec!("id","name","qualname","value","type","scopeid"),
107 Enum => ("enum", vec!("id","qualname","scopeid"), true, true),
108 Variant => ("variant", vec!("id","name","qualname","value","scopeid"), true, true),
109 VariantStruct => ("variant_struct",
110 vec!("id","ctor_id","qualname","value","scopeid"), true, true),
111 Function => ("function", vec!("id","qualname","declid","declidcrate","scopeid"),
113 MethodDecl => ("method_decl", vec!("id","qualname","scopeid"), true, true),
114 Struct => ("struct", vec!("id","ctor_id","qualname","scopeid"), true, true),
115 Trait => ("trait", vec!("id","qualname","scopeid"), true, true),
116 Impl => ("impl", vec!("id","refid","refidcrate","scopeid"), true, true),
117 Module => ("module", vec!("id","qualname","scopeid","def_file"), true, false),
118 UseAlias => ("use_alias",
119 vec!("id","refid","refidcrate","name","scopeid"),
121 ExternCrate => ("extern_crate",
122 vec!("id","name","location","crate","scopeid"),
124 Inheritance => ("inheritance",
125 vec!("base","basecrate","derived","derivedcrate"),
127 MethodCall => ("method_call",
128 vec!("refid","refidcrate","declid","declidcrate","scopeid"),
130 Typedef => ("typedef", vec!("id","qualname","value"), true, true),
131 ExternalCrate => ("external_crate", vec!("name","crate","file_name"), false, false),
132 Crate => ("crate", vec!("name"), true, false),
133 FnCall => ("fn_call", vec!("refid","refidcrate","qualname","scopeid"), true, true),
134 ModRef => ("mod_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
135 VarRef => ("var_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
136 TypeRef => ("type_ref",
137 vec!("refid","refidcrate","qualname","scopeid"),
139 StructRef => ("struct_ref",
140 vec!("refid","refidcrate","qualname","scopeid"),
142 FnRef => ("fn_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true)
146 pub fn make_values_str(&self,
148 fields: &Vec<&'static str>,
150 span: Span) -> Option<String> {
151 if values.len() != fields.len() {
152 self.span.sess.span_bug(span, format!(
153 "Mismatch between length of fields for '{}', expected '{}', found '{}'",
154 kind, fields.len(), values.len()).as_slice());
157 let values = values.iter().map(|s| {
159 s.as_slice().slice_to(1020)
165 let pairs = fields.iter().zip(values);
166 let mut strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(
167 if *f == "qualname" {
168 self.krate.clone().append("::").append(v)
173 Some(strs.fold(String::new(), |s, ss| s.append(ss.as_slice()))).map(|s| s.into_owned())
176 pub fn record_without_span(&mut self,
180 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
183 self.span.sess.span_bug(span, format!(
184 "Called record_without_span for '{}' which does requires a span",
187 assert!(!dump_spans);
189 if self.recorder.dump_spans {
193 let values_str = match self.make_values_str(label, fields, values, span) {
198 let result = String::from_str(label);
199 self.recorder.record(result.append(values_str.as_slice()).append("\n").as_slice());
202 pub fn record_with_span(&mut self,
206 values: Vec<String>) {
207 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
209 if self.recorder.dump_spans {
211 self.recorder.dump_span(self.span, label, span, Some(sub_span));
217 self.span.sess.span_bug(span,
218 format!("Called record_with_span for '{}' \
219 which does not require a span", label).as_slice());
222 let values_str = match self.make_values_str(label, fields, values, span) {
226 let result = format!("{},{}{}\n", label, self.span.extent_str(sub_span), values_str);
227 self.recorder.record(result.as_slice());
230 pub fn check_and_record(&mut self,
233 sub_span: Option<Span>,
234 values: Vec<String>) {
236 Some(sub_span) => self.record_with_span(kind, span, sub_span, values),
238 let (label, _, _, _) = FmtStrs::lookup_row(kind);
239 self.span.report_span_err(label, span);
244 pub fn variable_str(&mut self,
246 sub_span: Option<Span>,
251 // Getting a fully qualified name for a variable is hard because in
252 // the local case they can be overridden in one block and there is no nice way
253 // to refer to such a scope in english, so we just hack it by appending the
254 // variable def's node id
255 let qualname = String::from_str(name).append("$").append(id.to_str().as_slice());
256 self.check_and_record(Variable,
259 svec!(id, name, qualname, value, typ, 0));
263 pub fn formal_str(&mut self,
265 sub_span: Option<Span>,
270 let qualname = String::from_str(fn_name).append("::").append(name);
271 self.check_and_record(Variable,
274 svec!(id, name, qualname, "", typ, 0));
277 // value is the initialising expression of the static if it is not mut, otherwise "".
278 pub fn static_str(&mut self,
280 sub_span: Option<Span>,
287 self.check_and_record(Variable,
290 svec!(id, name, qualname, value, typ, scope_id));
293 pub fn field_str(&mut self,
295 sub_span: Option<Span>,
301 self.check_and_record(Variable,
304 svec!(id, name, qualname, "", typ, scope_id));
307 pub fn enum_str(&mut self,
309 sub_span: Option<Span>,
313 self.check_and_record(Enum,
316 svec!(id, name, scope_id));
319 pub fn tuple_variant_str(&mut self,
321 sub_span: Option<Span>,
327 self.check_and_record(Variant,
330 svec!(id, name, qualname, val, scope_id));
333 pub fn struct_variant_str(&mut self,
335 sub_span: Option<Span>,
341 self.check_and_record(VariantStruct,
344 svec!(id, ctor_id, name, val, scope_id));
347 pub fn fn_str(&mut self,
349 sub_span: Option<Span>,
353 self.check_and_record(Function,
356 svec!(id, name, "", "", scope_id));
359 pub fn method_str(&mut self,
361 sub_span: Option<Span>,
364 decl_id: Option<DefId>,
366 let values = match decl_id {
367 Some(decl_id) => svec!(id, name, decl_id.node, decl_id.krate, scope_id),
368 None => svec!(id, name, "", "", scope_id)
370 self.check_and_record(Function,
376 pub fn method_decl_str(&mut self,
378 sub_span: Option<Span>,
382 self.check_and_record(MethodDecl,
385 svec!(id, name, scope_id));
388 pub fn struct_str(&mut self,
390 sub_span: Option<Span>,
395 self.check_and_record(Struct,
398 svec!(id, ctor_id, name, scope_id));
401 pub fn trait_str(&mut self,
403 sub_span: Option<Span>,
407 self.check_and_record(Trait,
410 svec!(id, name, scope_id));
413 pub fn impl_str(&mut self,
415 sub_span: Option<Span>,
419 self.check_and_record(Impl,
422 svec!(id, ref_id.node, ref_id.krate, scope_id));
425 pub fn mod_str(&mut self,
427 sub_span: Option<Span>,
432 self.check_and_record(Module,
435 svec!(id, name, parent, filename));
438 pub fn use_alias_str(&mut self,
440 sub_span: Option<Span>,
442 mod_id: Option<DefId>,
445 let (mod_node, mod_crate) = match mod_id {
446 Some(mod_id) => (mod_id.node, mod_id.krate),
449 self.check_and_record(UseAlias,
452 svec!(id, mod_node, mod_crate, name, parent));
455 pub fn extern_crate_str(&mut self,
457 sub_span: Option<Span>,
463 self.check_and_record(ExternCrate,
466 svec!(id, name, loc, cnum, parent));
469 pub fn inherit_str(&mut self,
471 sub_span: Option<Span>,
474 self.check_and_record(Inheritance,
477 svec!(base_id.node, base_id.krate, deriv_id, 0));
480 pub fn fn_call_str(&mut self,
482 sub_span: Option<Span>,
485 self.check_and_record(FnCall,
488 svec!(id.node, id.krate, "", scope_id));
491 pub fn meth_call_str(&mut self,
493 sub_span: Option<Span>,
494 defid: Option<DefId>,
495 declid: Option<DefId>,
497 let (dfn, dfk) = match defid {
498 Some(defid) => (defid.node, defid.krate),
501 let (dcn, dck) = match declid {
502 Some(declid) => (s!(declid.node), s!(declid.krate)),
503 None => ("".to_owned(), "".to_owned())
505 self.check_and_record(MethodCall,
508 svec!(dfn, dfk, dcn, dck, scope_id));
511 pub fn sub_mod_ref_str(&mut self,
516 self.record_with_span(ModRef,
519 svec!(0, 0, qualname, parent));
522 pub fn typedef_str(&mut self,
524 sub_span: Option<Span>,
528 self.check_and_record(Typedef,
531 svec!(id, qualname, value));
534 pub fn crate_str(&mut self,
537 self.record_with_span(Crate,
543 pub fn external_crate_str(&mut self,
546 num: ast::CrateNum) {
547 let lo_loc = self.span.sess.codemap().lookup_char_pos(span.lo);
548 self.record_without_span(ExternalCrate,
549 svec!(name, num, lo_loc.file.name),
553 pub fn sub_type_ref_str(&mut self,
557 self.record_with_span(TypeRef,
560 svec!(0, 0, qualname, 0));
563 // A slightly generic function for a reference to an item of any kind.
564 pub fn ref_str(&mut self,
567 sub_span: Option<Span>,
570 self.check_and_record(kind,
573 svec!(id.node, id.krate, "", scope_id));