Skip to content

Commit 1a6a924

Browse files
committed
Move raw syntax validation from gyb to code gen
1 parent 27be381 commit 1a6a924

File tree

6 files changed

+170
-134
lines changed

6 files changed

+170
-134
lines changed

CodeGeneration/Sources/generate-swiftsyntax/GenerateSwiftSyntax.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ struct GenerateSwiftSyntax: ParsableCommand {
7373
TemplateSpec(sourceFile: keywordFile, module: swiftSyntaxDir, filename: "Keyword.swift"),
7474
TemplateSpec(sourceFile: miscFile, module: swiftSyntaxDir, filename: "Misc.swift"),
7575
TemplateSpec(sourceFile: rawSyntaxNodesFile, module: swiftSyntaxDir, filename: "raw/RawSyntaxNodes.swift"),
76+
TemplateSpec(sourceFile: rawSyntaxValidationFile, module: swiftSyntaxDir, filename: "raw/RawSyntaxValidation.swift"),
7677
TemplateSpec(sourceFile: syntaxAnyVisitorFile, module: swiftSyntaxDir, filename: "SyntaxAnyVisitor.swift"),
7778
TemplateSpec(sourceFile: syntaxBaseNodesFile, module: swiftSyntaxDir, filename: "SyntaxBaseNodes.swift"),
7879
TemplateSpec(sourceFile: syntaxCollectionsFile, module: swiftSyntaxDir, filename: "SyntaxCollections.swift"),
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
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 rawSyntaxValidationFile = try! SourceFileSyntax(leadingTrivia: "\(generateCopyrightHeader(for: "generate-swiftsyntax"))" + .newline) {
19+
try FunctionDeclSyntax("func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind)") {
20+
IfConfigDeclSyntax(
21+
clauses: IfConfigClauseListSyntax {
22+
IfConfigClauseSyntax(
23+
poundKeyword: .poundIfKeyword(),
24+
condition: ExprSyntax("DEBUG"),
25+
elements: .statements(
26+
CodeBlockItemListSyntax {
27+
DeclSyntax(
28+
#"""
29+
enum ValidationError: CustomStringConvertible {
30+
case expectedNonNil(expectedKind: RawSyntaxNodeProtocol.Type, file: StaticString, line: UInt)
31+
case kindMismatch(expectedKind: RawSyntaxNodeProtocol.Type, actualKind: SyntaxKind, file: StaticString, line: UInt)
32+
33+
var description: String {
34+
switch self {
35+
case .expectedNonNil(expectedKind: let expectedKind, file: _, line: _):
36+
return "Expected non-nil node of type \(expectedKind) but received nil"
37+
case .kindMismatch(expectedKind: let expectedKind, actualKind: let actualKind, file: _, line: _):
38+
return "Expected node of type \(expectedKind) but received \(actualKind)"
39+
}
40+
}
41+
42+
var fileAndLine: (StaticString, UInt) {
43+
switch self {
44+
case .expectedNonNil(expectedKind: _, file: let file, line: let line):
45+
return (file, line)
46+
case .kindMismatch(expectedKind: _, actualKind: _, file: let file, line: let line):
47+
return (file, line)
48+
}
49+
}
50+
}
51+
"""#
52+
)
53+
54+
DeclSyntax(
55+
"""
56+
func verify<Node: RawSyntaxNodeProtocol>(_ raw: RawSyntax?, as _: Node.Type, file: StaticString = #file, line: UInt = #line) -> ValidationError? {
57+
guard let raw = raw else {
58+
return .expectedNonNil(expectedKind: Node.self, file: file, line: line)
59+
}
60+
guard Node.isKindOf(raw) else {
61+
return .kindMismatch(expectedKind: Node.self, actualKind: raw.kind, file: file, line: line)
62+
}
63+
return nil
64+
}
65+
"""
66+
)
67+
68+
DeclSyntax(
69+
"""
70+
func verify<Node: RawSyntaxNodeProtocol>(_ raw: RawSyntax?, as _: Node?.Type, file: StaticString = #file, line: UInt = #line) -> ValidationError? {
71+
if raw != nil {
72+
return verify(raw, as: Node.self, file: file, line: line)
73+
}
74+
return nil
75+
}
76+
"""
77+
)
78+
79+
DeclSyntax(
80+
#"""
81+
func assertNoError(_ nodeKind: SyntaxKind, _ index: Int, _ error: ValidationError?) {
82+
if let error = error {
83+
let (file, line) = error.fileAndLine
84+
assertionFailure("""
85+
Error validating child at index \(index) of \(nodeKind):
86+
\(error.description)
87+
""", file: file, line: line)
88+
_ = 1
89+
}
90+
}
91+
"""#
92+
)
93+
94+
DeclSyntax(
95+
#"""
96+
func assertAnyHasNoError(_ nodeKind: SyntaxKind, _ index: Int, _ errors: [ValidationError?]) {
97+
let nonNilErrors = errors.compactMap({ $0 })
98+
if nonNilErrors.count == errors.count, let firstError = nonNilErrors.first {
99+
let (file, line) = firstError.fileAndLine
100+
assertionFailure("""
101+
Error validating child at index \(index) of \(nodeKind):
102+
Node did not satisfy any node choice requirement.
103+
Validation failures:
104+
\(nonNilErrors.map({ "- \($0.description)" }).joined(separator: "\n") )
105+
""", file: file, line: line)
106+
_ = 1
107+
}
108+
}
109+
"""#
110+
)
111+
112+
try! SwitchExprSyntax("switch kind") {
113+
SwitchCaseSyntax(
114+
"""
115+
case .token:
116+
assertionFailure("validateLayout for .token kind is not supported")
117+
"""
118+
)
119+
120+
for node in NON_BASE_SYNTAX_NODES {
121+
try SwitchCaseSyntax("case .\(raw: node.swiftSyntaxKind):") {
122+
if node.isBuildable || node.isMissing {
123+
ExprSyntax("assert(layout.count == \(raw: node.children.count))")
124+
for (index, child) in node.children.enumerated() {
125+
switch child.kind {
126+
case .nodeChoices(let choices):
127+
let verifiedChoices = ArrayExprSyntax {
128+
ArrayElementSyntax(expression: ExprSyntax("verify(layout[\(raw: index)], as: Raw\(raw: child.type.buildable).self)"))
129+
}
130+
131+
ExprSyntax("assertAnyHasNoError(kind, \(raw: index), \(verifiedChoices))")
132+
default:
133+
ExprSyntax("assertNoError(kind, \(raw: index), verify(layout[\(raw: index)], as: Raw\(raw: child.type.buildable).self))")
134+
}
135+
}
136+
} else if node.isSyntaxCollection {
137+
try ForInStmtSyntax("for (index, element) in layout.enumerated()") {
138+
if let collectionElementChoices = node.collectionElementChoices, !collectionElementChoices.isEmpty {
139+
let verifiedChoices = ArrayExprSyntax {
140+
for choiceName in node.collectionElementChoices! {
141+
let choice = SYNTAX_NODE_MAP[choiceName]!
142+
ArrayElementSyntax(expression: ExprSyntax("verify(element, as: Raw\(raw: choice.name).self)"))
143+
}
144+
}
145+
ExprSyntax("assertAnyHasNoError(kind, index, \(verifiedChoices))")
146+
} else {
147+
ExprSyntax("assertNoError(kind, index, verify(element, as: Raw\(node.collectionElementType.buildable).self))")
148+
}
149+
}
150+
}
151+
152+
BreakStmtSyntax()
153+
}
154+
}
155+
}
156+
}
157+
)
158+
)
159+
}
160+
)
161+
162+
}
163+
}

Package.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@ let package = Package(
6464
name: "SwiftSyntax",
6565
dependencies: [],
6666
exclude: [
67-
"CMakeLists.txt",
68-
"Raw/RawSyntaxValidation.swift.gyb",
67+
"CMakeLists.txt"
6968
],
7069
swiftSettings: swiftSyntaxSwiftSettings
7170
),

Sources/SwiftSyntax/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ add_swift_host_library(SwiftSyntax
3030
Raw/RawSyntaxTokenView.swift
3131

3232
generated/raw/RawSyntaxNodes.swift
33-
Raw/gyb_generated/RawSyntaxValidation.swift
33+
generated/raw/RawSyntaxValidation.swift
3434

3535
generated/Keyword.swift
3636
generated/Misc.swift

Sources/SwiftSyntax/Raw/RawSyntaxValidation.swift.gyb

Lines changed: 0 additions & 129 deletions
This file was deleted.

Sources/SwiftSyntax/Raw/gyb_generated/RawSyntaxValidation.swift renamed to Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
//// Automatically Generated From RawSyntaxValidation.swift.gyb.
1+
2+
3+
//// Automatically Generated by generate-swiftsyntax
24
//// Do Not Edit Directly!
3-
//===----------- RawSyntaxValidation.swift - Layout validation ------------===//
5+
//===----------------------------------------------------------------------===//
46
//
57
// This source file is part of the Swift.org open source project
68
//

0 commit comments

Comments
 (0)