ErrorHighlight 모듈

ErrorHighlight 모듈 (ErrorHighlight)

주어진 예외가 발생한 코드 조각(fragment)을 식별해 주는 모듈이에요. 런타임 에러가 났을 때 정확한 위치를 짚어주는 데 사용돼요.

출처: Ruby 3.3 API

본문

ErrorHighlight는 예외가 발생한 지점의 코드 일부를 찾아 객체로 돌려줘요. 포매터를 교체해서 에러 출력 스타일을 바꿀 수도 있어요.

상수 (Constants)

  • VERSION — 모듈 버전

::formatter (Public Class Method)

formatter() — 현재 포매터를 돌려줘요. 기본은 DefaultFormatter예요.

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

::formatter= (Public Class Method)

formatter=(formatter) — 포매터를 설정해요. 레이커(Ractor) 단위로 저장돼요.

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

::spot (Public Class Method)

spot(obj, **opts) — 주어진 예외가 발생한 코드 조각을 식별해요.

옵션:

  • point_type: :name | :args:name(기본)은 메서드/변수 이름을, :args는 메서드 호출의 인자 부분을 가리켜요.
  • backtrace_location: Thread::Backtrace::Location — 주어진 backtrace_location의 코드 조각을 찾아요. 기본은 예외의 backtrace_locations 중 첫 프레임을 사용해요.

반환값:

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

제약: 현재 ErrorHighlight.spot는 단일 줄 코드 조각만 지원해요. 반환값이 nil이 아니면 first_linenolast_lineno는 같은 값이에요. 코드 조각이 여러 줄에 걸쳐 있으면 nil을 돌려줘요. 이 제약은 미래에 풀릴 수 있어요.

# 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 = RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true)

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

  when RubyVM::AbstractSyntaxTree::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