# module ErrorHighlight

### Constants

VERSION

### Public Class Methods

formatter ()
Source

    # File lib/error_highlight/formatter.rb, line 67
    def self.formatter
      Ractor.current[:__error_highlight_formatter__] || DefaultFormatter
    end

formatter= (formatter)
Source

    # File lib/error_highlight/formatter.rb, line 71
    def self.formatter=(formatter)
      Ractor.current[:__error_highlight_formatter__] = formatter
    end

spot (obj, **opts)
Source

    # File lib/error_highlight/base.rb, line 33
    def self.spot(obj, **opts)
      case obj
      when Exception
        exc = obj
        loc = opts[:backtrace_location]
        opts = { point_type: opts.fetch(:point_type, :name) }

        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

        return nil unless Thread::Backtrace::Location === loc

        node =
          begin
            RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true)
          rescue RuntimeError => error
            # RubyVM::AbstractSyntaxTree.of raises an error with a message that
            # includes "prism" when the ISEQ was compiled with the prism compiler.
            # In this case, we'll try to parse again with prism instead.
            raise unless error.message.include?("prism")
            prism_find(loc)
          end

        Spotter.new(node, **opts).spot

      when RubyVM::AbstractSyntaxTree::Node, Prism::Node
        Spotter.new(obj, **opts).spot

      else
        raise TypeError, "Exception is expected"
      end

    rescue SyntaxError,
           SystemCallError, # file not found or something
           ArgumentError # eval'ed code

      return nil
    end

Identify the code fragment at that a given exception occurred.

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:

    {
      first_lineno: Integer,
      first_column: Integer,
      last_lineno: Integer,
      last_column: Integer,
      snippet: String,
      script_lines: [String],
    } | nil

Limitations:

Currently, `ErrorHighlight.spot` only supports a single-line code fragment. Therefore, if the return value is not nil, first_lineno and last_lineno will have the same value. If the relevant code fragment spans multiple lines (e.g., `Array#[]` of +ary+), the method will return nil. This restriction may be removed in the future.

### Private Class Methods

prism_find (location)
Source

    # File lib/error_highlight/base.rb, line 86
    def self.prism_find(location)
      require "prism"
      return nil if Prism::VERSION < "1.0.0"

      absolute_path = location.absolute_path
      return unless absolute_path

      node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(location)
      Prism.parse_file(absolute_path).value.breadth_first_search { |node| node.node_id == node_id }
    end

Accepts a `Thread::Backtrace::Location` object and returns a `Prism::Node` corresponding to the backtrace location in the source code.