11use rusty_common:: { Position , Positioned } ;
22use rusty_parser:: * ;
33
4+ use crate :: delegate_visitor;
45use crate :: LintErrorPos ;
56
67/// The result of a visitor.
@@ -19,6 +20,20 @@ pub trait SetPosition {
1920 fn set_position ( & mut self , pos : Position ) ;
2021}
2122
23+ // Blanket implementation for Option
24+
25+ impl < P , T > Visitor < Option < T > > for P
26+ where
27+ P : Visitor < T > ,
28+ {
29+ fn visit ( & mut self , element : & Option < T > ) -> VisitResult {
30+ match element {
31+ Some ( t) => self . visit ( t) ,
32+ _ => Ok ( ( ) ) ,
33+ }
34+ }
35+ }
36+
2237// Blanket implementation for Vec
2338
2439impl < P , T > Visitor < Vec < T > > for P
@@ -51,34 +66,14 @@ pub trait DelegateVisitor<T> {
5166 fn delegate ( & mut self ) -> impl Visitor < T > ;
5267}
5368
54- /// A visitor that can visit global statements
55- /// but does not enter the implementations of functions or subs.
56- /// Actual visiting logic is handled by the delegate.
57- pub struct ShallowVisitor < P > {
58- delegate : P ,
59- }
60-
61- impl < P > ShallowVisitor < P > {
62- pub fn new ( delegate : P ) -> Self {
63- Self { delegate }
64- }
69+ delegate_visitor ! (
70+ /// A visitor that can visit global statements
71+ /// but does not enter the implementations of functions or subs.
72+ /// Actual visiting logic is handled by the delegate.
73+ GlobalVisitor
74+ ) ;
6575
66- /// Returns the delegate back.
67- pub fn delegate ( self ) -> P {
68- self . delegate
69- }
70- }
71-
72- impl < P > SetPosition for ShallowVisitor < P >
73- where
74- P : SetPosition ,
75- {
76- fn set_position ( & mut self , pos : Position ) {
77- self . delegate . set_position ( pos) ;
78- }
79- }
80-
81- impl < P > Visitor < GlobalStatement > for ShallowVisitor < P >
76+ impl < P > Visitor < GlobalStatement > for GlobalVisitor < P >
8277where
8378 P : Visitor < DefType >
8479 + Visitor < FunctionDeclaration >
@@ -102,3 +97,180 @@ where
10297 }
10398 }
10499}
100+
101+ delegate_visitor ! (
102+ /// A visitor that can visit statements
103+ /// and also enters the implementations of functions or subs,
104+ /// as well as nested block statements (e.g. inside IF statements).
105+ /// Actual visiting logic is handled by the delegate.
106+ DeepStatementVisitor
107+ ) ;
108+
109+ impl < P > Visitor < GlobalStatement > for DeepStatementVisitor < P >
110+ where
111+ P : Visitor < DefType >
112+ + Visitor < FunctionDeclaration >
113+ + Visitor < FunctionImplementation >
114+ + Visitor < SubDeclaration >
115+ + Visitor < SubImplementation >
116+ + Visitor < UserDefinedType >
117+ + Visitor < Statement >
118+ + SetPosition ,
119+ {
120+ fn visit ( & mut self , element : & GlobalStatement ) -> VisitResult {
121+ match element {
122+ GlobalStatement :: DefType ( def_type) => self . delegate . visit ( def_type) ,
123+ GlobalStatement :: FunctionDeclaration ( f) => self . delegate . visit ( f) ,
124+ GlobalStatement :: FunctionImplementation ( f) => {
125+ // notify first the delegate about the FUNCTION implementation
126+ self . delegate . visit ( f) ?;
127+ // then visit the body (this will go into the statements of the FUNCTION)
128+ self . visit ( & f. body )
129+ }
130+ GlobalStatement :: Statement ( statement) => self . visit ( statement) ,
131+ GlobalStatement :: SubDeclaration ( s) => self . delegate . visit ( s) ,
132+ GlobalStatement :: SubImplementation ( s) => {
133+ // notify first the delegate about the SUB implementation
134+ self . delegate . visit ( s) ?;
135+ // then visit the body (this will go into the statements of the SUB)
136+ self . visit ( & s. body )
137+ }
138+ GlobalStatement :: UserDefinedType ( user_defined_type) => {
139+ self . delegate . visit ( user_defined_type)
140+ }
141+ }
142+ }
143+ }
144+
145+ impl < P > Visitor < Statement > for DeepStatementVisitor < P >
146+ where
147+ P : Visitor < Statement > + SetPosition ,
148+ {
149+ fn visit ( & mut self , element : & Statement ) -> VisitResult {
150+ // first visit the delegate
151+ self . delegate . visit ( element) ?;
152+
153+ // then dive into the statement to for cases of blocks
154+ match element {
155+ Statement :: IfBlock ( if_block) => self . visit ( if_block) ,
156+ Statement :: SelectCase ( select_case) => self . visit ( select_case) ,
157+ Statement :: ForLoop ( for_loop) => self . visit ( for_loop) ,
158+ Statement :: While ( conditional_block) => self . visit ( conditional_block) ,
159+ Statement :: DoLoop ( do_loop) => self . visit ( do_loop) ,
160+ _ => Ok ( ( ) ) ,
161+ }
162+ }
163+ }
164+
165+ impl < P > Visitor < ForLoop > for DeepStatementVisitor < P >
166+ where
167+ P : Visitor < Statement > + SetPosition ,
168+ {
169+ fn visit ( & mut self , element : & ForLoop ) -> VisitResult {
170+ self . visit ( & element. statements )
171+ }
172+ }
173+
174+ impl < P > Visitor < SelectCase > for DeepStatementVisitor < P >
175+ where
176+ P : Visitor < Statement > + SetPosition ,
177+ {
178+ fn visit ( & mut self , element : & SelectCase ) -> VisitResult {
179+ self . visit ( & element. case_blocks ) ?;
180+ self . visit ( & element. else_block )
181+ }
182+ }
183+
184+ impl < P > Visitor < CaseBlock > for DeepStatementVisitor < P >
185+ where
186+ P : Visitor < Statement > + SetPosition ,
187+ {
188+ fn visit ( & mut self , element : & CaseBlock ) -> VisitResult {
189+ self . visit ( & element. statements )
190+ }
191+ }
192+
193+ impl < P > Visitor < IfBlock > for DeepStatementVisitor < P >
194+ where
195+ P : Visitor < Statement > + SetPosition ,
196+ {
197+ fn visit ( & mut self , element : & IfBlock ) -> VisitResult {
198+ self . visit ( & element. if_block ) ?;
199+ self . visit ( & element. else_if_blocks ) ?;
200+ self . visit ( & element. else_block )
201+ }
202+ }
203+
204+ impl < P > Visitor < DoLoop > for DeepStatementVisitor < P >
205+ where
206+ P : Visitor < Statement > + SetPosition ,
207+ {
208+ fn visit ( & mut self , element : & DoLoop ) -> VisitResult {
209+ self . visit ( & element. statements )
210+ }
211+ }
212+
213+ impl < P > Visitor < ConditionalBlock > for DeepStatementVisitor < P >
214+ where
215+ P : Visitor < Statement > + SetPosition ,
216+ {
217+ fn visit ( & mut self , element : & ConditionalBlock ) -> VisitResult {
218+ self . visit ( & element. statements )
219+ }
220+ }
221+
222+ /// Creates a no-op visitor implementation
223+ /// for the given types.
224+ #[ macro_export]
225+ macro_rules! no_op_visitor {
226+ ( $visitor_name: ident: $( $types: tt) ,+) => {
227+ $(
228+ impl Visitor <$types> for $visitor_name {
229+ fn visit( & mut self , _element: & $types) -> VisitResult {
230+ Ok ( ( ) )
231+ }
232+ }
233+ ) +
234+ } ;
235+ }
236+
237+ #[ macro_export]
238+ macro_rules! no_pos_visitor {
239+ ( $visitor_name: ident) => {
240+ impl SetPosition for $visitor_name {
241+ fn set_position( & mut self , _pos: Position ) { }
242+ }
243+ } ;
244+ }
245+
246+ /// Creates a visitor that delegates to another.
247+ #[ macro_export]
248+ macro_rules! delegate_visitor {
249+ ( $( #[ $( $attrss: tt) * ] ) * $name: ident) => {
250+ $( #[ $( $attrss) * ] ) *
251+ pub struct $name<P > {
252+ delegate: P
253+ }
254+
255+ impl <P > $name<P > {
256+ pub fn new( delegate: P ) -> Self {
257+ Self { delegate }
258+ }
259+
260+ /// Returns the delegate back.
261+ #[ allow( unused) ]
262+ pub fn delegate( self ) -> P {
263+ self . delegate
264+ }
265+ }
266+
267+ impl <P > SetPosition for $name<P >
268+ where
269+ P : SetPosition ,
270+ {
271+ fn set_position( & mut self , pos: Position ) {
272+ self . delegate. set_position( pos) ;
273+ }
274+ }
275+ } ;
276+ }
0 commit comments