@@ -30,33 +30,28 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
3030 open class SyntaxRewriter
3131 """
3232 ) {
33- DeclSyntax ( " public init() {} " )
33+ DeclSyntax ( " public let viewMode: SyntaxTreeViewMode " )
3434
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
5839 }
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+ return withExtendedLifetime(rewritten) {
50+ return Syntax(node.data.replacingSelf(rewritten.raw, rawNodeArena: rewritten.raw.arena, allocationArena: SyntaxArena()))
51+ }
52+ }
53+ """
54+ )
6055
6156 DeclSyntax (
6257 """
@@ -105,6 +100,7 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
105100 /// Visit any Syntax node.
106101 /// - Parameter node: the node that is being visited
107102 /// - Returns: the rewritten node
103+ @available(*, deprecated, renamed: " rewrite(_:) " )
108104 public func visit(_ node: Syntax) -> Syntax {
109105 return visit(node.data)
110106 }
@@ -114,11 +110,37 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
114110 DeclSyntax (
115111 """
116112 public func visit<T: SyntaxChildChoices>(_ node: T) -> T {
117- return visit(Syntax( node) ).cast(T.self)
113+ return visit(node.data ).cast(T.self)
118114 }
119115 """
120116 )
121117
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+
122144 for baseKind in SyntaxNodeKind . allCases where baseKind. isBase && baseKind != . syntax && baseKind != . syntaxCollection {
123145 DeclSyntax (
124146 """
@@ -258,42 +280,44 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
258280 // initialize the new layout. Once we know that we have to rewrite the
259281 // layout, we need to collect all futher children, regardless of whether
260282 // they are rewritten or not.
261-
283+
262284 // newLayout is nil until the first child node is rewritten and rewritten
263285 // nodes are being collected.
264286 var newLayout: ContiguousArray<RawSyntax?>?
265-
287+
266288 // Rewritten children just to keep their 'SyntaxArena' alive until they are
267289 // wrapped with 'Syntax'
268290 var rewrittens: ContiguousArray<Syntax> = []
269-
291+
270292 let syntaxNode = node._syntaxNode
271-
293+
272294 // Incrementing i manually is faster than using .enumerated()
273295 var childIndex = 0
274296 for (raw, info) in RawSyntaxChildren(syntaxNode) {
275297 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.
279303 if newLayout != nil {
280- newLayout!.append(nil )
304+ newLayout!.append(raw )
281305 }
282306 continue
283307 }
284-
308+
285309 // Build the Syntax node to rewrite
286310 let absoluteRaw = AbsoluteRawSyntax(raw: child, info: info)
287311 let data = SyntaxData(absoluteRaw, parent: syntaxNode)
288-
312+
289313 let rewritten = visit(data)
290314 if rewritten.data.nodeId != info.nodeId {
291315 // The node was rewritten, let's handle it
292316 if newLayout == nil {
293317 // We have not yet collected any previous rewritten nodes. Initialize
294318 // the new layout with the previous nodes of the parent. This is
295319 // possible, since we know they were not rewritten.
296-
320+
297321 // The below implementation is based on Collection.map but directly
298322 // reserves enough capacity for the entire layout.
299323 newLayout = ContiguousArray<RawSyntax?>()
@@ -302,7 +326,7 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
302326 newLayout!.append(node.raw.layoutView!.children[j])
303327 }
304328 }
305-
329+
306330 // Now that we know we have a new layout in which we collect rewritten
307331 // nodes, add it.
308332 rewrittens.append(rewritten)
@@ -315,13 +339,13 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
315339 }
316340 }
317341 }
318-
342+
319343 if let newLayout {
320344 // A child node was rewritten. Build the updated node.
321-
345+
322346 // Sanity check, ensure the new children are the same length.
323347 precondition(newLayout.count == node.raw.layoutView!.children.count)
324-
348+
325349 let arena = SyntaxArena()
326350 let newRaw = node.raw.layoutView!.replacingLayout(with: Array(newLayout), arena: arena)
327351 // 'withExtendedLifetime' to keep 'SyntaxArena's of them alive until here.
@@ -335,18 +359,5 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
335359 }
336360 """
337361 )
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- )
351362 }
352363}
0 commit comments