[前][次][番号順一覧][スレッド一覧]

ruby-changes:74298

From: eileencodes <ko1@a...>
Date: Mon, 31 Oct 2022 13:40:24 +0900 (JST)
Subject: [ruby-changes:74298] 3391c51eff (master): Add `node_id_for_backtrace_location` function

https://git.ruby-lang.org/ruby.git/commit/?id=3391c51eff

From 3391c51effcd61f9a718adf59740661d99f57b5b Mon Sep 17 00:00:00 2001
From: eileencodes <eileencodes@g...>
Date: Wed, 19 Oct 2022 13:23:53 -0400
Subject: 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: https://github.com/ruby/error_highlight/pull/26

Co-authored-by: Aaron Patterson <tenderlove@r...>
---
 ast.c                 | 12 ++++++++++++
 ast.rb                | 15 +++++++++++++++
 test/ruby/test_ast.rb | 13 +++++++++++++
 3 files changed, 40 insertions(+)

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) https://github.com/ruby/ruby/blob/trunk/ast.c#L195
     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 https://github.com/ruby/ruby/blob/trunk/ast.rb#L67
     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 https://github.com/ruby/ruby/blob/trunk/test/ruby/test_ast.rb#L186
     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__)
-- 
cgit v1.2.3


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]