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

ruby-changes:66630

From: Yusuke <ko1@a...>
Date: Tue, 29 Jun 2021 23:46:13 +0900 (JST)
Subject: [ruby-changes:66630] 9438c99590 (master): Rename error_squiggle to error_highlight

https://git.ruby-lang.org/ruby.git/commit/?id=9438c99590

From 9438c99590f5476a81cee8b4cf2de25084a40b42 Mon Sep 17 00:00:00 2001
From: Yusuke Endoh <mame@r...>
Date: Mon, 28 Jun 2021 13:27:35 +0900
Subject: Rename error_squiggle to error_highlight

---
 gem_prelude.rb                               |   6 +-
 lib/error_highlight.rb                       |   2 +
 lib/error_highlight/base.rb                  | 446 ++++++++++++
 lib/error_highlight/core_ext.rb              |  48 ++
 lib/error_highlight/version.rb               |   3 +
 lib/error_squiggle.rb                        |   2 -
 lib/error_squiggle/base.rb                   | 446 ------------
 lib/error_squiggle/core_ext.rb               |  48 --
 lib/error_squiggle/version.rb                |   3 -
 ruby.c                                       |   8 +-
 test/error_highlight/test_error_highlight.rb | 984 +++++++++++++++++++++++++++
 test/error_squiggle/test_error_squiggle.rb   | 984 ---------------------------
 12 files changed, 1490 insertions(+), 1490 deletions(-)
 create mode 100644 lib/error_highlight.rb
 create mode 100644 lib/error_highlight/base.rb
 create mode 100644 lib/error_highlight/core_ext.rb
 create mode 100644 lib/error_highlight/version.rb
 delete mode 100644 lib/error_squiggle.rb
 delete mode 100644 lib/error_squiggle/base.rb
 delete mode 100644 lib/error_squiggle/core_ext.rb
 delete mode 100644 lib/error_squiggle/version.rb
 create mode 100644 test/error_highlight/test_error_highlight.rb
 delete mode 100644 test/error_squiggle/test_error_squiggle.rb

diff --git a/gem_prelude.rb b/gem_prelude.rb
index f5616e6..f60ea46 100644
--- a/gem_prelude.rb
+++ b/gem_prelude.rb
@@ -5,10 +5,10 @@ rescue LoadError https://github.com/ruby/ruby/blob/trunk/gem_prelude.rb#L5
 end if defined?(Gem)
 
 begin
-  require 'error_squiggle'
+  require 'error_highlight'
 rescue LoadError
-  warn "`error_squiggle' was not loaded."
-end if defined?(ErrorSquiggle)
+  warn "`error_highlight' was not loaded."
+end if defined?(ErrorHighlight)
 
 begin
   require 'did_you_mean'
diff --git a/lib/error_highlight.rb b/lib/error_highlight.rb
new file mode 100644
index 0000000..31db95d
--- /dev/null
+++ b/lib/error_highlight.rb
@@ -0,0 +1,2 @@ https://github.com/ruby/ruby/blob/trunk/lib/error_highlight.rb#L1
+require_relative "error_highlight/base"
+require_relative "error_highlight/core_ext"
diff --git a/lib/error_highlight/base.rb b/lib/error_highlight/base.rb
new file mode 100644
index 0000000..49c7725
--- /dev/null
+++ b/lib/error_highlight/base.rb
@@ -0,0 +1,446 @@ 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
+  #
+  # Arguments:
+  #  node: RubyVM::AbstractSyntaxTree::Node
+  #  point: :name | :args
+  #  name: The name associated with the NameError/NoMethodError
+  #  fetch: A block to fetch a specified code line (or lines)
+  #
+  # Returns:
+  #  {
+  #    first_lineno: Integer,
+  #    first_column: Integer,
+  #    last_lineno: Integer,
+  #    last_column: Integer,
+  #    line: String,
+  #  } | nil
+  def self.spot(...)
+    Spotter.new(...).spot
+  end
+
+  class Spotter
+    def initialize(node, point, name: nil, &fetch)
+      @node = node
+      @point = point
+      @name = name
+
+      # Not-implemented-yet options
+      @arg = nil # Specify the index or keyword at which argument caused the TypeError/ArgumentError
+      @multiline = false # Allow multiline spot
+
+      @fetch = fetch
+    end
+
+    def spot
+      return nil unless @node
+
+      case @node.type
+
+      when :CALL, :QCALL
+        case @point
+        when :name
+          spot_call_for_name
+        when :args
+          spot_call_for_args
+        end
+
+      when :ATTRASGN
+        case @point
+        when :name
+          spot_attrasgn_for_name
+        when :args
+          spot_attrasgn_for_args
+        end
+
+      when :OPCALL
+        case @point
+        when :name
+          spot_opcall_for_name
+        when :args
+          spot_opcall_for_args
+        end
+
+      when :FCALL
+        case @point
+        when :name
+          spot_fcall_for_name
+        when :args
+          spot_fcall_for_args
+        end
+
+      when :VCALL
+        spot_vcall
+
+      when :OP_ASGN1
+        case @point
+        when :name
+          spot_op_asgn1_for_name
+        when :args
+          spot_op_asgn1_for_args
+        end
+
+      when :OP_ASGN2
+        case @point
+        when :name
+          spot_op_asgn2_for_name
+        when :args
+          spot_op_asgn2_for_args
+        end
+
+      when :CONST
+        spot_vcall
+
+      when :COLON2
+        spot_colon2
+
+      when :COLON3
+        spot_vcall
+
+      when :OP_CDECL
+        spot_op_cdecl
+      end
+
+      if @line && @beg_column && @end_column && @beg_column < @end_column
+        return {
+          first_lineno: @beg_lineno,
+          first_column: @beg_column,
+          last_lineno: @end_lineno,
+          last_column: @end_column,
+          line: @line,
+        }
+      else
+        return nil
+      end
+    end
+
+    private
+
+    # Example:
+    #   x.foo
+    #    ^^^^
+    #   x.foo(42)
+    #    ^^^^
+    #   x&.foo
+    #    ^^^^^
+    #   x[42]
+    #    ^^^^
+    #   x += 1
+    #     ^
+    def spot_call_for_name
+      nd_recv, mid, nd_args = @node.children
+      lineno = nd_recv.last_lineno
+      lines = @fetch[lineno, @node.last_lineno]
+      if mid == :[] && lines.match(/\G\s*(\[(?:\s*\])?)/, nd_recv.last_column)
+        @beg_column = $~.begin(1)
+        @line = lines[/.*\n/]
+        @beg_lineno = @end_lineno = lineno
+        if nd_args
+          if nd_recv.last_lineno == nd_args.last_lineno && @line.match(/\s*\]/, nd_args.last_column)
+            @end_column = $~.end(0)
+          end
+        else
+          if lines.match(/\G\s*?\[\s*\]/, nd_recv.last_column)
+            @end_column = $~.end(0)
+          end
+        end
+      elsif lines.match(/\G\s*?(\&?\.)(\s*?)(#{ Regexp.quote(mid) }).*\n/, nd_recv.last_column)
+        lines = $` + $&
+        @beg_column = $~.begin($2.include?("\n") ? 3 : 1)
+        @end_column = $~.end(3)
+        if i = lines[..@beg_column].rindex("\n")
+          @beg_lineno = @end_lineno = lineno + lines[..@beg_column].count("\n")
+          @line = lines[i + 1..]
+          @beg_column -= i + 1
+          @end_column -= i + 1
+        else
+          @line = lines
+          @beg_lineno = @end_lineno = lineno
+        end
+      elsif mid.to_s =~ /\A\W+\z/ && lines.match(/\G\s*(#{ Regexp.quote(mid) })=.*\n/, nd_recv.last_column)
+        @line = $` + $&
+        @beg_column = $~.begin(1)
+        @end_column = $~.end(1)
+      end
+    end
+
+    # Example:
+    #   x.foo(42)
+    #         ^^
+    #   x[42]
+    #     ^^
+    #   x += 1
+    #        ^
+    def spot_call_for_args
+      _nd_recv, _mid, nd_args = @node.children
+      if nd_args && nd_args.first_lineno == nd_args.last_lineno
+        fetch_line(nd_args.first_lineno)
+        @beg_column = nd_args.first_column
+        @end_column = nd_args.last_column
+      end
+      # TODO: support @arg
+    end
+
+    # Example:
+    #   x.foo = 1
+    #    ^^^^^^
+    #   x[42] = 1
+    #    ^^^^^^
+    def spot_attrasgn_for_name
+      nd_recv, mid, nd_args = @node.children
+      *nd_args, _nd_last_arg, _nil = nd_args.children
+      fetch_line(nd_recv.last_lineno)
+      if mid == :[]= && @line.match(/\G\s*(\[)/, nd_recv.last_column)
+        @beg_column = $~.begin(1)
+        args_last_column = $~.end(0)
+        if nd_args.last && nd_recv.last_lineno == nd_args.last.last_lineno
+          args_last_column = nd_args.last.last_column
+        end
+        if @line.match(/\s*\]\s*=/, args_last_column)
+          @end_column = $~.end(0)
+        end
+      elsif @line.match(/\G\s*(\.\s*#{ Regexp.quote(mid.to_s.sub(/=\z/, "")) }\s*=)/, nd_recv.last_column)
+        @beg_column = $~.begin(1)
+        @end_column = $~.end(1)
+      end
+    end
+
+    # Example:
+    #   x.foo = 1
+    #           ^
+    #   x[42] = 1
+    #     ^^^^^^^
+    #   x[] = 1
+    #     ^^^^^
+    def spot_attrasgn_for_args
+      nd_recv, mid, nd_args = @node.children
+      fetch_line(nd_recv.last_lineno)
+      if mid == :[]= && @line.match(/\G\s*\[/, nd_recv.last_column)
+        @beg_column = $~.end(0)
+        if nd_recv.last_lineno == nd_args.last_lineno
+          @end_column = nd_args.last_column
+        end
+      elsif nd_args && nd_args.first_lineno == nd_args.last_lineno
+        @beg_column = nd_args.first_column
+        @end_column = nd_args.last_column
+      end
+      # TODO: support @arg
+    end
+
+    # Example:
+    #   x + 1
+    #     ^
+    #   +x
+    #   ^
+    def spot_opcall_for_name
+      nd_recv, op, nd_arg = @node.children
+      fetch_line(nd_recv.last_lineno)
+      if nd_arg
+        # binary operator
+        if @line.match(/\G\s*(#{ Regexp.quote(op) })/, nd_recv.last_column)
+          @beg_column = $~.begin(1)
+          @end_column = $~.end(1)
+        end
+      else
+        # unary operator
+        if @line[...nd_recv.first_column].match(/(#{ Regexp.quote(op.to_s.sub(/@\z/, "")) })\s*\(?\s*\z/)
+          @beg_column = $~.begin(1)
+          @end_column = $~.end(1)
+        end
+      end
+    end
+
+    # Example:
+    #   x + 1
+    #       ^
+    def spot_opcall_for_args
+      _nd_recv, _op, nd_arg = @node.children
+      if nd_arg && nd_arg.first_lineno == nd_arg.last_lineno
+        # binary operator
+        fetch_line(nd_arg.first_lineno)
+        @beg_column = nd_arg.first_column
+        @end_column = nd_arg.last_column
+      end
+    end
+
+    # Example:
+    #   foo(42)
+    #   ^^^
+    #   foo 42
+    #   ^^^
+    def spot_fcall_for_name
+      mid, _nd_args = @node.children
+      fetch_line(@node.first_lineno)
+      if @line.match(/(#{ Regexp.quote(mid) })/, @node.first_column)
+        @beg_column = $~.begin(1)
+        @end_column = $~.end(1) (... truncated)

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

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