]> git.lizzy.rs Git - rust.git/blob - src/librustc_save_analysis/dump_visitor.rs
Auto merge of #53830 - davidtwco:issue-53228, r=nikomatsakis
[rust.git] / src / librustc_save_analysis / dump_visitor.rs
1 // Copyright 2015 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.
4 //
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.
10
11 //! Write the output of rustc's analysis to an implementor of Dump.
12 //!
13 //! Dumping the analysis is implemented by walking the AST and getting a bunch of
14 //! info out from all over the place. We use Def IDs to identify objects. The
15 //! tricky part is getting syntactic (span, source text) and semantic (reference
16 //! Def IDs) information for parts of expressions which the compiler has discarded.
17 //! E.g., in a path `foo::bar::baz`, the compiler only keeps a span for the whole
18 //! path and a reference to `baz`, but we want spans and references for all three
19 //! idents.
20 //!
21 //! SpanUtils is used to manipulate spans. In particular, to extract sub-spans
22 //! from spans (e.g., the span for `bar` from the above example path).
23 //! DumpVisitor walks the AST and processes it, and JsonDumper is used for
24 //! recording the output.
25
26 use rustc::hir::def::Def as HirDef;
27 use rustc::hir::def_id::DefId;
28 use rustc::ty::{self, TyCtxt};
29 use rustc_data_structures::fx::FxHashSet;
30
31 use std::path::Path;
32
33 use syntax::ast::{self, Attribute, NodeId, PatKind, CRATE_NODE_ID};
34 use syntax::parse::token;
35 use syntax::symbol::keywords;
36 use syntax::visit::{self, Visitor};
37 use syntax::print::pprust::{
38     bounds_to_string,
39     generic_params_to_string,
40     path_to_string,
41     ty_to_string
42 };
43 use syntax::ptr::P;
44 use syntax::source_map::{Spanned, DUMMY_SP, respan};
45 use syntax_pos::*;
46
47 use {escape, generated_code, lower_attributes, PathCollector, SaveContext};
48 use json_dumper::{Access, DumpOutput, JsonDumper};
49 use span_utils::SpanUtils;
50 use sig;
51
52 use rls_data::{CratePreludeData, Def, DefKind, GlobalCrateId, Import, ImportKind, Ref, RefKind,
53                Relation, RelationKind, SpanData};
54
55 macro_rules! down_cast_data {
56     ($id:ident, $kind:ident, $sp:expr) => {
57         let $id = if let super::Data::$kind(data) = $id {
58             data
59         } else {
60             span_bug!($sp, "unexpected data kind: {:?}", $id);
61         };
62     };
63 }
64
65 macro_rules! access_from {
66     ($save_ctxt:expr, $vis:expr, $id:expr) => {
67         Access {
68             public: $vis.node.is_pub(),
69             reachable: $save_ctxt.analysis.access_levels.is_reachable($id),
70         }
71     };
72
73     ($save_ctxt:expr, $item:expr) => {
74         Access {
75             public: $item.vis.node.is_pub(),
76             reachable: $save_ctxt.analysis.access_levels.is_reachable($item.id),
77         }
78     };
79 }
80
81 pub struct DumpVisitor<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> {
82     save_ctxt: SaveContext<'l, 'tcx>,
83     tcx: TyCtxt<'l, 'tcx, 'tcx>,
84     dumper: &'ll mut JsonDumper<O>,
85
86     span: SpanUtils<'l>,
87
88     cur_scope: NodeId,
89
90     // Set of macro definition (callee) spans, and the set
91     // of macro use (callsite) spans. We store these to ensure
92     // we only write one macro def per unique macro definition, and
93     // one macro use per unique callsite span.
94     // mac_defs: FxHashSet<Span>,
95     macro_calls: FxHashSet<Span>,
96 }
97
98 impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
99     pub fn new(
100         save_ctxt: SaveContext<'l, 'tcx>,
101         dumper: &'ll mut JsonDumper<O>,
102     ) -> DumpVisitor<'l, 'tcx, 'll, O> {
103         let span_utils = SpanUtils::new(&save_ctxt.tcx.sess);
104         DumpVisitor {
105             tcx: save_ctxt.tcx,
106             save_ctxt,
107             dumper,
108             span: span_utils.clone(),
109             cur_scope: CRATE_NODE_ID,
110             // mac_defs: FxHashSet::default(),
111             macro_calls: FxHashSet(),
112         }
113     }
114
115     fn nest_scope<F>(&mut self, scope_id: NodeId, f: F)
116     where
117         F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, O>),
118     {
119         let parent_scope = self.cur_scope;
120         self.cur_scope = scope_id;
121         f(self);
122         self.cur_scope = parent_scope;
123     }
124
125     fn nest_tables<F>(&mut self, item_id: NodeId, f: F)
126     where
127         F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, O>),
128     {
129         let item_def_id = self.tcx.hir.local_def_id(item_id);
130         if self.tcx.has_typeck_tables(item_def_id) {
131             let tables = self.tcx.typeck_tables_of(item_def_id);
132             let old_tables = self.save_ctxt.tables;
133             self.save_ctxt.tables = tables;
134             f(self);
135             self.save_ctxt.tables = old_tables;
136         } else {
137             f(self);
138         }
139     }
140
141     fn span_from_span(&self, span: Span) -> SpanData {
142         self.save_ctxt.span_from_span(span)
143     }
144
145     pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
146         let source_file = self.tcx.sess.local_crate_source_file.as_ref();
147         let crate_root = source_file.map(|source_file| {
148             let source_file = Path::new(source_file);
149             match source_file.file_name() {
150                 Some(_) => source_file.parent().unwrap().display(),
151                 None => source_file.display(),
152             }.to_string()
153         });
154
155         let data = CratePreludeData {
156             crate_id: GlobalCrateId {
157                 name: name.into(),
158                 disambiguator: self.tcx
159                     .sess
160                     .local_crate_disambiguator()
161                     .to_fingerprint()
162                     .as_value(),
163             },
164             crate_root: crate_root.unwrap_or("<no source>".to_owned()),
165             external_crates: self.save_ctxt.get_external_crates(),
166             span: self.span_from_span(krate.span),
167         };
168
169         self.dumper.crate_prelude(data);
170     }
171
172     // Return all non-empty prefixes of a path.
173     // For each prefix, we return the span for the last segment in the prefix and
174     // a str representation of the entire prefix.
175     fn process_path_prefixes(&self, path: &ast::Path) -> Vec<(Span, String)> {
176         let segments = &path.segments[if path.is_global() { 1 } else { 0 }..];
177
178         let mut result = Vec::with_capacity(segments.len());
179         let mut segs = Vec::with_capacity(segments.len());
180
181         for (i, seg) in segments.iter().enumerate() {
182             segs.push(seg.clone());
183             let sub_path = ast::Path {
184                 span: seg.ident.span, // span for the last segment
185                 segments: segs,
186             };
187             let qualname = if i == 0 && path.is_global() {
188                 format!("::{}", path_to_string(&sub_path))
189             } else {
190                 path_to_string(&sub_path)
191             };
192             result.push((seg.ident.span, qualname));
193             segs = sub_path.segments;
194         }
195
196         result
197     }
198
199     fn write_sub_paths(&mut self, path: &ast::Path) {
200         let sub_paths = self.process_path_prefixes(path);
201         for (span, _) in sub_paths {
202             let span = self.span_from_span(span);
203             self.dumper.dump_ref(Ref {
204                 kind: RefKind::Mod,
205                 span,
206                 ref_id: ::null_id(),
207             });
208         }
209     }
210
211     // As write_sub_paths, but does not process the last ident in the path (assuming it
212     // will be processed elsewhere). See note on write_sub_paths about global.
213     fn write_sub_paths_truncated(&mut self, path: &ast::Path) {
214         let sub_paths = self.process_path_prefixes(path);
215         let len = sub_paths.len();
216         if len <= 1 {
217             return;
218         }
219
220         for (span, _) in sub_paths.into_iter().take(len - 1) {
221             let span = self.span_from_span(span);
222             self.dumper.dump_ref(Ref {
223                 kind: RefKind::Mod,
224                 span,
225                 ref_id: ::null_id(),
226             });
227         }
228     }
229
230     // As write_sub_paths, but expects a path of the form module_path::trait::method
231     // Where trait could actually be a struct too.
232     fn write_sub_path_trait_truncated(&mut self, path: &ast::Path) {
233         let sub_paths = self.process_path_prefixes(path);
234         let len = sub_paths.len();
235         if len <= 1 {
236             return;
237         }
238         let sub_paths = &sub_paths[..(len - 1)];
239
240         // write the trait part of the sub-path
241         let (ref span, _) = sub_paths[len - 2];
242         let span = self.span_from_span(*span);
243         self.dumper.dump_ref(Ref {
244             kind: RefKind::Type,
245             ref_id: ::null_id(),
246             span,
247         });
248
249         // write the other sub-paths
250         if len <= 2 {
251             return;
252         }
253         let sub_paths = &sub_paths[..len - 2];
254         for &(ref span, _) in sub_paths {
255             let span = self.span_from_span(*span);
256             self.dumper.dump_ref(Ref {
257                 kind: RefKind::Mod,
258                 span,
259                 ref_id: ::null_id(),
260             });
261         }
262     }
263
264     fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
265         match self.save_ctxt.get_path_def(ref_id) {
266             HirDef::PrimTy(..) | HirDef::SelfTy(..) | HirDef::Err => None,
267             def => Some(def.def_id()),
268         }
269     }
270
271     fn process_formals(&mut self, formals: &'l [ast::Arg], qualname: &str) {
272         for arg in formals {
273             self.visit_pat(&arg.pat);
274             let mut collector = PathCollector::new();
275             collector.visit_pat(&arg.pat);
276             let span_utils = self.span.clone();
277
278             for (id, ident, ..) in collector.collected_idents {
279                 let hir_id = self.tcx.hir.node_to_hir_id(id);
280                 let typ = match self.save_ctxt.tables.node_id_to_type_opt(hir_id) {
281                     Some(s) => s.to_string(),
282                     None => continue,
283                 };
284                 let sub_span = span_utils.span_for_last_ident(ident.span);
285                 if !self.span.filter_generated(sub_span, ident.span) {
286                     let id = ::id_from_node_id(id, &self.save_ctxt);
287                     let span = self.span_from_span(sub_span.expect("No span found for variable"));
288
289                     self.dumper.dump_def(
290                         &Access {
291                             public: false,
292                             reachable: false,
293                         },
294                         Def {
295                             kind: DefKind::Local,
296                             id,
297                             span,
298                             name: ident.to_string(),
299                             qualname: format!("{}::{}", qualname, ident.to_string()),
300                             value: typ,
301                             parent: None,
302                             children: vec![],
303                             decl_id: None,
304                             docs: String::new(),
305                             sig: None,
306                             attributes: vec![],
307                         },
308                     );
309                 }
310             }
311         }
312     }
313
314     fn process_method(
315         &mut self,
316         sig: &'l ast::MethodSig,
317         body: Option<&'l ast::Block>,
318         id: ast::NodeId,
319         ident: ast::Ident,
320         generics: &'l ast::Generics,
321         vis: ast::Visibility,
322         span: Span,
323     ) {
324         debug!("process_method: {}:{}", id, ident);
325
326         if let Some(mut method_data) = self.save_ctxt.get_method_data(id, ident.name, span) {
327             let sig_str = ::make_signature(&sig.decl, &generics);
328             if body.is_some() {
329                 self.nest_tables(
330                     id,
331                     |v| v.process_formals(&sig.decl.inputs, &method_data.qualname),
332                 );
333             }
334
335             self.process_generic_params(&generics, span, &method_data.qualname, id);
336
337             method_data.value = sig_str;
338             method_data.sig = sig::method_signature(id, ident, generics, sig, &self.save_ctxt);
339             self.dumper.dump_def(&access_from!(self.save_ctxt, vis, id), method_data);
340         }
341
342         // walk arg and return types
343         for arg in &sig.decl.inputs {
344             self.visit_ty(&arg.ty);
345         }
346
347         if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output {
348             self.visit_ty(ret_ty);
349         }
350
351         // walk the fn body
352         if let Some(body) = body {
353             self.nest_tables(id, |v| v.nest_scope(id, |v| v.visit_block(body)));
354         }
355     }
356
357     fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) {
358         let field_data = self.save_ctxt.get_field_data(field, parent_id);
359         if let Some(field_data) = field_data {
360             self.dumper.dump_def(&access_from!(self.save_ctxt, field), field_data);
361         }
362     }
363
364     // Dump generic params bindings, then visit_generics
365     fn process_generic_params(
366         &mut self,
367         generics: &'l ast::Generics,
368         full_span: Span,
369         prefix: &str,
370         id: NodeId,
371     ) {
372         for param in &generics.params {
373             match param.kind {
374                 ast::GenericParamKind::Lifetime { .. } => {}
375                 ast::GenericParamKind::Type { .. } => {
376                     let param_ss = param.ident.span;
377                     let name = escape(self.span.snippet(param_ss));
378                     // Append $id to name to make sure each one is unique.
379                     let qualname = format!("{}::{}${}", prefix, name, id);
380                     if !self.span.filter_generated(Some(param_ss), full_span) {
381                         let id = ::id_from_node_id(param.id, &self.save_ctxt);
382                         let span = self.span_from_span(param_ss);
383
384                         self.dumper.dump_def(
385                             &Access {
386                                 public: false,
387                                 reachable: false,
388                             },
389                             Def {
390                                 kind: DefKind::Type,
391                                 id,
392                                 span,
393                                 name,
394                                 qualname,
395                                 value: String::new(),
396                                 parent: None,
397                                 children: vec![],
398                                 decl_id: None,
399                                 docs: String::new(),
400                                 sig: None,
401                                 attributes: vec![],
402                             },
403                         );
404                     }
405                 }
406             }
407         }
408         self.visit_generics(generics);
409     }
410
411     fn process_fn(
412         &mut self,
413         item: &'l ast::Item,
414         decl: &'l ast::FnDecl,
415         ty_params: &'l ast::Generics,
416         body: &'l ast::Block,
417     ) {
418         if let Some(fn_data) = self.save_ctxt.get_item_data(item) {
419             down_cast_data!(fn_data, DefData, item.span);
420             self.nest_tables(
421                 item.id,
422                 |v| v.process_formals(&decl.inputs, &fn_data.qualname),
423             );
424             self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id);
425             self.dumper.dump_def(&access_from!(self.save_ctxt, item), fn_data);
426         }
427
428         for arg in &decl.inputs {
429             self.visit_ty(&arg.ty);
430         }
431
432         if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
433             self.visit_ty(&ret_ty);
434         }
435
436         self.nest_tables(item.id, |v| v.nest_scope(item.id, |v| v.visit_block(&body)));
437     }
438
439     fn process_static_or_const_item(
440         &mut self,
441         item: &'l ast::Item,
442         typ: &'l ast::Ty,
443         expr: &'l ast::Expr,
444     ) {
445         self.nest_tables(item.id, |v| {
446             if let Some(var_data) = v.save_ctxt.get_item_data(item) {
447                 down_cast_data!(var_data, DefData, item.span);
448                 v.dumper.dump_def(&access_from!(v.save_ctxt, item), var_data);
449             }
450             v.visit_ty(&typ);
451             v.visit_expr(expr);
452         });
453     }
454
455     fn process_assoc_const(
456         &mut self,
457         id: ast::NodeId,
458         name: ast::Name,
459         span: Span,
460         typ: &'l ast::Ty,
461         expr: Option<&'l ast::Expr>,
462         parent_id: DefId,
463         vis: ast::Visibility,
464         attrs: &'l [Attribute],
465     ) {
466         let qualname = format!("::{}", self.tcx.node_path_str(id));
467
468         let sub_span = self.span.sub_span_after_keyword(span, keywords::Const);
469
470         if !self.span.filter_generated(sub_span, span) {
471             let sig = sig::assoc_const_signature(id, name, typ, expr, &self.save_ctxt);
472             let span = self.span_from_span(sub_span.expect("No span found for variable"));
473
474             self.dumper.dump_def(
475                 &access_from!(self.save_ctxt, vis, id),
476                 Def {
477                     kind: DefKind::Const,
478                     id: ::id_from_node_id(id, &self.save_ctxt),
479                     span,
480                     name: name.to_string(),
481                     qualname,
482                     value: ty_to_string(&typ),
483                     parent: Some(::id_from_def_id(parent_id)),
484                     children: vec![],
485                     decl_id: None,
486                     docs: self.save_ctxt.docs_for_attrs(attrs),
487                     sig,
488                     attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
489                 },
490             );
491         }
492
493         // walk type and init value
494         self.visit_ty(typ);
495         if let Some(expr) = expr {
496             self.visit_expr(expr);
497         }
498     }
499
500     // FIXME tuple structs should generate tuple-specific data.
501     fn process_struct(
502         &mut self,
503         item: &'l ast::Item,
504         def: &'l ast::VariantData,
505         ty_params: &'l ast::Generics,
506     ) {
507         debug!("process_struct {:?} {:?}", item, item.span);
508         let name = item.ident.to_string();
509         let qualname = format!("::{}", self.tcx.node_path_str(item.id));
510
511         let (kind, keyword) = match item.node {
512             ast::ItemKind::Struct(_, _) => (DefKind::Struct, keywords::Struct),
513             ast::ItemKind::Union(_, _) => (DefKind::Union, keywords::Union),
514             _ => unreachable!(),
515         };
516
517         let sub_span = self.span.sub_span_after_keyword(item.span, keyword);
518         let (value, fields) = match item.node {
519             ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) |
520             ast::ItemKind::Union(ast::VariantData::Struct(ref fields, _), _) => {
521                 let include_priv_fields = !self.save_ctxt.config.pub_only;
522                 let fields_str = fields
523                     .iter()
524                     .enumerate()
525                     .filter_map(|(i, f)| {
526                         if include_priv_fields || f.vis.node.is_pub() {
527                             f.ident
528                                 .map(|i| i.to_string())
529                                 .or_else(|| Some(i.to_string()))
530                         } else {
531                             None
532                         }
533                     })
534                     .collect::<Vec<_>>()
535                     .join(", ");
536                 let value = format!("{} {{ {} }}", name, fields_str);
537                 (
538                     value,
539                     fields
540                         .iter()
541                         .map(|f| ::id_from_node_id(f.id, &self.save_ctxt))
542                         .collect(),
543                 )
544             }
545             _ => (String::new(), vec![]),
546         };
547
548         if !self.span.filter_generated(sub_span, item.span) {
549             let span = self.span_from_span(sub_span.expect("No span found for struct"));
550             self.dumper.dump_def(
551                 &access_from!(self.save_ctxt, item),
552                 Def {
553                     kind,
554                     id: ::id_from_node_id(item.id, &self.save_ctxt),
555                     span,
556                     name,
557                     qualname: qualname.clone(),
558                     value,
559                     parent: None,
560                     children: fields,
561                     decl_id: None,
562                     docs: self.save_ctxt.docs_for_attrs(&item.attrs),
563                     sig: sig::item_signature(item, &self.save_ctxt),
564                     attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
565                 },
566             );
567         }
568
569         for field in def.fields() {
570             self.process_struct_field_def(field, item.id);
571             self.visit_ty(&field.ty);
572         }
573
574         self.process_generic_params(ty_params, item.span, &qualname, item.id);
575     }
576
577     fn process_enum(
578         &mut self,
579         item: &'l ast::Item,
580         enum_definition: &'l ast::EnumDef,
581         ty_params: &'l ast::Generics,
582     ) {
583         let enum_data = self.save_ctxt.get_item_data(item);
584         let enum_data = match enum_data {
585             None => return,
586             Some(data) => data,
587         };
588         down_cast_data!(enum_data, DefData, item.span);
589
590         let access = access_from!(self.save_ctxt, item);
591
592         for variant in &enum_definition.variants {
593             let name = variant.node.ident.name.to_string();
594             let qualname = format!("{}::{}", enum_data.qualname, name);
595
596             match variant.node.data {
597                 ast::VariantData::Struct(ref fields, _) => {
598                     let sub_span = self.span.span_for_first_ident(variant.span);
599                     let fields_str = fields
600                         .iter()
601                         .enumerate()
602                         .map(|(i, f)| {
603                             f.ident.map(|i| i.to_string()).unwrap_or(i.to_string())
604                         })
605                         .collect::<Vec<_>>()
606                         .join(", ");
607                     let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
608                     if !self.span.filter_generated(sub_span, variant.span) {
609                         let span = self
610                             .span_from_span(sub_span.expect("No span found for struct variant"));
611                         let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt);
612                         let parent = Some(::id_from_node_id(item.id, &self.save_ctxt));
613
614                         self.dumper.dump_def(
615                             &access,
616                             Def {
617                                 kind: DefKind::StructVariant,
618                                 id,
619                                 span,
620                                 name,
621                                 qualname,
622                                 value,
623                                 parent,
624                                 children: vec![],
625                                 decl_id: None,
626                                 docs: self.save_ctxt.docs_for_attrs(&variant.node.attrs),
627                                 sig: sig::variant_signature(variant, &self.save_ctxt),
628                                 attributes: lower_attributes(
629                                     variant.node.attrs.clone(),
630                                     &self.save_ctxt,
631                                 ),
632                             },
633                         );
634                     }
635                 }
636                 ref v => {
637                     let sub_span = self.span.span_for_first_ident(variant.span);
638                     let mut value = format!("{}::{}", enum_data.name, name);
639                     if let &ast::VariantData::Tuple(ref fields, _) = v {
640                         value.push('(');
641                         value.push_str(&fields
642                             .iter()
643                             .map(|f| ty_to_string(&f.ty))
644                             .collect::<Vec<_>>()
645                             .join(", "));
646                         value.push(')');
647                     }
648                     if !self.span.filter_generated(sub_span, variant.span) {
649                         let span =
650                             self.span_from_span(sub_span.expect("No span found for tuple variant"));
651                         let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt);
652                         let parent = Some(::id_from_node_id(item.id, &self.save_ctxt));
653
654                         self.dumper.dump_def(
655                             &access,
656                             Def {
657                                 kind: DefKind::TupleVariant,
658                                 id,
659                                 span,
660                                 name,
661                                 qualname,
662                                 value,
663                                 parent,
664                                 children: vec![],
665                                 decl_id: None,
666                                 docs: self.save_ctxt.docs_for_attrs(&variant.node.attrs),
667                                 sig: sig::variant_signature(variant, &self.save_ctxt),
668                                 attributes: lower_attributes(
669                                     variant.node.attrs.clone(),
670                                     &self.save_ctxt,
671                                 ),
672                             },
673                         );
674                     }
675                 }
676             }
677
678
679             for field in variant.node.data.fields() {
680                 self.process_struct_field_def(field, variant.node.data.id());
681                 self.visit_ty(&field.ty);
682             }
683         }
684         self.process_generic_params(ty_params, item.span, &enum_data.qualname, item.id);
685         self.dumper.dump_def(&access, enum_data);
686     }
687
688     fn process_impl(
689         &mut self,
690         item: &'l ast::Item,
691         type_parameters: &'l ast::Generics,
692         trait_ref: &'l Option<ast::TraitRef>,
693         typ: &'l ast::Ty,
694         impl_items: &'l [ast::ImplItem],
695     ) {
696         if let Some(impl_data) = self.save_ctxt.get_item_data(item) {
697             if let super::Data::RelationData(rel, imp) = impl_data {
698                 self.dumper.dump_relation(rel);
699                 self.dumper.dump_impl(imp);
700             } else {
701                 span_bug!(item.span, "unexpected data kind: {:?}", impl_data);
702             }
703         }
704         self.visit_ty(&typ);
705         if let &Some(ref trait_ref) = trait_ref {
706             self.process_path(trait_ref.ref_id, &trait_ref.path);
707         }
708         self.process_generic_params(type_parameters, item.span, "", item.id);
709         for impl_item in impl_items {
710             let map = &self.tcx.hir;
711             self.process_impl_item(impl_item, map.local_def_id(item.id));
712         }
713     }
714
715     fn process_trait(
716         &mut self,
717         item: &'l ast::Item,
718         generics: &'l ast::Generics,
719         trait_refs: &'l ast::GenericBounds,
720         methods: &'l [ast::TraitItem],
721     ) {
722         let name = item.ident.to_string();
723         let qualname = format!("::{}", self.tcx.node_path_str(item.id));
724         let mut val = name.clone();
725         if !generics.params.is_empty() {
726             val.push_str(&generic_params_to_string(&generics.params));
727         }
728         if !trait_refs.is_empty() {
729             val.push_str(": ");
730             val.push_str(&bounds_to_string(trait_refs));
731         }
732         let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait);
733         if !self.span.filter_generated(sub_span, item.span) {
734             let id = ::id_from_node_id(item.id, &self.save_ctxt);
735             let span = self.span_from_span(sub_span.expect("No span found for trait"));
736             let children = methods
737                 .iter()
738                 .map(|i| ::id_from_node_id(i.id, &self.save_ctxt))
739                 .collect();
740             self.dumper.dump_def(
741                 &access_from!(self.save_ctxt, item),
742                 Def {
743                     kind: DefKind::Trait,
744                     id,
745                     span,
746                     name,
747                     qualname: qualname.clone(),
748                     value: val,
749                     parent: None,
750                     children,
751                     decl_id: None,
752                     docs: self.save_ctxt.docs_for_attrs(&item.attrs),
753                     sig: sig::item_signature(item, &self.save_ctxt),
754                     attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
755                 },
756             );
757         }
758
759         // super-traits
760         for super_bound in trait_refs.iter() {
761             let trait_ref = match *super_bound {
762                 ast::GenericBound::Trait(ref trait_ref, _) => trait_ref,
763                 ast::GenericBound::Outlives(..) => continue,
764             };
765
766             let trait_ref = &trait_ref.trait_ref;
767             if let Some(id) = self.lookup_def_id(trait_ref.ref_id) {
768                 let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span);
769                 if !self.span.filter_generated(sub_span, trait_ref.path.span) {
770                     let span = self.span_from_span(sub_span.expect("No span found for trait ref"));
771                     self.dumper.dump_ref(Ref {
772                         kind: RefKind::Type,
773                         span,
774                         ref_id: ::id_from_def_id(id),
775                     });
776                 }
777
778                 if !self.span.filter_generated(sub_span, trait_ref.path.span) {
779                     let sub_span = self.span_from_span(sub_span.expect("No span for inheritance"));
780                     self.dumper.dump_relation(Relation {
781                         kind: RelationKind::SuperTrait,
782                         span: sub_span,
783                         from: ::id_from_def_id(id),
784                         to: ::id_from_node_id(item.id, &self.save_ctxt),
785                     });
786                 }
787             }
788         }
789
790         // walk generics and methods
791         self.process_generic_params(generics, item.span, &qualname, item.id);
792         for method in methods {
793             let map = &self.tcx.hir;
794             self.process_trait_item(method, map.local_def_id(item.id))
795         }
796     }
797
798     // `item` is the module in question, represented as an item.
799     fn process_mod(&mut self, item: &ast::Item) {
800         if let Some(mod_data) = self.save_ctxt.get_item_data(item) {
801             down_cast_data!(mod_data, DefData, item.span);
802             self.dumper.dump_def(&access_from!(self.save_ctxt, item), mod_data);
803         }
804     }
805
806     fn dump_path_ref(&mut self, id: NodeId, path: &ast::Path) {
807         let path_data = self.save_ctxt.get_path_data(id, path);
808         if let Some(path_data) = path_data {
809             self.dumper.dump_ref(path_data);
810         }
811     }
812
813     fn process_path(&mut self, id: NodeId, path: &'l ast::Path) {
814         debug!("process_path {:?}", path);
815         if generated_code(path.span) {
816             return;
817         }
818         self.dump_path_ref(id, path);
819
820         // Type arguments
821         for seg in &path.segments {
822             if let Some(ref generic_args) = seg.args {
823                 match **generic_args {
824                     ast::GenericArgs::AngleBracketed(ref data) => {
825                         for arg in &data.args {
826                             match arg {
827                                 ast::GenericArg::Type(ty) => self.visit_ty(ty),
828                                 _ => {}
829                             }
830                         }
831                     }
832                     ast::GenericArgs::Parenthesized(ref data) => {
833                         for t in &data.inputs {
834                             self.visit_ty(t);
835                         }
836                         if let Some(ref t) = data.output {
837                             self.visit_ty(t);
838                         }
839                     }
840                 }
841             }
842         }
843
844         // Modules or types in the path prefix.
845         match self.save_ctxt.get_path_def(id) {
846             HirDef::Method(did) => {
847                 let ti = self.tcx.associated_item(did);
848                 if ti.kind == ty::AssociatedKind::Method && ti.method_has_self_argument {
849                     self.write_sub_path_trait_truncated(path);
850                 }
851             }
852             HirDef::Fn(..) |
853             HirDef::Const(..) |
854             HirDef::Static(..) |
855             HirDef::StructCtor(..) |
856             HirDef::VariantCtor(..) |
857             HirDef::AssociatedConst(..) |
858             HirDef::Local(..) |
859             HirDef::Upvar(..) |
860             HirDef::Struct(..) |
861             HirDef::Union(..) |
862             HirDef::Variant(..) |
863             HirDef::TyAlias(..) |
864             HirDef::AssociatedTy(..) => self.write_sub_paths_truncated(path),
865             _ => {}
866         }
867     }
868
869     fn process_struct_lit(
870         &mut self,
871         ex: &'l ast::Expr,
872         path: &'l ast::Path,
873         fields: &'l [ast::Field],
874         variant: &'l ty::VariantDef,
875         base: &'l Option<P<ast::Expr>>,
876     ) {
877         self.write_sub_paths_truncated(path);
878
879         if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) {
880             down_cast_data!(struct_lit_data, RefData, ex.span);
881             if !generated_code(ex.span) {
882                 self.dumper.dump_ref(struct_lit_data);
883             }
884
885             for field in fields {
886                 if let Some(field_data) = self.save_ctxt.get_field_ref_data(field, variant) {
887                     self.dumper.dump_ref(field_data);
888                 }
889
890                 self.visit_expr(&field.expr)
891             }
892         }
893
894         walk_list!(self, visit_expr, base);
895     }
896
897     fn process_method_call(
898         &mut self,
899         ex: &'l ast::Expr,
900         seg: &'l ast::PathSegment,
901         args: &'l [P<ast::Expr>],
902     ) {
903         debug!("process_method_call {:?} {:?}", ex, ex.span);
904         if let Some(mcd) = self.save_ctxt.get_expr_data(ex) {
905             down_cast_data!(mcd, RefData, ex.span);
906             if !generated_code(ex.span) {
907                 self.dumper.dump_ref(mcd);
908             }
909         }
910
911         // Explicit types in the turbo-fish.
912         if let Some(ref generic_args) = seg.args {
913             if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args {
914                 for arg in &data.args {
915                     match arg {
916                         ast::GenericArg::Type(ty) => self.visit_ty(ty),
917                         _ => {}
918                     }
919                 }
920             }
921         }
922
923         // walk receiver and args
924         walk_list!(self, visit_expr, args);
925     }
926
927     fn process_pat(&mut self, p: &'l ast::Pat) {
928         match p.node {
929             PatKind::Struct(ref _path, ref fields, _) => {
930                 // FIXME do something with _path?
931                 let hir_id = self.tcx.hir.node_to_hir_id(p.id);
932                 let adt = match self.save_ctxt.tables.node_id_to_type_opt(hir_id) {
933                     Some(ty) => ty.ty_adt_def().unwrap(),
934                     None => {
935                         visit::walk_pat(self, p);
936                         return;
937                     }
938                 };
939                 let variant = adt.variant_of_def(self.save_ctxt.get_path_def(p.id));
940
941                 for &Spanned { node: ref field, span } in fields {
942                     let sub_span = self.span.span_for_first_ident(span);
943                     if let Some(index) = self.tcx.find_field_index(field.ident, variant) {
944                         if !self.span.filter_generated(sub_span, span) {
945                             let span =
946                                 self.span_from_span(sub_span.expect("No span fund for var ref"));
947                             self.dumper.dump_ref(Ref {
948                                 kind: RefKind::Variable,
949                                 span,
950                                 ref_id: ::id_from_def_id(variant.fields[index].did),
951                             });
952                         }
953                     }
954                     self.visit_pat(&field.pat);
955                 }
956             }
957             _ => visit::walk_pat(self, p),
958         }
959     }
960
961     fn process_var_decl_multi(&mut self, pats: &'l [P<ast::Pat>]) {
962         let mut collector = PathCollector::new();
963         for pattern in pats {
964             // collect paths from the arm's patterns
965             collector.visit_pat(&pattern);
966             self.visit_pat(&pattern);
967         }
968
969         // process collected paths
970         for (id, ident, immut) in collector.collected_idents {
971             match self.save_ctxt.get_path_def(id) {
972                 HirDef::Local(id) => {
973                     let mut value = if immut == ast::Mutability::Immutable {
974                         self.span.snippet(ident.span)
975                     } else {
976                         "<mutable>".to_owned()
977                     };
978                     let hir_id = self.tcx.hir.node_to_hir_id(id);
979                     let typ = self.save_ctxt
980                         .tables
981                         .node_id_to_type_opt(hir_id)
982                         .map(|t| t.to_string())
983                         .unwrap_or(String::new());
984                     value.push_str(": ");
985                     value.push_str(&typ);
986
987                     if !self.span.filter_generated(Some(ident.span), ident.span) {
988                         let qualname = format!("{}${}", ident.to_string(), id);
989                         let id = ::id_from_node_id(id, &self.save_ctxt);
990                         let span = self.span_from_span(ident.span);
991
992                         self.dumper.dump_def(
993                             &Access {
994                                 public: false,
995                                 reachable: false,
996                             },
997                             Def {
998                                 kind: DefKind::Local,
999                                 id,
1000                                 span,
1001                                 name: ident.to_string(),
1002                                 qualname,
1003                                 value: typ,
1004                                 parent: None,
1005                                 children: vec![],
1006                                 decl_id: None,
1007                                 docs: String::new(),
1008                                 sig: None,
1009                                 attributes: vec![],
1010                             },
1011                         );
1012                     }
1013                 }
1014                 HirDef::StructCtor(..) |
1015                 HirDef::VariantCtor(..) |
1016                 HirDef::Const(..) |
1017                 HirDef::AssociatedConst(..) |
1018                 HirDef::Struct(..) |
1019                 HirDef::Variant(..) |
1020                 HirDef::TyAlias(..) |
1021                 HirDef::AssociatedTy(..) |
1022                 HirDef::SelfTy(..) => {
1023                     self.dump_path_ref(id, &ast::Path::from_ident(ident));
1024                 }
1025                 def => error!(
1026                     "unexpected definition kind when processing collected idents: {:?}",
1027                     def
1028                 ),
1029             }
1030         }
1031
1032         for (id, ref path) in collector.collected_paths {
1033             self.process_path(id, path);
1034         }
1035     }
1036
1037     fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
1038         // The local could declare multiple new vars, we must walk the
1039         // pattern and collect them all.
1040         let mut collector = PathCollector::new();
1041         collector.visit_pat(&p);
1042         self.visit_pat(&p);
1043
1044         for (id, ident, immut) in collector.collected_idents {
1045             let mut value = match immut {
1046                 ast::Mutability::Immutable => value.to_string(),
1047                 _ => String::new(),
1048             };
1049             let hir_id = self.tcx.hir.node_to_hir_id(id);
1050             let typ = match self.save_ctxt.tables.node_id_to_type_opt(hir_id) {
1051                 Some(typ) => {
1052                     let typ = typ.to_string();
1053                     if !value.is_empty() {
1054                         value.push_str(": ");
1055                     }
1056                     value.push_str(&typ);
1057                     typ
1058                 }
1059                 None => String::new(),
1060             };
1061
1062             // Get the span only for the name of the variable (I hope the path
1063             // is only ever a variable name, but who knows?).
1064             let sub_span = self.span.span_for_last_ident(ident.span);
1065             // Rust uses the id of the pattern for var lookups, so we'll use it too.
1066             if !self.span.filter_generated(sub_span, ident.span) {
1067                 let qualname = format!("{}${}", ident.to_string(), id);
1068                 let id = ::id_from_node_id(id, &self.save_ctxt);
1069                 let span = self.span_from_span(sub_span.expect("No span found for variable"));
1070
1071                 self.dumper.dump_def(
1072                     &Access {
1073                         public: false,
1074                         reachable: false,
1075                     },
1076                     Def {
1077                         kind: DefKind::Local,
1078                         id,
1079                         span,
1080                         name: ident.to_string(),
1081                         qualname,
1082                         value: typ,
1083                         parent: None,
1084                         children: vec![],
1085                         decl_id: None,
1086                         docs: String::new(),
1087                         sig: None,
1088                         attributes: vec![],
1089                     },
1090                 );
1091             }
1092         }
1093     }
1094
1095     /// Extract macro use and definition information from the AST node defined
1096     /// by the given NodeId, using the expansion information from the node's
1097     /// span.
1098     ///
1099     /// If the span is not macro-generated, do nothing, else use callee and
1100     /// callsite spans to record macro definition and use data, using the
1101     /// mac_uses and mac_defs sets to prevent multiples.
1102     fn process_macro_use(&mut self, span: Span) {
1103         let source_span = span.source_callsite();
1104         if !self.macro_calls.insert(source_span) {
1105             return;
1106         }
1107
1108         let data = match self.save_ctxt.get_macro_use_data(span) {
1109             None => return,
1110             Some(data) => data,
1111         };
1112
1113         self.dumper.macro_use(data);
1114
1115         // FIXME write the macro def
1116         // let mut hasher = DefaultHasher::new();
1117         // data.callee_span.hash(&mut hasher);
1118         // let hash = hasher.finish();
1119         // let qualname = format!("{}::{}", data.name, hash);
1120         // Don't write macro definition for imported macros
1121         // if !self.mac_defs.contains(&data.callee_span)
1122         //     && !data.imported {
1123         //     self.mac_defs.insert(data.callee_span);
1124         //     if let Some(sub_span) = self.span.span_for_macro_def_name(data.callee_span) {
1125         //         self.dumper.macro_data(MacroData {
1126         //             span: sub_span,
1127         //             name: data.name.clone(),
1128         //             qualname: qualname.clone(),
1129         //             // FIXME where do macro docs come from?
1130         //             docs: String::new(),
1131         //         }.lower(self.tcx));
1132         //     }
1133         // }
1134     }
1135
1136     fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId) {
1137         self.process_macro_use(trait_item.span);
1138         let vis_span = trait_item.span.shrink_to_lo();
1139         match trait_item.node {
1140             ast::TraitItemKind::Const(ref ty, ref expr) => {
1141                 self.process_assoc_const(
1142                     trait_item.id,
1143                     trait_item.ident.name,
1144                     trait_item.span,
1145                     &ty,
1146                     expr.as_ref().map(|e| &**e),
1147                     trait_id,
1148                     respan(vis_span, ast::VisibilityKind::Public),
1149                     &trait_item.attrs,
1150                 );
1151             }
1152             ast::TraitItemKind::Method(ref sig, ref body) => {
1153                 self.process_method(
1154                     sig,
1155                     body.as_ref().map(|x| &**x),
1156                     trait_item.id,
1157                     trait_item.ident,
1158                     &trait_item.generics,
1159                     respan(vis_span, ast::VisibilityKind::Public),
1160                     trait_item.span,
1161                 );
1162             }
1163             ast::TraitItemKind::Type(ref bounds, ref default_ty) => {
1164                 // FIXME do something with _bounds (for type refs)
1165                 let name = trait_item.ident.name.to_string();
1166                 let qualname = format!("::{}", self.tcx.node_path_str(trait_item.id));
1167                 let sub_span = self.span
1168                     .sub_span_after_keyword(trait_item.span, keywords::Type);
1169
1170                 if !self.span.filter_generated(sub_span, trait_item.span) {
1171                     let span = self.span_from_span(sub_span.expect("No span found for assoc type"));
1172                     let id = ::id_from_node_id(trait_item.id, &self.save_ctxt);
1173
1174                     self.dumper.dump_def(
1175                         &Access {
1176                             public: true,
1177                             reachable: true,
1178                         },
1179                         Def {
1180                             kind: DefKind::Type,
1181                             id,
1182                             span,
1183                             name,
1184                             qualname,
1185                             value: self.span.snippet(trait_item.span),
1186                             parent: Some(::id_from_def_id(trait_id)),
1187                             children: vec![],
1188                             decl_id: None,
1189                             docs: self.save_ctxt.docs_for_attrs(&trait_item.attrs),
1190                             sig: sig::assoc_type_signature(
1191                                 trait_item.id,
1192                                 trait_item.ident,
1193                                 Some(bounds),
1194                                 default_ty.as_ref().map(|ty| &**ty),
1195                                 &self.save_ctxt,
1196                             ),
1197                             attributes: lower_attributes(trait_item.attrs.clone(), &self.save_ctxt),
1198                         },
1199                     );
1200                 }
1201
1202                 if let &Some(ref default_ty) = default_ty {
1203                     self.visit_ty(default_ty)
1204                 }
1205             }
1206             ast::TraitItemKind::Macro(_) => {}
1207         }
1208     }
1209
1210     fn process_impl_item(&mut self, impl_item: &'l ast::ImplItem, impl_id: DefId) {
1211         self.process_macro_use(impl_item.span);
1212         match impl_item.node {
1213             ast::ImplItemKind::Const(ref ty, ref expr) => {
1214                 self.process_assoc_const(
1215                     impl_item.id,
1216                     impl_item.ident.name,
1217                     impl_item.span,
1218                     &ty,
1219                     Some(expr),
1220                     impl_id,
1221                     impl_item.vis.clone(),
1222                     &impl_item.attrs,
1223                 );
1224             }
1225             ast::ImplItemKind::Method(ref sig, ref body) => {
1226                 self.process_method(
1227                     sig,
1228                     Some(body),
1229                     impl_item.id,
1230                     impl_item.ident,
1231                     &impl_item.generics,
1232                     impl_item.vis.clone(),
1233                     impl_item.span,
1234                 );
1235             }
1236             ast::ImplItemKind::Type(ref ty) => {
1237                 // FIXME uses of the assoc type should ideally point to this
1238                 // 'def' and the name here should be a ref to the def in the
1239                 // trait.
1240                 self.visit_ty(ty)
1241             }
1242             ast::ImplItemKind::Existential(ref bounds) => {
1243                 // FIXME uses of the assoc type should ideally point to this
1244                 // 'def' and the name here should be a ref to the def in the
1245                 // trait.
1246                 for bound in bounds.iter() {
1247                     if let ast::GenericBound::Trait(trait_ref, _) = bound {
1248                         self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
1249                     }
1250                 }
1251             }
1252             ast::ImplItemKind::Macro(_) => {}
1253         }
1254     }
1255
1256     /// Dumps imports in a use tree recursively.
1257     ///
1258     /// A use tree is an import that may contain nested braces (RFC 2128). The `use_tree` parameter
1259     /// is the current use tree under scrutiny, while `id` and `prefix` are its corresponding node
1260     /// id and path. `root_item` is the topmost use tree in the hierarchy.
1261     ///
1262     /// If `use_tree` is a simple or glob import, it is dumped into the analysis data. Otherwise,
1263     /// each child use tree is dumped recursively.
1264     fn process_use_tree(&mut self,
1265                          use_tree: &'l ast::UseTree,
1266                          id: NodeId,
1267                          root_item: &'l ast::Item,
1268                          prefix: &ast::Path) {
1269         let path = &use_tree.prefix;
1270
1271         // The access is calculated using the current tree ID, but with the root tree's visibility
1272         // (since nested trees don't have their own visibility).
1273         let access = access_from!(self.save_ctxt, root_item.vis, id);
1274
1275         // The parent def id of a given use tree is always the enclosing item.
1276         let parent = self.save_ctxt.tcx.hir.opt_local_def_id(id)
1277             .and_then(|id| self.save_ctxt.tcx.parent_def_id(id))
1278             .map(::id_from_def_id);
1279
1280         match use_tree.kind {
1281             ast::UseTreeKind::Simple(..) => {
1282                 let ident = use_tree.ident();
1283                 let path = ast::Path {
1284                     segments: prefix.segments
1285                         .iter()
1286                         .chain(path.segments.iter())
1287                         .cloned()
1288                         .collect(),
1289                     span: path.span,
1290                 };
1291
1292                 let sub_span = self.span.span_for_last_ident(path.span);
1293                 let alias_span = self.span.sub_span_after_keyword(use_tree.span, keywords::As);
1294                 let ref_id = self.lookup_def_id(id);
1295
1296                 if !self.span.filter_generated(sub_span, path.span) {
1297                     let span = self.span_from_span(sub_span.expect("No span found for use"));
1298                     let alias_span = alias_span.map(|sp| self.span_from_span(sp));
1299                     self.dumper.import(&access, Import {
1300                         kind: ImportKind::Use,
1301                         ref_id: ref_id.map(|id| ::id_from_def_id(id)),
1302                         span,
1303                         alias_span,
1304                         name: ident.to_string(),
1305                         value: String::new(),
1306                         parent,
1307                     });
1308                 }
1309                 self.write_sub_paths_truncated(&path);
1310             }
1311             ast::UseTreeKind::Glob => {
1312                 let path = ast::Path {
1313                     segments: prefix.segments
1314                         .iter()
1315                         .chain(path.segments.iter())
1316                         .cloned()
1317                         .collect(),
1318                     span: path.span,
1319                 };
1320
1321                 // Make a comma-separated list of names of imported modules.
1322                 let glob_map = &self.save_ctxt.analysis.glob_map;
1323                 let glob_map = glob_map.as_ref().unwrap();
1324                 let names = if glob_map.contains_key(&id) {
1325                     glob_map.get(&id).unwrap().iter().map(|n| n.to_string()).collect()
1326                 } else {
1327                     Vec::new()
1328                 };
1329
1330                 let sub_span = self.span.sub_span_of_token(use_tree.span,
1331                                                            token::BinOp(token::Star));
1332                 if !self.span.filter_generated(sub_span, use_tree.span) {
1333                     let span =
1334                         self.span_from_span(sub_span.expect("No span found for use glob"));
1335                     self.dumper.import(&access, Import {
1336                         kind: ImportKind::GlobUse,
1337                         ref_id: None,
1338                         span,
1339                         alias_span: None,
1340                         name: "*".to_owned(),
1341                         value: names.join(", "),
1342                         parent,
1343                     });
1344                 }
1345                 self.write_sub_paths(&path);
1346             }
1347             ast::UseTreeKind::Nested(ref nested_items) => {
1348                 let prefix = ast::Path {
1349                     segments: prefix.segments
1350                         .iter()
1351                         .chain(path.segments.iter())
1352                         .cloned()
1353                         .collect(),
1354                     span: path.span,
1355                 };
1356                 for &(ref tree, id) in nested_items {
1357                     self.process_use_tree(tree, id, root_item, &prefix);
1358                 }
1359             }
1360         }
1361     }
1362
1363     fn process_bounds(&mut self, bounds: &'l ast::GenericBounds) {
1364         for bound in bounds {
1365             if let ast::GenericBound::Trait(ref trait_ref, _) = *bound {
1366                 self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
1367             }
1368         }
1369     }
1370 }
1371
1372 impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, O> {
1373     fn visit_mod(&mut self, m: &'l ast::Mod, span: Span, attrs: &[ast::Attribute], id: NodeId) {
1374         // Since we handle explicit modules ourselves in visit_item, this should
1375         // only get called for the root module of a crate.
1376         assert_eq!(id, ast::CRATE_NODE_ID);
1377
1378         let qualname = format!("::{}", self.tcx.node_path_str(id));
1379
1380         let cm = self.tcx.sess.source_map();
1381         let filename = cm.span_to_filename(span);
1382         let data_id = ::id_from_node_id(id, &self.save_ctxt);
1383         let children = m.items
1384             .iter()
1385             .map(|i| ::id_from_node_id(i.id, &self.save_ctxt))
1386             .collect();
1387         let span = self.span_from_span(span);
1388
1389         self.dumper.dump_def(
1390             &Access {
1391                 public: true,
1392                 reachable: true,
1393             },
1394             Def {
1395                 kind: DefKind::Mod,
1396                 id: data_id,
1397                 name: String::new(),
1398                 qualname,
1399                 span,
1400                 value: filename.to_string(),
1401                 children,
1402                 parent: None,
1403                 decl_id: None,
1404                 docs: self.save_ctxt.docs_for_attrs(attrs),
1405                 sig: None,
1406                 attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
1407             },
1408         );
1409         self.nest_scope(id, |v| visit::walk_mod(v, m));
1410     }
1411
1412     fn visit_item(&mut self, item: &'l ast::Item) {
1413         use syntax::ast::ItemKind::*;
1414         self.process_macro_use(item.span);
1415         match item.node {
1416             Use(ref use_tree) => {
1417                 let prefix = ast::Path {
1418                     segments: vec![],
1419                     span: DUMMY_SP,
1420                 };
1421                 self.process_use_tree(use_tree, item.id, item, &prefix);
1422             }
1423             ExternCrate(_) => {
1424                 let alias_span = self.span.span_for_last_ident(item.span);
1425
1426                 if !self.span.filter_generated(alias_span, item.span) {
1427                     let span =
1428                         self.span_from_span(alias_span.expect("No span found for extern crate"));
1429                     let parent = self.save_ctxt.tcx.hir.opt_local_def_id(item.id)
1430                         .and_then(|id| self.save_ctxt.tcx.parent_def_id(id))
1431                         .map(::id_from_def_id);
1432                     self.dumper.import(
1433                         &Access {
1434                             public: false,
1435                             reachable: false,
1436                         },
1437                         Import {
1438                             kind: ImportKind::ExternCrate,
1439                             ref_id: None,
1440                             span,
1441                             alias_span: None,
1442                             name: item.ident.to_string(),
1443                             value: String::new(),
1444                             parent,
1445                         },
1446                     );
1447                 }
1448             }
1449             Fn(ref decl, .., ref ty_params, ref body) => {
1450                 self.process_fn(item, &decl, ty_params, &body)
1451             }
1452             Static(ref typ, _, ref expr) => self.process_static_or_const_item(item, typ, expr),
1453             Const(ref typ, ref expr) => self.process_static_or_const_item(item, &typ, &expr),
1454             Struct(ref def, ref ty_params) | Union(ref def, ref ty_params) => {
1455                 self.process_struct(item, def, ty_params)
1456             }
1457             Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
1458             Impl(.., ref ty_params, ref trait_ref, ref typ, ref impl_items) => {
1459                 self.process_impl(item, ty_params, trait_ref, &typ, impl_items)
1460             }
1461             Trait(_, _, ref generics, ref trait_refs, ref methods) => {
1462                 self.process_trait(item, generics, trait_refs, methods)
1463             }
1464             Mod(ref m) => {
1465                 self.process_mod(item);
1466                 self.nest_scope(item.id, |v| visit::walk_mod(v, m));
1467             }
1468             Ty(ref ty, ref ty_params) => {
1469                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
1470                 let value = ty_to_string(&ty);
1471                 let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type);
1472                 if !self.span.filter_generated(sub_span, item.span) {
1473                     let span = self.span_from_span(sub_span.expect("No span found for typedef"));
1474                     let id = ::id_from_node_id(item.id, &self.save_ctxt);
1475
1476                     self.dumper.dump_def(
1477                         &access_from!(self.save_ctxt, item),
1478                         Def {
1479                             kind: DefKind::Type,
1480                             id,
1481                             span,
1482                             name: item.ident.to_string(),
1483                             qualname: qualname.clone(),
1484                             value,
1485                             parent: None,
1486                             children: vec![],
1487                             decl_id: None,
1488                             docs: self.save_ctxt.docs_for_attrs(&item.attrs),
1489                             sig: sig::item_signature(item, &self.save_ctxt),
1490                             attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
1491                         },
1492                     );
1493                 }
1494
1495                 self.visit_ty(&ty);
1496                 self.process_generic_params(ty_params, item.span, &qualname, item.id);
1497             }
1498             Existential(ref _bounds, ref ty_params) => {
1499                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
1500                 // FIXME do something with _bounds
1501                 let value = String::new();
1502                 let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type);
1503                 if !self.span.filter_generated(sub_span, item.span) {
1504                     let span = self.span_from_span(sub_span.expect("No span found for typedef"));
1505                     let id = ::id_from_node_id(item.id, &self.save_ctxt);
1506
1507                     self.dumper.dump_def(
1508                         &access_from!(self.save_ctxt, item),
1509                         Def {
1510                             kind: DefKind::Type,
1511                             id,
1512                             span,
1513                             name: item.ident.to_string(),
1514                             qualname: qualname.clone(),
1515                             value,
1516                             parent: None,
1517                             children: vec![],
1518                             decl_id: None,
1519                             docs: self.save_ctxt.docs_for_attrs(&item.attrs),
1520                             sig: sig::item_signature(item, &self.save_ctxt),
1521                             attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
1522                         },
1523                     );
1524                 }
1525
1526                 self.process_generic_params(ty_params, item.span, &qualname, item.id);
1527             }
1528             Mac(_) => (),
1529             _ => visit::walk_item(self, item),
1530         }
1531     }
1532
1533     fn visit_generics(&mut self, generics: &'l ast::Generics) {
1534         for param in &generics.params {
1535             if let ast::GenericParamKind::Type { ref default, .. } = param.kind {
1536                 self.process_bounds(&param.bounds);
1537                 if let Some(ref ty) = default {
1538                     self.visit_ty(&ty);
1539                 }
1540             }
1541         }
1542         for pred in &generics.where_clause.predicates {
1543             if let ast::WherePredicate::BoundPredicate(ref wbp) = *pred {
1544                 self.process_bounds(&wbp.bounds);
1545                 self.visit_ty(&wbp.bounded_ty);
1546             }
1547         }
1548     }
1549
1550     fn visit_ty(&mut self, t: &'l ast::Ty) {
1551         self.process_macro_use(t.span);
1552         match t.node {
1553             ast::TyKind::Path(_, ref path) => {
1554                 if generated_code(t.span) {
1555                     return;
1556                 }
1557
1558                 if let Some(id) = self.lookup_def_id(t.id) {
1559                     if let Some(sub_span) = self.span.sub_span_for_type_name(t.span) {
1560                         let span = self.span_from_span(sub_span);
1561                         self.dumper.dump_ref(Ref {
1562                             kind: RefKind::Type,
1563                             span,
1564                             ref_id: ::id_from_def_id(id),
1565                         });
1566                     }
1567                 }
1568
1569                 self.write_sub_paths_truncated(path);
1570                 visit::walk_path(self, path);
1571             }
1572             ast::TyKind::Array(ref element, ref length) => {
1573                 self.visit_ty(element);
1574                 self.nest_tables(length.id, |v| v.visit_expr(&length.value));
1575             }
1576             _ => visit::walk_ty(self, t),
1577         }
1578     }
1579
1580     fn visit_expr(&mut self, ex: &'l ast::Expr) {
1581         debug!("visit_expr {:?}", ex.node);
1582         self.process_macro_use(ex.span);
1583         match ex.node {
1584             ast::ExprKind::Struct(ref path, ref fields, ref base) => {
1585                 let hir_expr = self.save_ctxt.tcx.hir.expect_expr(ex.id);
1586                 let adt = match self.save_ctxt.tables.expr_ty_opt(&hir_expr) {
1587                     Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(),
1588                     _ => {
1589                         visit::walk_expr(self, ex);
1590                         return;
1591                     }
1592                 };
1593                 let def = self.save_ctxt.get_path_def(hir_expr.id);
1594                 self.process_struct_lit(ex, path, fields, adt.variant_of_def(def), base)
1595             }
1596             ast::ExprKind::MethodCall(ref seg, ref args) => self.process_method_call(ex, seg, args),
1597             ast::ExprKind::Field(ref sub_ex, _) => {
1598                 self.visit_expr(&sub_ex);
1599
1600                 if let Some(field_data) = self.save_ctxt.get_expr_data(ex) {
1601                     down_cast_data!(field_data, RefData, ex.span);
1602                     if !generated_code(ex.span) {
1603                         self.dumper.dump_ref(field_data);
1604                     }
1605                 }
1606             }
1607             ast::ExprKind::Closure(_, _, _, ref decl, ref body, _fn_decl_span) => {
1608                 let id = format!("${}", ex.id);
1609
1610                 // walk arg and return types
1611                 for arg in &decl.inputs {
1612                     self.visit_ty(&arg.ty);
1613                 }
1614
1615                 if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
1616                     self.visit_ty(&ret_ty);
1617                 }
1618
1619                 // walk the body
1620                 self.nest_tables(ex.id, |v| {
1621                     v.process_formals(&decl.inputs, &id);
1622                     v.nest_scope(ex.id, |v| v.visit_expr(body))
1623                 });
1624             }
1625             ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) => {
1626                 let value = self.span.snippet(subexpression.span);
1627                 self.process_var_decl(pattern, value);
1628                 debug!("for loop, walk sub-expr: {:?}", subexpression.node);
1629                 self.visit_expr(subexpression);
1630                 visit::walk_block(self, block);
1631             }
1632             ast::ExprKind::WhileLet(ref pats, ref subexpression, ref block, _) => {
1633                 self.process_var_decl_multi(pats);
1634                 debug!("for loop, walk sub-expr: {:?}", subexpression.node);
1635                 self.visit_expr(subexpression);
1636                 visit::walk_block(self, block);
1637             }
1638             ast::ExprKind::IfLet(ref pats, ref subexpression, ref block, ref opt_else) => {
1639                 self.process_var_decl_multi(pats);
1640                 self.visit_expr(subexpression);
1641                 visit::walk_block(self, block);
1642                 opt_else.as_ref().map(|el| self.visit_expr(el));
1643             }
1644             ast::ExprKind::Repeat(ref element, ref count) => {
1645                 self.visit_expr(element);
1646                 self.nest_tables(count.id, |v| v.visit_expr(&count.value));
1647             }
1648             // In particular, we take this branch for call and path expressions,
1649             // where we'll index the idents involved just by continuing to walk.
1650             _ => visit::walk_expr(self, ex),
1651         }
1652     }
1653
1654     fn visit_mac(&mut self, mac: &'l ast::Mac) {
1655         // These shouldn't exist in the AST at this point, log a span bug.
1656         span_bug!(
1657             mac.span,
1658             "macro invocation should have been expanded out of AST"
1659         );
1660     }
1661
1662     fn visit_pat(&mut self, p: &'l ast::Pat) {
1663         self.process_macro_use(p.span);
1664         self.process_pat(p);
1665     }
1666
1667     fn visit_arm(&mut self, arm: &'l ast::Arm) {
1668         self.process_var_decl_multi(&arm.pats);
1669         match arm.guard {
1670             Some(ast::Guard::If(ref expr)) => self.visit_expr(expr),
1671             _ => {}
1672         }
1673         self.visit_expr(&arm.body);
1674     }
1675
1676     fn visit_path(&mut self, p: &'l ast::Path, id: NodeId) {
1677         self.process_path(id, p);
1678     }
1679
1680     fn visit_stmt(&mut self, s: &'l ast::Stmt) {
1681         self.process_macro_use(s.span);
1682         visit::walk_stmt(self, s)
1683     }
1684
1685     fn visit_local(&mut self, l: &'l ast::Local) {
1686         self.process_macro_use(l.span);
1687         let value = l.init
1688             .as_ref()
1689             .map(|i| self.span.snippet(i.span))
1690             .unwrap_or(String::new());
1691         self.process_var_decl(&l.pat, value);
1692
1693         // Just walk the initialiser and type (don't want to walk the pattern again).
1694         walk_list!(self, visit_ty, &l.ty);
1695         walk_list!(self, visit_expr, &l.init);
1696     }
1697
1698     fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
1699         let access = access_from!(self.save_ctxt, item);
1700
1701         match item.node {
1702             ast::ForeignItemKind::Fn(ref decl, ref generics) => {
1703                 if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) {
1704                     down_cast_data!(fn_data, DefData, item.span);
1705
1706                     self.nest_tables(
1707                         item.id,
1708                         |v| v.process_formals(&decl.inputs, &fn_data.qualname),
1709                     );
1710                     self.process_generic_params(generics, item.span, &fn_data.qualname, item.id);
1711                     self.dumper.dump_def(&access, fn_data);
1712                 }
1713
1714                 for arg in &decl.inputs {
1715                     self.visit_ty(&arg.ty);
1716                 }
1717
1718                 if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
1719                     self.visit_ty(&ret_ty);
1720                 }
1721             }
1722             ast::ForeignItemKind::Static(ref ty, _) => {
1723                 if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
1724                     down_cast_data!(var_data, DefData, item.span);
1725                     self.dumper.dump_def(&access, var_data);
1726                 }
1727
1728                 self.visit_ty(ty);
1729             }
1730             ast::ForeignItemKind::Ty => {
1731                 if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
1732                     down_cast_data!(var_data, DefData, item.span);
1733                     self.dumper.dump_def(&access, var_data);
1734                 }
1735             }
1736             ast::ForeignItemKind::Macro(..) => {}
1737         }
1738     }
1739 }