module SyntaxSuggest

常數

DEFAULT_VALUE

用於指示無法與其他輸入混淆的預設值。

TIMEOUT_DEFAULT
VERSION

公開類別方法

call(source:, filename: DEFAULT_VALUE, terminal: DEFAULT_VALUE, record_dir: DEFAULT_VALUE, timeout: TIMEOUT_DEFAULT, io: $stderr) 按一下以切換來源

SyntaxSuggest.call [私人]

主要的私人介面

# File lib/syntax_suggest/api.rb, line 91
def self.call(source:, filename: DEFAULT_VALUE, terminal: DEFAULT_VALUE, record_dir: DEFAULT_VALUE, timeout: TIMEOUT_DEFAULT, io: $stderr)
  search = nil
  filename = nil if filename == DEFAULT_VALUE
  Timeout.timeout(timeout) do
    record_dir ||= ENV["DEBUG"] ? "tmp" : nil
    search = CodeSearch.new(source, record_dir: record_dir).call
  end

  blocks = search.invalid_blocks
  DisplayInvalidBlocks.new(
    io: io,
    blocks: blocks,
    filename: filename,
    terminal: terminal,
    code_lines: search.code_lines
  ).call
rescue Timeout::Error => e
  io.puts "Search timed out SYNTAX_SUGGEST_TIMEOUT=#{timeout}, run with SYNTAX_SUGGEST_DEBUG=1 for more info"
  io.puts e.backtrace.first(3).join($/)
end
handle_error(e, re_raise: true, io: $stderr) 按一下以切換來源

SyntaxSuggest.handle_error [公開]

接收「語法錯誤」例外,使用錯誤訊息找出檔案。然後將分析檔案以找出語法錯誤的位置,並將該位置發佈到 stderr。

範例

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

預設情況下,它會重新引發例外,除非「re_raise: false」。可以使用「io: $stderr」輸入來設定訊息輸出位置。

如果無法確定有效的檔案名稱,則會重新引發原始例外(即使有「re_raise: false」)。

# File lib/syntax_suggest/api.rb, line 68
def self.handle_error(e, re_raise: true, io: $stderr)
  unless e.is_a?(SyntaxError)
    io.puts("SyntaxSuggest: Must pass a SyntaxError, got: #{e.class}")
    raise e
  end

  file = PathnameFromMessage.new(e.message, io: io).call.name
  raise e unless file

  io.sync = true

  call(
    io: io,
    source: file.read,
    filename: file
  )

  raise e if re_raise
end
invalid?(source) 按一下以切換來源
# File lib/syntax_suggest/api.rb, line 160
def self.invalid?(source)
  source = source.join if source.is_a?(Array)
  source = source.to_s

  Prism.parse(source).failure?
end
module_for_detailed_message() 按一下以切換來源

SyntaxSuggest.module_for_detailed_message [私人]

用於透過 Module.prepend 來猴子修補 SyntaxError

# File lib/syntax_suggest/core_ext.rb, line 27
def self.module_for_detailed_message
  Module.new {
    def detailed_message(highlight: true, syntax_suggest: true, **kwargs)
      return super unless syntax_suggest

      require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE)

      message = super

      if path
        file = Pathname.new(path)
        io = SyntaxSuggest::MiniStringIO.new

        SyntaxSuggest.call(
          io: io,
          source: file.read,
          filename: file,
          terminal: highlight
        )
        annotation = io.string

        annotation += "\n" unless annotation.end_with?("\n")

        annotation + message
      else
        message
      end
    rescue => e
      if ENV["SYNTAX_SUGGEST_DEBUG"]
        $stderr.warn(e.message)
        $stderr.warn(e.backtrace)
      end

      # Ignore internal errors
      message
    end
  }
end
record_dir(dir) 按一下以切換來源

SyntaxSuggest.record_dir [私人]

用於產生一個唯一的目錄來記錄搜尋步驟以進行偵錯

# File lib/syntax_suggest/api.rb, line 116
def self.record_dir(dir)
  time = Time.now.strftime("%Y-%m-%d-%H-%M-%s-%N")
  dir = Pathname(dir)
  dir.join(time).tap { |path|
    path.mkpath
    alias_dir = dir.join("last")
    FileUtils.rm_rf(alias_dir) if alias_dir.exist?
    FileUtils.ln_sf(time, alias_dir)
  }
end
use_prism_parser?() 按一下以切換來源

SyntaxSuggest.use_prism_parser? [私人]

告訴我們 prism 分析器是否可用,或者我們是否應回退到「Ripper`

# File lib/syntax_suggest/api.rb, line 42
def self.use_prism_parser?
  defined?(Prism)
end
valid?(source) 按一下以切換來源

SyntaxSuggest.valid? [私人]

如果給定的輸入來源是有效語法,則傳回真值

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 作為物件或陣列會將其轉換為其程式碼表示。

# File lib/syntax_suggest/api.rb, line 211
def self.valid?(source)
  !invalid?(source)
end
valid_without?(without_lines:, code_lines:) 按一下以切換來源

SyntaxSuggest.valid_without? [私人]

如果移除 `without_lines`,這將告訴您「code_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
# File lib/syntax_suggest/api.rb, line 146
def self.valid_without?(without_lines:, code_lines:)
  lines = code_lines - Array(without_lines).flatten

  if lines.empty?
    true
  else
    valid?(lines)
  end
end

公開實例方法

detailed_message(highlight: true, syntax_suggest: true, **kwargs) 按一下以切換來源
呼叫超類別方法
# File lib/syntax_suggest/core_ext.rb, line 29
def detailed_message(highlight: true, syntax_suggest: true, **kwargs)
  return super unless syntax_suggest

  require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE)

  message = super

  if path
    file = Pathname.new(path)
    io = SyntaxSuggest::MiniStringIO.new

    SyntaxSuggest.call(
      io: io,
      source: file.read,
      filename: file,
      terminal: highlight
    )
    annotation = io.string

    annotation += "\n" unless annotation.end_with?("\n")

    annotation + message
  else
    message
  end
rescue => e
  if ENV["SYNTAX_SUGGEST_DEBUG"]
    $stderr.warn(e.message)
    $stderr.warn(e.backtrace)
  end

  # Ignore internal errors
  message
end