Skip to content

Instantly share code, notes, and snippets.

@tompng
Created January 16, 2026 19:04
Show Gist options
  • Select an option

  • Save tompng/b984872899ebab449eba4670c73d53f7 to your computer and use it in GitHub Desktop.

Select an option

Save tompng/b984872899ebab449eba4670c73d53f7 to your computer and use it in GitHub Desktop.
require 'prism'
require 'irb'
# Collect syntax-valid code snippets from the given directory
def each_snippet(dir, max_size)
files = Dir.glob("#{dir.delete_suffix('/')}/**/*.rb")
snippets = Set.new
handle_snippet = ->(code) {
return if snippets.include?(code)
snippets << code
yield code
}
files.each do |file|
p file
code = File.read(file) rescue next
node = Prism.parse(code).value
node.breadth_first_search do |n|
if n.slice.size < max_size && Prism.parse_success?(n.slice)
handle_snippet.call(n.slice)
end
# Test code may include ruby-code as a string literal
if n.is_a?(Prism::StringNode) && n.slice.size < max_size && Prism.parse_success?(n.unescaped)
handle_snippet.call(n.unescaped)
end
false
end
end
end
# Split the snippet into code, newline, post and create an incomplete but recoverable code
def test_snippet(snippet)
[*0..snippet.size].sample(10).each do |len|
code = snippet[0, len] + "\n"
post = snippet[len..]
next unless !Prism.parse_success?(code) && Prism.parse_success?(code + post)
check_code(code, post)
end
end
def check_code(recoverable_error_code, next_line_code)
status = IRB::RubyLex.new.check_code_syntax(recoverable_error_code, local_variables: [])
case status
when :valid
raise 'unreachable'
when :recoverable_error
# Expected
when :unrecoverable_error
p BUG: [status, recoverable_error_code, next_line_code]
when :other_error
end
end
each_snippet(ARGV[0] || '.', 500) do |snippet|
test_snippet(snippet)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment