@@ -47,7 +47,7 @@ open class SyntaxRewriter {
47
47
return Syntax ( token)
48
48
}
49
49
50
- /// Visit a `UnknownSyntax`.
50
+ /// Visit an `UnknownSyntax`.
51
51
/// - Parameter node: the node that is being visited
52
52
/// - Returns: the rewritten node
53
53
open func visit( _ node: UnknownSyntax ) -> Syntax {
@@ -106,7 +106,7 @@ open class SyntaxRewriter {
106
106
107
107
% end
108
108
109
- final func visit ( _ data: SyntaxData) - > Syntax {
109
+ private func visit ( _ data: SyntaxData) - > Syntax {
110
110
switch data. raw. kind {
111
111
case . token:
112
112
let node = TokenSyntax ( data)
@@ -133,8 +133,9 @@ open class SyntaxRewriter {
133
133
}
134
134
}
135
135
136
- final func visitChildren < SyntaxType : SyntaxProtocol> ( _ node: SyntaxType)
137
- - > SyntaxType {
136
+ private func visitChildren < SyntaxType : SyntaxProtocol> (
137
+ _ node: SyntaxType
138
+ ) - > SyntaxType {
138
139
// Walk over all children of this node and rewrite them. Don't store any
139
140
// rewritten nodes until the first non-`nil` value is encountered. When this
140
141
// happens, retrieve all previous syntax nodes from the parent node to
@@ -222,71 +223,122 @@ public enum SyntaxVisitorContinueKind {
222
223
case skipChildren
223
224
}
224
225
225
- public protocol SyntaxVisitor {
226
+ open class SyntaxVisitor {
227
+ public init ( ) { }
228
+
229
+ /// Walk all nodes of the given syntax tree, calling the corresponding `visit`
230
+ /// function for every node that is being visited.
231
+ public func walk< SyntaxType: SyntaxProtocol > ( _ node: SyntaxType ) {
232
+ visit ( node. data)
233
+ }
234
+
226
235
% for node in SYNTAX_NODES:
227
236
% if is_visitable( node) :
228
237
/// Visiting `${node.name}` specifically.
229
238
/// - Parameter node: the node we are visiting.
230
239
/// - Returns: how should we continue visiting.
231
- mutating func visit( _ node: ${ node. name} ) -> SyntaxVisitorContinueKind
240
+ open func visit( _ node: ${ node. name} ) -> SyntaxVisitorContinueKind {
241
+ return . visitChildren
242
+ }
232
243
233
244
/// The function called after visiting `${node.name}` and its descendents.
234
245
/// - node: the node we just finished visiting.
235
- mutating func visitPost( _ node: ${ node. name} )
246
+ open func visitPost( _ node: ${ node. name} ) { }
236
247
% end
237
248
% end
238
249
239
250
/// Visiting `TokenSyntax` specifically.
240
251
/// - Parameter node: the node we are visiting.
241
252
/// - Returns: how should we continue visiting.
242
- mutating func visit( _ token: TokenSyntax ) -> SyntaxVisitorContinueKind
253
+ open func visit( _ token: TokenSyntax ) -> SyntaxVisitorContinueKind {
254
+ return . visitChildren
255
+ }
243
256
244
257
/// The function called after visiting the node and its descendents.
245
258
/// - node: the node we just finished visiting.
246
- mutating func visitPost( _ node: TokenSyntax )
259
+ open func visitPost( _ node: TokenSyntax ) { }
247
260
248
261
/// Visiting `UnknownSyntax` specifically.
249
262
/// - Parameter node: the node we are visiting.
250
263
/// - Returns: how should we continue visiting.
251
- mutating func visit( _ node: UnknownSyntax ) -> SyntaxVisitorContinueKind
264
+ open func visit( _ node: UnknownSyntax ) -> SyntaxVisitorContinueKind {
265
+ return . visitChildren
266
+ }
252
267
253
268
/// The function called after visiting the node and its descendents.
254
269
/// - node: the node we just finished visiting.
255
- mutating func visitPost( _ node: UnknownSyntax )
256
- }
270
+ open func visitPost( _ node: UnknownSyntax ) { }
257
271
258
- public extension SyntaxVisitor {
259
272
% for node in SYNTAX_NODES:
260
- % if is_visitable ( node) :
261
- mutating func visit( _ node: ${ node. name} ) -> SyntaxVisitorContinueKind {
262
- return . visitChildren
263
- }
264
- mutating func visitPost( _ node: ${ node. name} ) { }
273
+ /// Implementation detail of doVisit(_:_:). Do not call directly.
274
+ private func visitImpl${ node. name} ( _ data: SyntaxData ) {
275
+ % if node. is_base ( ) :
276
+ let node = Unknown${ node. name} ( data)
277
+ let needsChildren = ( visit ( node) == . visitChildren)
278
+ // Avoid calling into visitChildren if possible.
279
+ if needsChildren && node. raw. numberOfChildren > 0 {
280
+ visitChildren ( node)
281
+ }
282
+ visitPost ( node)
283
+ % else :
284
+ let node = ${ node. name} ( data)
285
+ let needsChildren = ( visit ( node) == . visitChildren)
286
+ // Avoid calling into visitChildren if possible.
287
+ if needsChildren && node. raw. numberOfChildren > 0 {
288
+ visitChildren ( node)
289
+ }
290
+ visitPost ( node)
265
291
% end
292
+ }
293
+
266
294
% end
267
295
268
- mutating func visit( _ token: TokenSyntax ) -> SyntaxVisitorContinueKind {
269
- return . visitChildren
296
+ private func visit( _ data: SyntaxData ) {
297
+ switch data. raw. kind {
298
+ case . token:
299
+ let node = TokenSyntax ( data)
300
+ _ = visit ( node)
301
+ // No children to visit.
302
+ visitPost ( node)
303
+ case . unknown:
304
+ let node = UnknownSyntax ( data)
305
+ let needsChildren = ( visit ( node) == . visitChildren)
306
+ // Avoid calling into visitChildren if possible.
307
+ if needsChildren && node. raw. numberOfChildren > 0 {
308
+ visitChildren ( node)
309
+ }
310
+ visitPost ( node)
311
+ // The implementation of every generated case goes into its own function. This
312
+ // circumvents an issue where the compiler allocates stack space for every
313
+ // case statement next to each other in debug builds, causing it to allocate
314
+ // ~50KB per call to this function. rdar://55929175
315
+ % for node in SYNTAX_NODES:
316
+ case . ${ node. swift_syntax_kind} :
317
+ visitImpl ${ node. name} ( data)
318
+ % end
319
+ }
270
320
}
271
- mutating func visitPost( _ node: TokenSyntax ) { }
272
321
273
- mutating func visit( _ node: UnknownSyntax ) -> SyntaxVisitorContinueKind {
274
- return . visitChildren
322
+ private func visitChildren< SyntaxType: SyntaxProtocol > ( _ node: SyntaxType ) {
323
+ let syntaxNode = Syntax ( node)
324
+ let parentBox = SyntaxBox ( syntaxNode)
325
+ for childRaw in PresentRawSyntaxChildren ( syntaxNode) {
326
+ let childData = SyntaxData ( childRaw, parentBox: parentBox)
327
+ visit ( childData)
328
+ }
275
329
}
276
- mutating func visitPost( _ node: UnknownSyntax ) { }
277
330
}
278
331
279
332
/// A `SyntaxVisitor` that can visit the nodes as generic `Syntax` values.
280
333
///
281
- /// This is a separate protocol because this kind of visitation is slower than
282
- /// the type-specific visitation of `SyntaxVisitor`. Use `SyntaxAnyVisitor` if
283
- /// the `visitAny(_)` function would be useful to have, otherwise use
284
- /// `SyntaxVisitor`.
334
+ /// This subclass of `SyntaxVisitor` is slower than the type-specific visitation
335
+ /// of `SyntaxVisitor`. Use `SyntaxAnyVisitor` if the `visitAny(_)` function
336
+ /// would be useful to have, otherwise inherit from `SyntaxVisitor`.
285
337
///
286
- /// This works by introducing default implementations of the type-specific
287
- /// visit function that delegate to `visitAny(_)`. A conformant type that
288
- /// provides a custom type-specific visit function, should also call
289
- /// `visitAny(_)` in its implementation, if calling `visitAny ` is needed:
338
+ /// This works by overriding the type-specific visit function that delegate to
339
+ /// `visitAny(_)`. A subclass that provides a custom type-specific visit
340
+ /// function, should also call `visitAny(_)` in its implementation, if calling
341
+ /// `visitAny` is needed:
290
342
///
291
343
/// struct MyVisitor: SyntaxAnyVisitor {
292
344
/// func visitAny(_ node: Syntax) -> SyntaxVisitorContinueKind {
@@ -299,143 +351,46 @@ public extension SyntaxVisitor {
299
351
/// visitAny(token)
300
352
/// }
301
353
///
302
- public protocol SyntaxAnyVisitor : SyntaxVisitor {
303
- mutating func visitAny( _ node: Syntax ) -> SyntaxVisitorContinueKind
304
- mutating func visitAnyPost( _ node: Syntax )
305
- }
354
+ open class SyntaxAnyVisitor : SyntaxVisitor {
355
+ /// Visiting `UnknownSyntax` specifically.
356
+ /// - Parameter node: the node we are visiting.
357
+ /// - Returns: how should we continue visiting.
358
+ open func visitAny( _ node: Syntax ) -> SyntaxVisitorContinueKind {
359
+ return . visitChildren
360
+ }
306
361
307
- public extension SyntaxAnyVisitor {
308
- mutating func visitAnyPost( _ node: Syntax ) { }
362
+ /// The function called after visiting the node and its descendents.
363
+ /// - node: the node we just finished visiting.
364
+ open func visitAnyPost( _ node: Syntax ) { }
309
365
310
- % for node in SYNTAX_NODES:
311
- % if is_visitable ( node) :
312
- mutating func visit( _ node: ${ node. name} ) -> SyntaxVisitorContinueKind {
313
- return visitAny ( node. _syntaxNode)
314
- }
315
- mutating func visitPost( _ node: ${ node. name} ) {
316
- return visitAnyPost ( node. _syntaxNode)
317
- }
318
- % end
319
- % end
366
+ // MARK: Override type specific visit methods
320
367
321
- mutating func visit( _ token: TokenSyntax ) -> SyntaxVisitorContinueKind {
368
+ override open func visit( _ token: TokenSyntax ) -> SyntaxVisitorContinueKind {
322
369
return visitAny ( token. _syntaxNode)
323
370
}
324
- mutating func visitPost( _ node: TokenSyntax ) {
325
- return visitAnyPost ( node. _syntaxNode)
371
+
372
+ override open func visitPost( _ node: TokenSyntax ) {
373
+ visitAnyPost ( node. _syntaxNode)
326
374
}
327
375
328
- mutating func visit( _ node: UnknownSyntax ) -> SyntaxVisitorContinueKind {
376
+ override open func visit( _ node: UnknownSyntax ) -> SyntaxVisitorContinueKind {
329
377
return visitAny ( node. _syntaxNode)
330
378
}
331
- mutating func visitPost( _ node: UnknownSyntax ) {
332
- return visitAnyPost ( node. _syntaxNode)
333
- }
334
- }
335
-
336
- /// A class version of the `SyntaxVisitor` protocol. This is useful if you
337
- /// intend to have subclasses overriding specific methods of a common base
338
- /// `SyntaxVisitor` class.
339
- ///
340
- /// It workarounds the issue of not being able to override the default
341
- /// implementations of the protocol (see https://bugs.swift.org/browse/SR-103).
342
- open class SyntaxVisitorBase : SyntaxVisitor {
343
- public init ( ) { }
344
379
380
+ override open func visitPost( _ node: UnknownSyntax ) {
381
+ visitAnyPost ( node. _syntaxNode)
382
+ }
383
+
345
384
% for node in SYNTAX_NODES:
346
385
% if is_visitable( node) :
347
- open func visit( _ node: ${ node. name} ) -> SyntaxVisitorContinueKind {
348
- return . visitChildren
349
- }
350
- open func visitPost( _ node: ${ node. name} ) { }
351
- % end
352
- % end
353
-
354
- open func visit( _ token: TokenSyntax ) -> SyntaxVisitorContinueKind {
355
- return . visitChildren
356
- }
357
- open func visitPost( _ node: TokenSyntax ) { }
358
-
359
- open func visit( _ node: UnknownSyntax ) -> SyntaxVisitorContinueKind {
360
- return . visitChildren
361
- }
362
- open func visitPost( _ node: UnknownSyntax ) { }
363
- }
364
-
365
- public extension Syntax {
366
- func walk< Visitor> ( _ visitor: inout Visitor ) where Visitor : SyntaxVisitor {
367
- guard isPresent else { return }
368
- return doVisit ( data, & visitor)
386
+ override open func visit( _ node: ${ node. name} ) -> SyntaxVisitorContinueKind {
387
+ return visitAny ( node. _syntaxNode)
369
388
}
370
- }
371
389
372
- public extension SyntaxProtocol {
373
- func walk< Visitor> ( _ visitor: inout Visitor ) where Visitor : SyntaxVisitor {
374
- return _syntaxNode. walk ( & visitor)
390
+ override open func visitPost( _ node: ${ node. name} ) {
391
+ visitAnyPost ( node. _syntaxNode)
375
392
}
376
- }
377
-
378
- % for node in SYNTAX_NODES:
379
- /// Implementation detail of doVisit(_:_:). Do not call directly.
380
- private func _doVisitImpl${ node. name} < Visitor> (
381
- _ data: SyntaxData, _ visitor : inout Visitor
382
- ) where Visitor : SyntaxVisitor {
383
- % if node. is_base ( ) :
384
- let node = Unknown${ node. name} ( data)
385
- let needsChildren = ( visitor. visit ( node) == . visitChildren)
386
- // Avoid calling into visitChildren if possible.
387
- if needsChildren && node. raw. numberOfChildren > 0 {
388
- visitChildren ( node, & visitor)
389
- }
390
- visitor. visitPost ( node)
391
- % else :
392
- let node = ${ node. name} ( data)
393
- let needsChildren = ( visitor. visit ( node) == . visitChildren)
394
- // Avoid calling into visitChildren if possible.
395
- if needsChildren && node. raw. numberOfChildren > 0 {
396
- visitChildren ( node, & visitor)
397
- }
398
- visitor. visitPost ( node)
399
393
% end
400
- }
401
-
402
394
% end
403
395
404
- fileprivate func doVisit< Visitor> (
405
- _ data: SyntaxData , _ visitor: inout Visitor
406
- ) where Visitor : SyntaxVisitor {
407
- switch data. raw. kind {
408
- case . token:
409
- let node = TokenSyntax ( data)
410
- _ = visitor. visit ( node)
411
- // No children to visit.
412
- visitor. visitPost ( node)
413
- case . unknown:
414
- let node = UnknownSyntax ( data)
415
- let needsChildren = ( visitor. visit ( node) == . visitChildren)
416
- // Avoid calling into visitChildren if possible.
417
- if needsChildren && node. raw. numberOfChildren > 0 {
418
- visitChildren ( node, & visitor)
419
- }
420
- visitor. visitPost ( node)
421
- // The implementation of every generated case goes into its own function. This
422
- // circumvents an issue where the compiler allocates stack space for every
423
- // case statement next to each other in debug builds, causing it to allocate
424
- // ~50KB per call to this function. rdar://55929175
425
- % for node in SYNTAX_NODES:
426
- case . ${ node. swift_syntax_kind} :
427
- _doVisitImpl ${ node. name} ( data, & visitor)
428
- % end
429
- }
430
- }
431
-
432
- fileprivate func visitChildren< SyntaxType: SyntaxProtocol , Visitor> (
433
- _ syntax: SyntaxType , _ visitor: inout Visitor
434
- ) where Visitor : SyntaxVisitor {
435
- let syntaxNode = Syntax ( syntax)
436
- let parentBox = SyntaxBox ( syntaxNode)
437
- for childRaw in PresentRawSyntaxChildren ( syntaxNode) {
438
- let childData = SyntaxData ( childRaw, parentBox: parentBox)
439
- doVisit ( childData, & visitor)
440
- }
441
396
}
0 commit comments