@@ -67,6 +67,14 @@ impl<'a> FnKind<'a> {
67
67
}
68
68
}
69
69
70
+ /// Specifies what nested things a visitor wants to visit. Currently there are
71
+ /// two modes: `OnlyBodies` descends into item bodies, but not into nested
72
+ /// items; `All` descends into item bodies and nested items.
73
+ pub enum NestedVisitMode {
74
+ OnlyBodies ,
75
+ All
76
+ }
77
+
70
78
/// Each method of the Visitor trait is a hook to be potentially
71
79
/// overridden. Each method's default implementation recursively visits
72
80
/// the substructure of the input via the corresponding `walk` method;
@@ -102,7 +110,7 @@ pub trait Visitor<'v> : Sized {
102
110
/// `panic!()`. This way, if a new `visit_nested_XXX` variant is
103
111
/// added in the future, we will see the panic in your code and
104
112
/// fix it appropriately.
105
- fn nested_visit_map ( & mut self ) -> Option < & Map < ' v > > {
113
+ fn nested_visit_map ( & mut self ) -> Option < ( & Map < ' v > , NestedVisitMode ) > {
106
114
None
107
115
}
108
116
@@ -116,7 +124,7 @@ pub trait Visitor<'v> : Sized {
116
124
/// but cannot supply a `Map`; see `nested_visit_map` for advice.
117
125
#[ allow( unused_variables) ]
118
126
fn visit_nested_item ( & mut self , id : ItemId ) {
119
- let opt_item = self . nested_visit_map ( )
127
+ let opt_item = map_for_item ( self )
120
128
. map ( |map| map. expect_item ( id. id ) ) ;
121
129
if let Some ( item) = opt_item {
122
130
self . visit_item ( item) ;
@@ -128,13 +136,25 @@ pub trait Visitor<'v> : Sized {
128
136
/// method.
129
137
#[ allow( unused_variables) ]
130
138
fn visit_nested_impl_item ( & mut self , id : ImplItemId ) {
131
- let opt_item = self . nested_visit_map ( )
139
+ let opt_item = map_for_item ( self )
132
140
. map ( |map| map. impl_item ( id) ) ;
133
141
if let Some ( item) = opt_item {
134
142
self . visit_impl_item ( item) ;
135
143
}
136
144
}
137
145
146
+ /// Invoked to visit the body of a function, method or closure. Like
147
+ /// visit_nested_item, does nothing by default unless you override
148
+ /// `nested_visit_map` to return `Some(_)`, in which case it will walk the
149
+ /// body.
150
+ fn visit_body ( & mut self , id : ExprId ) {
151
+ let opt_expr = map_for_body ( self )
152
+ . map ( |map| map. expr ( id) ) ;
153
+ if let Some ( expr) = opt_expr {
154
+ self . visit_expr ( expr) ;
155
+ }
156
+ }
157
+
138
158
/// Visit the top-level item and (optionally) nested items / impl items. See
139
159
/// `visit_nested_item` for details.
140
160
fn visit_item ( & mut self , i : & ' v Item ) {
@@ -200,7 +220,7 @@ pub trait Visitor<'v> : Sized {
200
220
fn visit_where_predicate ( & mut self , predicate : & ' v WherePredicate ) {
201
221
walk_where_predicate ( self , predicate)
202
222
}
203
- fn visit_fn ( & mut self , fk : FnKind < ' v > , fd : & ' v FnDecl , b : & ' v Expr , s : Span , id : NodeId ) {
223
+ fn visit_fn ( & mut self , fk : FnKind < ' v > , fd : & ' v FnDecl , b : ExprId , s : Span , id : NodeId ) {
204
224
walk_fn ( self , fk, fd, b, s, id)
205
225
}
206
226
fn visit_trait_item ( & mut self , ti : & ' v TraitItem ) {
@@ -279,6 +299,19 @@ pub trait Visitor<'v> : Sized {
279
299
}
280
300
}
281
301
302
+ fn map_for_body < ' v , V : Visitor < ' v > > ( visitor : & mut V ) -> Option < & Map < ' v > > {
303
+ visitor. nested_visit_map ( ) . map ( |( map, _mode) | map)
304
+ }
305
+
306
+ fn map_for_item < ' v , V : Visitor < ' v > > ( visitor : & mut V ) -> Option < & Map < ' v > > {
307
+ visitor. nested_visit_map ( ) . and_then ( |( map, mode) | {
308
+ match mode {
309
+ NestedVisitMode :: OnlyBodies => None ,
310
+ NestedVisitMode :: All => Some ( map)
311
+ }
312
+ } )
313
+ }
314
+
282
315
pub fn walk_opt_name < ' v , V : Visitor < ' v > > ( visitor : & mut V , span : Span , opt_name : Option < Name > ) {
283
316
if let Some ( name) = opt_name {
284
317
visitor. visit_name ( span, name) ;
@@ -363,7 +396,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
363
396
visitor. visit_ty ( typ) ;
364
397
visitor. visit_expr ( expr) ;
365
398
}
366
- ItemFn ( ref declaration, unsafety, constness, abi, ref generics, ref body ) => {
399
+ ItemFn ( ref declaration, unsafety, constness, abi, ref generics, body_id ) => {
367
400
visitor. visit_fn ( FnKind :: ItemFn ( item. name ,
368
401
generics,
369
402
unsafety,
@@ -372,7 +405,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
372
405
& item. vis ,
373
406
& item. attrs ) ,
374
407
declaration,
375
- body ,
408
+ body_id ,
376
409
item. span ,
377
410
item. id )
378
411
}
@@ -697,13 +730,25 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
697
730
pub fn walk_fn < ' v , V : Visitor < ' v > > ( visitor : & mut V ,
698
731
function_kind : FnKind < ' v > ,
699
732
function_declaration : & ' v FnDecl ,
700
- function_body : & ' v Expr ,
733
+ body_id : ExprId ,
701
734
_span : Span ,
702
735
id : NodeId ) {
703
736
visitor. visit_id ( id) ;
704
737
walk_fn_decl ( visitor, function_declaration) ;
705
738
walk_fn_kind ( visitor, function_kind) ;
706
- visitor. visit_expr ( function_body)
739
+ visitor. visit_body ( body_id)
740
+ }
741
+
742
+ pub fn walk_fn_with_body < ' v , V : Visitor < ' v > > ( visitor : & mut V ,
743
+ function_kind : FnKind < ' v > ,
744
+ function_declaration : & ' v FnDecl ,
745
+ body : & ' v Expr ,
746
+ _span : Span ,
747
+ id : NodeId ) {
748
+ visitor. visit_id ( id) ;
749
+ walk_fn_decl ( visitor, function_declaration) ;
750
+ walk_fn_kind ( visitor, function_kind) ;
751
+ visitor. visit_expr ( body)
707
752
}
708
753
709
754
pub fn walk_trait_item < ' v , V : Visitor < ' v > > ( visitor : & mut V , trait_item : & ' v TraitItem ) {
@@ -720,13 +765,13 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
720
765
visitor. visit_generics ( & sig. generics ) ;
721
766
walk_fn_decl ( visitor, & sig. decl ) ;
722
767
}
723
- MethodTraitItem ( ref sig, Some ( ref body ) ) => {
768
+ MethodTraitItem ( ref sig, Some ( body_id ) ) => {
724
769
visitor. visit_fn ( FnKind :: Method ( trait_item. name ,
725
770
sig,
726
771
None ,
727
772
& trait_item. attrs ) ,
728
773
& sig. decl ,
729
- body ,
774
+ body_id ,
730
775
trait_item. span ,
731
776
trait_item. id ) ;
732
777
}
@@ -752,13 +797,13 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
752
797
visitor. visit_ty ( ty) ;
753
798
visitor. visit_expr ( expr) ;
754
799
}
755
- ImplItemKind :: Method ( ref sig, ref body ) => {
800
+ ImplItemKind :: Method ( ref sig, body_id ) => {
756
801
visitor. visit_fn ( FnKind :: Method ( impl_item. name ,
757
802
sig,
758
803
Some ( & impl_item. vis ) ,
759
804
& impl_item. attrs ) ,
760
805
& sig. decl ,
761
- body ,
806
+ body_id ,
762
807
impl_item. span ,
763
808
impl_item. id ) ;
764
809
}
@@ -883,7 +928,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
883
928
visitor. visit_expr ( subexpression) ;
884
929
walk_list ! ( visitor, visit_arm, arms) ;
885
930
}
886
- ExprClosure ( _, ref function_declaration, ref body, _fn_decl_span) => {
931
+ ExprClosure ( _, ref function_declaration, body, _fn_decl_span) => {
887
932
visitor. visit_fn ( FnKind :: Closure ( & expression. attrs ) ,
888
933
function_declaration,
889
934
body,
@@ -998,34 +1043,40 @@ impl IdRange {
998
1043
}
999
1044
1000
1045
1001
- pub struct IdRangeComputingVisitor {
1002
- pub result : IdRange ,
1046
+ pub struct IdRangeComputingVisitor < ' a , ' ast : ' a > {
1047
+ result : IdRange ,
1048
+ map : & ' a map:: Map < ' ast > ,
1003
1049
}
1004
1050
1005
- impl IdRangeComputingVisitor {
1006
- pub fn new ( ) -> IdRangeComputingVisitor {
1007
- IdRangeComputingVisitor { result : IdRange :: max ( ) }
1051
+ impl < ' a , ' ast > IdRangeComputingVisitor < ' a , ' ast > {
1052
+ pub fn new ( map : & ' a map :: Map < ' ast > ) -> IdRangeComputingVisitor < ' a , ' ast > {
1053
+ IdRangeComputingVisitor { result : IdRange :: max ( ) , map : map }
1008
1054
}
1009
1055
1010
1056
pub fn result ( & self ) -> IdRange {
1011
1057
self . result
1012
1058
}
1013
1059
}
1014
1060
1015
- impl < ' v > Visitor < ' v > for IdRangeComputingVisitor {
1061
+ impl < ' a , ' ast > Visitor < ' ast > for IdRangeComputingVisitor < ' a , ' ast > {
1062
+ fn nested_visit_map ( & mut self ) -> Option < ( & Map < ' ast > , NestedVisitMode ) > {
1063
+ Some ( ( & self . map , NestedVisitMode :: OnlyBodies ) )
1064
+ }
1065
+
1016
1066
fn visit_id ( & mut self , id : NodeId ) {
1017
1067
self . result . add ( id) ;
1018
1068
}
1019
1069
}
1020
1070
1021
1071
/// Computes the id range for a single fn body, ignoring nested items.
1022
- pub fn compute_id_range_for_fn_body ( fk : FnKind ,
1023
- decl : & FnDecl ,
1024
- body : & Expr ,
1025
- sp : Span ,
1026
- id : NodeId )
1027
- -> IdRange {
1028
- let mut visitor = IdRangeComputingVisitor :: new ( ) ;
1029
- visitor. visit_fn ( fk, decl, body, sp, id) ;
1072
+ pub fn compute_id_range_for_fn_body < ' v > ( fk : FnKind < ' v > ,
1073
+ decl : & ' v FnDecl ,
1074
+ body : & ' v Expr ,
1075
+ sp : Span ,
1076
+ id : NodeId ,
1077
+ map : & map:: Map < ' v > )
1078
+ -> IdRange {
1079
+ let mut visitor = IdRangeComputingVisitor :: new ( map) ;
1080
+ walk_fn_with_body ( & mut visitor, fk, decl, body, sp, id) ;
1030
1081
visitor. result ( )
1031
1082
}
0 commit comments