Created
January 16, 2026 19:04
-
-
Save tompng/b984872899ebab449eba4670c73d53f7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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