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.
12 use super::MapEntry
::*;
15 use hir
::intravisit
::Visitor
;
16 use hir
::def_id
::{CRATE_DEF_INDEX, DefId, DefIndex}
;
17 use middle
::cstore
::InlinedItem
;
18 use std
::iter
::repeat
;
19 use syntax
::ast
::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID}
;
20 use syntax
::codemap
::Span
;
22 /// A Visitor that walks over an AST and collects Node's into an AST
24 pub struct NodeCollector
<'ast
> {
25 pub krate
: &'ast Crate
,
26 pub map
: Vec
<MapEntry
<'ast
>>,
27 pub definitions
: Definitions
,
28 pub parent_node
: NodeId
,
31 impl<'ast
> NodeCollector
<'ast
> {
32 pub fn root(krate
: &'ast Crate
) -> NodeCollector
<'ast
> {
33 let mut collector
= NodeCollector
{
36 definitions
: Definitions
::new(),
37 parent_node
: CRATE_NODE_ID
,
39 collector
.insert_entry(CRATE_NODE_ID
, RootCrate
);
41 let result
= collector
.create_def_with_parent(None
, CRATE_NODE_ID
, DefPathData
::CrateRoot
);
42 assert_eq
!(result
, CRATE_DEF_INDEX
);
44 collector
.create_def_with_parent(Some(CRATE_DEF_INDEX
), DUMMY_NODE_ID
, DefPathData
::Misc
);
49 pub fn extend(krate
: &'ast Crate
,
50 parent
: &'ast InlinedItem
,
52 parent_def_path
: DefPath
,
54 map
: Vec
<MapEntry
<'ast
>>,
55 definitions
: Definitions
)
56 -> NodeCollector
<'ast
> {
57 let mut collector
= NodeCollector
{
60 parent_node
: parent_node
,
61 definitions
: definitions
,
64 assert_eq
!(parent_def_path
.krate
, parent_def_id
.krate
);
65 let root_path
= Box
::new(InlinedRootPath
{
66 data
: parent_def_path
.data
,
67 def_id
: parent_def_id
,
70 collector
.insert_entry(parent_node
, RootInlinedParent(parent
));
71 collector
.create_def(parent_node
, DefPathData
::InlinedRoot(root_path
));
76 fn parent_def(&self) -> Option
<DefIndex
> {
77 let mut parent_node
= Some(self.parent_node
);
78 while let Some(p
) = parent_node
{
79 if let Some(q
) = self.definitions
.opt_def_index(p
) {
82 parent_node
= self.map
[p
as usize].parent_node();
87 fn create_def(&mut self, node_id
: NodeId
, data
: DefPathData
) -> DefIndex
{
88 let parent_def
= self.parent_def();
89 debug
!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id
, data
, parent_def
);
90 self.definitions
.create_def_with_parent(parent_def
, node_id
, data
)
93 fn create_def_with_parent(&mut self,
94 parent
: Option
<DefIndex
>,
98 self.definitions
.create_def_with_parent(parent
, node_id
, data
)
101 fn insert_entry(&mut self, id
: NodeId
, entry
: MapEntry
<'ast
>) {
102 debug
!("ast_map: {:?} => {:?}", id
, entry
);
103 let len
= self.map
.len();
104 if id
as usize >= len
{
105 self.map
.extend(repeat(NotPresent
).take(id
as usize - len
+ 1));
107 self.map
[id
as usize] = entry
;
110 fn insert_def(&mut self, id
: NodeId
, node
: Node
<'ast
>, data
: DefPathData
) -> DefIndex
{
111 self.insert(id
, node
);
112 self.create_def(id
, data
)
115 fn insert(&mut self, id
: NodeId
, node
: Node
<'ast
>) {
116 let entry
= MapEntry
::from_node(self.parent_node
, node
);
117 self.insert_entry(id
, entry
);
121 impl<'ast
> Visitor
<'ast
> for NodeCollector
<'ast
> {
122 /// Because we want to track parent items and so forth, enable
123 /// deep walking so that we walk nested items in the context of
124 /// their outer items.
125 fn visit_nested_item(&mut self, item
: ItemId
) {
126 debug
!("visit_nested_item: {:?}", item
);
127 self.visit_item(self.krate
.item(item
.id
))
130 fn visit_item(&mut self, i
: &'ast Item
) {
131 debug
!("visit_item: {:?}", i
);
133 // Pick the def data. This need not be unique, but the more
134 // information we encapsulate into
135 let def_data
= match i
.node
{
136 ItemDefaultImpl(..) | ItemImpl(..) =>
138 ItemEnum(..) | ItemStruct(..) | ItemTrait(..) |
139 ItemExternCrate(..) | ItemMod(..) | ItemForeignMod(..) |
141 DefPathData
::TypeNs(i
.name
),
142 ItemStatic(..) | ItemConst(..) | ItemFn(..) =>
143 DefPathData
::ValueNs(i
.name
),
148 self.insert_def(i
.id
, NodeItem(i
), def_data
);
150 let parent_node
= self.parent_node
;
151 self.parent_node
= i
.id
;
155 ItemEnum(ref enum_definition
, _
) => {
156 for v
in &enum_definition
.variants
{
157 let variant_def_index
=
158 self.insert_def(v
.node
.data
.id(),
160 DefPathData
::EnumVariant(v
.node
.name
));
162 for field
in v
.node
.data
.fields() {
163 self.create_def_with_parent(
164 Some(variant_def_index
),
166 DefPathData
::Field(field
.name
));
170 ItemForeignMod(..) => {
172 ItemStruct(ref struct_def
, _
) => {
173 // If this is a tuple-like struct, register the constructor.
174 if !struct_def
.is_struct() {
175 self.insert_def(struct_def
.id(),
176 NodeStructCtor(struct_def
),
177 DefPathData
::StructCtor
);
180 for field
in struct_def
.fields() {
181 self.create_def(field
.id
, DefPathData
::Field(field
.name
));
184 ItemTrait(_
, _
, ref bounds
, _
) => {
185 for b
in bounds
.iter() {
186 if let TraitTyParamBound(ref t
, TraitBoundModifier
::None
) = *b
{
187 self.insert(t
.trait_ref
.ref_id
, NodeItem(i
));
191 ItemUse(ref view_path
) => {
192 match view_path
.node
{
193 ViewPathList(_
, ref paths
) => {
195 self.insert(path
.node
.id(), NodeItem(i
));
203 intravisit
::walk_item(self, i
);
204 self.parent_node
= parent_node
;
207 fn visit_foreign_item(&mut self, foreign_item
: &'ast ForeignItem
) {
208 self.insert_def(foreign_item
.id
,
209 NodeForeignItem(foreign_item
),
210 DefPathData
::ValueNs(foreign_item
.name
));
212 let parent_node
= self.parent_node
;
213 self.parent_node
= foreign_item
.id
;
214 intravisit
::walk_foreign_item(self, foreign_item
);
215 self.parent_node
= parent_node
;
218 fn visit_generics(&mut self, generics
: &'ast Generics
) {
219 for ty_param
in generics
.ty_params
.iter() {
220 self.insert_def(ty_param
.id
,
221 NodeTyParam(ty_param
),
222 DefPathData
::TypeParam(ty_param
.name
));
225 intravisit
::walk_generics(self, generics
);
228 fn visit_trait_item(&mut self, ti
: &'ast TraitItem
) {
229 let def_data
= match ti
.node
{
230 MethodTraitItem(..) | ConstTraitItem(..) => DefPathData
::ValueNs(ti
.name
),
231 TypeTraitItem(..) => DefPathData
::TypeNs(ti
.name
),
234 self.insert(ti
.id
, NodeTraitItem(ti
));
235 self.create_def(ti
.id
, def_data
);
237 let parent_node
= self.parent_node
;
238 self.parent_node
= ti
.id
;
241 ConstTraitItem(_
, Some(ref expr
)) => {
242 self.create_def(expr
.id
, DefPathData
::Initializer
);
247 intravisit
::walk_trait_item(self, ti
);
249 self.parent_node
= parent_node
;
252 fn visit_impl_item(&mut self, ii
: &'ast ImplItem
) {
253 let def_data
= match ii
.node
{
254 ImplItemKind
::Method(..) | ImplItemKind
::Const(..) => DefPathData
::ValueNs(ii
.name
),
255 ImplItemKind
::Type(..) => DefPathData
::TypeNs(ii
.name
),
258 self.insert_def(ii
.id
, NodeImplItem(ii
), def_data
);
260 let parent_node
= self.parent_node
;
261 self.parent_node
= ii
.id
;
264 ImplItemKind
::Const(_
, ref expr
) => {
265 self.create_def(expr
.id
, DefPathData
::Initializer
);
270 intravisit
::walk_impl_item(self, ii
);
272 self.parent_node
= parent_node
;
275 fn visit_pat(&mut self, pat
: &'ast Pat
) {
276 let maybe_binding
= match pat
.node
{
277 PatKind
::Ident(_
, id
, _
) => Some(id
.node
),
281 if let Some(id
) = maybe_binding
{
282 self.insert_def(pat
.id
, NodeLocal(pat
), DefPathData
::Binding(id
.name
));
284 self.insert(pat
.id
, NodePat(pat
));
287 let parent_node
= self.parent_node
;
288 self.parent_node
= pat
.id
;
289 intravisit
::walk_pat(self, pat
);
290 self.parent_node
= parent_node
;
293 fn visit_expr(&mut self, expr
: &'ast Expr
) {
294 self.insert(expr
.id
, NodeExpr(expr
));
297 ExprClosure(..) => { self.create_def(expr.id, DefPathData::ClosureExpr); }
301 let parent_node
= self.parent_node
;
302 self.parent_node
= expr
.id
;
303 intravisit
::walk_expr(self, expr
);
304 self.parent_node
= parent_node
;
307 fn visit_stmt(&mut self, stmt
: &'ast Stmt
) {
308 let id
= stmt
.node
.id();
309 self.insert(id
, NodeStmt(stmt
));
310 let parent_node
= self.parent_node
;
311 self.parent_node
= id
;
312 intravisit
::walk_stmt(self, stmt
);
313 self.parent_node
= parent_node
;
316 fn visit_fn(&mut self, fk
: intravisit
::FnKind
<'ast
>, fd
: &'ast FnDecl
,
317 b
: &'ast Block
, s
: Span
, id
: NodeId
) {
318 assert_eq
!(self.parent_node
, id
);
319 intravisit
::walk_fn(self, fk
, fd
, b
, s
);
322 fn visit_block(&mut self, block
: &'ast Block
) {
323 self.insert(block
.id
, NodeBlock(block
));
324 let parent_node
= self.parent_node
;
325 self.parent_node
= block
.id
;
326 intravisit
::walk_block(self, block
);
327 self.parent_node
= parent_node
;
330 fn visit_lifetime(&mut self, lifetime
: &'ast Lifetime
) {
331 self.insert(lifetime
.id
, NodeLifetime(lifetime
));
334 fn visit_lifetime_def(&mut self, def
: &'ast LifetimeDef
) {
335 self.create_def(def
.lifetime
.id
, DefPathData
::LifetimeDef(def
.lifetime
.name
));
336 self.visit_lifetime(&def
.lifetime
);
339 fn visit_macro_def(&mut self, macro_def
: &'ast MacroDef
) {
340 self.create_def(macro_def
.id
, DefPathData
::MacroDef(macro_def
.name
));