SyntaxSuggest

SyntaxSuggest

SyntaxSuggest 모듈은 SyntaxError가 났을 때 오류 위치를 더 자세히 찾아주는 기능을 담아요. 오류 메시지에서 파일을 찾아 그 파일을 분석해 문법 오류 위치를 추정하고 stderr로 내보내 줘요.

출처: Ruby 3.3 API

본문

일반적으로 SyntaxError가 발생하면 SyntaxError#detailed_message가 이 모듈의 기능을 호출해, 어디가 잘못됐는지 주석을 곁들여 보여줘요. 이 모듈은 SyntaxErrorModule.prepend으로 몽키패치해서 사용돼요.

Constants

DEFAULT_VALUE

다른 입력과 혼동될 수 없는 기본값을 나타내는 데 쓰여요.

TIMEOUT_DEFAULT

탐색 시간 초과 기본값이에요.

VERSION

Public Class Methods

call(source:, filename: DEFAULT_VALUE, terminal: DEFAULT_VALUE, record_dir: DEFAULT_VALUE, timeout: TIMEOUT_DEFAULT, io: $stderr)

SyntaxSuggest.call은 [Private] 내부 인터페이스예요. 소스를 분석해 잘못된 블록을 찾고 DisplayInvalidBlocks로 출력해요. Timeout::Error가 나면 타임아웃 안내 메시지를 io에 출력해요.

handle_error(e, re_raise: true, io: $stderr)

SyntaxSuggest.handle_error는 [Public]이에요. SyntaxError 예외를 받아 오류 메시지로 파일을 찾은 뒤, 그 파일을 분석해 문법 오류 위치를 찾아 stderr로 출력해요.

begin
  require 'bad_file'
rescue => e
  SyntaxSuggest.handle_error(e)
end

기본적으로 예외를 다시 던지지만, re_raise: false로 바꾸면 다시 던지지 않아요. 출력 위치는 io: $stderr 인자로 설정할 수 있어요. 유효한 파일 이름을 알아낼 수 없으면 re_raise: false여도 원래 예외를 다시 던져요. 또한 SyntaxError가 아닌 예외를 넘기면 오류를 알리고 그 예외를 그대로 던져요.

invalid?(source)

주어진 소스가 유효하지 않은 문법인지 판별해요. prism 파서의 failure? 결과를 돌려줘요.

valid?(source)

SyntaxSuggest.valid?은 [Private]로, 주어진 소스 입력이 유효한 문법인지 truthy 값을 돌려줘요.

SyntaxSuggest.valid?(<<~EOM) # => true
  def foo
  end
EOM

SyntaxSuggest.valid?(<<~EOM) # => false
  def foo
    def bar # Syntax error here
  end
EOM

줄(라인) 배열을 넘기면 평가 전에 합쳐줘요.

SyntaxSuggest.valid?(
  [
    "def foo\n",
    "end\n"
  ]
) # => true

SyntaxSuggest.valid?(
  [
    "def foo\n",
    "  def bar\n", # Syntax error here
    "end\n"
  ]
) # => false

참고로 CodeLine 인스턴스는 to_s에 응답하므로 CodeLine을 객체나 배열로 넘겨도 코드 표현으로 변환돼요.

valid_without?(without_lines:, code_lines:)

SyntaxSuggest.valid_without?은 [Private]로, code_lines에서 without_lines를 제거하면 유효해지는지 알려줘요. 한마디로 문서 안에서 문법 오류가 있는 줄을 찾아냈는지 감지하는 방법이에요.

code_lines = [
  CodeLine.new(line: "def foo\n",   index: 0)
  CodeLine.new(line: "  def bar\n", index: 1)
  CodeLine.new(line: "end\n",       index: 2)
]

SyntaxSuggest.valid_without?(
  without_lines: code_lines[1],
  code_lines: code_lines
)                                    # => true

SyntaxSuggest.valid?(code_lines) # => false

Public Instance Methods

detailed_message(highlight: true, syntax_suggest: true, **kwargs)

SyntaxError#detailed_message을 개선한 버전이에요. syntax_suggest: false면 원래 동작(super)을 그대로 돌려줘요. 경로가 있으면 SyntaxSuggest.call로 주석을 만들어 원래 메시지와 합쳐 반환해요.