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
<Write
+'
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 // FIXME recorder should operate on super::Data, rather than lots of ad hoc
68 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
96 impl<'a> FmtStrs<'a> {
97 pub fn new(rec: Box<Recorder>, span: SpanUtils<'a>) -> FmtStrs<'a> {
104 // A map from kind of item to a tuple of
105 // a string representation of the name
106 // a vector of field names
107 // whether this kind requires a span
108 // whether dump_spans should dump for this kind
109 fn lookup_row(r: Row) -> (&'static str, Vec<&'static str>, bool, bool) {
111 Variable => ("variable
",
112 vec!("id
","name
","qualname
","value
","type","scopeid
"),
114 Enum => ("enum", vec!("id
","qualname
","scopeid
","value
"), true, true),
115 Variant => ("variant
",
116 vec!("id
","name
","qualname
","type","value
","scopeid
"),
118 VariantStruct => ("variant_struct
",
119 vec!("id
","ctor_id
","qualname
","type","value
","scopeid
"),
121 Function => ("function
",
122 vec!("id
","qualname
","declid
","declidcrate
","scopeid
"),
124 MethodDecl => ("method_decl
", vec!("id
","qualname
","scopeid
"), true, true),
125 Struct => ("struct", vec!("id
","ctor_id
","qualname
","scopeid
","value
"), true, true),
126 Trait => ("trait", vec!("id
","qualname
","scopeid
","value
"), true, true),
128 vec!("id
","refid
","refidcrate
","traitid
","traitidcrate
","scopeid
"),
130 Module => ("module
", vec!("id
","qualname
","scopeid
","def_file
"), true, false),
131 UseAlias => ("use_alias
",
132 vec!("id
","refid
","refidcrate
","name
","scopeid
"),
134 UseGlob => ("use_glob
", vec!("id
","value
","scopeid
"), true, true),
135 ExternCrate => ("extern_crate
",
136 vec!("id
","name
","location
","crate","scopeid
"),
138 Inheritance => ("inheritance
",
139 vec!("base
","basecrate
","derived
","derivedcrate
"),
141 MethodCall => ("method_call
",
142 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
",
151 vec!("refid
","refidcrate
","qualname
","scopeid
"),
153 StructRef => ("struct_ref
",
154 vec!("refid
","refidcrate
","qualname
","scopeid
"),
156 FnRef => ("fn_ref
", vec!("refid
","refidcrate
","qualname
","scopeid
"), true, true)
160 pub fn make_values_str(&self,
162 fields: &Vec<&'static str>,
164 span: Span) -> Option<String> {
165 if values.len() != fields.len() {
166 self.span.sess.span_bug(span, &format!(
167 "Mismatch between length of fields
for '{}'
, expected '{}'
, found '{}'
",
168 kind, fields.len(), values.len()));
171 let values = values.iter().map(|s| {
172 // Never take more than 1020 chars
180 let pairs = fields.iter().zip(values);
181 let strs = pairs.map(|(f, v)| format!(",{}
,\"{}
\"", f, escape(String::from_str(v))));
182 Some(strs.fold(String::new(), |mut s, ss| {
188 pub fn record_without_span(&mut self,
192 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
195 self.span.sess.span_bug(span, &format!(
196 "Called record_without_span
for '{}' which does requires a span
",
199 assert!(!dump_spans);
201 if self.recorder.dump_spans {
205 let values_str = match self.make_values_str(label, fields, values, span) {
210 let mut result = String::from_str(label);
211 result.push_str(&values_str[..]);
212 result.push_str("\n");
213 self.recorder.record(&result[..]);
216 pub fn record_with_span(&mut self,
220 values: Vec<String>) {
221 let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
223 if self.recorder.dump_spans {
225 self.recorder.dump_span(self.span.clone(),
234 self.span.sess.span_bug(span,
235 &format!("Called record_with_span
for '{}'
\
236 which does not require a span
", label));
239 let values_str = match self.make_values_str(label, fields, values, span) {
243 let result = format!("{}
,{}{}
\n", label, self.span.extent_str(sub_span), values_str);
244 self.recorder.record(&result[..]);
247 pub fn check_and_record(&mut self,
250 sub_span: Option<Span>,
251 values: Vec<String>) {
253 Some(sub_span) => self.record_with_span(kind, span, sub_span, values),
255 let (label, _, _, _) = FmtStrs::lookup_row(kind);
256 self.span.report_span_err(label, span);
261 pub fn variable_str(&mut self,
263 sub_span: Option<Span>,
268 // Getting a fully qualified name for a variable is hard because in
269 // the local case they can be overridden in one block and there is no nice way
270 // to refer to such a scope in english, so we just hack it by appending the
271 // variable def's node id
272 let mut qualname = String::from_str(name);
273 qualname.push_str("$
");
274 qualname.push_str(&id.to_string());
275 self.check_and_record(Variable,
278 svec!(id, name, qualname, value, typ, 0));
282 pub fn formal_str(&mut self,
284 sub_span: Option<Span>,
289 let mut qualname = String::from_str(fn_name);
290 qualname.push_str("::");
291 qualname.push_str(name);
292 self.check_and_record(Variable,
295 svec!(id, name, qualname, "", typ, 0));
298 // value is the initialising expression of the static if it is not mut, otherwise "".
299 pub fn static_str(&mut self,
301 sub_span: Option<Span>,
308 self.check_and_record(Variable,
311 svec!(id, name, qualname, value, typ, scope_id));
314 pub fn field_str(&mut self,
316 sub_span: Option<Span>,
322 self.check_and_record(Variable,
325 svec!(id, name, qualname, "", typ, scope_id));
328 pub fn enum_str(&mut self,
330 sub_span: Option<Span>,
335 self.check_and_record(Enum,
338 svec!(id, name, scope_id, value));
341 pub fn tuple_variant_str(&mut self,
343 sub_span: Option<Span>,
350 self.check_and_record(Variant,
353 svec!(id, name, qualname, typ, val, scope_id));
356 pub fn struct_variant_str(&mut self,
358 sub_span: Option<Span>,
365 self.check_and_record(VariantStruct,
368 svec!(id, ctor_id, name, typ, val, scope_id));
371 pub fn fn_str(&mut self,
373 sub_span: Option<Span>,
377 self.check_and_record(Function,
380 svec!(id, name, "", "", scope_id));
383 pub fn method_str(&mut self,
385 sub_span: Option<Span>,
388 decl_id: Option<DefId>,
390 let values = match decl_id {
391 Some(decl_id) => svec!(id, name, decl_id.node, decl_id.krate, scope_id),
392 None => svec!(id, name, "", "", scope_id)
394 self.check_and_record(Function,
400 pub fn method_decl_str(&mut self,
402 sub_span: Option<Span>,
406 self.check_and_record(MethodDecl,
409 svec!(id, name, scope_id));
412 pub fn struct_str(&mut self,
414 sub_span: Option<Span>,
420 self.check_and_record(Struct,
423 svec!(id, ctor_id, name, scope_id, value));
426 pub fn trait_str(&mut self,
428 sub_span: Option<Span>,
433 self.check_and_record(Trait,
436 svec!(id, name, scope_id, value));
439 pub fn impl_str(&mut self,
441 sub_span: Option<Span>,
443 ref_id: Option<DefId>,
444 trait_id: Option<DefId>,
446 let ref_id = ref_id.unwrap_or(ZERO_DEF_ID);
447 let trait_id = trait_id.unwrap_or(ZERO_DEF_ID);
448 self.check_and_record(Impl,
459 pub fn mod_str(&mut self,
461 sub_span: Option<Span>,
466 self.check_and_record(Module,
469 svec!(id, name, parent, filename));
472 pub fn use_alias_str(&mut self,
474 sub_span: Option<Span>,
476 mod_id: Option<DefId>,
479 let (mod_node, mod_crate) = match mod_id {
480 Some(mod_id) => (mod_id.node, mod_id.krate),
483 self.check_and_record(UseAlias,
486 svec!(id, mod_node, mod_crate, name, parent));
489 pub fn use_glob_str(&mut self,
491 sub_span: Option<Span>,
495 self.check_and_record(UseGlob,
498 svec!(id, values, parent));
501 pub fn extern_crate_str(&mut self,
503 sub_span: Option<Span>,
509 self.check_and_record(ExternCrate,
512 svec!(id, name, loc, cnum, parent));
515 pub fn inherit_str(&mut self,
517 sub_span: Option<Span>,
520 self.check_and_record(Inheritance,
529 pub fn fn_call_str(&mut self,
531 sub_span: Option<Span>,
534 self.check_and_record(FnCall,
537 svec!(id.node, id.krate, "", scope_id));
540 pub fn meth_call_str(&mut self,
542 sub_span: Option<Span>,
543 defid: Option<DefId>,
544 declid: Option<DefId>,
546 let (dfn, dfk) = match defid {
547 Some(defid) => (defid.node, defid.krate),
550 let (dcn, dck) = match declid {
551 Some(declid) => (s!(declid.node), s!(declid.krate)),
552 None => ("".to_string(), "".to_string())
554 self.check_and_record(MethodCall,
557 svec!(dfn, dfk, dcn, dck, scope_id));
560 pub fn sub_mod_ref_str(&mut self,
565 self.record_with_span(ModRef,
568 svec!(0, 0, qualname, parent));
571 pub fn typedef_str(&mut self,
573 sub_span: Option<Span>,
577 self.check_and_record(Typedef,
580 svec!(id, qualname, value));
583 pub fn crate_str(&mut self,
586 self.record_with_span(Crate,
592 pub fn external_crate_str(&mut self,
595 num: ast::CrateNum) {
596 let lo_loc = self.span.sess.codemap().lookup_char_pos(span.lo);
597 self.record_without_span(ExternalCrate,
598 svec!(name, num, lo_loc.file.name),
602 pub fn sub_type_ref_str(&mut self,
606 self.record_with_span(TypeRef,
609 svec!(0, 0, qualname, 0));
612 // A slightly generic function for a reference to an item of any kind.
613 pub fn ref_str(&mut self,
616 sub_span: Option<Span>,
619 self.check_and_record(kind,
622 svec!(id.node, id.krate, "", scope_id));