Used to indicate a default value that cannot be confused with another input.
# File tmp/rubies/ruby-3.3.0/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
SyntaxSuggest.call
[Private]
Main private interface
# File tmp/rubies/ruby-3.3.0/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
SyntaxSuggest.handle_error
[Public]
Takes a ‘SyntaxError` exception, uses the error message to locate the file. Then the file will be analyzed to find the location of the syntax error and emit that location to stderr.
Example:
begin require 'bad_file' rescue => e SyntaxSuggest.handle_error(e) end
By default it will re-raise the exception unless ‘re_raise: false`. The message output location can be configured using the `io: $stderr` input.
If a valid filename cannot be determined, the original exception will be re-raised (even with ‘re_raise: false`).
# File tmp/rubies/ruby-3.3.0/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
# File tmp/rubies/ruby-3.3.0/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
SyntaxSuggest.module_for_detailed_message
[Private]
Used to monkeypatch SyntaxError
via Module.prepend
# File tmp/rubies/ruby-3.3.0/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
SyntaxSuggest.record_dir
[Private]
Used to generate a unique directory to record search steps for debugging
# File tmp/rubies/ruby-3.3.0/lib/syntax_suggest/api.rb, line 42
def self.use_prism_parser?
defined?(Prism)
end
SyntaxSuggest.use_prism_parser?
[Private]
Tells us if the prism parser is available for use or if we should fallback to ‘Ripper`
# File tmp/rubies/ruby-3.3.0/lib/syntax_suggest/api.rb, line 211
def self.valid?(source)
!invalid?(source)
end
SyntaxSuggest.valid?
[Private]
Returns truthy if a given input source is valid syntax
SyntaxSuggest.valid?(<<~EOM) # => true def foo end EOM SyntaxSuggest.valid?(<<~EOM) # => false def foo def bar # Syntax error here end EOM
You can also pass in an array of lines and they’ll be joined before evaluating
SyntaxSuggest.valid?( [ "def foo\n", "end\n" ] ) # => true SyntaxSuggest.valid?( [ "def foo\n", " def bar\n", # Syntax error here "end\n" ] ) # => false
As an FYI the CodeLine
class instances respond to ‘to_s` so passing a CodeLine
in as an object or as an array will convert it to it’s code representation.
# File tmp/rubies/ruby-3.3.0/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
SyntaxSuggest.valid_without?
[Private]
This will tell you if the ‘code_lines` would be valid if you removed the `without_lines`. In short it’s a way to detect if we’ve found the lines with syntax errors in our document yet.
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 tmp/rubies/ruby-3.3.0/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