From 584b492e706122ddd6eabb3aeba9cd4a8efb7549 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Fri, 3 Oct 2014 21:00:31 +0000 Subject: [PATCH] Line numbers for all parse errors --- lib/liquid/block.rb | 63 +++++++++++++------------ lib/liquid/errors.rb | 1 + test/integration/error_handling_test.rb | 49 +++++++++++++++++++ 3 files changed, 84 insertions(+), 29 deletions(-) diff --git a/lib/liquid/block.rb b/lib/liquid/block.rb index b2d5913..2e0ef9a 100644 --- a/lib/liquid/block.rb +++ b/lib/liquid/block.rb @@ -15,42 +15,47 @@ module Liquid @nodelist.clear while token = tokens.shift - unless token.empty? - case - when token.start_with?(TAGSTART) - if token =~ FullToken + begin + unless token.empty? + case + when token.start_with?(TAGSTART) + if token =~ FullToken - # if we found the proper block delimiter just end parsing here and let the outer block - # proceed - if block_delimiter == $1 - end_tag - return - end + # if we found the proper block delimiter just end parsing here and let the outer block + # proceed + if block_delimiter == $1 + end_tag + return + end - # fetch the tag from registered blocks - if tag = Template.tags[$1] - markup = token.is_a?(Token) ? token.child($2) : $2 - new_tag = tag.parse($1, markup, tokens, @options) - new_tag.line_number = token.line_number if token.is_a?(Token) - @blank &&= new_tag.blank? - @nodelist << new_tag + # fetch the tag from registered blocks + if tag = Template.tags[$1] + markup = token.is_a?(Token) ? token.child($2) : $2 + new_tag = tag.parse($1, markup, tokens, @options) + new_tag.line_number = token.line_number if token.is_a?(Token) + @blank &&= new_tag.blank? + @nodelist << new_tag + else + # this tag is not registered with the system + # pass it to the current block for special handling or error reporting + unknown_tag($1, $2, tokens) + end else - # this tag is not registered with the system - # pass it to the current block for special handling or error reporting - unknown_tag($1, $2, tokens) + raise SyntaxError.new(options[:locale].t("errors.syntax.tag_termination".freeze, :token => token, :tag_end => TagEnd.inspect)) end + when token.start_with?(VARSTART) + new_var = create_variable(token) + new_var.line_number = token.line_number if token.is_a?(Token) + @nodelist << new_var + @blank = false else - raise SyntaxError.new(options[:locale].t("errors.syntax.tag_termination".freeze, :token => token, :tag_end => TagEnd.inspect)) + @nodelist << token + @blank &&= (token =~ /\A\s*\z/) end - when token.start_with?(VARSTART) - new_var = create_variable(token) - new_var.line_number = token.line_number if token.is_a?(Token) - @nodelist << new_var - @blank = false - else - @nodelist << token - @blank &&= (token =~ /\A\s*\z/) end + rescue SyntaxError => e + e.set_line_number_from_token(token) + raise end end diff --git a/lib/liquid/errors.rb b/lib/liquid/errors.rb index bb9132d..6de9d00 100644 --- a/lib/liquid/errors.rb +++ b/lib/liquid/errors.rb @@ -18,6 +18,7 @@ module Liquid def set_line_number_from_token(token) return unless token.respond_to?(:line_number) + return if self.line_number self.line_number = token.line_number end diff --git a/test/integration/error_handling_test.rb b/test/integration/error_handling_test.rb index ee07204..7334402 100644 --- a/test/integration/error_handling_test.rb +++ b/test/integration/error_handling_test.rb @@ -100,6 +100,55 @@ class ErrorHandlingTest < Minitest::Test assert_equal Liquid::ArgumentError, template.errors.first.class end + def test_with_line_numbers_adds_numbers_to_parser_errors + err = assert_raises(SyntaxError) do + template = Liquid::Template.parse(%q{ + foobar + + {% "cat" | foobar %} + + bla + }, + :line_numbers => true + ) + end + + assert_match /Liquid syntax error \(line 4\)/, err.message + end + + def test_parsing_warn_with_line_numbers_adds_numbers_to_lexer_errors + template = Liquid::Template.parse(%q{ + foobar + + {% if 1 =! 2 %}ok{% endif %} + + bla + }, + :error_mode => :warn, + :line_numbers => true + ) + + assert_equal ['Liquid syntax error (line 4): Unexpected character = in "1 =! 2"'], + template.warnings.map(&:message) + end + + def test_parsing_strict_with_line_numbers_adds_numbers_to_lexer_errors + err = assert_raises(SyntaxError) do + Liquid::Template.parse(%q{ + foobar + + {% if 1 =! 2 %}ok{% endif %} + + bla + }, + :error_mode => :strict, + :line_numbers => true + ) + end + + assert_equal 'Liquid syntax error (line 4): Unexpected character = in "1 =! 2"', err.message + end + def test_strict_error_messages err = assert_raises(SyntaxError) do Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ', :error_mode => :strict)