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