]>
git.proxmox.com Git - rustc.git/blob - src/librustc/hir/map/collector.rs
1 // Copyright 2015-2016 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.
12 use super::MapEntry
::*;
15 use hir
::intravisit
::Visitor
;
16 use hir
::def_id
::DefId
;
17 use middle
::cstore
::InlinedItem
;
18 use std
::iter
::repeat
;
19 use syntax
::ast
::{NodeId, CRATE_NODE_ID}
;
20 use syntax
::codemap
::Span
;
22 /// A Visitor that walks over the HIR and collects Nodes into a HIR map
23 pub struct NodeCollector
<'ast
> {
25 pub krate
: &'ast Crate
,
27 pub map
: Vec
<MapEntry
<'ast
>>,
28 /// The parent of this node
29 pub parent_node
: NodeId
,
32 impl<'ast
> NodeCollector
<'ast
> {
33 pub fn root(krate
: &'ast Crate
) -> NodeCollector
<'ast
> {
34 let mut collector
= NodeCollector
{
37 parent_node
: CRATE_NODE_ID
,
39 collector
.insert_entry(CRATE_NODE_ID
, RootCrate
);
44 pub fn extend(krate
: &'ast Crate
,
45 parent
: &'ast InlinedItem
,
47 parent_def_path
: DefPath
,
49 map
: Vec
<MapEntry
<'ast
>>)
50 -> NodeCollector
<'ast
> {
51 let mut collector
= NodeCollector
{
54 parent_node
: parent_node
,
57 assert_eq
!(parent_def_path
.krate
, parent_def_id
.krate
);
58 collector
.insert_entry(parent_node
, RootInlinedParent(parent
));
63 fn insert_entry(&mut self, id
: NodeId
, entry
: MapEntry
<'ast
>) {
64 debug
!("ast_map: {:?} => {:?}", id
, entry
);
65 let len
= self.map
.len();
66 if id
as usize >= len
{
67 self.map
.extend(repeat(NotPresent
).take(id
as usize - len
+ 1));
69 self.map
[id
as usize] = entry
;
72 fn insert(&mut self, id
: NodeId
, node
: Node
<'ast
>) {
73 let entry
= MapEntry
::from_node(self.parent_node
, node
);
74 self.insert_entry(id
, entry
);
77 fn with_parent
<F
: FnOnce(&mut Self)>(&mut self, parent_id
: NodeId
, f
: F
) {
78 let parent_node
= self.parent_node
;
79 self.parent_node
= parent_id
;
81 self.parent_node
= parent_node
;
85 impl<'ast
> Visitor
<'ast
> for NodeCollector
<'ast
> {
86 /// Because we want to track parent items and so forth, enable
87 /// deep walking so that we walk nested items in the context of
88 /// their outer items.
89 fn visit_nested_item(&mut self, item
: ItemId
) {
90 debug
!("visit_nested_item: {:?}", item
);
91 self.visit_item(self.krate
.item(item
.id
))
94 fn visit_item(&mut self, i
: &'ast Item
) {
95 debug
!("visit_item: {:?}", i
);
97 self.insert(i
.id
, NodeItem(i
));
99 self.with_parent(i
.id
, |this
| {
101 ItemEnum(ref enum_definition
, _
) => {
102 for v
in &enum_definition
.variants
{
103 this
.insert(v
.node
.data
.id(), NodeVariant(v
));
106 ItemStruct(ref struct_def
, _
) => {
107 // If this is a tuple-like struct, register the constructor.
108 if !struct_def
.is_struct() {
109 this
.insert(struct_def
.id(), NodeStructCtor(struct_def
));
112 ItemTrait(_
, _
, ref bounds
, _
) => {
113 for b
in bounds
.iter() {
114 if let TraitTyParamBound(ref t
, TraitBoundModifier
::None
) = *b
{
115 this
.insert(t
.trait_ref
.ref_id
, NodeItem(i
));
119 ItemUse(ref view_path
) => {
120 match view_path
.node
{
121 ViewPathList(_
, ref paths
) => {
123 this
.insert(path
.node
.id(), NodeItem(i
));
131 intravisit
::walk_item(this
, i
);
135 fn visit_foreign_item(&mut self, foreign_item
: &'ast ForeignItem
) {
136 self.insert(foreign_item
.id
, NodeForeignItem(foreign_item
));
138 self.with_parent(foreign_item
.id
, |this
| {
139 intravisit
::walk_foreign_item(this
, foreign_item
);
143 fn visit_generics(&mut self, generics
: &'ast Generics
) {
144 for ty_param
in generics
.ty_params
.iter() {
145 self.insert(ty_param
.id
, NodeTyParam(ty_param
));
148 intravisit
::walk_generics(self, generics
);
151 fn visit_trait_item(&mut self, ti
: &'ast TraitItem
) {
152 self.insert(ti
.id
, NodeTraitItem(ti
));
154 self.with_parent(ti
.id
, |this
| {
155 intravisit
::walk_trait_item(this
, ti
);
159 fn visit_impl_item(&mut self, ii
: &'ast ImplItem
) {
160 self.insert(ii
.id
, NodeImplItem(ii
));
162 self.with_parent(ii
.id
, |this
| {
163 intravisit
::walk_impl_item(this
, ii
);
167 fn visit_pat(&mut self, pat
: &'ast Pat
) {
168 let node
= if let PatKind
::Ident(..) = pat
.node
{
173 self.insert(pat
.id
, node
);
175 self.with_parent(pat
.id
, |this
| {
176 intravisit
::walk_pat(this
, pat
);
180 fn visit_expr(&mut self, expr
: &'ast Expr
) {
181 self.insert(expr
.id
, NodeExpr(expr
));
183 self.with_parent(expr
.id
, |this
| {
184 intravisit
::walk_expr(this
, expr
);
188 fn visit_stmt(&mut self, stmt
: &'ast Stmt
) {
189 let id
= stmt
.node
.id();
190 self.insert(id
, NodeStmt(stmt
));
192 self.with_parent(id
, |this
| {
193 intravisit
::walk_stmt(this
, stmt
);
197 fn visit_fn(&mut self, fk
: intravisit
::FnKind
<'ast
>, fd
: &'ast FnDecl
,
198 b
: &'ast Block
, s
: Span
, id
: NodeId
) {
199 assert_eq
!(self.parent_node
, id
);
200 intravisit
::walk_fn(self, fk
, fd
, b
, s
);
203 fn visit_block(&mut self, block
: &'ast Block
) {
204 self.insert(block
.id
, NodeBlock(block
));
205 self.with_parent(block
.id
, |this
| {
206 intravisit
::walk_block(this
, block
);
210 fn visit_lifetime(&mut self, lifetime
: &'ast Lifetime
) {
211 self.insert(lifetime
.id
, NodeLifetime(lifetime
));