Skip to content

Commit a47eec9

Browse files
committed
Simplify SyntaxVisitor
Use generics instead of code generation to significantly improve compile time of `SyntaxVisitor` (and also clean it up).
1 parent 39a4239 commit a47eec9

File tree

2 files changed

+1680
-3312
lines changed

2 files changed

+1680
-3312
lines changed

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SyntaxVisitorFile.swift

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -92,22 +92,26 @@ let syntaxVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
9292
"""
9393
)
9494

95-
for node in NON_BASE_SYNTAX_NODES {
96-
DeclSyntax(
97-
"""
98-
/// Implementation detail of doVisit(_:_:). Do not call directly.
99-
private func visitImpl\(node.kind.syntaxType)(_ data: SyntaxData) {
100-
let node = \(node.kind.syntaxType)(data)
101-
let needsChildren = (visit(node) == .visitChildren)
102-
// Avoid calling into visitChildren if possible.
103-
if needsChildren && !node.raw.layoutView!.children.isEmpty {
104-
visitChildren(node)
105-
}
106-
visitPost(node)
95+
DeclSyntax(
96+
"""
97+
/// Interpret `data` as a node of type `nodeType`, visit it, calling
98+
/// the `visit` and `visitPost` functions during visitation.
99+
private func visitImpl<NodeType: SyntaxProtocol>(
100+
_ data: SyntaxData,
101+
_ nodeType: NodeType.Type,
102+
_ visit: (NodeType) -> SyntaxVisitorContinueKind,
103+
_ visitPost: (NodeType) -> Void
104+
) {
105+
let node = NodeType(Syntax(data))!
106+
let needsChildren = (visit(node) == .visitChildren)
107+
// Avoid calling into visitChildren if possible.
108+
if needsChildren && !node.raw.layoutView!.children.isEmpty {
109+
visitChildren(node)
107110
}
108-
"""
109-
)
110-
}
111+
visitPost(node)
112+
}
113+
"""
114+
)
111115

112116
try FunctionDeclSyntax("private func visit(_ data: SyntaxData)") {
113117
try SwitchExprSyntax("switch data.raw.kind") {
@@ -119,17 +123,13 @@ let syntaxVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
119123
"""
120124
// No children to visit.
121125
visitPost(node)
122-
// The implementation of every generated case goes into its own function. This
123-
// circumvents an issue where the compiler allocates stack space for every
124-
// case statement next to each other in debug builds, causing it to allocate
125-
// ~50KB per call to this function. rdar://55929175
126126
"""
127127
)
128128
}
129129

130130
for node in NON_BASE_SYNTAX_NODES {
131131
SwitchCaseSyntax("case .\(node.varOrCaseName):") {
132-
ExprSyntax("visitImpl\(node.kind.syntaxType)(data)")
132+
ExprSyntax("visitImpl(data, \(node.kind.syntaxType).self, visit, visitPost)")
133133
}
134134
}
135135
}

0 commit comments

Comments
 (0)