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 metadata::cstore::LOCAL_CRATE;
17 use middle::def_id::{CRATE_DEF_INDEX, DefId};
23 use syntax::ast::NodeId;
24 use syntax::codemap::*;
26 const CRATE_ROOT_DEF_ID: DefId = DefId {
28 index: CRATE_DEF_INDEX,
33 pub out: Box<Write + 'static>,
38 pub fn record(&mut self, info: &str) {
39 match write!(self.out, "{}", info) {
40 Err(_) => error!("Error writing output '{}'", info),
45 pub fn dump_span(&mut self, su: SpanUtils, kind: &str, span: Span, _sub_span: Option<Span>) {
46 assert!(self.dump_spans);
47 let result = format!("span,kind,{},{},text,\"{}\"\n",
50 escape(su.snippet(span)));
51 self.record(&result[..]);
55 pub struct FmtStrs<'a, 'tcx: 'a> {
56 pub recorder: Box<Recorder>,
58 tcx: &'a ty::ctxt<'tcx>,
61 macro_rules! s { ($e:expr) => { format!("{}", $e) }}
64 // leading _ to allow empty construction without a warning.
65 let mut _temp = ::std::vec::Vec::new();
66 $(_temp.push(s!($e));)*
71 // FIXME recorder should operate on super::Data, rather than lots of ad hoc
74 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
101 impl<'a, 'tcx: 'a> FmtStrs<'a, 'tcx> {
102 pub fn new(rec: Box<Recorder>,
104 tcx: &'a ty::ctxt<'tcx>)
105 -> FmtStrs<'a, 'tcx> {
113 // Emitted ids are used to cross-reference items across crates. DefIds and
114 // NodeIds do not usually correspond in any way. The strategy is to use the
115 // index from the DefId as a crate-local id. However, within a crate, DefId
116 // indices and NodeIds can overlap. So, we must adjust the NodeIds. If an
117 // item can be identified by a DefId as well as a NodeId, then we use the
118 // DefId index as the id. If it can't, then we have to use the NodeId, but
119 // need to adjust it so it will not clash with any possible DefId index.
120 fn normalize_node_id(&self, id: NodeId) -> usize {
121 match self.tcx.map.opt_local_def_id(id) {
122 Some(id) => id.index.as_usize(),
123 None => id as usize + self.tcx.map.num_local_def_ids()
127 // A map from kind of item to a tuple of
128 // a string representation of the name
129 // a vector of field names
130 // whether this kind requires a span
131 // whether dump_spans should dump for this kind
132 fn lookup_row(r: Row) -> (&'static str, Vec<&'static str>, bool, bool) {
134 Variable => ("variable",
135 vec!("id", "name", "qualname", "value", "type", "scopeid"),
139 vec!("id", "qualname", "scopeid", "value"),
142 Variant => ("variant",
143 vec!("id", "name", "qualname", "type", "value", "scopeid"),
146 VariantStruct => ("variant_struct",
147 vec!("id", "ctor_id", "qualname", "type", "value", "scopeid"),
150 Function => ("function",
151 vec!("id", "qualname", "declid", "declidcrate", "scopeid"),
154 MethodDecl => ("method_decl",
155 vec!("id", "qualname", "scopeid"),
159 vec!("id", "ctor_id", "qualname", "scopeid", "value"),
163 vec!("id", "qualname", "scopeid", "value"),
176 vec!("id", "qualname", "scopeid", "def_file"),
179 UseAlias => ("use_alias",
180 vec!("id", "refid", "refidcrate", "name", "scopeid"),
183 UseGlob => ("use_glob", vec!("id", "value", "scopeid"), true, true),
184 ExternCrate => ("extern_crate",
185 vec!("id", "name", "location", "crate", "scopeid"),
188 Inheritance => ("inheritance",
189 vec!("base", "basecrate", "derived", "derivedcrate"),
192 MethodCall => ("method_call",
193 vec!("refid", "refidcrate", "declid", "declidcrate", "scopeid"),
196 Typedef => ("typedef", vec!("id", "qualname", "value"), true, true),
197 ExternalCrate => ("external_crate",
198 vec!("name", "crate", "file_name"),
201 Crate => ("crate", vec!("name"), true, false),
202 FnCall => ("fn_call",
203 vec!("refid", "refidcrate", "qualname", "scopeid"),
206 ModRef => ("mod_ref",
207 vec!("refid", "refidcrate", "qualname", "scopeid"),
210 VarRef => ("var_ref",
211 vec!("refid", "refidcrate", "qualname", "scopeid"),
214 TypeRef => ("type_ref",
215 vec!("refid", "refidcrate", "qualname", "scopeid"),
219 vec!("refid", "refidcrate", "qualname", "scopeid"),
225 pub fn make_values_str(&self,
227 fields: &Vec<&'static str>,
231 if values.len() != fields.len() {
232 self.span.sess.span_bug(span,
233 &format!("Mismatch between length of fields for '{}', \
234 expected '{}', found '{}'",
240 let values = values.iter().map(|s| {
241 // Never take more than 1020 chars
249 let pairs = fields.iter().zip(values);
250 let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from(v))));
251 Some(strs.fold(String::new(),
258 pub fn record_without_span(&mut self, kind: Row, values: Vec<String>, span: Span) {
259 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
262 self.span.sess.span_bug(span,
263 &format!("Called record_without_span for '{}' which does \
267 assert!(!dump_spans);
269 if self.recorder.dump_spans {
273 let values_str = match self.make_values_str(label, fields, values, span) {
278 let mut result = String::from(label);
279 result.push_str(&values_str[..]);
280 result.push_str("\n");
281 self.recorder.record(&result[..]);
284 pub fn record_with_span(&mut self,
288 values: Vec<String>) {
289 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
291 if self.recorder.dump_spans {
293 self.recorder.dump_span(self.span.clone(), label, span, Some(sub_span));
299 self.span.sess.span_bug(span,
300 &format!("Called record_with_span for '{}' which does not \
305 let values_str = match self.make_values_str(label, fields, values, span) {
309 let result = format!("{},{}{}\n",
311 self.span.extent_str(sub_span),
313 self.recorder.record(&result[..]);
316 pub fn check_and_record(&mut self,
319 sub_span: Option<Span>,
320 values: Vec<String>) {
322 Some(sub_span) => self.record_with_span(kind, span, sub_span, values),
324 let (label, _, _, _) = FmtStrs::lookup_row(kind);
325 self.span.report_span_err(label, span);
330 pub fn variable_str(&mut self,
332 sub_span: Option<Span>,
337 // Getting a fully qualified name for a variable is hard because in
338 // the local case they can be overridden in one block and there is no nice way
339 // to refer to such a scope in english, so we just hack it by appending the
340 // variable def's node id
341 let mut qualname = String::from(name);
342 qualname.push_str("$");
343 qualname.push_str(&id.to_string());
344 let id = self.normalize_node_id(id);
345 self.check_and_record(Variable,
348 svec!(id, name, qualname, value, typ, 0));
352 pub fn formal_str(&mut self,
354 sub_span: Option<Span>,
359 let mut qualname = String::from(fn_name);
360 qualname.push_str("::");
361 qualname.push_str(name);
362 let id = self.normalize_node_id(id);
363 self.check_and_record(Variable,
366 svec!(id, name, qualname, "", typ, 0));
369 // value is the initialising expression of the static if it is not mut, otherwise "".
370 pub fn static_str(&mut self,
372 sub_span: Option<Span>,
379 let id = self.normalize_node_id(id);
380 let scope_id = self.normalize_node_id(scope_id);
381 self.check_and_record(Variable,
384 svec!(id, name, qualname, value, typ, scope_id));
387 pub fn field_str(&mut self,
389 sub_span: Option<Span>,
395 let id = self.normalize_node_id(id);
396 let scope_id = self.normalize_node_id(scope_id);
397 self.check_and_record(Variable,
400 svec!(id, name, qualname, "", typ, scope_id));
403 pub fn enum_str(&mut self,
405 sub_span: Option<Span>,
410 let id = self.normalize_node_id(id);
411 let scope_id = self.normalize_node_id(scope_id);
412 self.check_and_record(Enum, span, sub_span, svec!(id, name, scope_id, value));
415 pub fn tuple_variant_str(&mut self,
417 sub_span: Option<Span>,
424 let id = self.normalize_node_id(id);
425 let scope_id = self.normalize_node_id(scope_id);
426 self.check_and_record(Variant,
429 svec!(id, name, qualname, typ, val, scope_id));
432 pub fn struct_variant_str(&mut self,
434 sub_span: Option<Span>,
441 let id = self.normalize_node_id(id);
442 let scope_id = self.normalize_node_id(scope_id);
443 let ctor_id = self.normalize_node_id(ctor_id);
444 self.check_and_record(VariantStruct,
447 svec!(id, ctor_id, name, typ, val, scope_id));
450 pub fn fn_str(&mut self,
452 sub_span: Option<Span>,
456 let id = self.normalize_node_id(id);
457 let scope_id = self.normalize_node_id(scope_id);
458 self.check_and_record(Function,
461 svec!(id, name, "", "", scope_id));
464 pub fn method_str(&mut self,
466 sub_span: Option<Span>,
469 decl_id: Option<DefId>,
471 let id = self.normalize_node_id(id);
472 let scope_id = self.normalize_node_id(scope_id);
473 let values = match decl_id {
474 Some(decl_id) => svec!(id,
476 decl_id.index.as_usize(),
479 None => svec!(id, name, "", "", scope_id),
481 self.check_and_record(Function, span, sub_span, values);
484 pub fn method_decl_str(&mut self,
486 sub_span: Option<Span>,
490 let id = self.normalize_node_id(id);
491 let scope_id = self.normalize_node_id(scope_id);
492 self.check_and_record(MethodDecl, span, sub_span, svec!(id, name, scope_id));
495 pub fn struct_str(&mut self,
497 sub_span: Option<Span>,
503 let id = self.normalize_node_id(id);
504 let scope_id = self.normalize_node_id(scope_id);
505 let ctor_id = self.normalize_node_id(ctor_id);
506 self.check_and_record(Struct,
509 svec!(id, ctor_id, name, scope_id, value));
512 pub fn trait_str(&mut self,
514 sub_span: Option<Span>,
519 let id = self.normalize_node_id(id);
520 let scope_id = self.normalize_node_id(scope_id);
521 self.check_and_record(Trait, span, sub_span, svec!(id, name, scope_id, value));
524 pub fn impl_str(&mut self,
526 sub_span: Option<Span>,
528 ref_id: Option<DefId>,
529 trait_id: Option<DefId>,
531 let id = self.normalize_node_id(id);
532 let scope_id = self.normalize_node_id(scope_id);
533 let ref_id = ref_id.unwrap_or(CRATE_ROOT_DEF_ID);
534 let trait_id = trait_id.unwrap_or(CRATE_ROOT_DEF_ID);
535 self.check_and_record(Impl,
539 ref_id.index.as_usize(),
541 trait_id.index.as_usize(),
546 pub fn mod_str(&mut self,
548 sub_span: Option<Span>,
553 let id = self.normalize_node_id(id);
554 let parent = self.normalize_node_id(parent);
555 self.check_and_record(Module,
558 svec!(id, name, parent, filename));
561 pub fn use_alias_str(&mut self,
563 sub_span: Option<Span>,
565 mod_id: Option<DefId>,
568 let id = self.normalize_node_id(id);
569 let parent = self.normalize_node_id(parent);
570 let mod_id = mod_id.unwrap_or(CRATE_ROOT_DEF_ID);
571 self.check_and_record(UseAlias,
574 svec!(id, mod_id.index.as_usize(), mod_id.krate, name, parent));
577 pub fn use_glob_str(&mut self,
579 sub_span: Option<Span>,
583 let id = self.normalize_node_id(id);
584 let parent = self.normalize_node_id(parent);
585 self.check_and_record(UseGlob, span, sub_span, svec!(id, values, parent));
588 pub fn extern_crate_str(&mut self,
590 sub_span: Option<Span>,
596 let id = self.normalize_node_id(id);
597 let parent = self.normalize_node_id(parent);
598 self.check_and_record(ExternCrate,
601 svec!(id, name, loc, cnum, parent));
604 pub fn inherit_str(&mut self,
606 sub_span: Option<Span>,
609 let deriv_id = self.normalize_node_id(deriv_id);
610 self.check_and_record(Inheritance,
613 svec!(base_id.index.as_usize(), base_id.krate, deriv_id, 0));
616 pub fn fn_call_str(&mut self,
618 sub_span: Option<Span>,
621 let scope_id = self.normalize_node_id(scope_id);
622 self.check_and_record(FnCall,
625 svec!(id.index.as_usize(), id.krate, "", scope_id));
628 pub fn meth_call_str(&mut self,
630 sub_span: Option<Span>,
631 defid: Option<DefId>,
632 declid: Option<DefId>,
634 let scope_id = self.normalize_node_id(scope_id);
635 let defid = defid.unwrap_or(CRATE_ROOT_DEF_ID);
636 let (dcn, dck) = match declid {
637 Some(declid) => (s!(declid.index.as_usize()), s!(declid.krate)),
638 None => ("".to_string(), "".to_string()),
640 self.check_and_record(MethodCall,
643 svec!(defid.index.as_usize(), defid.krate, dcn, dck, scope_id));
646 pub fn sub_mod_ref_str(&mut self, span: Span, sub_span: Span, qualname: &str, parent: NodeId) {
647 let parent = self.normalize_node_id(parent);
648 self.record_with_span(ModRef, span, sub_span, svec!(0, 0, qualname, parent));
651 pub fn typedef_str(&mut self,
653 sub_span: Option<Span>,
657 let id = self.normalize_node_id(id);
658 self.check_and_record(Typedef, span, sub_span, svec!(id, qualname, value));
661 pub fn crate_str(&mut self, span: Span, name: &str) {
662 self.record_with_span(Crate, span, span, svec!(name));
665 pub fn external_crate_str(&mut self, span: Span, name: &str, num: ast::CrateNum) {
666 let lo_loc = self.span.sess.codemap().lookup_char_pos(span.lo);
667 self.record_without_span(ExternalCrate,
668 svec!(name, num, lo_loc.file.name),
672 pub fn sub_type_ref_str(&mut self, span: Span, sub_span: Span, qualname: &str) {
673 self.record_with_span(TypeRef, span, sub_span, svec!(0, 0, qualname, 0));
676 // A slightly generic function for a reference to an item of any kind.
677 pub fn ref_str(&mut self,
680 sub_span: Option<Span>,
683 let scope_id = self.normalize_node_id(scope_id);
684 self.check_and_record(kind,
687 svec!(id.index.as_usize(), id.krate, "", scope_id));