diff options
author | Yusuke Endoh <mame@ruby-lang.org> | 2022-08-10 18:36:59 +0900 |
---|---|---|
committer | git <svn-admin@ruby-lang.org> | 2022-08-10 18:37:13 +0900 |
commit | 99e7fa5b3718d61d61427c67d244ec50b9eb8578 (patch) | |
tree | 34e74d18354ac62cbcd44bbdd29d791c2693e083 /lib/error_highlight/base.rb | |
parent | 1139bc8c20d243b17f159d6c6518df17fcf887fe (diff) | |
download | ruby-99e7fa5b3718d61d61427c67d244ec50b9eb8578.tar.gz |
[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
Diffstat (limited to 'lib/error_highlight/base.rb')
-rw-r--r-- | lib/error_highlight/base.rb | 58 |
1 files changed, 51 insertions, 7 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 @@ 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 # 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 last_lineno: @end_lineno, last_column: @end_column, snippet: @snippet, + script_lines: @node.script_lines, } else return nil |