@@ -30,33 +30,27 @@ 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+ let arena = SyntaxArena()
50+ return Syntax(node.data.replacingSelf(rewritten.raw, arena: arena))
51+ }
52+ """
53+ )
6054
6155 DeclSyntax (
6256 """
@@ -102,22 +96,37 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
10296
10397 DeclSyntax (
10498 """
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)
110101 }
111102 """
112103 )
113104
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+ )
118128 }
119- """
120- )
129+ }
121130
122131 for baseKind in SyntaxNodeKind . allCases where baseKind. isBase && baseKind != . syntax && baseKind != . syntaxCollection {
123132 DeclSyntax (
@@ -258,42 +267,44 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
258267 // initialize the new layout. Once we know that we have to rewrite the
259268 // layout, we need to collect all futher children, regardless of whether
260269 // they are rewritten or not.
261-
270+
262271 // newLayout is nil until the first child node is rewritten and rewritten
263272 // nodes are being collected.
264273 var newLayout: ContiguousArray<RawSyntax?>?
265-
274+
266275 // Rewritten children just to keep their 'SyntaxArena' alive until they are
267276 // wrapped with 'Syntax'
268277 var rewrittens: ContiguousArray<Syntax> = []
269-
278+
270279 let syntaxNode = node._syntaxNode
271-
280+
272281 // Incrementing i manually is faster than using .enumerated()
273282 var childIndex = 0
274283 for (raw, info) in RawSyntaxChildren(syntaxNode) {
275284 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.
279290 if newLayout != nil {
280- newLayout!.append(nil )
291+ newLayout!.append(raw )
281292 }
282293 continue
283294 }
284-
295+
285296 // Build the Syntax node to rewrite
286297 let absoluteRaw = AbsoluteRawSyntax(raw: child, info: info)
287298 let data = SyntaxData(absoluteRaw, parent: syntaxNode)
288-
299+
289300 let rewritten = visit(data)
290301 if rewritten.data.nodeId != info.nodeId {
291302 // The node was rewritten, let's handle it
292303 if newLayout == nil {
293304 // We have not yet collected any previous rewritten nodes. Initialize
294305 // the new layout with the previous nodes of the parent. This is
295306 // possible, since we know they were not rewritten.
296-
307+
297308 // The below implementation is based on Collection.map but directly
298309 // reserves enough capacity for the entire layout.
299310 newLayout = ContiguousArray<RawSyntax?>()
@@ -302,7 +313,7 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
302313 newLayout!.append(node.raw.layoutView!.children[j])
303314 }
304315 }
305-
316+
306317 // Now that we know we have a new layout in which we collect rewritten
307318 // nodes, add it.
308319 rewrittens.append(rewritten)
@@ -315,13 +326,13 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
315326 }
316327 }
317328 }
318-
329+
319330 if let newLayout {
320331 // A child node was rewritten. Build the updated node.
321-
332+
322333 // Sanity check, ensure the new children are the same length.
323334 precondition(newLayout.count == node.raw.layoutView!.children.count)
324-
335+
325336 let arena = SyntaxArena()
326337 let newRaw = node.raw.layoutView!.replacingLayout(with: Array(newLayout), arena: arena)
327338 // 'withExtendedLifetime' to keep 'SyntaxArena's of them alive until here.
@@ -335,17 +346,5 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
335346 }
336347 """
337348 )
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- )
350349 }
351350}
0 commit comments