Skip to content

Commit 77aad96

Browse files
authored
Merge pull request #1136 from kimdv/kimdv/move-gyb-files-to-codegen
2 parents 724b5d3 + fbc1903 commit 77aad96

File tree

10 files changed

+1779
-1430
lines changed

10 files changed

+1779
-1430
lines changed

CodeGeneration/Sources/SyntaxSupport/Node.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ public class Node {
7373
return syntaxKind.contains("Token") || collectionElement.contains("Token")
7474
}
7575

76+
public var isVisitable: Bool {
77+
return !isBase
78+
}
79+
7680
init(name: String,
7781
nameForDiagnostics: String?,
7882
description: String? = nil,

CodeGeneration/Sources/generate-swiftsyntax/GenerateSwiftSyntax.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ struct GenerateSwiftSyntax: ParsableCommand {
2727
try generateTemplates(
2828
templates: [
2929
(miscFile, "Misc.swift"),
30+
(syntaxAnyVisitorFile, "SyntaxAnyVisitor.swift"),
31+
(syntaxBaseNodesFile, "SyntaxBaseNodes.swift"),
3032
],
3133
destination: URL(fileURLWithPath: generatedPath),
3234
verbose: verbose
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SwiftSyntax
14+
import SwiftSyntaxBuilder
15+
import SyntaxSupport
16+
import Utils
17+
18+
let syntaxAnyVisitorFile = SourceFile {
19+
ClassDecl("""
20+
\(generateCopyrightHeader(for: "generate-swiftsyntax"))
21+
22+
/// A `SyntaxVisitor` that can visit the nodes as generic `Syntax` values.
23+
///
24+
/// This subclass of `SyntaxVisitor` is slower than the type-specific visitation
25+
/// of `SyntaxVisitor`. Use `SyntaxAnyVisitor` if the `visitAny(_)` function
26+
/// would be useful to have, otherwise inherit from `SyntaxVisitor`.
27+
///
28+
/// This works by overriding the type-specific visit function that delegate to
29+
/// `visitAny(_)`. A subclass that provides a custom type-specific visit
30+
/// function, should also call `visitAny(_)` in its implementation, if calling
31+
/// `visitAny` is needed:
32+
///
33+
/// struct MyVisitor: SyntaxAnyVisitor {
34+
/// func visitAny(_ node: Syntax) -> SyntaxVisitorContinueKind {
35+
/// <code>
36+
/// }
37+
///
38+
/// func visit(_ token: TokenSyntax) -> SyntaxVisitorContinueKind {
39+
/// <code>
40+
/// // Call this to pass tokens to `visitAny(_)` as well if needed
41+
/// visitAny(token)
42+
/// }
43+
open class SyntaxAnyVisitor: SyntaxVisitor
44+
""") {
45+
FunctionDecl("""
46+
open func visitAny(_ node: Syntax) -> SyntaxVisitorContinueKind {
47+
return .visitChildren
48+
}
49+
""")
50+
51+
FunctionDecl("""
52+
/// The function called after visiting the node and its descendents.
53+
/// - node: the node we just finished visiting.
54+
open func visitAnyPost(_ node: Syntax) {}
55+
""")
56+
57+
FunctionDecl("""
58+
// MARK: Override type specific visit methods
59+
60+
override open func visit(_ token: TokenSyntax) -> SyntaxVisitorContinueKind {
61+
return visitAny(token._syntaxNode)
62+
}
63+
""")
64+
65+
FunctionDecl("""
66+
override open func visitPost(_ node: TokenSyntax) {
67+
visitAnyPost(node._syntaxNode)
68+
}
69+
""")
70+
71+
for node in SYNTAX_NODES where node.isVisitable {
72+
FunctionDecl("""
73+
override open func visit(_ node: \(raw: node.name)) -> SyntaxVisitorContinueKind {
74+
return visitAny(node._syntaxNode)
75+
}
76+
""")
77+
78+
FunctionDecl("""
79+
override open func visitPost(_ node: \(raw: node.name)) {
80+
visitAnyPost(node._syntaxNode)
81+
}
82+
""")
83+
}
84+
}
85+
}
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SwiftSyntax
14+
import SwiftSyntaxBuilder
15+
import SyntaxSupport
16+
import Utils
17+
18+
let syntaxBaseNodesFile = SourceFile(leadingTrivia: [.blockComment(generateCopyrightHeader(for: "generate-swiftsyntax"))]) {
19+
for node in SYNTAX_NODES where node.isBase {
20+
ProtocolDecl("""
21+
// MARK: - \(raw: node.name)
22+
23+
/// Protocol to which all `\(raw: node.name)` nodes conform. Extension point to add
24+
/// common methods to all `\(raw: node.name)` nodes.
25+
/// DO NOT CONFORM TO THIS PROTOCOL YOURSELF!
26+
public protocol \(raw: node.name)Protocol: \(raw: node.baseType.baseName)Protocol {}
27+
""")
28+
29+
ExtensionDecl("public extension Syntax") {
30+
FunctionDecl("""
31+
/// Check whether the non-type erased version of this syntax node conforms to
32+
/// \(raw: node.name)Protocol.
33+
/// Note that this will incur an existential conversion.
34+
func isProtocol(_: \(raw: node.name)Protocol.Protocol) -> Bool {
35+
return self.asProtocol(\(raw: node.name)Protocol.self) != nil
36+
}
37+
""")
38+
39+
FunctionDecl("""
40+
/// Return the non-type erased version of this syntax node if it conforms to
41+
/// \(raw: node.name)Protocol. Otherwise return nil.
42+
/// Note that this will incur an existential conversion.
43+
func asProtocol(_: \(raw: node.name)Protocol.Protocol) -> \(raw: node.name)Protocol? {
44+
return self.asProtocol(SyntaxProtocol.self) as? \(raw: node.name)Protocol
45+
}
46+
""")
47+
}
48+
49+
StructDecl("""
50+
\(node.description ?? "")
51+
public struct \(node.name): \(node.name)Protocol, SyntaxHashable
52+
""") {
53+
VariableDecl("public let _syntaxNode: Syntax")
54+
55+
InitializerDecl("""
56+
/// Create a `\(raw: node.name)` node from a specialized syntax node.
57+
public init<S: \(raw: node.name)Protocol>(_ syntax: S) {
58+
// We know this cast is going to succeed. Go through init(_: SyntaxData)
59+
// to do a sanity check and verify the kind matches in debug builds and get
60+
// maximum performance in release builds.
61+
self.init(syntax._syntaxNode.data)
62+
}
63+
""")
64+
65+
InitializerDecl("""
66+
/// Create a `\(raw: node.name)` node from a specialized optional syntax node.
67+
public init?<S: \(raw: node.name)Protocol>(_ syntax: S?) {
68+
guard let syntax = syntax else { return nil }
69+
self.init(syntax)
70+
}
71+
""")
72+
73+
InitializerDecl("""
74+
public init(fromProtocol syntax: \(raw: node.name)Protocol) {
75+
// We know this cast is going to succeed. Go through init(_: SyntaxData)
76+
// to do a sanity check and verify the kind matches in debug builds and get
77+
// maximum performance in release builds.
78+
self.init(syntax._syntaxNode.data)
79+
}
80+
""")
81+
82+
InitializerDecl("""
83+
/// Create a `\(raw: node.name)` node from a specialized optional syntax node.
84+
public init?(fromProtocol syntax: \(raw: node.name)Protocol?) {
85+
guard let syntax = syntax else { return nil }
86+
self.init(fromProtocol: syntax)
87+
}
88+
""")
89+
90+
InitializerDecl("public init?<S: SyntaxProtocol>(_ node: S)") {
91+
SwitchStmt(expression: MemberAccessExpr("node.raw.kind")) {
92+
SwitchCaseList {
93+
SwitchCase(
94+
label: .case(SwitchCaseLabel {
95+
for childNode in SYNTAX_NODES where childNode.baseKind == node.syntaxKind {
96+
CaseItem(
97+
pattern: EnumCasePattern(
98+
period: .period,
99+
caseName: .identifier(childNode.swiftSyntaxKind))
100+
)
101+
}
102+
})) {
103+
Expr("self._syntaxNode = node._syntaxNode")
104+
}
105+
106+
SwitchCase("default:") {
107+
ReturnStmt("return nil")
108+
}
109+
}
110+
}
111+
}
112+
113+
InitializerDecl("""
114+
/// Creates a `\(node.name)` node from the given `SyntaxData`. This assumes
115+
/// that the `SyntaxData` is of the correct kind. If it is not, the behaviour
116+
/// is undefined.
117+
internal init(_ data: SyntaxData)
118+
""") {
119+
IfConfigDecl(
120+
clauses: IfConfigClauseList {
121+
IfConfigClause(
122+
poundKeyword: .poundIfKeyword(),
123+
condition: Expr("DEBUG"),
124+
elements: IfConfigClauseSyntax.Elements.statements(CodeBlockItemList {
125+
SwitchStmt(
126+
expression: Expr("data.raw.kind")) {
127+
SwitchCase(
128+
label: .case(SwitchCaseLabel {
129+
for childNode in SYNTAX_NODES where childNode.baseKind == node.syntaxKind {
130+
CaseItem(
131+
pattern: EnumCasePatternSyntax(
132+
period: .period,
133+
caseName: .identifier(childNode.swiftSyntaxKind))
134+
)
135+
}
136+
})) {
137+
BreakStmt()
138+
}
139+
140+
SwitchCase("default:") {
141+
FunctionCallExpr("fatalError(\"Unable to create \(raw: node.name) from \\(data.raw.kind)\")")
142+
}
143+
}
144+
})
145+
)
146+
}
147+
)
148+
149+
Expr("self._syntaxNode = Syntax(data)")
150+
}
151+
152+
FunctionDecl("""
153+
public func `is`<S: \(raw: node.name)Protocol>(_ syntaxType: S.Type) -> Bool {
154+
return self.as(syntaxType) != nil
155+
}
156+
""")
157+
158+
FunctionDecl("""
159+
public func `as`<S: \(raw: node.name)Protocol>(_ syntaxType: S.Type) -> S? {
160+
return S.init(self)
161+
}
162+
""")
163+
164+
FunctionDecl("""
165+
public func cast<S: \(raw: node.name)Protocol>(_ syntaxType: S.Type) -> S {
166+
return self.as(S.self)!
167+
}
168+
""")
169+
170+
FunctionDecl("""
171+
/// Syntax nodes always conform to `\(raw: node.name)Protocol`. This API is just
172+
/// added for consistency.
173+
/// Note that this will incur an existential conversion.
174+
@available(*, deprecated, message: "Expression always evaluates to true")
175+
public func isProtocol(_: \(raw: node.name)Protocol.Protocol) -> Bool {
176+
return true
177+
}
178+
""")
179+
180+
FunctionDecl("""
181+
/// Return the non-type erased version of this syntax node.
182+
/// Note that this will incur an existential conversion.
183+
public func asProtocol(_: \(raw: node.name)Protocol.Protocol) -> \(raw: node.name)Protocol {
184+
return Syntax(self).asProtocol(\(raw: node.name)Protocol.self)!
185+
}
186+
""")
187+
188+
189+
VariableDecl(
190+
modifiers: [DeclModifier(name: .public), DeclModifier(name: .static)],
191+
name: IdentifierPattern("structure"),
192+
type: TypeAnnotation(
193+
type: TypeSyntax("SyntaxNodeStructure"))
194+
) {
195+
ReturnStmt(
196+
expression: FunctionCallExpr(
197+
callee: MemberAccessExpr(".choices")) {
198+
TupleExprElement(
199+
expression: ArrayExprSyntax {
200+
for childNode in SYNTAX_NODES where childNode.baseKind == node.syntaxKind {
201+
ArrayElement(
202+
expression: FunctionCallExpr("\n.node(\(raw: childNode.name).self)")
203+
)
204+
}
205+
})
206+
}
207+
)
208+
}
209+
210+
FunctionDecl("""
211+
public func childNameForDiagnostics(_ index: SyntaxChildrenIndex) -> String? {
212+
return Syntax(self).childNameForDiagnostics(index)
213+
}
214+
""")
215+
}
216+
217+
ExtensionDecl("""
218+
extension \(raw: node.name): CustomReflectable {
219+
/// Reconstructs the real syntax type for this type from the node's kind and
220+
/// provides a mirror that reflects this type.
221+
public var customMirror: Mirror {
222+
return Mirror(reflecting: Syntax(self).asProtocol(SyntaxProtocol.self))
223+
}
224+
}
225+
""")
226+
227+
}
228+
}

Package.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,6 @@ let package = Package(
6565
"CMakeLists.txt",
6666
"Raw/RawSyntaxNodes.swift.gyb",
6767
"Raw/RawSyntaxValidation.swift.gyb",
68-
"SyntaxAnyVisitor.swift.gyb",
69-
"SyntaxBaseNodes.swift.gyb",
7068
"SyntaxCollections.swift.gyb",
7169
"SyntaxEnum.swift.gyb",
7270
"SyntaxFactory.swift.gyb",

Sources/SwiftSyntax/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ add_swift_host_library(SwiftSyntax
3232
Raw/gyb_generated/RawSyntaxValidation.swift
3333

3434
generated/Misc.swift
35-
gyb_generated/SyntaxAnyVisitor.swift
36-
gyb_generated/SyntaxBaseNodes.swift
35+
generated/SyntaxAnyVisitor.swift
36+
generated/SyntaxBaseNodes.swift
3737
gyb_generated/SyntaxCollections.swift
3838
gyb_generated/SyntaxEnum.swift
3939
gyb_generated/SyntaxFactory.swift

0 commit comments

Comments
 (0)