Skip to content

Commit 350d0aa

Browse files
eileencodestenderlove
authored andcommitted
[ruby/error_highlight] Support nodes in spot
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#6593 ruby/error_highlight@0b1b650a59 Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
1 parent 3391c51 commit 350d0aa

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

lib/error_highlight/base.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,7 @@ def self.spot(obj, **opts)
5959
Spotter.new(node, **opts).spot
6060

6161
when RubyVM::AbstractSyntaxTree::Node
62-
# Just for compatibility
63-
Spotter.new(node, **opts).spot
62+
Spotter.new(obj, **opts).spot
6463

6564
else
6665
raise TypeError, "Exception is expected"

test/error_highlight/test_error_highlight.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,4 +1257,36 @@ def test_spot_with_backtrace_location
12571257
assert_equal(22, spot[:last_column])
12581258
assert_equal(" raise_name_error\n", spot[:snippet])
12591259
end
1260+
1261+
def test_spot_with_node
1262+
omit unless RubyVM::AbstractSyntaxTree.respond_to?(:node_id_for_backtrace_location)
1263+
1264+
begin
1265+
raise_name_error
1266+
rescue NameError => exc
1267+
end
1268+
1269+
bl = exc.backtrace_locations.first
1270+
expected_spot = ErrorHighlight.spot(exc, backtrace_location: bl)
1271+
ast = RubyVM::AbstractSyntaxTree.parse_file(__FILE__, keep_script_lines: true)
1272+
node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(bl)
1273+
node = find_node_by_id(ast, node_id)
1274+
actual_spot = ErrorHighlight.spot(node)
1275+
1276+
assert_equal expected_spot, actual_spot
1277+
end
1278+
1279+
private
1280+
1281+
def find_node_by_id(node, node_id)
1282+
return node if node.node_id == node_id
1283+
1284+
node.children.each do |child|
1285+
next unless child.is_a?(RubyVM::AbstractSyntaxTree::Node)
1286+
found = find_node_by_id(child, node_id)
1287+
return found if found
1288+
end
1289+
1290+
return false
1291+
end
12601292
end

0 commit comments

Comments
 (0)