diff --git a/lib/oga/xml/parser.y b/lib/oga/xml/parser.y index ff4f4c9..afddde6 100644 --- a/lib/oga/xml/parser.y +++ b/lib/oga/xml/parser.y @@ -228,31 +228,35 @@ end # @raise [Racc::ParseError] # def on_error(type, value, stack) - name = token_to_str(type) - index = @line - 1 - lines = @data.each_line.to_a - code = '' + name = token_to_str(type) + index = @line - 1 + index_range = (index - 5)..(index + 5) + code = '' + + # For IO we sadly have to re-read the input :< + if @data.respond_to?(:rewind) + @data.rewind + end # Show up to 5 lines before and after the offending line (if they exist). - (-5..5).each do |offset| - line = lines[index + offset] - number = @line + offset + @data.each_line.with_index do |line, line_index| + next unless index_range.cover?(line_index) - if line and number > 0 - if offset == 0 - prefix = '=> ' - else - prefix = ' ' - end + number = line_index + 1 - line = line.strip - - if line.length > 80 - line = line[0..79] + ' (more)' - end - - code << "#{prefix}#{number}: #{line}\n" + if line_index == index + prefix = '=> ' + else + prefix = ' ' end + + line = line.strip + + if line.length > 80 + line = line[0..79] + ' (more)' + end + + code << "#{prefix}#{number}: #{line}\n" end raise Racc::ParseError, <<-EOF.strip diff --git a/spec/oga/xml/parser/error_spec.rb b/spec/oga/xml/parser/error_spec.rb index dbbd07b..617864b 100644 --- a/spec/oga/xml/parser/error_spec.rb +++ b/spec/oga/xml/parser/error_spec.rb @@ -16,7 +16,7 @@ describe Oga::XML::Parser do expect { parse(@invalid_xml) }.to raise_error(Racc::ParseError) end - example 'display a more meaningful error message' do + example 'include the offending input when using String as input' do # Racc basically reports errors at the last moment instead of where they # *actually* occur. partial = <<-EOF.strip @@ -29,5 +29,19 @@ describe Oga::XML::Parser do parse_error(@invalid_xml).should =~ /#{partial}/ end + + example 'include the offending input when using IO as input' do + # Racc basically reports errors at the last moment instead of where they + # *actually* occur. + partial = <<-EOF.strip + 1. + 2. Alice + 3. 25 + 4. Dutch +=> 5. + EOF + + parse_error(StringIO.new(@invalid_xml)).should =~ /#{partial}/ + end end end