diff options
Diffstat (limited to 'lib/error_highlight')
| -rw-r--r-- | lib/error_highlight/base.rb | 112 | ||||
| -rw-r--r-- | lib/error_highlight/core_ext.rb | 35 |
2 files changed, 144 insertions, 3 deletions
diff --git a/lib/error_highlight/base.rb b/lib/error_highlight/base.rb index 14e0ce5785..b4a31f8e80 100644 --- a/lib/error_highlight/base.rb +++ b/lib/error_highlight/base.rb @@ -239,6 +239,20 @@ module ErrorHighlight when :OP_CDECL spot_op_cdecl + when :DEFN + raise NotImplementedError if @point_type != :name + spot_defn + + when :DEFS + raise NotImplementedError if @point_type != :name + spot_defs + + when :LAMBDA + spot_lambda + + when :ITER + spot_iter + when :call_node case @point_type when :name @@ -280,6 +294,30 @@ module ErrorHighlight when :constant_path_operator_write_node prism_spot_constant_path_operator_write + when :def_node + case @point_type + when :name + prism_spot_def_for_name + when :args + raise NotImplementedError + end + + when :lambda_node + case @point_type + when :name + prism_spot_lambda_for_name + when :args + raise NotImplementedError + end + + when :block_node + case @point_type + when :name + prism_spot_block_for_name + when :args + raise NotImplementedError + end + end if @snippet && @beg_column && @end_column && @beg_column < @end_column @@ -621,6 +659,55 @@ module ErrorHighlight end end + # Example: + # def bar; end + # ^^^ + def spot_defn + mid, = @node.children + fetch_line(@node.first_lineno) + if @snippet.match(/\Gdef\s+(#{ Regexp.quote(mid) }\b)/, @node.first_column) + @beg_column = $~.begin(1) + @end_column = $~.end(1) + end + end + + # Example: + # def Foo.bar; end + # ^^^^ + def spot_defs + nd_recv, mid, = @node.children + fetch_line(nd_recv.last_lineno) + if @snippet.match(/\G\s*(\.\s*#{ Regexp.quote(mid) }\b)/, nd_recv.last_column) + @beg_column = $~.begin(1) + @end_column = $~.end(1) + end + end + + # Example: + # -> { ... } + # ^^ + def spot_lambda + fetch_line(@node.first_lineno) + if @snippet.match(/\G->/, @node.first_column) + @beg_column = $~.begin(0) + @end_column = $~.end(0) + end + end + + # Example: + # lambda { ... } + # ^ + # define_method :foo do + # ^^ + def spot_iter + _nd_fcall, nd_scope = @node.children + fetch_line(nd_scope.first_lineno) + if @snippet.match(/\G(?:do\b|\{)/, nd_scope.first_column) + @beg_column = $~.begin(0) + @end_column = $~.end(0) + end + end + def fetch_line(lineno) @beg_lineno = @end_lineno = lineno @snippet = @fetch[lineno] @@ -826,6 +913,31 @@ module ErrorHighlight prism_location(@node.binary_operator_loc.chop) end end + + # Example: + # def foo() + # ^^^ + def prism_spot_def_for_name + location = @node.name_loc + location = location.join(@node.operator_loc) if @node.operator_loc + prism_location(location) + end + + # Example: + # -> x, y { } + # ^^ + def prism_spot_lambda_for_name + prism_location(@node.operator_loc) + end + + # Example: + # lambda { } + # ^ + # define_method :foo do |x, y| + # ^ + def prism_spot_block_for_name + prism_location(@node.opening_loc) + end end private_constant :Spotter diff --git a/lib/error_highlight/core_ext.rb b/lib/error_highlight/core_ext.rb index b69093f74e..2fb07f2e65 100644 --- a/lib/error_highlight/core_ext.rb +++ b/lib/error_highlight/core_ext.rb @@ -3,9 +3,38 @@ require_relative "formatter" module ErrorHighlight module CoreExt private def generate_snippet - spot = ErrorHighlight.spot(self) - return "" unless spot - return ErrorHighlight.formatter.message_for(spot) + if ArgumentError === self && message =~ /\A(?:wrong number of arguments|missing keyword|unknown keyword|no keywords accepted)\b/ + locs = self.backtrace_locations + return "" if locs.size < 2 + callee_loc, caller_loc = locs + callee_spot = ErrorHighlight.spot(self, backtrace_location: callee_loc, point_type: :name) + caller_spot = ErrorHighlight.spot(self, backtrace_location: caller_loc, point_type: :name) + if caller_spot && callee_spot && + caller_loc.path == callee_loc.path && + caller_loc.lineno == callee_loc.lineno && + caller_spot == callee_spot + callee_loc = callee_spot = nil + end + ret = +"\n" + [["caller", caller_loc, caller_spot], ["callee", callee_loc, callee_spot]].each do |header, loc, spot| + out = nil + if loc + out = " #{ header }: #{ loc.path }:#{ loc.lineno }" + if spot + _, _, snippet, highlight = ErrorHighlight.formatter.message_for(spot).lines + out += "\n | #{ snippet } #{ highlight }" + else + out += "\n (cannot create a snippet of the method definition; use Ruby 3.5 or later)" + end + end + ret << "\n" + out if out + end + ret + else + spot = ErrorHighlight.spot(self) + return "" unless spot + return ErrorHighlight.formatter.message_for(spot) + end end if Exception.method_defined?(:detailed_message) |
