Skip to content

Commit

Permalink
Support nodes in spot
Browse files Browse the repository at this point in the history
Fixes a bug where `spot` was using the wrong local variable.

We want to use error highlight with code that has been eval'd,
specifically ERB templates. We can recover the compiled source code of
the ERB template but we need an API to pass the node into error
highlight's `spot`.

Required Ruby PR: ruby/ruby#6593

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
  • Loading branch information
2 people authored and mame committed Oct 31, 2022
1 parent defcaf1 commit 0b1b650
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
3 changes: 1 addition & 2 deletions lib/error_highlight/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ def self.spot(obj, **opts)
Spotter.new(node, **opts).spot

when RubyVM::AbstractSyntaxTree::Node
# Just for compatibility
Spotter.new(node, **opts).spot
Spotter.new(obj, **opts).spot

else
raise TypeError, "Exception is expected"
Expand Down
32 changes: 32 additions & 0 deletions test/test_error_highlight.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1257,4 +1257,36 @@ def test_spot_with_backtrace_location
assert_equal(22, spot[:last_column])
assert_equal(" raise_name_error\n", spot[:snippet])
end

def test_spot_with_node
omit unless RubyVM::AbstractSyntaxTree.respond_to?(:node_id_for_backtrace_location)

begin
raise_name_error
rescue NameError => exc
end

bl = exc.backtrace_locations.first
expected_spot = ErrorHighlight.spot(exc, backtrace_location: bl)
ast = RubyVM::AbstractSyntaxTree.parse_file(__FILE__, keep_script_lines: true)
node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(bl)
node = find_node_by_id(ast, node_id)
actual_spot = ErrorHighlight.spot(node)

assert_equal expected_spot, actual_spot
end

private

def find_node_by_id(node, node_id)
return node if node.node_id == node_id

node.children.each do |child|
next unless child.is_a?(RubyVM::AbstractSyntaxTree::Node)
found = find_node_by_id(child, node_id)
return found if found
end

return false
end
end

0 comments on commit 0b1b650

Please sign in to comment.