Merge pull request #244 from Shopify/proper-parse-warnings

Add Better Parse Warnings To recursive-parser Branch
This commit is contained in:
Tristan Hume
2013-08-27 06:53:34 -07:00
8 changed files with 36 additions and 12 deletions
+19 -1
View File
@@ -14,6 +14,9 @@ module Liquid
@nodelist ||= [] @nodelist ||= []
@nodelist.clear @nodelist.clear
# All child tags of the current block.
@children = []
while token = tokens.shift while token = tokens.shift
case token case token
when IsTag when IsTag
@@ -31,6 +34,7 @@ module Liquid
new_tag = tag.new_with_options($1, $2, tokens, @options || {}) new_tag = tag.new_with_options($1, $2, tokens, @options || {})
@blank &&= new_tag.blank? @blank &&= new_tag.blank?
@nodelist << new_tag @nodelist << new_tag
@children << new_tag
else else
# this tag is not registered with the system # this tag is not registered with the system
# pass it to the current block for special handling or error reporting # pass it to the current block for special handling or error reporting
@@ -40,7 +44,9 @@ module Liquid
raise SyntaxError, "Tag '#{token}' was not properly terminated with regexp: #{TagEnd.inspect} " raise SyntaxError, "Tag '#{token}' was not properly terminated with regexp: #{TagEnd.inspect} "
end end
when IsVariable when IsVariable
@nodelist << create_variable(token) new_var = create_variable(token)
@nodelist << new_var
@children << new_var
@blank = false @blank = false
when '' when ''
# pass # pass
@@ -56,6 +62,18 @@ module Liquid
assert_missing_delimitation! assert_missing_delimitation!
end end
# warnings of this block and all sub-tags
def warnings
all_warnings = []
all_warnings.concat(@warnings) if @warnings
@children.each do |node|
all_warnings.concat(node.warnings || [])
end
all_warnings
end
def end_tag def end_tag
end end
+1 -1
View File
@@ -13,7 +13,7 @@ module Liquid
def consume(type = nil) def consume(type = nil)
token = @tokens[@p] token = @tokens[@p]
if type && token[0] != type if type && token[0] != type
raise SyntaxError, "Expected #{type} but found #{@tokens[@p]}" raise SyntaxError, "Expected #{type} but found #{@tokens[@p].first}"
end end
@p += 1 @p += 1
token[1] token[1]
+1
View File
@@ -1,6 +1,7 @@
module Liquid module Liquid
class Tag class Tag
attr_accessor :nodelist, :options attr_accessor :nodelist, :options
attr_reader :warnings
def self.new_with_options(tag_name, markup, tokens, options) def self.new_with_options(tag_name, markup, tokens, options)
# Forgive me Matz for I have sinned. I know this code is weird # Forgive me Matz for I have sinned. I know this code is weird
-1
View File
@@ -58,7 +58,6 @@ module Liquid
end end
def render(context) def render(context)
context.errors.concat(@warnings) if @warnings
context.registers[:for] ||= Hash.new(0) context.registers[:for] ||= Hash.new(0)
collection = context[@collection_name] collection = context[@collection_name]
-1
View File
@@ -29,7 +29,6 @@ module Liquid
end end
def render(context) def render(context)
context.errors.concat(@warnings) if @warnings
context.stack do context.stack do
@blocks.each do |block| @blocks.each do |block|
if block.evaluate(context) if block.evaluate(context)
+6
View File
@@ -69,9 +69,15 @@ module Liquid
# Returns self for easy chaining # Returns self for easy chaining
def parse(source, options = {}) def parse(source, options = {})
@root = Document.new(tokenize(source), options) @root = Document.new(tokenize(source), options)
@warnings = nil
self self
end end
def warnings
return [] unless @root
@warnings ||= @root.warnings
end
def registers def registers
@registers ||= {} @registers ||= {}
end end
+3 -4
View File
@@ -13,12 +13,11 @@ module Liquid
class Variable class Variable
FilterParser = /(?:#{FilterSeparator}|(?:\s*(?:#{QuotedFragment}|#{ArgumentSeparator})\s*)+)/o FilterParser = /(?:#{FilterSeparator}|(?:\s*(?:#{QuotedFragment}|#{ArgumentSeparator})\s*)+)/o
EasyParse = /^ *(\w+(?:\.\w+)*) *$/ EasyParse = /^ *(\w+(?:\.\w+)*) *$/
attr_accessor :filters, :name attr_accessor :filters, :name, :warnings
def initialize(markup, options = {}) def initialize(markup, options = {})
@markup = markup @markup = markup
@name = nil @name = nil
@warning = nil
@options = options || {} @options = options || {}
@@ -29,7 +28,8 @@ module Liquid
begin begin
strict_parse(markup) strict_parse(markup)
rescue SyntaxError => e rescue SyntaxError => e
@warning = e @warnings ||= []
@warnings << e
lax_parse(markup) lax_parse(markup)
end end
end end
@@ -87,7 +87,6 @@ module Liquid
def render(context) def render(context)
return '' if @name.nil? return '' if @name.nil?
context.errors << @warning if @warning
@filters.inject(context[@name]) do |output, filter| @filters.inject(context[@name]) do |output, filter|
filterargs = [] filterargs = []
keyword_args = {} keyword_args = {}
+6 -4
View File
@@ -92,10 +92,12 @@ class ErrorHandlingTest < Test::Unit::TestCase
end end
def test_warnings def test_warnings
template = Liquid::Template.parse('{% if ~~~ %}derp{% else %}wat{% endif %}', :error_mode => :warn) template = Liquid::Template.parse('{% if ~~~ %}{{%%%}}{% else %}{{ hello. }}{% endif %}', :error_mode => :warn)
assert_equal 'wat', template.render assert_equal 3, template.warnings.size
assert_equal 1, template.errors.size assert_equal 'Unexpected character ~ in "~~~"', template.warnings[0].message
assert_equal 'Unexpected character ~ in "~~~"', template.errors.first.message assert_equal 'Unexpected character % in "{{%%%}}"', template.warnings[1].message
assert_equal 'Expected id but found end_of_string in "{{ hello. }}"', template.warnings[2].message
assert_equal '', template.render
end end
# Liquid should not catch Exceptions that are not subclasses of StandardError, like Interrupt and NoMemoryError # Liquid should not catch Exceptions that are not subclasses of StandardError, like Interrupt and NoMemoryError