1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

[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
This commit is contained in:
Yusuke Endoh 2022-08-10 18:36:59 +09:00 committed by git
parent 1139bc8c20
commit 99e7fa5b37
3 changed files with 55 additions and 38 deletions

View file

@ -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

View file

@ -3,36 +3,9 @@ require_relative "formatter"
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)

View file

@ -1150,7 +1150,7 @@ nil can't be coerced into Integer
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