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