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

ruby-changes:72888

From: Yusuke <ko1@a...>
Date: Wed, 10 Aug 2022 18:37:26 +0900 (JST)
Subject: [ruby-changes:72888] 99e7fa5b37 (master): [ruby/error_highlight] Make ErrorHighlight.spot accept Exception (https://github.com/ruby/error_highlight/pull/25)

https://git.ruby-lang.org/ruby.git/commit/?id=99e7fa5b37

From 99e7fa5b3718d61d61427c67d244ec50b9eb8578 Mon Sep 17 00:00:00 2001
From: Yusuke Endoh <mame@r...>
Date: Wed, 10 Aug 2022 18:36:59 +0900
Subject: [ruby/error_highlight] Make ErrorHighlight.spot accept Exception
 (https://github.com/ruby/error_highlight/pull/25)

... and move things from core_ext.rb to base.rb.
This will confine CRuby-dependent things to ErrorHighlight.spot.

https://github.com/ruby/error_highlight/commit/22d1dd7824
---
 lib/error_highlight/base.rb                  | 58 ++++++++++++++++++++++++----
 lib/error_highlight/core_ext.rb              | 33 ++--------------
 test/error_highlight/test_error_highlight.rb |  2 +-
 3 files changed, 55 insertions(+), 38 deletions(-)

diff --git a/lib/error_highlight/base.rb b/lib/error_highlight/base.rb
index 8392979e24..51f1ce369d 100644
--- a/lib/error_highlight/base.rb
+++ b/lib/error_highlight/base.rb
@@ -1,12 +1,17 @@ https://github.com/ruby/ruby/blob/trunk/lib/error_highlight/base.rb#L1
 require_relative "version"
 
 module ErrorHighlight
-  # Identify the code fragment that seems associated with a given error
+  # Identify the code fragment at that a given exception occurred.
   #
-  # Arguments:
-  #  node: RubyVM::AbstractSyntaxTree::Node (script_lines should be enabled)
-  #  point_type: :name | :args
-  #  name: The name associated with the NameError/NoMethodError
+  # Options:
+  #
+  # point_type: :name | :args
+  #   :name (default) points the method/variable name that the exception occurred.
+  #   :args points the arguments of the method call that the exception occurred.
+  #
+  # backtrace_location: Thread::Backtrace::Location
+  #   It locates the code fragment of the given backtrace_location.
+  #   By default, it uses the first frame of backtrace_locations of the given exception.
   #
   # Returns:
   #  {
@@ -15,9 +20,47 @@ module ErrorHighlight https://github.com/ruby/ruby/blob/trunk/lib/error_highlight/base.rb#L20
   #    last_lineno: Integer,
   #    last_column: Integer,
   #    snippet: String,
+  #    script_lines: [String],
   #  } | nil
-  def self.spot(...)
-    Spotter.new(...).spot
+  def self.spot(obj, **opts)
+    case obj
+    when Exception
+      exc = obj
+      opts = { point_type: opts.fetch(:point_type, :name) }
+
+      loc = opts[:backtrace_location]
+      unless loc
+        case exc
+        when TypeError, ArgumentError
+          opts[:point_type] = :args
+        end
+
+        locs = exc.backtrace_locations
+        return nil unless locs
+
+        loc = locs.first
+        return nil unless loc
+
+        opts[:name] = exc.name if NameError === obj
+      end
+
+      node = RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true)
+
+      Spotter.new(node, **opts).spot
+
+    when RubyVM::AbstractSyntaxTree::Node
+      # Just for compatibility
+      Spotter.new(node, **opts).spot
+
+    else
+      raise TypeError, "Exception is expected"
+    end
+
+  rescue SyntaxError,
+         SystemCallError, # file not found or something
+         ArgumentError # eval'ed code
+
+    return nil
   end
 
   class Spotter
@@ -122,6 +165,7 @@ module ErrorHighlight https://github.com/ruby/ruby/blob/trunk/lib/error_highlight/base.rb#L165
           last_lineno: @end_lineno,
           last_column: @end_column,
           snippet: @snippet,
+          script_lines: @node.script_lines,
         }
       else
         return nil
diff --git a/lib/error_highlight/core_ext.rb b/lib/error_highlight/core_ext.rb
index 53e409dd8f..130f9ef832 100644
--- a/lib/error_highlight/core_ext.rb
+++ b/lib/error_highlight/core_ext.rb
@@ -3,36 +3,9 @@ require_relative "formatter" https://github.com/ruby/ruby/blob/trunk/lib/error_highlight/core_ext.rb#L3
 module ErrorHighlight
   module CoreExt
     private def generate_snippet
-      locs = backtrace_locations
-      return "" unless locs
-
-      loc = locs.first
-      return "" unless loc
-
-      begin
-        node = RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true)
-        opts = {}
-
-        case self
-        when NoMethodError, NameError
-          opts[:point_type] = :name
-          opts[:name] = name
-        when TypeError, ArgumentError
-          opts[:point_type] = :args
-        end
-
-        spot = ErrorHighlight.spot(node, **opts)
-
-      rescue SyntaxError
-      rescue SystemCallError # file not found or something
-      rescue ArgumentError   # eval'ed code
-      end
-
-      if spot
-        return ErrorHighlight.formatter.message_for(spot)
-      end
-
-      ""
+      spot = ErrorHighlight.spot(self)
+      return "" unless spot
+      return ErrorHighlight.formatter.message_for(spot)
     end
 
     if Exception.method_defined?(:detailed_message)
diff --git a/test/error_highlight/test_error_highlight.rb b/test/error_highlight/test_error_highlight.rb
index 5b7c05e5f4..89c930f5e6 100644
--- a/test/error_highlight/test_error_highlight.rb
+++ b/test/error_highlight/test_error_highlight.rb
@@ -1150,7 +1150,7 @@ nil can't be coerced into Integer https://github.com/ruby/ruby/blob/trunk/test/error_highlight/test_error_highlight.rb#L1150
   def test_custom_formatter
     custom_formatter = Object.new
     def custom_formatter.message_for(spot)
-      "\n\n" + spot.inspect
+      "\n\n" + spot.except(:script_lines).inspect
     end
 
     original_formatter, ErrorHighlight.formatter = ErrorHighlight.formatter, custom_formatter
-- 
cgit v1.2.1


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

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