Skip to content

Commit bbf5297

Browse files
committed
Add a conditional compilation flag to verify token choices
Verification of token choice is currently causing assertion failures where the list of expected token choices in the syntax tree doesn't match those the parser generates. I’d still like to get the verification code into `main` so I can conditionally enable it locally while working on the issues, so add it behind a conditional compilation flag.
1 parent f340316 commit bbf5297

File tree

2 files changed

+665
-352
lines changed

2 files changed

+665
-352
lines changed

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

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,39 @@ let rawSyntaxValidationFile = try! SourceFileSyntax(leadingTrivia: copyrightHead
3232
condition: ExprSyntax("DEBUG"),
3333
elements: .statements(
3434
try CodeBlockItemListSyntax {
35+
DeclSyntax(
36+
#"""
37+
enum TokenChoice: CustomStringConvertible {
38+
case keyword(StaticString)
39+
case tokenKind(RawTokenKind)
40+
41+
var description: String {
42+
switch self {
43+
case .keyword(let keyword):
44+
return "keyword('\(keyword)')"
45+
case .tokenKind(let kind):
46+
return "\(kind)"
47+
}
48+
}
49+
}
50+
"""#
51+
)
52+
3553
DeclSyntax(
3654
#"""
3755
enum ValidationError: CustomStringConvertible {
3856
case expectedNonNil(expectedKind: RawSyntaxNodeProtocol.Type, file: StaticString, line: UInt)
3957
case kindMismatch(expectedKind: RawSyntaxNodeProtocol.Type, actualKind: SyntaxKind, file: StaticString, line: UInt)
58+
case tokenMismatch(expectedTokenChoices: [TokenChoice], actualKind: RawTokenKind, actualText: SyntaxText, file: StaticString, line: UInt)
4059
4160
var description: String {
4261
switch self {
4362
case .expectedNonNil(expectedKind: let expectedKind, file: _, line: _):
4463
return "Expected non-nil node of type \(expectedKind) but received nil"
4564
case .kindMismatch(expectedKind: let expectedKind, actualKind: let actualKind, file: _, line: _):
4665
return "Expected node of type \(expectedKind) but received \(actualKind)"
66+
case .tokenMismatch(expectedTokenChoices: let tokenChoices, actualKind: let actualKind, actualText: let actualText, file: _, line: _):
67+
return "Expected token with one of \(tokenChoices) but received \(actualKind) with text '\(actualText)'"
4768
}
4869
}
4970
@@ -53,6 +74,8 @@ let rawSyntaxValidationFile = try! SourceFileSyntax(leadingTrivia: copyrightHead
5374
return (file, line)
5475
case .kindMismatch(expectedKind: _, actualKind: _, file: let file, line: let line):
5576
return (file, line)
77+
case .tokenMismatch(expectedTokenChoices: _, actualKind: _, actualText: _, file: let file, line: let line):
78+
return (file, line)
5679
}
5780
}
5881
}
@@ -84,6 +107,61 @@ let rawSyntaxValidationFile = try! SourceFileSyntax(leadingTrivia: copyrightHead
84107
"""
85108
)
86109

110+
DeclSyntax(
111+
"""
112+
func verify(_ raw: RawSyntax?, as _: RawTokenSyntax?.Type, tokenChoices: [TokenChoice], file: StaticString = #file, line: UInt = #line) -> ValidationError? {
113+
// Validation of token choice is currently causing assertion failures where
114+
// the list of expected token choices in the syntax tree doesn't match those
115+
// the parser generates. Disable the verification for now until all issues
116+
// regarding it are fixed.
117+
#if VALIDATE_TOKEN_CHOICES
118+
if raw != nil {
119+
return verify(raw, as: RawTokenSyntax.self, tokenChoices: tokenChoices, file: file, line: line)
120+
}
121+
return nil
122+
#else
123+
return verify(raw, as: RawTokenSyntax?.self)
124+
#endif
125+
}
126+
"""
127+
)
128+
129+
DeclSyntax(
130+
"""
131+
func verify(_ raw: RawSyntax?, as _: RawTokenSyntax.Type, tokenChoices: [TokenChoice], file: StaticString = #file, line: UInt = #line) -> ValidationError? {
132+
// Validation of token choice is currently causing assertion failures where
133+
// the list of expected token choices in the syntax tree doesn't match those
134+
// the parser generates. Disable the verification for now until all issues
135+
// regarding it are fixed.
136+
#if VALIDATE_TOKEN_CHOICES
137+
guard let raw = raw else {
138+
return .expectedNonNil(expectedKind: RawTokenSyntax.self, file: file, line: line)
139+
}
140+
if let error = verify(raw, as: RawTokenSyntax?.self) {
141+
return error
142+
}
143+
let tokenView = raw.tokenView!
144+
for tokenChoice in tokenChoices {
145+
switch tokenChoice {
146+
case .tokenKind(let tokenKind):
147+
if raw.tokenView?.rawKind == tokenKind {
148+
return nil
149+
}
150+
case .keyword(let keyword):
151+
if tokenView.rawKind == .keyword && tokenView.rawText == SyntaxText(keyword) {
152+
return nil
153+
}
154+
}
155+
}
156+
return ValidationError.tokenMismatch(expectedTokenChoices: tokenChoices, actualKind: tokenView.rawKind, actualText: tokenView.rawText, file: file, line: line)
157+
#else
158+
return verify(raw, as: RawTokenSyntax.self)
159+
#endif
160+
}
161+
162+
"""
163+
)
164+
87165
DeclSyntax(
88166
#"""
89167
func assertNoError(_ nodeKind: SyntaxKind, _ index: Int, _ error: ValidationError?) {
@@ -139,6 +217,19 @@ let rawSyntaxValidationFile = try! SourceFileSyntax(leadingTrivia: copyrightHead
139217
}
140218

141219
ExprSyntax("assertAnyHasNoError(kind, \(raw: index), \(verifiedChoices))")
220+
case .token(choices: let choices, requiresLeadingSpace: _, requiresTrailingSpace: _):
221+
let choices = ArrayExprSyntax {
222+
for choice in choices {
223+
switch choice {
224+
case .keyword(text: let text):
225+
ArrayElementSyntax(expression: ExprSyntax(#".keyword("\#(raw: text)")"#))
226+
case .token(tokenKind: let tokenKind):
227+
ArrayElementSyntax(expression: ExprSyntax(".tokenKind(.\(raw: SYNTAX_TOKEN_MAP[tokenKind]!.swiftKind))"))
228+
}
229+
}
230+
}
231+
let verifyCall = ExprSyntax("verify(layout[\(raw: index)], as: Raw\(raw: child.type.buildable).self, tokenChoices: \(choices))")
232+
ExprSyntax("assertNoError(kind, \(raw: index), \(verifyCall))")
142233
default:
143234
ExprSyntax("assertNoError(kind, \(raw: index), verify(layout[\(raw: index)], as: Raw\(raw: child.type.buildable).self))")
144235
}

0 commit comments

Comments
 (0)