From d5f0be959f6f1c5c52486414539095618ed67de7 Mon Sep 17 00:00:00 2001 From: Ilya Puchka Date: Sat, 7 Oct 2017 21:01:28 +0200 Subject: [PATCH] using error reporter from environment to handle syntax errors --- Sources/Environment.swift | 22 +++++++++++-- Tests/StencilTests/EnvironmentSpec.swift | 42 +++++++++++++++++++++++- Tests/StencilTests/TemplateSpec.swift | 24 -------------- 3 files changed, 60 insertions(+), 28 deletions(-) diff --git a/Sources/Environment.swift b/Sources/Environment.swift index 6b78fec..940c146 100644 --- a/Sources/Environment.swift +++ b/Sources/Environment.swift @@ -3,9 +3,15 @@ public struct Environment { public var extensions: [Extension] public var loader: Loader? + public var errorReporter: ErrorReporter - public init(loader: Loader? = nil, extensions: [Extension]? = nil, templateClass: Template.Type = Template.self) { + public init(loader: Loader? = nil, + extensions: [Extension]? = nil, + templateClass: Template.Type = Template.self, + errorReporter: ErrorReporter = SimpleErrorReporter()) { + self.templateClass = templateClass + self.errorReporter = errorReporter self.loader = loader self.extensions = (extensions ?? []) + [DefaultExtension()] } @@ -28,11 +34,21 @@ public struct Environment { public func renderTemplate(name: String, context: [String: Any]? = nil) throws -> String { let template = try loadTemplate(name: name) - return try template.render(context) + return try render(template: template, context: context) } public func renderTemplate(string: String, context: [String: Any]? = nil) throws -> String { let template = templateClass.init(templateString: string, environment: self) - return try template.render(context) + return try render(template: template, context: context) + } + + func render(template: Template, context: [String: Any]?) throws -> String { + errorReporter.context = ErrorReporterContext(template: template) + do { + return try template.render(context) + } catch { + try errorReporter.report(error: error) + return "" + } } } diff --git a/Tests/StencilTests/EnvironmentSpec.swift b/Tests/StencilTests/EnvironmentSpec.swift index 8bb5bfc..afc8d9b 100644 --- a/Tests/StencilTests/EnvironmentSpec.swift +++ b/Tests/StencilTests/EnvironmentSpec.swift @@ -1,5 +1,5 @@ import Spectre -import Stencil +@testable import Stencil func testEnvironment() { @@ -32,6 +32,46 @@ func testEnvironment() { try expect(result) == "here" } + + func expectedSyntaxError(token: String, template: Template, description: String) -> TemplateSyntaxError { + var error = TemplateSyntaxError(description) + error.lexeme = Token.block(value: token, at: template.templateString.range(of: token)!) + let context = ErrorReporterContext(template: template) + error = environment.errorReporter.contextAwareError(error, context: context) as! TemplateSyntaxError + print(error) + return error + } + + $0.it("throws syntax error on invalid for tag syntax") { + let template: Template = "Hello {% for name in %}{{ name }}, {% endfor %}!" + let error = expectedSyntaxError( + token: "{% for name in %}", + template: template, + description: "'for' statements should use the following syntax 'for x in y where condition'." + ) + try expect(try environment.renderTemplate(string: template.templateString, context:["names": ["Bob", "Alice"]])).toThrow(error) + } + + $0.it("throws syntax error on missing endfor") { + let template: Template = "{% for name in names %}{{ name }}" + let error = expectedSyntaxError( + token: "{% for name in names %}", + template: template, + description: "`endfor` was not found." + ) + try expect(try environment.renderTemplate(string: template.templateString, context: ["names": ["Bob", "Alice"]])).toThrow(error) + } + + $0.it("throws syntax error on unknown tag") { + let template: Template = "{% for name in names %}{{ name }}{% end %}" + let error = expectedSyntaxError( + token: "{% end %}", + template: template, + description: "Unknown template tag 'end'" + ) + try expect(try environment.renderTemplate(string: template.templateString, context: ["names": ["Bob", "Alice"]])).toThrow(error) + } + } } diff --git a/Tests/StencilTests/TemplateSpec.swift b/Tests/StencilTests/TemplateSpec.swift index 42dac28..fee0c5e 100644 --- a/Tests/StencilTests/TemplateSpec.swift +++ b/Tests/StencilTests/TemplateSpec.swift @@ -15,30 +15,6 @@ func testTemplate() { let result = try template.render([ "name": "Kyle" ]) try expect(result) == "Hello World" } - - $0.it("throws syntax error on invalid for tag syntax") { - let template: Template = "Hello {% for name in %}{{ name }}, {% endfor %}!" - var error = TemplateSyntaxError("'for' statements should use the following syntax 'for x in y where condition'.") - error.token = Token.block(value: "{% for name in %}", at: template.templateString.range(of: "{% for name in %}")!) - error = error.contextAwareError(templateName: nil, templateContent: template.templateString)! - try expect(try template.render(["names": ["Bob", "Alice"]])).toThrow(error) - } - - $0.it("throws syntax error on missing endfor") { - let template: Template = "{% for name in names %}{{ name }}" - var error = TemplateSyntaxError("`endfor` was not found.") - error.token = Token.block(value: "{% for name in names %}", at: template.templateString.range(of: "{% for name in names %}")!) - error = error.contextAwareError(templateName: nil, templateContent: template.templateString)! - try expect(try template.render(["names": ["Bob", "Alice"]])).toThrow(error) - } - - $0.it("throws syntax error on unknown tag") { - let template: Template = "{% for name in names %}{{ name }}{% end %}" - var error = TemplateSyntaxError("Unknown template tag 'end'") - error.token = Token.block(value: "{% end %}", at: template.templateString.range(of: "{% end %}")!) - error = error.contextAwareError(templateName: nil, templateContent: template.templateString)! - try expect(try template.render(["names": ["Bob", "Alice"]])).toThrow(error) - } } }