Skip to content

Commit 3391c51

Browse files
eileencodestenderlove
authored andcommitted
Add node_id_for_backtrace_location function
We want to use error highlight with eval'd code, specifically ERB templates. We're able to recover the generated code for eval'd templates and can get a parse tree for the ERB generated code, but we don't have a way to get the node id from the backtrace location. So we can't pass the right node into error highlight. This patch gives us an API to get the node id from the backtrace location so we can find the node in the AST. Error Highlight PR: ruby/error_highlight#26 Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
1 parent 7ed10ab commit 3391c51

File tree

3 files changed

+40
-0
lines changed

3 files changed

+40
-0
lines changed

ast.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,18 @@ script_lines(VALUE path)
195195
return lines;
196196
}
197197

198+
static VALUE
199+
node_id_for_backtrace_location(rb_execution_context_t *ec, VALUE module, VALUE location)
200+
{
201+
int node_id;
202+
node_id = rb_get_node_id_from_frame_info(location);
203+
if (node_id == -1) {
204+
return Qnil;
205+
}
206+
207+
return INT2NUM(node_id);
208+
}
209+
198210
static VALUE
199211
ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script_lines, VALUE error_tolerant)
200212
{

ast.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,21 @@ def self.of body, keep_script_lines: false, error_tolerant: false
6767
Primitive.ast_s_of body, keep_script_lines, error_tolerant
6868
end
6969

70+
# call-seq:
71+
# RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(backtrace_location) -> integer
72+
#
73+
# Returns the node id for the given backtrace location.
74+
#
75+
# begin
76+
# raise
77+
# rescue => e
78+
# loc = e.backtrace_locations.first
79+
# RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(loc)
80+
# end # => 0
81+
def self.node_id_for_backtrace_location backtrace_location
82+
Primitive.node_id_for_backtrace_location backtrace_location
83+
end
84+
7085
# RubyVM::AbstractSyntaxTree::Node instances are created by parse methods in
7186
# RubyVM::AbstractSyntaxTree.
7287
#

test/ruby/test_ast.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,19 @@ def test_parse_file_raises_syntax_error
186186
end
187187
end
188188

189+
def test_node_id_for_location
190+
exception = begin
191+
raise
192+
rescue => e
193+
e
194+
end
195+
loc = exception.backtrace_locations.first
196+
node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(loc)
197+
node = RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true)
198+
199+
assert_equal node.node_id, node_id
200+
end
201+
189202
def test_of_proc_and_method
190203
proc = Proc.new { 1 + 2 }
191204
method = self.method(__method__)

0 commit comments

Comments
 (0)