handling unknown filter errors

This commit is contained in:
Ilya Puchka
2017-10-07 23:10:27 +02:00
parent d5f0be959f
commit e59609f140
9 changed files with 114 additions and 43 deletions

View File

@@ -51,4 +51,9 @@ public struct Environment {
return ""
}
}
var template: Template? {
return errorReporter.context?.template
}
}

View File

@@ -15,7 +15,7 @@ class FilterNode : NodeType {
throw TemplateSyntaxError("`endfilter` was not found.")
}
let resolvable = try parser.compileFilter("filter_value|\(bits[1])")
let resolvable = try parser.compileFilter("filter_value|\(bits[1])", containedIn: token)
return FilterNode(nodes: blocks, resolvable: resolvable)
}

View File

@@ -21,24 +21,24 @@ class ForNode : NodeType {
.map { $0.trimmingCharacters(in: CharacterSet.whitespaces) }
let variable = components[3]
let filter = try parser.compileFilter(variable, containedIn: token)
var emptyNodes = [NodeType]()
let forNodes = try parser.parse(until(["endfor", "empty"]))
guard let token = parser.nextToken() else {
if let token = parser.nextToken() {
if token.contents == "empty" {
emptyNodes = try parser.parse(until(["endfor"]))
_ = parser.nextToken()
}
} else {
throw TemplateSyntaxError("`endfor` was not found.")
}
if token.contents == "empty" {
emptyNodes = try parser.parse(until(["endfor"]))
_ = parser.nextToken()
}
let filter = try parser.compileFilter(variable)
let `where`: Expression?
if components.count >= 6 {
`where` = try parseExpression(components: Array(components.suffix(from: 5)), tokenParser: parser)
`where` = try parseExpression(components: Array(components.suffix(from: 5)), tokenParser: parser, token: token)
} else {
`where` = nil
}

View File

@@ -100,7 +100,7 @@ final class IfExpressionParser {
let tokens: [IfToken]
var position: Int = 0
init(components: [String], tokenParser: TokenParser) throws {
init(components: [String], tokenParser: TokenParser, token: Token) throws {
self.tokens = try components.map { component in
if let op = findOperator(name: component) {
switch op {
@@ -111,7 +111,7 @@ final class IfExpressionParser {
}
}
return .variable(try tokenParser.compileFilter(component))
return .variable(try tokenParser.compileFilter(component, containedIn: token))
}
}
@@ -155,8 +155,8 @@ final class IfExpressionParser {
}
func parseExpression(components: [String], tokenParser: TokenParser) throws -> Expression {
let parser = try IfExpressionParser(components: components, tokenParser: tokenParser)
func parseExpression(components: [String], tokenParser: TokenParser, token: Token) throws -> Expression {
let parser = try IfExpressionParser(components: components, tokenParser: tokenParser, token: token)
return try parser.parse()
}
@@ -187,7 +187,7 @@ class IfNode : NodeType {
var components = token.components()
components.removeFirst()
let expression = try parseExpression(components: components, tokenParser: parser)
let expression = try parseExpression(components: components, tokenParser: parser, token: token)
let nodes = try parser.parse(until(["endif", "elif", "else"]))
var conditions: [IfCondition] = [
IfCondition(expression: expression, nodes: nodes)
@@ -197,7 +197,7 @@ class IfNode : NodeType {
while let current = token, current.contents.hasPrefix("elif") {
var components = current.components()
components.removeFirst()
let expression = try parseExpression(components: components, tokenParser: parser)
let expression = try parseExpression(components: components, tokenParser: parser, token: current)
let nodes = try parser.parse(until(["endif", "elif", "else"]))
token = parser.nextToken()
@@ -227,16 +227,16 @@ class IfNode : NodeType {
falseNodes = try parser.parse(until(["endif", "else"]))
guard let token = parser.nextToken() else {
if let token = parser.nextToken() {
if token.contents == "else" {
trueNodes = try parser.parse(until(["endif"]))
_ = parser.nextToken()
}
} else {
throw TemplateSyntaxError("`endif` was not found.")
}
if token.contents == "else" {
trueNodes = try parser.parse(until(["endif"]))
_ = parser.nextToken()
}
let expression = try parseExpression(components: components, tokenParser: parser)
let expression = try parseExpression(components: components, tokenParser: parser, token: token)
return IfNode(conditions: [
IfCondition(expression: expression, nodes: trueNodes),
IfCondition(expression: nil, nodes: falseNodes),

View File

@@ -40,7 +40,7 @@ public class TokenParser {
case .text(let text, _):
nodes.append(TextNode(text: text))
case .variable:
nodes.append(VariableNode(variable: try compileFilter(token.contents)))
nodes.append(VariableNode(variable: try compileFilter(token.contents, containedIn: token)))
case .block:
if let parse_until = parse_until , parse_until(self, token) {
prependToken(token)
@@ -100,7 +100,23 @@ public class TokenParser {
throw TemplateSyntaxError("Unknown filter '\(name)'")
}
public func compileFilter(_ filterToken: String, containedIn containingToken: Token) throws -> Resolvable {
do {
return try FilterExpression(token: filterToken, parser: self)
} catch {
if var syntaxError = error as? TemplateSyntaxError, syntaxError.lexeme == nil,
let filterTokenRange = environment.template?.templateString.range(of: filterToken, range: containingToken.range) {
syntaxError.lexeme = Token.block(value: filterToken, at: filterTokenRange)
throw syntaxError
} else {
throw error
}
}
}
@available(*, deprecated, message: "Use compileFilter(_:containedIn:)")
public func compileFilter(_ token: String) throws -> Resolvable {
return try FilterExpression(token: token, parser: self)
}

View File

@@ -11,8 +11,6 @@ class FilterExpression : Resolvable {
init(token: String, parser: TokenParser) throws {
let bits = token.characters.split(separator: "|").map({ String($0).trim(character: " ") })
if bits.isEmpty {
filters = []
variable = Variable("")
throw TemplateSyntaxError("Variable tags must include at least 1 argument")
}