Module: ErrorHighlight

Defined in:
lib/error_highlight/base.rb,
lib/error_highlight/version.rb,
lib/error_highlight/core_ext.rb,
lib/error_highlight/formatter.rb

Defined Under Namespace

Modules: CoreExt Classes: DefaultFormatter

Constant Summary collapse

VERSION =
"0.7.0"

Class Method Summary collapse

Class Method Details

.formatterObject



67
68
69
# File 'lib/error_highlight/formatter.rb', line 67

def self.formatter
  Ractor.current[:__error_highlight_formatter__] || DefaultFormatter
end

.formatter=(formatter) ⇒ Object



71
72
73
# File 'lib/error_highlight/formatter.rb', line 71

def self.formatter=(formatter)
  Ractor.current[:__error_highlight_formatter__] = formatter
end

.spot(obj, **opts) ⇒ Object

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.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# 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