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
::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)]
103 impl<'a, 'tcx: 'a> FmtStrs<'a, 'tcx> {
104 pub fn new(rec: Box<Recorder>,
106 tcx: &'a ty::ctxt<'tcx>)
107 -> FmtStrs<'a, 'tcx> {
115 // Emitted ids are used to cross-reference items across crates. DefIds and
116 // NodeIds do not usually correspond in any way. The strategy is to use the
117 // index from the DefId as a crate-local id. However, within a crate, DefId
118 // indices and NodeIds can overlap. So, we must adjust the NodeIds. If an
119 // item can be identified by a DefId as well as a NodeId, then we use the
120 // DefId index as the id. If it can't, then we have to use the NodeId, but
121 // need to adjust it so it will not clash with any possible DefId index.
122 fn normalize_node_id(&self, id: NodeId) -> usize {
123 match self.tcx.map.opt_local_def_id(id) {
124 Some(id) => id.index.as_usize(),
125 None => id as usize + self.tcx.map.num_local_def_ids()
129 // A map from kind of item to a tuple of
130 // a string representation of the name
131 // a vector of field names
132 // whether this kind requires a span
133 // whether dump_spans should dump for this kind
134 fn lookup_row(r: Row) -> (&'static str, Vec<&'static str>, bool, bool) {
136 Variable => ("variable
",
137 vec!("id
", "name
", "qualname
", "value
", "type", "scopeid
"),
141 vec!("id
", "qualname
", "scopeid
", "value
"),
144 Variant => ("variant
",
145 vec!("id
", "name
", "qualname
", "type", "value
", "scopeid
"),
148 VariantStruct => ("variant_struct
",
149 vec!("id
", "ctor_id
", "qualname
", "type", "value
", "scopeid
"),
152 Function => ("function
",
153 vec!("id
", "qualname
", "declid
", "declidcrate
", "scopeid
"),
156 MethodDecl => ("method_decl
",
157 vec!("id
", "qualname
", "scopeid
"),
161 vec!("id
", "ctor_id
", "qualname
", "scopeid
", "value
"),
165 vec!("id
", "qualname
", "scopeid
", "value
"),
178 vec!("id
", "qualname
", "scopeid
", "def_file
"),
181 UseAlias => ("use_alias
",
182 vec!("id
", "refid
", "refidcrate
", "name
", "scopeid
"),
185 UseGlob => ("use_glob
", vec!("id
", "value
", "scopeid
"), true, true),
186 ExternCrate => ("extern_crate
",
187 vec!("id
", "name
", "location
", "crate", "scopeid
"),
190 Inheritance => ("inheritance
",
191 vec!("base
", "basecrate
", "derived
", "derivedcrate
"),
194 MethodCall => ("method_call
",
195 vec!("refid
", "refidcrate
", "declid
", "declidcrate
", "scopeid
"),
198 Typedef => ("typedef
", vec!("id
", "qualname
", "value
"), true, true),
199 ExternalCrate => ("external_crate
",
200 vec!("name
", "crate", "file_name
"),
203 Crate => ("crate", vec!("name
", "crate_root
"), true, false),
204 FnCall => ("fn_call
",
205 vec!("refid
", "refidcrate
", "qualname
", "scopeid
"),
208 ModRef => ("mod_ref
",
209 vec!("refid
", "refidcrate
", "qualname
", "scopeid
"),
212 VarRef => ("var_ref
",
213 vec!("refid
", "refidcrate
", "qualname
", "scopeid
"),
216 TypeRef => ("type_ref
",
217 vec!("refid
", "refidcrate
", "qualname
", "scopeid
"),
221 vec!("refid
", "refidcrate
", "qualname
", "scopeid
"),
225 vec!("name
", "qualname
"),
228 MacroUse => ("macro_use
",
229 vec!("callee_name
", "qualname
", "scopeid
"),
235 pub fn make_values_str(&self,
237 fields: &Vec<&'static str>,
241 if values.len() != fields.len() {
242 self.span.sess.span_bug(span,
243 &format!("Mismatch between length of fields
for '{}'
, \
244 expected '{}'
, found '{}'
",
250 let values = values.iter().map(|s| {
251 // Never take more than 1020 chars
259 let pairs = fields.iter().zip(values);
260 let strs = pairs.map(|(f, v)| format!(",{}
,\"{}
\"", f, escape(String::from(v))));
261 Some(strs.fold(String::new(),
268 pub fn record_without_span(&mut self, kind: Row, values: Vec<String>, span: Span) {
269 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
272 self.span.sess.span_bug(span,
273 &format!("Called record_without_span
for '{}' which does
\
277 assert!(!dump_spans);
279 if self.recorder.dump_spans {
283 let values_str = match self.make_values_str(label, fields, values, span) {
288 let mut result = String::from(label);
289 result.push_str(&values_str[..]);
290 result.push_str("\n");
291 self.recorder.record(&result[..]);
294 pub fn record_with_span(&mut self,
298 values: Vec<String>) {
299 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
301 if self.recorder.dump_spans {
303 self.recorder.dump_span(self.span.clone(), label, span, Some(sub_span));
309 self.span.sess.span_bug(span,
310 &format!("Called record_with_span
for '{}' which does not
\
315 let values_str = match self.make_values_str(label, fields, values, span) {
319 let result = format!("{}
,{}{}
\n",
321 self.span.extent_str(sub_span),
323 self.recorder.record(&result[..]);
326 pub fn check_and_record(&mut self,
329 sub_span: Option<Span>,
330 values: Vec<String>) {
331 filter!(self.span, sub_span, span);
333 Some(sub_span) => self.record_with_span(kind, span, sub_span, values),
335 let (label, _, _, _) = FmtStrs::lookup_row(kind);
336 self.span.report_span_err(label, span);
341 pub fn variable_str(&mut self,
343 sub_span: Option<Span>,
348 // Getting a fully qualified name for a variable is hard because in
349 // the local case they can be overridden in one block and there is no nice way
350 // to refer to such a scope in english, so we just hack it by appending the
351 // variable def's node id
352 let mut qualname = String::from(name);
353 qualname.push_str("$
");
354 qualname.push_str(&id.to_string());
355 let id = self.normalize_node_id(id);
356 self.check_and_record(Variable,
359 svec!(id, name, qualname, value, typ, 0));
363 pub fn formal_str(&mut self,
365 sub_span: Option<Span>,
370 let mut qualname = String::from(fn_name);
371 qualname.push_str("::");
372 qualname.push_str(name);
373 let id = self.normalize_node_id(id);
374 self.check_and_record(Variable,
377 svec!(id, name, qualname, "", typ, 0));
380 // value is the initialising expression of the static if it is not mut, otherwise "".
381 pub fn static_str(&mut self,
383 sub_span: Option<Span>,
390 let id = self.normalize_node_id(id);
391 let scope_id = self.normalize_node_id(scope_id);
392 self.check_and_record(Variable,
395 svec!(id, name, qualname, value, typ, scope_id));
398 pub fn field_str(&mut self,
400 sub_span: Option<Span>,
406 let id = self.normalize_node_id(id);
407 let scope_id = self.normalize_node_id(scope_id);
408 self.check_and_record(Variable,
411 svec!(id, name, qualname, "", typ, scope_id));
414 pub fn enum_str(&mut self,
416 sub_span: Option<Span>,
421 let id = self.normalize_node_id(id);
422 let scope_id = self.normalize_node_id(scope_id);
423 self.check_and_record(Enum, span, sub_span, svec!(id, name, scope_id, value));
426 pub fn tuple_variant_str(&mut self,
428 sub_span: Option<Span>,
435 let id = self.normalize_node_id(id);
436 let scope_id = self.normalize_node_id(scope_id);
437 self.check_and_record(Variant,
440 svec!(id, name, qualname, typ, val, scope_id));
443 pub fn struct_variant_str(&mut self,
445 sub_span: Option<Span>,
451 let id = self.normalize_node_id(id);
453 let scope_id = self.normalize_node_id(scope_id);
454 self.check_and_record(VariantStruct,
457 svec!(id, ctor_id, name, typ, val, scope_id));
460 pub fn fn_str(&mut self,
462 sub_span: Option<Span>,
466 let id = self.normalize_node_id(id);
467 let scope_id = self.normalize_node_id(scope_id);
468 self.check_and_record(Function,
471 svec!(id, name, "", "", scope_id));
474 pub fn method_str(&mut self,
476 sub_span: Option<Span>,
479 decl_id: Option<DefId>,
481 let id = self.normalize_node_id(id);
482 let scope_id = self.normalize_node_id(scope_id);
483 let values = match decl_id {
484 Some(decl_id) => svec!(id,
486 decl_id.index.as_usize(),
489 None => svec!(id, name, "", "", scope_id),
491 self.check_and_record(Function, span, sub_span, values);
494 pub fn method_decl_str(&mut self,
496 sub_span: Option<Span>,
500 let id = self.normalize_node_id(id);
501 let scope_id = self.normalize_node_id(scope_id);
502 self.check_and_record(MethodDecl, span, sub_span, svec!(id, name, scope_id));
505 pub fn struct_str(&mut self,
507 sub_span: Option<Span>,
513 let id = self.normalize_node_id(id);
514 let scope_id = self.normalize_node_id(scope_id);
515 let ctor_id = self.normalize_node_id(ctor_id);
516 self.check_and_record(Struct,
519 svec!(id, ctor_id, name, scope_id, value));
522 pub fn trait_str(&mut self,
524 sub_span: Option<Span>,
529 let id = self.normalize_node_id(id);
530 let scope_id = self.normalize_node_id(scope_id);
531 self.check_and_record(Trait, span, sub_span, svec!(id, name, scope_id, value));
534 pub fn impl_str(&mut self,
536 sub_span: Option<Span>,
538 ref_id: Option<DefId>,
539 trait_id: Option<DefId>,
541 let id = self.normalize_node_id(id);
542 let scope_id = self.normalize_node_id(scope_id);
543 let ref_id = ref_id.unwrap_or(CRATE_ROOT_DEF_ID);
544 let trait_id = trait_id.unwrap_or(CRATE_ROOT_DEF_ID);
545 self.check_and_record(Impl,
549 ref_id.index.as_usize(),
551 trait_id.index.as_usize(),
556 pub fn mod_str(&mut self,
558 sub_span: Option<Span>,
563 let id = self.normalize_node_id(id);
564 let parent = self.normalize_node_id(parent);
565 self.check_and_record(Module,
568 svec!(id, name, parent, filename));
571 pub fn use_alias_str(&mut self,
573 sub_span: Option<Span>,
575 mod_id: Option<DefId>,
578 let id = self.normalize_node_id(id);
579 let parent = self.normalize_node_id(parent);
580 let mod_id = mod_id.unwrap_or(CRATE_ROOT_DEF_ID);
581 self.check_and_record(UseAlias,
584 svec!(id, mod_id.index.as_usize(), mod_id.krate, name, parent));
587 pub fn use_glob_str(&mut self,
589 sub_span: Option<Span>,
593 let id = self.normalize_node_id(id);
594 let parent = self.normalize_node_id(parent);
595 self.check_and_record(UseGlob, span, sub_span, svec!(id, values, parent));
598 pub fn extern_crate_str(&mut self,
600 sub_span: Option<Span>,
606 let id = self.normalize_node_id(id);
607 let parent = self.normalize_node_id(parent);
608 self.check_and_record(ExternCrate,
611 svec!(id, name, loc, cnum, parent));
614 pub fn inherit_str(&mut self,
616 sub_span: Option<Span>,
619 let deriv_id = self.normalize_node_id(deriv_id);
620 self.check_and_record(Inheritance,
623 svec!(base_id.index.as_usize(), base_id.krate, deriv_id, 0));
626 pub fn fn_call_str(&mut self,
628 sub_span: Option<Span>,
631 let scope_id = self.normalize_node_id(scope_id);
632 self.check_and_record(FnCall,
635 svec!(id.index.as_usize(), id.krate, "", scope_id));
638 pub fn meth_call_str(&mut self,
640 sub_span: Option<Span>,
641 defid: Option<DefId>,
642 declid: Option<DefId>,
644 let scope_id = self.normalize_node_id(scope_id);
645 let defid = defid.unwrap_or(CRATE_ROOT_DEF_ID);
646 let (dcn, dck) = match declid {
647 Some(declid) => (s!(declid.index.as_usize()), s!(declid.krate)),
648 None => ("".to_string(), "".to_string()),
650 self.check_and_record(MethodCall,
653 svec!(defid.index.as_usize(), defid.krate, dcn, dck, scope_id));
656 pub fn sub_mod_ref_str(&mut self, span: Span, sub_span: Span, qualname: &str, parent: NodeId) {
657 let parent = self.normalize_node_id(parent);
658 self.record_with_span(ModRef, span, sub_span, svec!(0, 0, qualname, parent));
661 pub fn typedef_str(&mut self,
663 sub_span: Option<Span>,
667 let id = self.normalize_node_id(id);
668 self.check_and_record(Typedef, span, sub_span, svec!(id, qualname, value));
671 pub fn crate_str(&mut self, span: Span, name: &str, crate_root: &str) {
672 self.record_with_span(Crate, span, span, svec!(name, crate_root));
675 pub fn external_crate_str(&mut self, span: Span, name: &str, num: ast::CrateNum) {
676 let lo_loc = self.span.sess.codemap().lookup_char_pos(span.lo);
677 self.record_without_span(ExternalCrate,
678 svec!(name, num, SpanUtils::make_path_string(&lo_loc.file.name)),
682 pub fn sub_type_ref_str(&mut self, span: Span, sub_span: Span, qualname: &str) {
683 self.record_with_span(TypeRef, span, sub_span, svec!(0, 0, qualname, 0));
686 // A slightly generic function for a reference to an item of any kind.
687 pub fn ref_str(&mut self,
690 sub_span: Option<Span>,
693 let scope_id = self.normalize_node_id(scope_id);
694 self.check_and_record(kind,
697 svec!(id.index.as_usize(), id.krate, "", scope_id));
700 pub fn macro_str(&mut self, span: Span, sub_span: Span, name: String, qualname: String) {
701 self.record_with_span(Macro, span, sub_span, svec!(name, qualname));
704 pub fn macro_use_str(&mut self,
710 let scope_id = self.normalize_node_id(scope_id);
711 self.record_with_span(MacroUse, span, sub_span,
712 svec!(name, qualname, scope_id));