diff --git a/ast.c b/ast.c index c9d0b41fac..93c33a1f8d 100644 --- a/ast.c +++ b/ast.c @@ -195,6 +195,18 @@ script_lines(VALUE path) return lines; } +static VALUE +node_id_for_backtrace_location(rb_execution_context_t *ec, VALUE module, VALUE location) +{ + int node_id; + node_id = rb_get_node_id_from_frame_info(location); + if (node_id == -1) { + return Qnil; + } + + return INT2NUM(node_id); +} + static VALUE ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script_lines, VALUE error_tolerant) { diff --git a/ast.rb b/ast.rb index 24fd8e5526..1bc1168b80 100644 --- a/ast.rb +++ b/ast.rb @@ -67,6 +67,21 @@ module RubyVM::AbstractSyntaxTree Primitive.ast_s_of body, keep_script_lines, error_tolerant end + # call-seq: + # RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(backtrace_location) -> integer + # + # Returns the node id for the given backtrace location. + # + # begin + # raise + # rescue => e + # loc = e.backtrace_locations.first + # RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(loc) + # end # => 0 + def self.node_id_for_backtrace_location backtrace_location + Primitive.node_id_for_backtrace_location backtrace_location + end + # RubyVM::AbstractSyntaxTree::Node instances are created by parse methods in # RubyVM::AbstractSyntaxTree. # diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb index aaf626e801..0932e93d5a 100644 --- a/test/ruby/test_ast.rb +++ b/test/ruby/test_ast.rb @@ -186,6 +186,19 @@ class TestAst < Test::Unit::TestCase end end + def test_node_id_for_location + exception = begin + raise + rescue => e + e + end + loc = exception.backtrace_locations.first + node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(loc) + node = RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true) + + assert_equal node.node_id, node_id + end + def test_of_proc_and_method proc = Proc.new { 1 + 2 } method = self.method(__method__)