# frozen_string_literal: true

# This file’s purpose is to extract the examples from the whitequark/parser # gem and generate a test file that we can use to ensure that our parser # generates equivalent syntax trees when translating. To do this, it runs the # parser’s test suite but overrides the ‘assert_parses` method to collect the # examples into a hash. Then, it writes out the hash to a file that we can use # to generate our own tests. # # To run the test suite, it’s important to note that we have to mirror both any # APIs provided to the test suite (for example the ParseHelper module below). # This is obviously relatively brittle, but it’s effective for now.

require “ast”

module ParseHelper

# This object is going to collect all of the examples from the parser gem into
# a hash that we can use to generate our own tests.
COLLECTED = Hash.new { |hash, key| hash[key] = [] }

include AST::Sexp
ALL_VERSIONS = %w[3.1 3.2]

private

def assert_context(*)
end

def assert_diagnoses(*)
end

def assert_diagnoses_many(*)
end

def refute_diagnoses(*)
end

def with_versions(*)
end

def assert_parses(_ast, code, _source_maps = "", versions = ALL_VERSIONS)
  # We're going to skip any examples that are for older Ruby versions
  # that we do not support.
  return if (versions & %w[3.1 3.2]).empty?

  entry = caller.find { _1.include?("test_parser.rb") }
  _, lineno, name = *entry.match(/(\d+):in `(.+)'/)

  COLLECTED["#{name}:#{lineno}"] << code
end

end

namespace :extract do

desc "Extract the whitequark/parser tests"
task :whitequark do
  directory = File.expand_path("../tmp/parser", __dir__)
  unless File.directory?(directory)
    sh "git clone --depth 1 https://github.com/whitequark/parser #{directory}"
  end

  mkdir_p "#{directory}/extract"
  touch "#{directory}/extract/helper.rb"
  touch "#{directory}/extract/parse_helper.rb"
  touch "#{directory}/extract/extracted.txt"
  $:.unshift "#{directory}/extract"

  require "parser/current"
  require "minitest/autorun"
  require_relative "#{directory}/test/test_parser"

  Minitest.after_run do
    filepath = File.expand_path("../test/translation/parser.txt", __dir__)

    File.open(filepath, "w") do |file|
      ParseHelper::COLLECTED.sort.each do |(key, codes)|
        if codes.length == 1
          file.puts("!!! #{key}\n#{codes.first}")
        else
          codes.each_with_index do |code, index|
            file.puts("!!! #{key}:#{index}\n#{code}")
          end
        end
      end
    end
  end
end

end