Skip to content

Commit 6be3f55

Browse files
committed
Modify SyntaxVisitor to supprt throwing during travresal.
SyntaxVisitor becomes ThrowingSyntaxVisitor<E: Error>, and each visit method now supports throwing an error of type `E`. This does not impact existing users of SwiftSyntax. SyntaxVisitor becomes a typealias for `ThrowingSyntaxVisitor<Never>`, which behaves the same the same as the current SyntaxVisitor.
1 parent 3274aaa commit 6be3f55

File tree

9 files changed

+3297
-3261
lines changed

9 files changed

+3297
-3261
lines changed

CodeGeneration/Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ let package = Package(
1212
.executable(name: "generate-swift-syntax", targets: ["generate-swift-syntax"])
1313
],
1414
dependencies: [
15-
.package(url: "https://github.com/swiftlang/swift-syntax", from: "510.0.0"),
15+
.package(url: "https://github.com/swiftlang/swift-syntax", from: "600.0.0"),
1616
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.2.2"),
1717
],
1818
targets: [

CodeGeneration/Sources/generate-swift-syntax/templates/swiftparserdiagnostics/TokenNameForDiagnosticsFile.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ let tokenNameForDiagnosticFile = SourceFileSyntax(leadingTrivia: copyrightHeader
3737
elements: .switchCases(
3838
SwitchCaseListSyntax {
3939
SwitchCaseSyntax("@unknown default:") {
40-
StmtSyntax("fatalError()")
40+
StmtSyntax("return fatalError()")
4141
}
4242
}
4343
)

CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/SyntaxAnyVisitorFile.swift

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,20 @@ import SyntaxSupport
1616
import Utils
1717

1818
let syntaxAnyVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
19+
DeclSyntax(
20+
"""
21+
/// An instance of `ThrowingSyntaxAnyVisitor` that nevers throws.
22+
public typealias SyntaxAnyVisitor = ThrowingSyntaxAnyVisitor<Never>
23+
"""
24+
)
25+
1926
try! ClassDeclSyntax(
2027
"""
21-
/// A `SyntaxVisitor` that can visit the nodes as generic ``Syntax`` values.
28+
/// A `ThrowingSyntaxVisitor` that can visit the nodes as generic ``Syntax`` values.
2229
///
23-
/// This subclass of `SyntaxVisitor` is slower than the type-specific visitation
24-
/// of `SyntaxVisitor`. Use `SyntaxAnyVisitor` if the `visitAny(_)` function
25-
/// would be useful to have, otherwise inherit from `SyntaxVisitor`.
30+
/// This subclass of `ThrowingSyntaxVisitor` is slower than the type-specific visitation
31+
/// of `ThrowingSyntaxVisitor`. Use `ThrowingSyntaxAnyVisitor` if the `visitAny(_)` function
32+
/// would be useful to have, otherwise inherit from `ThrowingSyntaxVisitor`.
2633
///
2734
/// This works by overriding the type-specific visit function that delegate to
2835
/// `visitAny(_)`. A subclass that provides a custom type-specific visit
@@ -42,12 +49,12 @@ let syntaxAnyVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
4249
/// }
4350
/// }
4451
/// ```
45-
open class SyntaxAnyVisitor: SyntaxVisitor
52+
open class ThrowingSyntaxAnyVisitor<E: Error>: ThrowingSyntaxVisitor<E>
4653
"""
4754
) {
4855
DeclSyntax(
4956
"""
50-
open func visitAny(_ node: Syntax) -> SyntaxVisitorContinueKind {
57+
open func visitAny(_ node: Syntax) throws(E) -> SyntaxVisitorContinueKind {
5158
return .visitChildren
5259
}
5360
"""
@@ -57,24 +64,24 @@ let syntaxAnyVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
5764
"""
5865
/// The function called after visiting the node and its descendants.
5966
/// - node: the node we just finished visiting.
60-
open func visitAnyPost(_ node: Syntax) {}
67+
open func visitAnyPost(_ node: Syntax) throws(E) {}
6168
"""
6269
)
6370

6471
DeclSyntax(
6572
"""
6673
// MARK: Override type specific visit methods
6774
68-
override open func visit(_ token: TokenSyntax) -> SyntaxVisitorContinueKind {
69-
return visitAny(token._syntaxNode)
75+
override open func visit(_ token: TokenSyntax) throws(E) -> SyntaxVisitorContinueKind {
76+
return try visitAny(token._syntaxNode)
7077
}
7178
"""
7279
)
7380

7481
DeclSyntax(
7582
"""
76-
override open func visitPost(_ node: TokenSyntax) {
77-
visitAnyPost(node._syntaxNode)
83+
override open func visitPost(_ node: TokenSyntax) throws(E) {
84+
try visitAnyPost(node._syntaxNode)
7885
}
7986
"""
8087
)
@@ -83,17 +90,17 @@ let syntaxAnyVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
8390
DeclSyntax(
8491
"""
8592
\(node.apiAttributes())\
86-
override open func visit(_ node: \(node.kind.syntaxType)) -> SyntaxVisitorContinueKind {
87-
return visitAny(node._syntaxNode)
93+
override open func visit(_ node: \(node.kind.syntaxType)) throws(E) -> SyntaxVisitorContinueKind {
94+
return try visitAny(node._syntaxNode)
8895
}
8996
"""
9097
)
9198

9299
DeclSyntax(
93100
"""
94101
\(node.apiAttributes())\
95-
override open func visitPost(_ node: \(node.kind.syntaxType)) {
96-
visitAnyPost(node._syntaxNode)
102+
override open func visitPost(_ node: \(node.kind.syntaxType)) throws(E) {
103+
try visitAnyPost(node._syntaxNode)
97104
}
98105
"""
99106
)

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

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@ let syntaxVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
2929
"""
3030
)
3131

32-
try! ClassDeclSyntax("open class SyntaxVisitor") {
32+
DeclSyntax(
33+
"""
34+
/// An instance of `ThrowingSyntaxVisitor` that never throws.
35+
public typealias SyntaxVisitor = ThrowingSyntaxVisitor<Never>
36+
"""
37+
)
38+
39+
try! ClassDeclSyntax("open class ThrowingSyntaxVisitor<E: Error>") {
3340
DeclSyntax("public let viewMode: SyntaxTreeViewMode")
3441

3542
DeclSyntax(
@@ -44,8 +51,8 @@ let syntaxVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
4451
"""
4552
/// Walk all nodes of the given syntax tree, calling the corresponding `visit`
4653
/// function for every node that is being visited.
47-
public func walk(_ node: some SyntaxProtocol) {
48-
dispatchVisit(Syntax(node))
54+
public func walk(_ node: some SyntaxProtocol) throws (E) {
55+
try dispatchVisit(Syntax(node))
4956
}
5057
"""
5158
)
@@ -57,7 +64,7 @@ let syntaxVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
5764
/// - Parameter node: the node we are visiting.
5865
/// - Returns: how should we continue visiting.
5966
\(node.apiAttributes())\
60-
open func visit(_ node: \(node.kind.syntaxType)) -> SyntaxVisitorContinueKind {
67+
open func visit(_ node: \(node.kind.syntaxType)) throws (E) -> SyntaxVisitorContinueKind {
6168
return .visitChildren
6269
}
6370
"""
@@ -68,7 +75,7 @@ let syntaxVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
6875
/// The function called after visiting \(raw: node.kind.doccLink) and its descendants.
6976
/// - node: the node we just finished visiting.
7077
\(node.apiAttributes())\
71-
open func visitPost(_ node: \(node.kind.syntaxType)) {}
78+
open func visitPost(_ node: \(node.kind.syntaxType)) throws (E) {}
7279
"""
7380
)
7481
}
@@ -78,7 +85,7 @@ let syntaxVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
7885
/// Visiting ``TokenSyntax`` specifically.
7986
/// - Parameter token: the token we are visiting.
8087
/// - Returns: how should we continue visiting.
81-
open func visit(_ token: TokenSyntax) -> SyntaxVisitorContinueKind {
88+
open func visit(_ token: TokenSyntax) throws (E) -> SyntaxVisitorContinueKind {
8289
return .visitChildren
8390
}
8491
"""
@@ -88,7 +95,7 @@ let syntaxVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
8895
"""
8996
/// The function called after visiting the node and its descendants.
9097
/// - node: the node we just finished visiting.
91-
open func visitPost(_ node: TokenSyntax) {}
98+
open func visitPost(_ node: TokenSyntax) throws (E) {}
9299
"""
93100
)
94101

@@ -98,10 +105,10 @@ let syntaxVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
98105
DeclSyntax(
99106
"""
100107
@inline(never)
101-
private func visitTokenSyntaxImpl(_ node: Syntax) {
102-
_ = visit(TokenSyntax(unsafeCasting: node))
108+
private func visitTokenSyntaxImpl(_ node: Syntax) throws (E) {
109+
_ = try visit(TokenSyntax(unsafeCasting: node))
103110
// No children to visit.
104-
visitPost(TokenSyntax(unsafeCasting: node))
111+
try visitPost(TokenSyntax(unsafeCasting: node))
105112
}
106113
"""
107114
)
@@ -110,11 +117,11 @@ let syntaxVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
110117
DeclSyntax(
111118
"""
112119
@inline(never)
113-
private func visit\(node.kind.syntaxType)Impl(_ node: Syntax) {
114-
if visit(\(node.kind.syntaxType)(unsafeCasting: node)) == .visitChildren {
115-
visitChildren(node)
120+
private func visit\(node.kind.syntaxType)Impl(_ node: Syntax) throws (E) {
121+
if try visit(\(node.kind.syntaxType)(unsafeCasting: node)) == .visitChildren {
122+
try visitChildren(node)
116123
}
117-
visitPost(\(node.kind.syntaxType)(unsafeCasting: node))
124+
try visitPost(\(node.kind.syntaxType)(unsafeCasting: node))
118125
}
119126
"""
120127
)
@@ -136,7 +143,7 @@ let syntaxVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
136143
condition: ExprSyntax("DEBUG"),
137144
elements: .statements(
138145
try CodeBlockItemListSyntax {
139-
try FunctionDeclSyntax(
146+
try FunctionDeclSyntax(
140147
"""
141148
/// Implementation detail of visit(_:). Do not call directly.
142149
///
@@ -156,28 +163,28 @@ let syntaxVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
156163
/// that determines the correct visitation function will be popped of the
157164
/// stack before the function is being called, making the switch's stack
158165
/// space transient instead of having it linger in the call stack.
159-
private func visitationFunc(for node: Syntax) -> (Syntax) -> Void
166+
private func visitationFunc(for node: Syntax) -> (Syntax) throws (E) -> Void
160167
"""
161-
) {
162-
try SwitchExprSyntax("switch node.raw.kind") {
163-
SwitchCaseSyntax("case .token:") {
164-
StmtSyntax("return self.visitTokenSyntaxImpl(_:)")
165-
}
168+
) {
169+
try SwitchExprSyntax("switch node.raw.kind") {
170+
SwitchCaseSyntax("case .token:") {
171+
StmtSyntax("return self.visitTokenSyntaxImpl(_:)")
172+
}
166173

167-
for node in NON_BASE_SYNTAX_NODES {
168-
SwitchCaseSyntax("case .\(node.enumCaseCallName):") {
169-
StmtSyntax(
170-
"return self.visit\(node.kind.syntaxType)Impl(_:)"
171-
)
174+
for node in NON_BASE_SYNTAX_NODES {
175+
SwitchCaseSyntax("case .\(node.enumCaseCallName):") {
176+
StmtSyntax(
177+
"return self.visit\(node.kind.syntaxType)Impl(_:)"
178+
)
179+
}
172180
}
173181
}
174182
}
175-
}
176183

177184
DeclSyntax(
178185
"""
179-
private func dispatchVisit(_ node: Syntax) {
180-
return visitationFunc(for: node)(node)
186+
private func dispatchVisit(_ node: Syntax) throws (E) {
187+
return try visitationFunc(for: node)(node)
181188
}
182189
"""
183190
)
@@ -190,17 +197,17 @@ let syntaxVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
190197
CodeBlockItemListSyntax {
191198
try! FunctionDeclSyntax(
192199
"""
193-
private func dispatchVisit(_ node: Syntax)
200+
private func dispatchVisit(_ node: Syntax) throws (E)
194201
"""
195202
) {
196203
try SwitchExprSyntax("switch node.raw.kind") {
197204
SwitchCaseSyntax("case .token:") {
198-
ExprSyntax("self.visitTokenSyntaxImpl(node)")
205+
ExprSyntax("try self.visitTokenSyntaxImpl(node)")
199206
}
200207

201208
for node in NON_BASE_SYNTAX_NODES {
202209
SwitchCaseSyntax("case .\(node.enumCaseCallName):") {
203-
ExprSyntax("self.visit\(node.kind.syntaxType)Impl(node)")
210+
ExprSyntax("try self.visit\(node.kind.syntaxType)Impl(node)")
204211
}
205212
}
206213
}
@@ -213,9 +220,9 @@ let syntaxVisitorFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
213220

214221
DeclSyntax(
215222
"""
216-
private func visitChildren(_ node: Syntax) {
223+
private func visitChildren(_ node: Syntax) throws (E) {
217224
for case let childDataRef? in node.layoutBuffer where viewMode.shouldTraverse(node: childDataRef.pointee.raw) {
218-
dispatchVisit(Syntax(arena: node.arena, dataRef: childDataRef))
225+
try dispatchVisit(Syntax(arena: node.arena, dataRef: childDataRef))
219226
}
220227
}
221228
"""

Sources/SwiftParser/generated/ExperimentalFeatures.swift

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/SwiftParserDiagnostics/generated/TokenNameForDiagnostics.swift

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)