@@ -30,33 +30,28 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
30
30
open class SyntaxRewriter
31
31
"""
32
32
) {
33
- DeclSyntax ( " public init() {} " )
33
+ DeclSyntax ( " public let viewMode: SyntaxTreeViewMode " )
34
34
35
- for node in SYNTAX_NODES where !node. kind. isBase {
36
- if ( node. base == . syntax || node. base == . syntaxCollection) && node. kind != . missing {
37
- DeclSyntax (
38
- """
39
- /// Visit a `` \( node. kind. syntaxType) ``.
40
- /// - Parameter node: the node that is being visited
41
- /// - Returns: the rewritten node
42
- open func visit(_ node: \( node. kind. syntaxType) ) -> \( node. kind. syntaxType) {
43
- return Syntax(visitChildren(node)).cast( \( node. kind. syntaxType) .self)
44
- }
45
- """
46
- )
47
- } else {
48
- DeclSyntax (
49
- """
50
- /// Visit a `` \( node. kind. syntaxType) ``.
51
- /// - Parameter node: the node that is being visited
52
- /// - Returns: the rewritten node
53
- open func visit(_ node: \( node. kind. syntaxType) ) -> \( raw: node. baseType. syntaxBaseName) {
54
- return \( raw: node. baseType. syntaxBaseName) (visitChildren(node))
55
- }
56
- """
57
- )
35
+ DeclSyntax (
36
+ """
37
+ public init(viewMode: SyntaxTreeViewMode = .sourceAccurate) {
38
+ self.viewMode = viewMode
58
39
}
59
- }
40
+ """
41
+ )
42
+
43
+ DeclSyntax (
44
+ """
45
+ /// Rewrite `node` and anchor, making sure that the rewritten node also has
46
+ /// a parent if `node` had one.
47
+ public func rewrite(_ node: some SyntaxProtocol) -> Syntax {
48
+ let rewritten = self.visit(node)
49
+ return withExtendedLifetime(rewritten) {
50
+ return Syntax(node.data.replacingSelf(rewritten.raw, rawNodeArena: rewritten.raw.arena, allocationArena: SyntaxArena()))
51
+ }
52
+ }
53
+ """
54
+ )
60
55
61
56
DeclSyntax (
62
57
"""
@@ -105,6 +100,7 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
105
100
/// Visit any Syntax node.
106
101
/// - Parameter node: the node that is being visited
107
102
/// - Returns: the rewritten node
103
+ @available(*, deprecated, renamed: " rewrite(_:) " )
108
104
public func visit(_ node: Syntax) -> Syntax {
109
105
return visit(node.data)
110
106
}
@@ -114,11 +110,37 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
114
110
DeclSyntax (
115
111
"""
116
112
public func visit<T: SyntaxChildChoices>(_ node: T) -> T {
117
- return visit(Syntax( node) ).cast(T.self)
113
+ return visit(node.data ).cast(T.self)
118
114
}
119
115
"""
120
116
)
121
117
118
+ for node in SYNTAX_NODES where !node. kind. isBase {
119
+ if ( node. base == . syntax || node. base == . syntaxCollection) && node. kind != . missing {
120
+ DeclSyntax (
121
+ """
122
+ /// Visit a `` \( node. kind. syntaxType) ``.
123
+ /// - Parameter node: the node that is being visited
124
+ /// - Returns: the rewritten node
125
+ open func visit(_ node: \( node. kind. syntaxType) ) -> \( node. kind. syntaxType) {
126
+ return Syntax(visitChildren(node)).cast( \( node. kind. syntaxType) .self)
127
+ }
128
+ """
129
+ )
130
+ } else {
131
+ DeclSyntax (
132
+ """
133
+ /// Visit a `` \( node. kind. syntaxType) ``.
134
+ /// - Parameter node: the node that is being visited
135
+ /// - Returns: the rewritten node
136
+ open func visit(_ node: \( node. kind. syntaxType) ) -> \( raw: node. baseType. syntaxBaseName) {
137
+ return \( raw: node. baseType. syntaxBaseName) (visitChildren(node))
138
+ }
139
+ """
140
+ )
141
+ }
142
+ }
143
+
122
144
for baseKind in SyntaxNodeKind . allCases where baseKind. isBase && baseKind != . syntax && baseKind != . syntaxCollection {
123
145
DeclSyntax (
124
146
"""
@@ -258,42 +280,44 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
258
280
// initialize the new layout. Once we know that we have to rewrite the
259
281
// layout, we need to collect all futher children, regardless of whether
260
282
// they are rewritten or not.
261
-
283
+
262
284
// newLayout is nil until the first child node is rewritten and rewritten
263
285
// nodes are being collected.
264
286
var newLayout: ContiguousArray<RawSyntax?>?
265
-
287
+
266
288
// Rewritten children just to keep their 'SyntaxArena' alive until they are
267
289
// wrapped with 'Syntax'
268
290
var rewrittens: ContiguousArray<Syntax> = []
269
-
291
+
270
292
let syntaxNode = node._syntaxNode
271
-
293
+
272
294
// Incrementing i manually is faster than using .enumerated()
273
295
var childIndex = 0
274
296
for (raw, info) in RawSyntaxChildren(syntaxNode) {
275
297
defer { childIndex += 1 }
276
- guard let child = raw else {
277
- // Node does not exist. If we are collecting rewritten nodes, we need to
278
- // collect this one as well, otherwise we can ignore it.
298
+
299
+ guard let child = raw, viewMode.shouldTraverse(node: child) else {
300
+ // Node does not exist or should not be visited. If we are collecting
301
+ // rewritten nodes, we need to collect this one as well, otherwise we
302
+ // can ignore it.
279
303
if newLayout != nil {
280
- newLayout!.append(nil )
304
+ newLayout!.append(raw )
281
305
}
282
306
continue
283
307
}
284
-
308
+
285
309
// Build the Syntax node to rewrite
286
310
let absoluteRaw = AbsoluteRawSyntax(raw: child, info: info)
287
311
let data = SyntaxData(absoluteRaw, parent: syntaxNode)
288
-
312
+
289
313
let rewritten = visit(data)
290
314
if rewritten.data.nodeId != info.nodeId {
291
315
// The node was rewritten, let's handle it
292
316
if newLayout == nil {
293
317
// We have not yet collected any previous rewritten nodes. Initialize
294
318
// the new layout with the previous nodes of the parent. This is
295
319
// possible, since we know they were not rewritten.
296
-
320
+
297
321
// The below implementation is based on Collection.map but directly
298
322
// reserves enough capacity for the entire layout.
299
323
newLayout = ContiguousArray<RawSyntax?>()
@@ -302,7 +326,7 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
302
326
newLayout!.append(node.raw.layoutView!.children[j])
303
327
}
304
328
}
305
-
329
+
306
330
// Now that we know we have a new layout in which we collect rewritten
307
331
// nodes, add it.
308
332
rewrittens.append(rewritten)
@@ -315,13 +339,13 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
315
339
}
316
340
}
317
341
}
318
-
342
+
319
343
if let newLayout {
320
344
// A child node was rewritten. Build the updated node.
321
-
345
+
322
346
// Sanity check, ensure the new children are the same length.
323
347
precondition(newLayout.count == node.raw.layoutView!.children.count)
324
-
348
+
325
349
let arena = SyntaxArena()
326
350
let newRaw = node.raw.layoutView!.replacingLayout(with: Array(newLayout), arena: arena)
327
351
// 'withExtendedLifetime' to keep 'SyntaxArena's of them alive until here.
@@ -335,18 +359,5 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
335
359
}
336
360
"""
337
361
)
338
-
339
- DeclSyntax (
340
- """
341
- /// Rewrite `node` and anchor, making sure that the rewritten node also has
342
- /// a parent if `node` had one.
343
- public func rewrite(_ node: Syntax) -> Syntax {
344
- let rewritten = self.visit(node)
345
- return withExtendedLifetime(rewritten) {
346
- return Syntax(node.data.replacingSelf(rewritten.raw, rawNodeArena: rewritten.raw.arena, allocationArena: SyntaxArena()))
347
- }
348
- }
349
- """
350
- )
351
362
}
352
363
}
0 commit comments