lib/gauntlet_parser.rb
# frozen_string_literal: true
require 'gauntlet'
require_relative 'parser/all'
require 'shellwords'
class ParserGauntlet < Gauntlet
RUBY20 = 'ruby'
RUBY19 = 'ruby1.9.1'
RUBY18 = '/opt/rubies/ruby-1.8.7-p370/bin/ruby'
def try(parser, ruby, file, show_ok: false)
try_ruby = lambda do |e|
Process.spawn(%{#{ruby} -c #{Shellwords.escape file}},
:err => '/dev/null', :out => '/dev/null')
_, status = Process.wait2
if status.success?
# Bug in Parser.
puts "Parser bug."
@result[file] = { parser.to_s => "#{e.class}: #{e.to_s}" }
else
# No, this file is not Ruby.
yield if block_given?
end
end
begin
parser.parse_file(file)
rescue Parser::SyntaxError => e
if e.diagnostic.location.resize(2).is?('<%')
puts "ERb."
return
end
try_ruby.call(e)
rescue ArgumentError, RegexpError,
Encoding::UndefinedConversionError => e
puts "#{file}: #{e.class}: #{e.to_s}"
try_ruby.call(e)
rescue Interrupt
raise
rescue Exception => e
puts "Parser bug: #{file} #{e.class}: #{e.to_s}"
@result[file] = { parser.to_s => "#{e.class}: #{e.to_s}" }
else
puts "Ok." if show_ok
end
end
def parse(name)
puts "GEM: #{name}"
@result = {}
if ENV.include?('FAST')
total_size = Dir["**/*.rb"].map(&File.method(:size)).reduce(:+)
if total_size > 300_000
puts "Skip."
return
end
end
Dir["**/*.rb"].each do |file|
next if File.directory? file
try(Parser::Ruby20, RUBY20, file) do
puts "Trying 1.9:"
try(Parser::Ruby19, RUBY19, file, show_ok: true) do
puts "Trying 1.8:"
try(Parser::Ruby18, RUBY18, file, show_ok: true) do
puts "Invalid syntax."
end
end
end
end
@result
end
def run(name)
data[name] = parse(name)
self.dirty = true
end
def should_skip?(name)
data[name] == {}
end
def load_yaml(*)
data = super
@was_errors = data.count { |_name, errs| errs != {} }
data
end
def shutdown
super
errors = data.count { |_name, errs| errs != {} }
total = data.count
percent = "%.5f" % [100 - errors.to_f / total * 100]
puts "!!! was: #{@was_errors} now: #{errors} total: #{total} frac: #{percent}%"
end
end
filter = ARGV.shift
filter = Regexp.new filter if filter
gauntlet = ParserGauntlet.new
if ENV.include? 'UPDATE'
gauntlet.source_index
gauntlet.update_gem_tarballs
end
gauntlet.run_the_gauntlet filter