8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- //! HIR walker. Each overridden visit method has full control over what
11
+ //! HIR walker for walking the contents of nodes.
12
+ //!
13
+ //! **For an overview of the visitor strategy, see the docs on the
14
+ //! `super::itemlikevisit::ItemLikeVisitor` trait.**
15
+ //!
16
+ //! If you have decided to use this visitor, here are some general
17
+ //! notes on how to do it:
18
+ //!
19
+ //! Each overridden visit method has full control over what
12
20
//! happens with its node, it can do its own traversal of the node's children,
13
21
//! call `intravisit::walk_*` to apply the default traversal algorithm, or prevent
14
22
//! deeper traversal by doing nothing.
@@ -30,6 +38,8 @@ use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
30
38
use syntax:: codemap:: Spanned ;
31
39
use syntax_pos:: Span ;
32
40
use hir:: * ;
41
+ use hir:: map:: Map ;
42
+ use super :: itemlikevisit:: DeepVisitor ;
33
43
34
44
use std:: cmp;
35
45
use std:: u32;
@@ -76,22 +86,70 @@ pub trait Visitor<'v> : Sized {
76
86
///////////////////////////////////////////////////////////////////////////
77
87
// Nested items.
78
88
79
- /// Invoked when a nested item is encountered. By default, does
80
- /// nothing. If you want a deep walk, you need to override to
81
- /// fetch the item contents. But most of the time, it is easier
82
- /// (and better) to invoke `Crate::visit_all_items`, which visits
83
- /// all items in the crate in some order (but doesn't respect
84
- /// nesting).
89
+ /// The default versions of the `visit_nested_XXX` routines invoke
90
+ /// this method to get a map to use; if they get back `None`, they
91
+ /// just skip nested things. Otherwise, they will lookup the
92
+ /// nested item-like things in the map and visit it. So the best
93
+ /// way to implement a nested visitor is to override this method
94
+ /// to return a `Map`; one advantage of this is that if we add
95
+ /// more types of nested things in the future, they will
96
+ /// automatically work.
97
+ ///
98
+ /// **If for some reason you want the nested behavior, but don't
99
+ /// have a `Map` are your disposal:** then you should override the
100
+ /// `visit_nested_XXX` methods, and override this method to
101
+ /// `panic!()`. This way, if a new `visit_nested_XXX` variant is
102
+ /// added in the future, we will see the panic in your code and
103
+ /// fix it appropriately.
104
+ fn nested_visit_map ( & mut self ) -> Option < & Map < ' v > > {
105
+ None
106
+ }
107
+
108
+ /// Invoked when a nested item is encountered. By default does
109
+ /// nothing unless you override `nested_visit_map` to return
110
+ /// `Some(_)`, in which case it will walk the item. **You probably
111
+ /// don't want to override this method** -- instead, override
112
+ /// `nested_visit_map` or use the "shallow" or "deep" visit
113
+ /// patterns described on `itemlikevisit::ItemLikeVisitor`. The only
114
+ /// reason to override this method is if you want a nested pattern
115
+ /// but cannot supply a `Map`; see `nested_visit_map` for advice.
85
116
#[ allow( unused_variables) ]
86
117
fn visit_nested_item ( & mut self , id : ItemId ) {
118
+ let opt_item = self . nested_visit_map ( )
119
+ . map ( |map| map. expect_item ( id. id ) ) ;
120
+ if let Some ( item) = opt_item {
121
+ self . visit_item ( item) ;
122
+ }
87
123
}
88
124
89
- /// Visit the top-level item and (optionally) nested items. See
125
+ /// Like `visit_nested_item()`, but for impl items. See
126
+ /// `visit_nested_item()` for advice on when to override this
127
+ /// method.
128
+ #[ allow( unused_variables) ]
129
+ fn visit_nested_impl_item ( & mut self , id : ImplItemId ) {
130
+ let opt_item = self . nested_visit_map ( )
131
+ . map ( |map| map. impl_item ( id) ) ;
132
+ if let Some ( item) = opt_item {
133
+ self . visit_impl_item ( item) ;
134
+ }
135
+ }
136
+
137
+ /// Visit the top-level item and (optionally) nested items / impl items. See
90
138
/// `visit_nested_item` for details.
91
139
fn visit_item ( & mut self , i : & ' v Item ) {
92
140
walk_item ( self , i)
93
141
}
94
142
143
+ /// When invoking `visit_all_item_likes()`, you need to supply an
144
+ /// item-like visitor. This method converts a "intra-visit"
145
+ /// visitor into an item-like visitor that walks the entire tree.
146
+ /// If you use this, you probably don't want to process the
147
+ /// contents of nested item-like things, since the outer loop will
148
+ /// visit them as well.
149
+ fn as_deep_visitor < ' s > ( & ' s mut self ) -> DeepVisitor < ' s , Self > {
150
+ DeepVisitor :: new ( self )
151
+ }
152
+
95
153
///////////////////////////////////////////////////////////////////////////
96
154
97
155
fn visit_id ( & mut self , _node_id : NodeId ) {
@@ -147,6 +205,9 @@ pub trait Visitor<'v> : Sized {
147
205
fn visit_impl_item ( & mut self , ii : & ' v ImplItem ) {
148
206
walk_impl_item ( self , ii)
149
207
}
208
+ fn visit_impl_item_ref ( & mut self , ii : & ' v ImplItemRef ) {
209
+ walk_impl_item_ref ( self , ii)
210
+ }
150
211
fn visit_trait_ref ( & mut self , t : & ' v TraitRef ) {
151
212
walk_trait_ref ( self , t)
152
213
}
@@ -206,6 +267,12 @@ pub trait Visitor<'v> : Sized {
206
267
fn visit_vis ( & mut self , vis : & ' v Visibility ) {
207
268
walk_vis ( self , vis)
208
269
}
270
+ fn visit_associated_item_kind ( & mut self , kind : & ' v AssociatedItemKind ) {
271
+ walk_associated_item_kind ( self , kind) ;
272
+ }
273
+ fn visit_defaultness ( & mut self , defaultness : & ' v Defaultness ) {
274
+ walk_defaultness ( self , defaultness) ;
275
+ }
209
276
}
210
277
211
278
pub fn walk_opt_name < ' v , V : Visitor < ' v > > ( visitor : & mut V , span : Span , opt_name : Option < Name > ) {
@@ -341,12 +408,14 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
341
408
visitor. visit_id ( item. id ) ;
342
409
visitor. visit_trait_ref ( trait_ref)
343
410
}
344
- ItemImpl ( .., ref type_parameters, ref opt_trait_reference, ref typ, ref impl_items ) => {
411
+ ItemImpl ( .., ref type_parameters, ref opt_trait_reference, ref typ, ref impl_item_refs ) => {
345
412
visitor. visit_id ( item. id ) ;
346
413
visitor. visit_generics ( type_parameters) ;
347
414
walk_list ! ( visitor, visit_trait_ref, opt_trait_reference) ;
348
415
visitor. visit_ty ( typ) ;
349
- walk_list ! ( visitor, visit_impl_item, impl_items) ;
416
+ for impl_item_ref in impl_item_refs {
417
+ visitor. visit_impl_item_ref ( impl_item_ref) ;
418
+ }
350
419
}
351
420
ItemStruct ( ref struct_definition, ref generics) |
352
421
ItemUnion ( ref struct_definition, ref generics) => {
@@ -677,10 +746,14 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
677
746
}
678
747
679
748
pub fn walk_impl_item < ' v , V : Visitor < ' v > > ( visitor : & mut V , impl_item : & ' v ImplItem ) {
680
- visitor. visit_vis ( & impl_item. vis ) ;
681
- visitor. visit_name ( impl_item. span , impl_item. name ) ;
682
- walk_list ! ( visitor, visit_attribute, & impl_item. attrs) ;
683
- match impl_item. node {
749
+ // NB: Deliberately force a compilation error if/when new fields are added.
750
+ let ImplItem { id : _, name, ref vis, ref defaultness, ref attrs, ref node, span } = * impl_item;
751
+
752
+ visitor. visit_name ( span, name) ;
753
+ visitor. visit_vis ( vis) ;
754
+ visitor. visit_defaultness ( defaultness) ;
755
+ walk_list ! ( visitor, visit_attribute, attrs) ;
756
+ match * node {
684
757
ImplItemKind :: Const ( ref ty, ref expr) => {
685
758
visitor. visit_id ( impl_item. id ) ;
686
759
visitor. visit_ty ( ty) ;
@@ -703,6 +776,17 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
703
776
}
704
777
}
705
778
779
+ pub fn walk_impl_item_ref < ' v , V : Visitor < ' v > > ( visitor : & mut V , impl_item_ref : & ' v ImplItemRef ) {
780
+ // NB: Deliberately force a compilation error if/when new fields are added.
781
+ let ImplItemRef { id, name, ref kind, span, ref vis, ref defaultness } = * impl_item_ref;
782
+ visitor. visit_nested_impl_item ( id) ;
783
+ visitor. visit_name ( span, name) ;
784
+ visitor. visit_associated_item_kind ( kind) ;
785
+ visitor. visit_vis ( vis) ;
786
+ visitor. visit_defaultness ( defaultness) ;
787
+ }
788
+
789
+
706
790
pub fn walk_struct_def < ' v , V : Visitor < ' v > > ( visitor : & mut V , struct_definition : & ' v VariantData ) {
707
791
visitor. visit_id ( struct_definition. id ( ) ) ;
708
792
walk_list ! ( visitor, visit_struct_field, struct_definition. fields( ) ) ;
@@ -872,6 +956,18 @@ pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) {
872
956
}
873
957
}
874
958
959
+ pub fn walk_associated_item_kind < ' v , V : Visitor < ' v > > ( _: & mut V , _: & ' v AssociatedItemKind ) {
960
+ // No visitable content here: this fn exists so you can call it if
961
+ // the right thing to do, should content be added in the future,
962
+ // would be to walk it.
963
+ }
964
+
965
+ pub fn walk_defaultness < ' v , V : Visitor < ' v > > ( _: & mut V , _: & ' v Defaultness ) {
966
+ // No visitable content here: this fn exists so you can call it if
967
+ // the right thing to do, should content be added in the future,
968
+ // would be to walk it.
969
+ }
970
+
875
971
#[ derive( Copy , Clone , RustcEncodable , RustcDecodable , Debug , PartialEq , Eq ) ]
876
972
pub struct IdRange {
877
973
pub min : NodeId ,
0 commit comments