reporting node rendering errors using reference to node’s token

This commit is contained in:
Ilya Puchka
2017-12-23 15:19:36 +01:00
parent 27135f3ea3
commit 53c1550c5b
15 changed files with 186 additions and 47 deletions

View File

@@ -3,18 +3,38 @@ import Foundation
public protocol NodeType {
/// Render the node in the given context
func render(_ context:Context) throws -> String
/// Reference to this node's token
var token: Token? { get }
}
/// Render the collection of nodes in the given context
public func renderNodes(_ nodes:[NodeType], _ context:Context) throws -> String {
return try nodes.map { try $0.render(context) }.joined(separator: "")
return try nodes.map({
do {
return try $0.render(context)
} catch {
if var syntaxError = error as? TemplateSyntaxError, syntaxError.lexeme == nil, let token = $0.token {
if let contentsRange = context.environment.template?.templateString.range(of: token.contents, range: token.range) {
syntaxError.lexeme = Token.block(value: token.contents, at: contentsRange)
} else {
syntaxError.lexeme = token
}
throw syntaxError
} else {
throw error
}
}
}).joined(separator: "")
}
public class SimpleNode : NodeType {
public let handler:(Context) throws -> String
public let token: Token?
public init(handler: @escaping (Context) throws -> String) {
public init(token: Token, handler: @escaping (Context) throws -> String) {
self.token = token
self.handler = handler
}
@@ -26,9 +46,11 @@ public class SimpleNode : NodeType {
public class TextNode : NodeType {
public let text:String
public let token: Token?
public init(text:String) {
self.text = text
self.token = nil
}
public func render(_ context:Context) throws -> String {
@@ -44,13 +66,16 @@ public protocol Resolvable {
public class VariableNode : NodeType {
public let variable: Resolvable
public var token: Token?
public init(variable: Resolvable) {
public init(variable: Resolvable, token: Token? = nil) {
self.variable = variable
self.token = token
}
public init(variable: String) {
public init(variable: String, token: Token? = nil) {
self.variable = Variable(variable)
self.token = token
}
public func render(_ context: Context) throws -> String {