File tree Expand file tree Collapse file tree 4 files changed +36
-1
lines changed Expand file tree Collapse file tree 4 files changed +36
-1
lines changed Original file line number Diff line number Diff line change
1
+ // A closure without a signature. The test will ensure it stays the same after
2
+ // applying a rewriting pass.
3
+ let x : ( ) -> Void = { }
Original file line number Diff line number Diff line change @@ -37,4 +37,20 @@ VisitorTests.test("Basic") {
37
37
} )
38
38
}
39
39
40
+ VisitorTests . test ( " RewritingNodeWithEmptyChild " ) {
41
+ class ClosureRewriter : SyntaxRewriter {
42
+ override func visit( _ node: ClosureExprSyntax ) -> ExprSyntax {
43
+ // Perform a no-op transform that requires rebuilding the node.
44
+ return node. withSignature ( node. signature)
45
+ }
46
+ }
47
+ expectDoesNotThrow ( {
48
+ let parsed = try SourceFileSyntax . decodeSourceFileSyntax ( try
49
+ SwiftLang . parse ( getInput ( " closure.swift " ) ) )
50
+ let rewriter = ClosureRewriter ( )
51
+ let rewritten = rewriter. visit ( parsed)
52
+ expectEqual ( parsed. description, rewritten. description)
53
+ } )
54
+ }
55
+
40
56
runAllTests ( )
Original file line number Diff line number Diff line change @@ -68,6 +68,12 @@ extension Syntax {
68
68
return SyntaxChildren ( node: self )
69
69
}
70
70
71
+ /// The number of children, `present` or `missing`, in this node.
72
+ /// This value can be used safely with `child(at:)`.
73
+ public var numberOfChildren : Int {
74
+ return data. childCaches. count
75
+ }
76
+
71
77
/// Whether or not this node it marked as `present`.
72
78
public var isPresent : Bool {
73
79
return raw. presence == . present
Original file line number Diff line number Diff line change @@ -64,7 +64,17 @@ open class SyntaxRewriter {
64
64
}
65
65
66
66
func visitChildren( _ node: Syntax ) -> Syntax {
67
- let newLayout = node. children. map { visit ( $0) . raw }
67
+ // Visit all children of this node, returning `nil` if child is not
68
+ // present. This will ensure that there are always the same number
69
+ // of children after transforming.
70
+ let newLayout = ( 0 ..< node. numberOfChildren) . map { ( i: Int ) -> RawSyntax ? in
71
+ guard let child = node. child ( at: i) else { return nil }
72
+ return visit ( child) . raw
73
+ }
74
+
75
+ // Sanity check, ensure the new children are the same length.
76
+ assert ( newLayout. count == node. raw. layout. count)
77
+
68
78
return makeSyntax ( node. raw. replacingLayout ( newLayout) )
69
79
}
70
80
}
You can’t perform that action at this time.
0 commit comments