Added error tests

This commit is contained in:
Adam Fowler
2021-03-12 10:14:17 +00:00
parent 633f494e18
commit 6be7a382fb
3 changed files with 60 additions and 20 deletions

View File

@@ -1,5 +1,11 @@
extension HBMustacheTemplate { extension HBMustacheTemplate {
enum Error: Swift.Error {
case sectionCloseNameIncorrect
case unfinishedName
case expectedSectionEnd
}
static func parse(_ string: String) throws -> [Token] { static func parse(_ string: String) throws -> [Token] {
var parser = HBParser(string) var parser = HBParser(string)
return try parse(&parser, sectionName: nil) return try parse(&parser, sectionName: nil)
@@ -9,14 +15,16 @@ extension HBMustacheTemplate {
var tokens: [Token] = [] var tokens: [Token] = []
while !parser.reachedEnd() { while !parser.reachedEnd() {
let text = try parser.read(untilString: "{{", throwOnOverflow: false, skipToEnd: true) let text = try parser.read(untilString: "{{", throwOnOverflow: false, skipToEnd: true)
if text.count > 0 {
tokens.append(.text(text.string)) tokens.append(.text(text.string))
}
if parser.reachedEnd() { if parser.reachedEnd() {
break break
} }
switch parser.current() { switch parser.current() {
case "#": case "#":
parser.unsafeAdvance() parser.unsafeAdvance()
let name = try parseSectionName(&parser) let name = try parseName(&parser)
if parser.current() == "\n" { if parser.current() == "\n" {
parser.unsafeAdvance() parser.unsafeAdvance()
} }
@@ -25,7 +33,7 @@ extension HBMustacheTemplate {
case "^": case "^":
parser.unsafeAdvance() parser.unsafeAdvance()
let name = try parseSectionName(&parser) let name = try parseName(&parser)
if parser.current() == "\n" { if parser.current() == "\n" {
parser.unsafeAdvance() parser.unsafeAdvance()
} }
@@ -34,9 +42,9 @@ extension HBMustacheTemplate {
case "/": case "/":
parser.unsafeAdvance() parser.unsafeAdvance()
let name = try parseSectionName(&parser) let name = try parseName(&parser)
guard name == sectionName else { guard name == sectionName else {
throw HBMustacheError.sectionCloseNameIncorrect throw Error.sectionCloseNameIncorrect
} }
if parser.current() == "\n" { if parser.current() == "\n" {
parser.unsafeAdvance() parser.unsafeAdvance()
@@ -45,40 +53,40 @@ extension HBMustacheTemplate {
case "{": case "{":
parser.unsafeAdvance() parser.unsafeAdvance()
let name = try parseSectionName(&parser) let name = try parseName(&parser)
guard try parser.read("}") else { throw HBMustacheError.unfinishedSectionName } guard try parser.read("}") else { throw Error.unfinishedName }
tokens.append(.unescapedVariable(name)) tokens.append(.unescapedVariable(name))
case "!": case "!":
parser.unsafeAdvance() parser.unsafeAdvance()
_ = try parseSection(&parser) _ = try parseComment(&parser)
case ">": case ">":
parser.unsafeAdvance() parser.unsafeAdvance()
let name = try parseSectionName(&parser) let name = try parseName(&parser)
tokens.append(.partial(name)) tokens.append(.partial(name))
default: default:
let name = try parseSectionName(&parser) let name = try parseName(&parser)
tokens.append(.variable(name)) tokens.append(.variable(name))
} }
} }
// should never get here if reading section // should never get here if reading section
guard sectionName == nil else { guard sectionName == nil else {
throw HBMustacheError.expectedSectionEnd throw Error.expectedSectionEnd
} }
return tokens return tokens
} }
static func parseSectionName(_ parser: inout HBParser) throws -> String { static func parseName(_ parser: inout HBParser) throws -> String {
parser.read(while: \.isWhitespace) parser.read(while: \.isWhitespace)
let text = parser.read(while: sectionNameChars ) let text = parser.read(while: sectionNameChars )
parser.read(while: \.isWhitespace) parser.read(while: \.isWhitespace)
guard try parser.read("}"), try parser.read("}") else { throw HBMustacheError.unfinishedSectionName } guard try parser.read("}"), try parser.read("}") else { throw Error.unfinishedName }
return text.string return text.string
} }
static func parseSection(_ parser: inout HBParser) throws -> String { static func parseComment(_ parser: inout HBParser) throws -> String {
let text = try parser.read(untilString: "}}", throwOnOverflow: true, skipToEnd: true) let text = try parser.read(untilString: "}}", throwOnOverflow: true, skipToEnd: true)
return text.string return text.string
} }

View File

@@ -1,10 +1,4 @@
enum HBMustacheError: Error {
case sectionCloseNameIncorrect
case unfinishedSectionName
case expectedSectionEnd
}
public class HBMustacheTemplate { public class HBMustacheTemplate {
public init(string: String) throws { public init(string: String) throws {
self.tokens = try Self.parse(string) self.tokens = try Self.parse(string)

View File

@@ -26,6 +26,44 @@ final class TemplateParserTests: XCTestCase {
let template = try HBMustacheTemplate(string: "test {{!section}}") let template = try HBMustacheTemplate(string: "test {{!section}}")
XCTAssertEqual(template.tokens, [.text("test ")]) XCTAssertEqual(template.tokens, [.text("test ")])
} }
func testWhitespace() throws {
let template = try HBMustacheTemplate(string: "{{ section }}")
XCTAssertEqual(template.tokens, [.variable("section")])
}
func testSectionEndError() throws {
XCTAssertThrowsError(_ = try HBMustacheTemplate(string: "test {{#section}}")) { error in
switch error {
case HBMustacheTemplate.Error.expectedSectionEnd:
break
default:
XCTFail("\(error)")
}
}
}
func testSectionCloseNameIncorrectError() throws {
XCTAssertThrowsError(_ = try HBMustacheTemplate(string: "test {{#section}}{{/error}}")) { error in
switch error {
case HBMustacheTemplate.Error.sectionCloseNameIncorrect:
break
default:
XCTFail("\(error)")
}
}
}
func testUnmatchedNameError() throws {
XCTAssertThrowsError(_ = try HBMustacheTemplate(string: "test {{section#}}")) { error in
switch error {
case HBMustacheTemplate.Error.unfinishedName:
break
default:
XCTFail("\(error)")
}
}
}
} }
extension HBMustacheTemplate: Equatable { extension HBMustacheTemplate: Equatable {