From ad3748af21a7f697d8db3b76f83a391c7069b166 Mon Sep 17 00:00:00 2001 From: Dylan Thacker-Smith Date: Thu, 21 May 2015 16:49:18 -0400 Subject: [PATCH] Include template name with line numbers in render errors. --- lib/liquid/context.rb | 3 ++- lib/liquid/errors.rb | 5 +++- lib/liquid/tags/include.rb | 33 ++++++++++++++----------- test/integration/error_handling_test.rb | 20 +++++++++++++++ 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/lib/liquid/context.rb b/lib/liquid/context.rb index c761d089..bb52558e 100644 --- a/lib/liquid/context.rb +++ b/lib/liquid/context.rb @@ -13,7 +13,7 @@ module Liquid # context['bob'] #=> nil class Context class Context attr_reader :scopes, :errors, :registers, :environments, :resource_limits - attr_accessor :exception_handler + attr_accessor :exception_handler, :template_name def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil) @environments = [environments].flatten @@ -64,6 +64,7 @@ module Liquid def handle_error(e, token = nil) if e.is_a?(Liquid::Error) + e.template_name = template_name e.set_line_number_from_token(token) end diff --git a/lib/liquid/errors.rb b/lib/liquid/errors.rb index e1defc5f..f1d4a2d4 100644 --- a/lib/liquid/errors.rb +++ b/lib/liquid/errors.rb @@ -1,6 +1,7 @@ module Liquid class Error < ::StandardError attr_accessor :line_number + attr_accessor :template_name attr_accessor :markup_context def to_s(with_prefix = true) @@ -41,7 +42,9 @@ module Liquid end if line_number - str << " (line #{line_number})" + str << " (" + str << template_name << " " if template_name + str << "line " << line_number.to_s << ")" end str << ": " diff --git a/lib/liquid/tags/include.rb b/lib/liquid/tags/include.rb index 80b46d93..3b1fc23d 100644 --- a/lib/liquid/tags/include.rb +++ b/lib/liquid/tags/include.rb @@ -41,9 +41,9 @@ module Liquid end def render(context) - partial = load_cached_partial(context) - template_name = context.evaluate(@template_name_expr) + partial = load_cached_partial(template_name, context) + context_variable_name = template_name.split('/'.freeze).last variable = if @variable_name_expr @@ -52,28 +52,33 @@ module Liquid context.find_variable(template_name) end - context.stack do - @attributes.each do |key, value| - context[key] = context.evaluate(value) - end + old_template_name = context.template_name + begin + context.template_name = template_name + context.stack do + @attributes.each do |key, value| + context[key] = context.evaluate(value) + end - if variable.is_a?(Array) - variable.collect do |var| - context[context_variable_name] = var + if variable.is_a?(Array) + variable.collect do |var| + context[context_variable_name] = var + partial.render(context) + end + else + context[context_variable_name] = variable partial.render(context) end - else - context[context_variable_name] = variable - partial.render(context) end + ensure + context.template_name = old_template_name end end private - def load_cached_partial(context) + def load_cached_partial(template_name, context) cached_partials = context.registers[:cached_partials] || {} - template_name = context.evaluate(@template_name_expr) if cached = cached_partials[template_name] return cached diff --git a/test/integration/error_handling_test.rb b/test/integration/error_handling_test.rb index 61091804..6e2623f2 100644 --- a/test/integration/error_handling_test.rb +++ b/test/integration/error_handling_test.rb @@ -203,4 +203,24 @@ class ErrorHandlingTest < Minitest::Test assert_equal 'This is a runtime error: Liquid error (line 1): internal', output assert_equal [InternalError], template.errors.map(&:class) end + + class TestFileSystem + def read_template_file(template_path) + "{{ errors.argument_error }}" + end + end + + def test_included_template_name_with_line_numbers + old_file_system = Liquid::Template.file_system + + begin + Liquid::Template.file_system = TestFileSystem.new + template = Liquid::Template.parse("Argument error:\n{% include 'product' %}", line_numbers: true) + page = template.render('errors' => ErrorDrop.new) + ensure + Liquid::Template.file_system = old_file_system + end + assert_equal "Argument error:\nLiquid error (product line 1): argument error", page + assert_equal "product", template.errors.first.template_name + end end