Skip to content

Commit f6a08a1

Browse files
authored
Fix crash with missing parameter (#130)
1 parent 38e3144 commit f6a08a1

2 files changed

Lines changed: 39 additions & 10 deletions

File tree

Sources/LeafKit/LeafParser/LeafParser.swift

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,20 @@ internal struct LeafParser {
183183

184184
var group = [ParameterDeclaration]()
185185
var paramsList = [ParameterDeclaration]()
186-
187-
func dump() {
188-
defer { group = [] }
189-
if group.isEmpty { return }
190-
group.evaluate()
191-
if group.count > 1 { paramsList.append(.expression(group)) }
192-
else { paramsList.append(group.first!) }
186+
187+
func dump() throws {
188+
defer { group = [] }
189+
if group.isEmpty { return }
190+
group.evaluate()
191+
if group.count > 1 { paramsList.append(.expression(group)) }
192+
else {
193+
guard let first = group.first else {
194+
// It's better to handle this case as well, even though logically it might never happen
195+
// since you're checking if group.isEmpty before.
196+
throw LeafError(.unknownError("Found nil while iterating through params"), file: #file, function: #function, line: #line, column: #column)
197+
}
198+
paramsList.append(first)
199+
}
193200
}
194201

195202
outer: while let next = peek() {
@@ -200,7 +207,12 @@ internal struct LeafParser {
200207
let params = try readParameters()
201208
// parameter tags not permitted to have bodies
202209
if params.count > 1 { group.append(.expression(params)) }
203-
else { group.append(params.first!) }
210+
else {
211+
guard let firstParam = params.first else {
212+
throw LeafError(.unknownError("Found nil while iterating through params"))
213+
}
214+
group.append(firstParam)
215+
}
204216
case .parameter(let p):
205217
pop()
206218
switch p {
@@ -214,11 +226,11 @@ internal struct LeafParser {
214226
}
215227
case .parametersEnd:
216228
pop()
217-
dump()
229+
try dump()
218230
break outer
219231
case .parameterDelimiter:
220232
pop()
221-
dump()
233+
try dump()
222234
case .whitespace:
223235
pop()
224236
continue

Tests/LeafKitTests/LeafErrorTests.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,21 @@ final class LeafErrorTests: XCTestCase {
4545
XCTFail("Wrong error: \(error.localizedDescription)")
4646
}
4747
}
48+
49+
/// Verify that rendering a template with a missing required parameter will throw `LeafError.missingParameter`
50+
func testMissingParameterError() {
51+
var test = TestFiles()
52+
// Assuming "/missingParam.leaf" is a template that requires a parameter we intentionally don't provide
53+
test.files["/missingParam.leaf"] = """
54+
#(foo.bar.trim())
55+
"""
56+
XCTAssertThrowsError(try TestRenderer(sources: .singleSource(test))
57+
.render(path: "missingParam", context: [:])
58+
.wait()
59+
) {
60+
guard case .unknownError("Found nil while iterating through params") = ($0 as? LeafError)?.reason else {
61+
return XCTFail("Expected LeafError.unknownError(\"Found nil while iterating through params\"), got \(String(reflecting: $0))")
62+
}
63+
}
64+
}
4865
}

0 commit comments

Comments
 (0)