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.
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.
11 //! Write the output of rustc's analysis to an implementor of Dump.
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
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 an implementor of Dump
24 //! is used for recording the output in a format-agnostic way (see CsvDumper
27 use rustc
::hir
::def
::Def
as HirDef
;
28 use rustc
::hir
::def_id
::DefId
;
29 use rustc
::hir
::map
::Node
;
30 use rustc
::ty
::{self, TyCtxt}
;
31 use rustc_data_structures
::fx
::FxHashSet
;
35 use syntax
::ast
::{self, Attribute, NodeId, PatKind, CRATE_NODE_ID}
;
36 use syntax
::parse
::token
;
37 use syntax
::symbol
::keywords
;
38 use syntax
::visit
::{self, Visitor}
;
39 use syntax
::print
::pprust
::{bounds_to_string, generics_to_string, path_to_string, ty_to_string}
;
41 use syntax
::codemap
::Spanned
;
44 use {escape, generated_code, lower_attributes, PathCollector, SaveContext}
;
45 use json_dumper
::{DumpOutput, JsonDumper}
;
46 use span_utils
::SpanUtils
;
49 use rls_data
::{CratePreludeData
, Def
, DefKind
, GlobalCrateId
, Import
, ImportKind
, Ref
, RefKind
,
50 Relation
, RelationKind
, SpanData
};
52 macro_rules
! down_cast_data
{
53 ($id
:ident
, $kind
:ident
, $sp
:expr
) => {
54 let $id
= if let super::Data
::$
kind(data
) = $id
{
57 span_bug
!($sp
, "unexpected data kind: {:?}", $id
);
62 pub struct DumpVisitor
<'l
, 'tcx
: 'l
, 'll
, O
: DumpOutput
+ 'll
> {
63 save_ctxt
: SaveContext
<'l
, 'tcx
>,
64 tcx
: TyCtxt
<'l
, 'tcx
, 'tcx
>,
65 dumper
: &'ll
mut JsonDumper
<O
>,
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.
75 // mac_defs: HashSet<Span>,
76 macro_calls
: FxHashSet
<Span
>,
79 impl<'l
, 'tcx
: 'l
, 'll
, O
: DumpOutput
+ 'll
> DumpVisitor
<'l
, 'tcx
, 'll
, O
> {
81 save_ctxt
: SaveContext
<'l
, 'tcx
>,
82 dumper
: &'ll
mut JsonDumper
<O
>,
83 ) -> DumpVisitor
<'l
, 'tcx
, 'll
, O
> {
84 let span_utils
= SpanUtils
::new(&save_ctxt
.tcx
.sess
);
89 span
: span_utils
.clone(),
90 cur_scope
: CRATE_NODE_ID
,
91 // mac_defs: HashSet::new(),
92 macro_calls
: FxHashSet(),
96 fn nest_scope
<F
>(&mut self, scope_id
: NodeId
, f
: F
)
98 F
: FnOnce(&mut DumpVisitor
<'l
, 'tcx
, 'll
, O
>),
100 let parent_scope
= self.cur_scope
;
101 self.cur_scope
= scope_id
;
103 self.cur_scope
= parent_scope
;
106 fn nest_tables
<F
>(&mut self, item_id
: NodeId
, f
: F
)
108 F
: FnOnce(&mut DumpVisitor
<'l
, 'tcx
, 'll
, O
>),
110 let item_def_id
= self.tcx
.hir
.local_def_id(item_id
);
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
;
116 self.save_ctxt
.tables
= old_tables
;
122 fn span_from_span(&self, span
: Span
) -> SpanData
{
123 self.save_ctxt
.span_from_span(span
)
126 pub fn dump_crate_info(&mut self, name
: &str, krate
: &ast
::Crate
) {
127 let source_file
= self.tcx
.sess
.local_crate_source_file
.as_ref();
128 let crate_root
= source_file
.map(|source_file
| {
129 let source_file
= Path
::new(source_file
);
130 match source_file
.file_name() {
131 Some(_
) => source_file
.parent().unwrap().display().to_string(),
132 None
=> source_file
.display().to_string(),
136 let data
= CratePreludeData
{
137 crate_id
: GlobalCrateId
{
139 disambiguator
: self.tcx
141 .local_crate_disambiguator()
145 crate_root
: crate_root
.unwrap_or("<no source>".to_owned()),
146 external_crates
: self.save_ctxt
.get_external_crates(),
147 span
: self.span_from_span(krate
.span
),
150 self.dumper
.crate_prelude(data
);
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
)> {
157 let segments
= &path
.segments
[if path
.is_global() { 1 }
else { 0 }
..];
159 let mut result
= Vec
::with_capacity(segments
.len());
161 let mut segs
= vec
![];
162 for (i
, seg
) in segments
.iter().enumerate() {
163 segs
.push(seg
.clone());
164 let sub_path
= ast
::Path
{
165 span
: seg
.span
, // span for the last segment
168 let qualname
= if i
== 0 && path
.is_global() {
169 format
!("::{}", path_to_string(&sub_path
))
171 path_to_string(&sub_path
)
173 result
.push((seg
.span
, qualname
));
174 segs
= sub_path
.segments
;
180 fn write_sub_paths(&mut self, path
: &ast
::Path
) {
181 let sub_paths
= self.process_path_prefixes(path
);
182 for (span
, _
) in sub_paths
{
183 let span
= self.span_from_span(span
);
184 self.dumper
.dump_ref(Ref
{
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.
194 fn write_sub_paths_truncated(&mut self, path
: &ast
::Path
) {
195 let sub_paths
= self.process_path_prefixes(path
);
196 let len
= sub_paths
.len();
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
{
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();
219 let sub_paths
= &sub_paths
[..(len
- 1)];
221 // write the trait part of the sub-path
222 let (ref span
, _
) = sub_paths
[len
- 2];
223 let span
= self.span_from_span(*span
);
224 self.dumper
.dump_ref(Ref
{
230 // write the other sub-paths
234 let sub_paths
= &sub_paths
[..len
- 2];
235 for &(ref span
, _
) in sub_paths
{
236 let span
= self.span_from_span(*span
);
237 self.dumper
.dump_ref(Ref
{
245 fn lookup_def_id(&self, ref_id
: NodeId
) -> Option
<DefId
> {
246 match self.save_ctxt
.get_path_def(ref_id
) {
247 HirDef
::PrimTy(..) | HirDef
::SelfTy(..) | HirDef
::Err
=> None
,
248 def
=> Some(def
.def_id()),
256 sub_span
: Option
<Span
>,
259 if self.span
.filter_generated(sub_span
, span
) {
263 let def
= self.save_ctxt
.get_path_def(ref_id
);
266 let span
= self.span_from_span(sub_span
.expect("No span found for mod ref"));
267 self.dumper
.dump_ref(Ref
{
270 ref_id
: ::id_from_def_id(def_id
),
274 HirDef
::Variant(..) |
277 HirDef
::TyAlias(..) |
278 HirDef
::TyForeign(..) |
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
{
284 ref_id
: ::id_from_def_id(def_id
),
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
,
295 ref_id
: ::id_from_def_id(def_id
),
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
,
303 ref_id
: ::id_from_def_id(def_id
),
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).
308 HirDef
::Macro(..) => {}
313 HirDef
::TyParam(..) |
315 HirDef
::AssociatedTy(..) |
316 HirDef
::AssociatedConst(..) |
318 HirDef
::GlobalAsm(_
) |
320 span_bug
!(span
, "process_def_kind for unexpected item: {:?}", def
);
325 fn process_formals(&mut self, formals
: &'l
[ast
::Arg
], qualname
: &str) {
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();
332 for (id
, i
, sp
, ..) in collector
.collected_idents
{
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
) {
335 Some(s
) => s
.to_string(),
338 let sub_span
= span_utils
.span_for_last_ident(sp
);
339 if !self.span
.filter_generated(sub_span
, sp
) {
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"));
343 self.dumper
.dump_def(
346 kind
: DefKind
::Local
,
350 qualname
: format
!("{}::{}", qualname
, i
.to_string()),
367 sig
: &'l ast
::MethodSig
,
368 body
: Option
<&'l ast
::Block
>,
371 generics
: &'l ast
::Generics
,
372 vis
: ast
::Visibility
,
375 debug
!("process_method: {}:{}", id
, name
);
377 if let Some(mut method_data
) = self.save_ctxt
.get_method_data(id
, name
.name
, span
) {
378 let sig_str
= ::make_signature(&sig
.decl
, &generics
);
382 |v
| v
.process_formals(&sig
.decl
.inputs
, &method_data
.qualname
),
386 self.process_generic_params(&generics
, span
, &method_data
.qualname
, id
);
388 method_data
.value
= sig_str
;
389 method_data
.sig
= sig
::method_signature(id
, name
, generics
, sig
, &self.save_ctxt
);
391 .dump_def(vis
== ast
::Visibility
::Public
, method_data
);
394 // walk arg and return types
395 for arg
in &sig
.decl
.inputs
{
396 self.visit_ty(&arg
.ty
);
399 if let ast
::FunctionRetTy
::Ty(ref ret_ty
) = sig
.decl
.output
{
400 self.visit_ty(ret_ty
);
404 if let Some(body
) = body
{
405 self.nest_tables(id
, |v
| v
.nest_scope(id
, |v
| v
.visit_block(body
)));
409 fn process_struct_field_def(&mut self, field
: &ast
::StructField
, parent_id
: NodeId
) {
410 let field_data
= self.save_ctxt
.get_field_data(field
, parent_id
);
411 if let Some(field_data
) = field_data
{
413 .dump_def(field
.vis
== ast
::Visibility
::Public
, field_data
);
417 // Dump generic params bindings, then visit_generics
418 fn process_generic_params(
420 generics
: &'l ast
::Generics
,
425 for param
in &generics
.ty_params
{
426 let param_ss
= param
.span
;
427 let name
= escape(self.span
.snippet(param_ss
));
428 // Append $id to name to make sure each one is unique
429 let qualname
= format
!("{}::{}${}", prefix
, name
, id
);
430 if !self.span
.filter_generated(Some(param_ss
), full_span
) {
431 let id
= ::id_from_node_id(param
.id
, &self.save_ctxt
);
432 let span
= self.span_from_span(param_ss
);
434 self.dumper
.dump_def(
442 value
: String
::new(),
453 self.visit_generics(generics
);
459 decl
: &'l ast
::FnDecl
,
460 ty_params
: &'l ast
::Generics
,
461 body
: &'l ast
::Block
,
463 if let Some(fn_data
) = self.save_ctxt
.get_item_data(item
) {
464 down_cast_data
!(fn_data
, DefData
, item
.span
);
467 |v
| v
.process_formals(&decl
.inputs
, &fn_data
.qualname
),
469 self.process_generic_params(ty_params
, item
.span
, &fn_data
.qualname
, item
.id
);
471 .dump_def(item
.vis
== ast
::Visibility
::Public
, fn_data
);
474 for arg
in &decl
.inputs
{
475 self.visit_ty(&arg
.ty
);
478 if let ast
::FunctionRetTy
::Ty(ref ret_ty
) = decl
.output
{
479 self.visit_ty(&ret_ty
);
482 self.nest_tables(item
.id
, |v
| v
.nest_scope(item
.id
, |v
| v
.visit_block(&body
)));
485 fn process_static_or_const_item(
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
);
495 .dump_def(item
.vis
== ast
::Visibility
::Public
, var_data
);
502 fn process_assoc_const(
508 expr
: Option
<&'l ast
::Expr
>,
510 vis
: ast
::Visibility
,
511 attrs
: &'l
[Attribute
],
513 let qualname
= format
!("::{}", self.tcx
.node_path_str(id
));
515 let sub_span
= self.span
.sub_span_after_keyword(span
, keywords
::Const
);
517 if !self.span
.filter_generated(sub_span
, span
) {
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"));
522 self.dumper
.dump_def(
523 vis
== ast
::Visibility
::Public
,
525 kind
: DefKind
::Const
,
528 name
: name
.to_string(),
530 value
: ty_to_string(&typ
),
531 parent
: Some(::id_from_def_id(parent_id
)),
534 docs
: self.save_ctxt
.docs_for_attrs(attrs
),
536 attributes
: lower_attributes(attrs
.to_owned(), &self.save_ctxt
),
541 // walk type and init value
543 if let Some(expr
) = expr
{
544 self.visit_expr(expr
);
548 // FIXME tuple structs should generate tuple-specific data.
552 def
: &'l ast
::VariantData
,
553 ty_params
: &'l ast
::Generics
,
555 debug
!("process_struct {:?} {:?}", item
, item
.span
);
556 let name
= item
.ident
.to_string();
557 let qualname
= format
!("::{}", self.tcx
.node_path_str(item
.id
));
559 let (kind
, keyword
) = match item
.node
{
560 ast
::ItemKind
::Struct(_
, _
) => (DefKind
::Struct
, keywords
::Struct
),
561 ast
::ItemKind
::Union(_
, _
) => (DefKind
::Union
, keywords
::Union
),
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
573 .filter_map(|(i
, f
)| {
574 if include_priv_fields
|| f
.vis
== ast
::Visibility
::Public
{
576 .map(|i
| i
.to_string())
577 .or_else(|| Some(i
.to_string()))
584 let value
= format
!("{} {{ {} }}", name
, fields_str
);
589 .map(|f
| ::id_from_node_id(f
.id
, &self.save_ctxt
))
593 _
=> (String
::new(), vec
![]),
596 if !self.span
.filter_generated(sub_span
, item
.span
) {
597 let span
= self.span_from_span(sub_span
.expect("No span found for struct"));
598 self.dumper
.dump_def(
599 item
.vis
== ast
::Visibility
::Public
,
602 id
: ::id_from_node_id(item
.id
, &self.save_ctxt
),
605 qualname
: qualname
.clone(),
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
),
617 for field
in def
.fields() {
618 self.process_struct_field_def(field
, item
.id
);
619 self.visit_ty(&field
.ty
);
622 self.process_generic_params(ty_params
, item
.span
, &qualname
, item
.id
);
628 enum_definition
: &'l ast
::EnumDef
,
629 ty_params
: &'l ast
::Generics
,
631 let enum_data
= self.save_ctxt
.get_item_data(item
);
632 let enum_data
= match enum_data
{
636 down_cast_data
!(enum_data
, DefData
, item
.span
);
638 for variant
in &enum_definition
.variants
{
639 let name
= variant
.node
.name
.name
.to_string();
640 let mut qualname
= enum_data
.qualname
.clone();
641 qualname
.push_str("::");
642 qualname
.push_str(&name
);
644 match variant
.node
.data
{
645 ast
::VariantData
::Struct(ref fields
, _
) => {
646 let sub_span
= self.span
.span_for_first_ident(variant
.span
);
647 let fields_str
= fields
651 f
.ident
.map(|i
| i
.to_string()).unwrap_or(i
.to_string())
655 let value
= format
!("{}::{} {{ {} }}", enum_data
.name
, name
, fields_str
);
656 if !self.span
.filter_generated(sub_span
, variant
.span
) {
658 .span_from_span(sub_span
.expect("No span found for struct variant"));
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
));
662 self.dumper
.dump_def(
663 item
.vis
== ast
::Visibility
::Public
,
665 kind
: DefKind
::StructVariant
,
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(),
685 let sub_span
= self.span
.span_for_first_ident(variant
.span
);
686 let mut value
= format
!("{}::{}", enum_data
.name
, name
);
687 if let &ast
::VariantData
::Tuple(ref fields
, _
) = v
{
689 value
.push_str(&fields
691 .map(|f
| ty_to_string(&f
.ty
))
696 if !self.span
.filter_generated(sub_span
, variant
.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
));
702 self.dumper
.dump_def(
703 item
.vis
== ast
::Visibility
::Public
,
705 kind
: DefKind
::TupleVariant
,
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(),
727 for field
in variant
.node
.data
.fields() {
728 self.process_struct_field_def(field
, variant
.node
.data
.id());
729 self.visit_ty(&field
.ty
);
732 self.process_generic_params(ty_params
, item
.span
, &enum_data
.qualname
, item
.id
);
734 .dump_def(item
.vis
== ast
::Visibility
::Public
, enum_data
);
740 type_parameters
: &'l ast
::Generics
,
741 trait_ref
: &'l Option
<ast
::TraitRef
>,
743 impl_items
: &'l
[ast
::ImplItem
],
745 if let Some(impl_data
) = self.save_ctxt
.get_item_data(item
) {
746 down_cast_data
!(impl_data
, RelationData
, item
.span
);
747 self.dumper
.dump_relation(impl_data
);
750 if let &Some(ref trait_ref
) = trait_ref
{
751 self.process_path(trait_ref
.ref_id
, &trait_ref
.path
);
753 self.process_generic_params(type_parameters
, item
.span
, "", item
.id
);
754 for impl_item
in impl_items
{
755 let map
= &self.tcx
.hir
;
756 self.process_impl_item(impl_item
, map
.local_def_id(item
.id
));
763 generics
: &'l ast
::Generics
,
764 trait_refs
: &'l ast
::TyParamBounds
,
765 methods
: &'l
[ast
::TraitItem
],
767 let name
= item
.ident
.to_string();
768 let qualname
= format
!("::{}", self.tcx
.node_path_str(item
.id
));
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
));
773 if !trait_refs
.is_empty() {
775 val
.push_str(&bounds_to_string(trait_refs
));
777 let sub_span
= self.span
.sub_span_after_keyword(item
.span
, keywords
::Trait
);
778 if !self.span
.filter_generated(sub_span
, item
.span
) {
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"));
781 let children
= methods
783 .map(|i
| ::id_from_node_id(i
.id
, &self.save_ctxt
))
785 self.dumper
.dump_def(
786 item
.vis
== ast
::Visibility
::Public
,
788 kind
: DefKind
::Trait
,
792 qualname
: qualname
.clone(),
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
),
805 for super_bound
in trait_refs
.iter() {
806 let trait_ref
= match *super_bound
{
807 ast
::TraitTyParamBound(ref trait_ref
, _
) => trait_ref
,
808 ast
::RegionTyParamBound(..) => {
813 let trait_ref
= &trait_ref
.trait_ref
;
814 if let Some(id
) = self.lookup_def_id(trait_ref
.ref_id
) {
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
) {
817 let span
= self.span_from_span(sub_span
.expect("No span found for trait ref"));
818 self.dumper
.dump_ref(Ref
{
821 ref_id
: ::id_from_def_id(id
),
825 if !self.span
.filter_generated(sub_span
, trait_ref
.path
.span
) {
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
,
830 from
: ::id_from_def_id(id
),
831 to
: ::id_from_node_id(item
.id
, &self.save_ctxt
),
837 // walk generics and methods
838 self.process_generic_params(generics
, item
.span
, &qualname
, item
.id
);
839 for method
in methods
{
840 let map
= &self.tcx
.hir
;
841 self.process_trait_item(method
, map
.local_def_id(item
.id
))
845 // `item` is the module in question, represented as an item.
846 fn process_mod(&mut self, item
: &ast
::Item
) {
847 if let Some(mod_data
) = self.save_ctxt
.get_item_data(item
) {
848 down_cast_data
!(mod_data
, DefData
, item
.span
);
850 .dump_def(item
.vis
== ast
::Visibility
::Public
, mod_data
);
854 fn dump_path_ref(&mut self, id
: NodeId
, path
: &ast
::Path
) {
855 let path_data
= self.save_ctxt
.get_path_data(id
, path
);
856 if let Some(path_data
) = path_data
{
857 self.dumper
.dump_ref(path_data
);
861 fn process_path(&mut self, id
: NodeId
, path
: &'l ast
::Path
) {
862 debug
!("process_path {:?}", path
);
863 if generated_code(path
.span
) {
866 self.dump_path_ref(id
, path
);
869 for seg
in &path
.segments
{
870 if let Some(ref params
) = seg
.parameters
{
872 ast
::PathParameters
::AngleBracketed(ref data
) => for t
in &data
.types
{
875 ast
::PathParameters
::Parenthesized(ref data
) => {
876 for t
in &data
.inputs
{
879 if let Some(ref t
) = data
.output
{
887 // Modules or types in the path prefix.
888 match self.save_ctxt
.get_path_def(id
) {
889 HirDef
::Method(did
) => {
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
);
898 HirDef
::StructCtor(..) |
899 HirDef
::VariantCtor(..) |
900 HirDef
::AssociatedConst(..) |
905 HirDef
::Variant(..) |
906 HirDef
::TyAlias(..) |
907 HirDef
::AssociatedTy(..) => self.write_sub_paths_truncated(path
),
912 fn process_struct_lit(
916 fields
: &'l
[ast
::Field
],
917 variant
: &'l ty
::VariantDef
,
918 base
: &'l Option
<P
<ast
::Expr
>>,
920 self.write_sub_paths_truncated(path
);
922 if let Some(struct_lit_data
) = self.save_ctxt
.get_expr_data(ex
) {
923 down_cast_data
!(struct_lit_data
, RefData
, ex
.span
);
924 if !generated_code(ex
.span
) {
925 self.dumper
.dump_ref(struct_lit_data
);
928 for field
in fields
{
929 if let Some(field_data
) = self.save_ctxt
.get_field_ref_data(field
, variant
) {
930 self.dumper
.dump_ref(field_data
);
933 self.visit_expr(&field
.expr
)
937 walk_list
!(self, visit_expr
, base
);
940 fn process_method_call(
943 seg
: &'l ast
::PathSegment
,
944 args
: &'l
[P
<ast
::Expr
>],
946 debug
!("process_method_call {:?} {:?}", ex
, ex
.span
);
947 if let Some(mcd
) = self.save_ctxt
.get_expr_data(ex
) {
948 down_cast_data
!(mcd
, RefData
, ex
.span
);
949 if !generated_code(ex
.span
) {
950 self.dumper
.dump_ref(mcd
);
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
{
963 // walk receiver and args
964 walk_list
!(self, visit_expr
, args
);
967 fn process_pat(&mut self, p
: &'l ast
::Pat
) {
969 PatKind
::Struct(ref _path
, ref fields
, _
) => {
970 // FIXME do something with _path?
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
) {
973 Some(ty
) => ty
.ty_adt_def().unwrap(),
975 visit
::walk_pat(self, p
);
979 let variant
= adt
.variant_of_def(self.save_ctxt
.get_path_def(p
.id
));
986 let sub_span
= self.span
.span_for_first_ident(span
);
987 if let Some(f
) = variant
.find_field_named(field
.ident
.name
) {
988 if !self.span
.filter_generated(sub_span
, 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
,
994 ref_id
: ::id_from_def_id(f
.did
),
998 self.visit_pat(&field
.pat
);
1001 _
=> visit
::walk_pat(self, p
),
1006 fn process_var_decl(&mut self, p
: &'l ast
::Pat
, value
: String
) {
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
);
1013 for (id
, i
, sp
, immut
) in collector
.collected_idents
{
1014 let mut value
= match immut
{
1015 ast
::Mutability
::Immutable
=> value
.to_string(),
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
) {
1021 let typ
= typ
.to_string();
1022 if !value
.is_empty() {
1023 value
.push_str(": ");
1025 value
.push_str(&typ
);
1028 None
=> String
::new(),
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?).
1033 let sub_span
= self.span
.span_for_last_ident(sp
);
1034 // Rust uses the id of the pattern for var lookups, so we'll use it too.
1035 if !self.span
.filter_generated(sub_span
, sp
) {
1036 let qualname
= format
!("{}${}", i
.to_string(), id
);
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"));
1040 self.dumper
.dump_def(
1043 kind
: DefKind
::Local
,
1046 name
: i
.to_string(),
1052 docs
: String
::new(),
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
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.
1068 fn process_macro_use(&mut self, span
: Span
) {
1069 let source_span
= span
.source_callsite();
1070 if self.macro_calls
.contains(&source_span
) {
1073 self.macro_calls
.insert(source_span
);
1075 let data
= match self.save_ctxt
.get_macro_use_data(span
) {
1080 self.dumper
.macro_use(data
);
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);
1087 // Don't write macro definition for imported macros
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 {
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));
1103 fn process_trait_item(&mut self, trait_item
: &'l ast
::TraitItem
, trait_id
: DefId
) {
1104 self.process_macro_use(trait_item
.span
);
1105 match trait_item
.node
{
1106 ast
::TraitItemKind
::Const(ref ty
, ref expr
) => {
1107 self.process_assoc_const(
1109 trait_item
.ident
.name
,
1112 expr
.as_ref().map(|e
| &**e
),
1114 ast
::Visibility
::Public
,
1118 ast
::TraitItemKind
::Method(ref sig
, ref body
) => {
1119 self.process_method(
1121 body
.as_ref().map(|x
| &**x
),
1124 &trait_item
.generics
,
1125 ast
::Visibility
::Public
,
1129 ast
::TraitItemKind
::Type(ref bounds
, ref default_ty
) => {
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
));
1133 let sub_span
= self.span
1134 .sub_span_after_keyword(trait_item
.span
, keywords
::Type
);
1136 if !self.span
.filter_generated(sub_span
, trait_item
.span
) {
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
);
1140 self.dumper
.dump_def(
1143 kind
: DefKind
::Type
,
1148 value
: self.span
.snippet(trait_item
.span
),
1149 parent
: Some(::id_from_def_id(trait_id
)),
1152 docs
: self.save_ctxt
.docs_for_attrs(&trait_item
.attrs
),
1153 sig
: sig
::assoc_type_signature(
1157 default_ty
.as_ref().map(|ty
| &**ty
),
1160 attributes
: lower_attributes(trait_item
.attrs
.clone(), &self.save_ctxt
),
1165 if let &Some(ref default_ty
) = default_ty
{
1166 self.visit_ty(default_ty
)
1169 ast
::TraitItemKind
::Macro(_
) => {}
1173 fn process_impl_item(&mut self, impl_item
: &'l ast
::ImplItem
, impl_id
: DefId
) {
1174 self.process_macro_use(impl_item
.span
);
1175 match impl_item
.node
{
1176 ast
::ImplItemKind
::Const(ref ty
, ref expr
) => {
1177 self.process_assoc_const(
1179 impl_item
.ident
.name
,
1184 impl_item
.vis
.clone(),
1188 ast
::ImplItemKind
::Method(ref sig
, ref body
) => {
1189 self.process_method(
1194 &impl_item
.generics
,
1195 impl_item
.vis
.clone(),
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
1205 ast
::ImplItemKind
::Macro(_
) => {}
1210 impl<'l
, 'tcx
: 'l
, 'll
, O
: DumpOutput
+ 'll
> Visitor
<'l
> for DumpVisitor
<'l
, 'tcx
, 'll
, O
> {
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
);
1216 let qualname
= format
!("::{}", self.tcx
.node_path_str(id
));
1218 let cm
= self.tcx
.sess
.codemap();
1219 let filename
= cm
.span_to_filename(span
);
1220 let data_id
= ::id_from_node_id(id
, &self.save_ctxt
);
1221 let children
= m
.items
1223 .map(|i
| ::id_from_node_id(i
.id
, &self.save_ctxt
))
1225 let span
= self.span_from_span(span
);
1227 self.dumper
.dump_def(
1232 name
: String
::new(),
1239 docs
: self.save_ctxt
.docs_for_attrs(attrs
),
1241 attributes
: lower_attributes(attrs
.to_owned(), &self.save_ctxt
),
1244 self.nest_scope(id
, |v
| visit
::walk_mod(v
, m
));
1247 fn visit_item(&mut self, item
: &'l ast
::Item
) {
1248 use syntax
::ast
::ItemKind
::*;
1249 self.process_macro_use(item
.span
);
1251 Use(ref use_item
) => {
1252 match use_item
.node
{
1253 ast
::ViewPathSimple(ident
, ref path
) => {
1254 let sub_span
= self.span
.span_for_last_ident(path
.span
);
1255 let mod_id
= match self.lookup_def_id(item
.id
) {
1257 self.process_def_kind(item
.id
, path
.span
, sub_span
, def_id
);
1263 // 'use' always introduces an alias, if there is not an explicit
1264 // one, there is an implicit one.
1265 let sub_span
= match self.span
1266 .sub_span_after_keyword(use_item
.span
, keywords
::As
)
1268 Some(sub_span
) => Some(sub_span
),
1272 if !self.span
.filter_generated(sub_span
, path
.span
) {
1274 self.span_from_span(sub_span
.expect("No span found for use"));
1276 item
.vis
== ast
::Visibility
::Public
,
1278 kind
: ImportKind
::Use
,
1279 ref_id
: mod_id
.map(|id
| ::id_from_def_id(id
)),
1281 name
: ident
.to_string(),
1282 value
: String
::new(),
1286 self.write_sub_paths_truncated(path
);
1288 ast
::ViewPathGlob(ref path
) => {
1289 // Make a comma-separated list of names of imported modules.
1290 let mut names
= vec
![];
1291 let glob_map
= &self.save_ctxt
.analysis
.glob_map
;
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() {
1295 names
.push(n
.to_string());
1299 let sub_span
= self.span
1300 .sub_span_of_token(item
.span
, token
::BinOp(token
::Star
));
1301 if !self.span
.filter_generated(sub_span
, item
.span
) {
1303 self.span_from_span(sub_span
.expect("No span found for use glob"));
1305 item
.vis
== ast
::Visibility
::Public
,
1307 kind
: ImportKind
::GlobUse
,
1310 name
: "*".to_owned(),
1311 value
: names
.join(", "),
1315 self.write_sub_paths(path
);
1317 ast
::ViewPathList(ref path
, ref list
) => {
1319 let id
= plid
.node
.id
;
1320 if let Some(def_id
) = self.lookup_def_id(id
) {
1321 let span
= plid
.span
;
1322 self.process_def_kind(id
, span
, Some(span
), def_id
);
1326 self.write_sub_paths(path
);
1331 let alias_span
= self.span
.span_for_last_ident(item
.span
);
1333 if !self.span
.filter_generated(alias_span
, item
.span
) {
1335 self.span_from_span(alias_span
.expect("No span found for extern crate"));
1339 kind
: ImportKind
::ExternCrate
,
1342 name
: item
.ident
.to_string(),
1343 value
: String
::new(),
1348 Fn(ref decl
, .., ref ty_params
, ref body
) => {
1349 self.process_fn(item
, &decl
, ty_params
, &body
)
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
)
1356 Enum(ref def
, ref ty_params
) => self.process_enum(item
, def
, ty_params
),
1357 Impl(.., ref ty_params
, ref trait_ref
, ref typ
, ref impl_items
) => {
1358 self.process_impl(item
, ty_params
, trait_ref
, &typ
, impl_items
)
1360 Trait(_
, _
, ref generics
, ref trait_refs
, ref methods
) => {
1361 self.process_trait(item
, generics
, trait_refs
, methods
)
1364 self.process_mod(item
);
1365 self.nest_scope(item
.id
, |v
| visit
::walk_mod(v
, m
));
1367 Ty(ref ty
, ref ty_params
) => {
1368 let qualname
= format
!("::{}", self.tcx
.node_path_str(item
.id
));
1369 let value
= ty_to_string(&ty
);
1370 let sub_span
= self.span
.sub_span_after_keyword(item
.span
, keywords
::Type
);
1371 if !self.span
.filter_generated(sub_span
, item
.span
) {
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
);
1375 self.dumper
.dump_def(
1376 item
.vis
== ast
::Visibility
::Public
,
1378 kind
: DefKind
::Type
,
1381 name
: item
.ident
.to_string(),
1382 qualname
: qualname
.clone(),
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
),
1395 self.process_generic_params(ty_params
, item
.span
, &qualname
, item
.id
);
1398 _
=> visit
::walk_item(self, item
),
1402 fn visit_generics(&mut self, generics
: &'l ast
::Generics
) {
1403 for param
in generics
.ty_params
.iter() {
1404 for bound
in param
.bounds
.iter() {
1405 if let ast
::TraitTyParamBound(ref trait_ref
, _
) = *bound
{
1406 self.process_path(trait_ref
.trait_ref
.ref_id
, &trait_ref
.trait_ref
.path
)
1409 if let Some(ref ty
) = param
.default {
1415 fn visit_ty(&mut self, t
: &'l ast
::Ty
) {
1416 self.process_macro_use(t
.span
);
1418 ast
::TyKind
::Path(_
, ref path
) => {
1419 if generated_code(t
.span
) {
1423 if let Some(id
) = self.lookup_def_id(t
.id
) {
1424 if let Some(sub_span
) = self.span
.sub_span_for_type_name(t
.span
) {
1425 let span
= self.span_from_span(sub_span
);
1426 self.dumper
.dump_ref(Ref
{
1427 kind
: RefKind
::Type
,
1429 ref_id
: ::id_from_def_id(id
),
1434 self.write_sub_paths_truncated(path
);
1435 visit
::walk_path(self, path
);
1437 ast
::TyKind
::Array(ref element
, ref length
) => {
1438 self.visit_ty(element
);
1439 self.nest_tables(length
.id
, |v
| v
.visit_expr(length
));
1441 _
=> visit
::walk_ty(self, t
),
1445 fn visit_expr(&mut self, ex
: &'l ast
::Expr
) {
1446 debug
!("visit_expr {:?}", ex
.node
);
1447 self.process_macro_use(ex
.span
);
1449 ast
::ExprKind
::Struct(ref path
, ref fields
, ref base
) => {
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
) {
1452 Some(ty
) if ty
.ty_adt_def().is_some() => ty
.ty_adt_def().unwrap(),
1454 visit
::walk_expr(self, ex
);
1458 let def
= self.save_ctxt
.get_path_def(hir_expr
.id
);
1459 self.process_struct_lit(ex
, path
, fields
, adt
.variant_of_def(def
), base
)
1461 ast
::ExprKind
::MethodCall(ref seg
, ref args
) => self.process_method_call(ex
, seg
, args
),
1462 ast
::ExprKind
::Field(ref sub_ex
, _
) => {
1463 self.visit_expr(&sub_ex
);
1465 if let Some(field_data
) = self.save_ctxt
.get_expr_data(ex
) {
1466 down_cast_data
!(field_data
, RefData
, ex
.span
);
1467 if !generated_code(ex
.span
) {
1468 self.dumper
.dump_ref(field_data
);
1472 ast
::ExprKind
::TupField(ref sub_ex
, idx
) => {
1473 self.visit_expr(&sub_ex
);
1475 let hir_node
= match self.save_ctxt
.tcx
.hir
.find(sub_ex
.id
) {
1476 Some(Node
::NodeExpr(expr
)) => expr
,
1479 "Missing or weird node for sub-expression {} in {:?}",
1486 let ty
= match self.save_ctxt
.tables
.expr_ty_adjusted_opt(&hir_node
) {
1487 Some(ty
) => &ty
.sty
,
1489 visit
::walk_expr(self, ex
);
1494 ty
::TyAdt(def
, _
) => {
1495 let sub_span
= self.span
.sub_span_after_token(ex
.span
, token
::Dot
);
1496 if !self.span
.filter_generated(sub_span
, ex
.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
,
1502 ref_id
: ::id_from_def_id(def
.struct_variant().fields
[idx
.node
].did
),
1506 ty
::TyTuple(..) => {}
1507 _
=> span_bug
!(ex
.span
, "Expected struct or tuple type, found {:?}", ty
),
1510 ast
::ExprKind
::Closure(_
, ref decl
, ref body
, _fn_decl_span
) => {
1511 let mut id
= String
::from("$");
1512 id
.push_str(&ex
.id
.to_string());
1514 // walk arg and return types
1515 for arg
in &decl
.inputs
{
1516 self.visit_ty(&arg
.ty
);
1519 if let ast
::FunctionRetTy
::Ty(ref ret_ty
) = decl
.output
{
1520 self.visit_ty(&ret_ty
);
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
))
1529 ast
::ExprKind
::ForLoop(ref pattern
, ref subexpression
, ref block
, _
) |
1530 ast
::ExprKind
::WhileLet(ref pattern
, ref subexpression
, ref block
, _
) => {
1531 let value
= self.span
.snippet(subexpression
.span
);
1532 self.process_var_decl(pattern
, value
);
1533 debug
!("for loop, walk sub-expr: {:?}", subexpression
.node
);
1534 self.visit_expr(subexpression
);
1535 visit
::walk_block(self, block
);
1537 ast
::ExprKind
::IfLet(ref pattern
, ref subexpression
, ref block
, ref opt_else
) => {
1538 let value
= self.span
.snippet(subexpression
.span
);
1539 self.process_var_decl(pattern
, value
);
1540 self.visit_expr(subexpression
);
1541 visit
::walk_block(self, block
);
1542 opt_else
.as_ref().map(|el
| self.visit_expr(el
));
1544 ast
::ExprKind
::Repeat(ref element
, ref count
) => {
1545 self.visit_expr(element
);
1546 self.nest_tables(count
.id
, |v
| v
.visit_expr(count
));
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.
1550 _
=> visit
::walk_expr(self, ex
),
1554 fn visit_mac(&mut self, mac
: &'l ast
::Mac
) {
1555 // These shouldn't exist in the AST at this point, log a span bug.
1558 "macro invocation should have been expanded out of AST"
1562 fn visit_pat(&mut self, p
: &'l ast
::Pat
) {
1563 self.process_macro_use(p
.span
);
1564 self.process_pat(p
);
1567 fn visit_arm(&mut self, arm
: &'l ast
::Arm
) {
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
);
1575 // process collected paths
1576 for (id
, i
, sp
, immut
) in collector
.collected_idents
{
1577 match self.save_ctxt
.get_path_def(id
) {
1578 HirDef
::Local(id
) => {
1579 let mut value
= if immut
== ast
::Mutability
::Immutable
{
1580 self.span
.snippet(sp
).to_string()
1582 "<mutable>".to_string()
1584 let hir_id
= self.tcx
.hir
.node_to_hir_id(id
);
1585 let typ
= self.save_ctxt
1587 .node_id_to_type_opt(hir_id
)
1588 .map(|t
| t
.to_string())
1589 .unwrap_or(String
::new());
1590 value
.push_str(": ");
1591 value
.push_str(&typ
);
1593 if !self.span
.filter_generated(Some(sp
), sp
) {
1594 let qualname
= format
!("{}${}", i
.to_string(), id
);
1595 let id
= ::id_from_node_id(id
, &self.save_ctxt
);
1596 let span
= self.span_from_span(sp
);
1598 self.dumper
.dump_def(
1601 kind
: DefKind
::Local
,
1604 name
: i
.to_string(),
1610 docs
: String
::new(),
1617 HirDef
::StructCtor(..) |
1618 HirDef
::VariantCtor(..) |
1620 HirDef
::AssociatedConst(..) |
1621 HirDef
::Struct(..) |
1622 HirDef
::Variant(..) |
1623 HirDef
::TyAlias(..) |
1624 HirDef
::AssociatedTy(..) |
1625 HirDef
::SelfTy(..) => {
1626 self.dump_path_ref(id
, &ast
::Path
::from_ident(sp
, i
));
1629 "unexpected definition kind when processing collected idents: {:?}",
1635 for (id
, ref path
) in collector
.collected_paths
{
1636 self.process_path(id
, path
);
1638 walk_list
!(self, visit_expr
, &arm
.guard
);
1639 self.visit_expr(&arm
.body
);
1642 fn visit_path(&mut self, p
: &'l ast
::Path
, id
: NodeId
) {
1643 self.process_path(id
, p
);
1646 fn visit_stmt(&mut self, s
: &'l ast
::Stmt
) {
1647 self.process_macro_use(s
.span
);
1648 visit
::walk_stmt(self, s
)
1651 fn visit_local(&mut self, l
: &'l ast
::Local
) {
1652 self.process_macro_use(l
.span
);
1655 .map(|i
| self.span
.snippet(i
.span
))
1656 .unwrap_or(String
::new());
1657 self.process_var_decl(&l
.pat
, value
);
1659 // Just walk the initialiser and type (don't want to walk the pattern again).
1660 walk_list
!(self, visit_ty
, &l
.ty
);
1661 walk_list
!(self, visit_expr
, &l
.init
);
1664 fn visit_foreign_item(&mut self, item
: &'l ast
::ForeignItem
) {
1666 ast
::ForeignItemKind
::Fn(ref decl
, ref generics
) => {
1667 if let Some(fn_data
) = self.save_ctxt
.get_extern_item_data(item
) {
1668 down_cast_data
!(fn_data
, DefData
, item
.span
);
1672 |v
| v
.process_formals(&decl
.inputs
, &fn_data
.qualname
),
1674 self.process_generic_params(generics
, item
.span
, &fn_data
.qualname
, item
.id
);
1676 .dump_def(item
.vis
== ast
::Visibility
::Public
, fn_data
);
1679 for arg
in &decl
.inputs
{
1680 self.visit_ty(&arg
.ty
);
1683 if let ast
::FunctionRetTy
::Ty(ref ret_ty
) = decl
.output
{
1684 self.visit_ty(&ret_ty
);
1687 ast
::ForeignItemKind
::Static(ref ty
, _
) => {
1688 if let Some(var_data
) = self.save_ctxt
.get_extern_item_data(item
) {
1689 down_cast_data
!(var_data
, DefData
, item
.span
);
1691 .dump_def(item
.vis
== ast
::Visibility
::Public
, var_data
);
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
);
1700 .dump_def(item
.vis
== ast
::Visibility
::Public
, var_data
);