Skip to content

Instantly share code, notes, and snippets.

@arika
Last active September 30, 2019 13:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arika/46a59329a91a1cb031349c074ada0fed to your computer and use it in GitHub Desktop.
Save arika/46a59329a91a1cb031349c074ada0fed to your computer and use it in GitHub Desktop.
# frozen_string_literal: true
require 'yaml'
require 'json'
require 'tempfile'
if ARGV.include?('-h') || ARGV.include?('--help')
<<~HELP.display
Usage: #{$0} [-r extension ...] [-- targets...]
Command line example:
#{$0} -r rubocop-rails -r rubocop-performance -- app lib Gemfile
HELP
exit
end
sep_idx = ARGV.index('--')
if sep_idx
options = ARGV[0, sep_idx]
targets = ARGV[(sep_idx + 1)..-1]
else
options = ARGV
targets = []
end
run_rubocop = ->(*opts, &b) { IO.popen(['rubocop', *options, *opts], &b) }
run_rubocop_with_targets = ->(*opts, &b) { run_rubocop[*opts, *targets, &b] }
all_cops = run_rubocop['--force-default-config', '--show-cops'] {|io| YAML.load(io) }
configs = []
default_styles = Hash.new {|h, k| h[k] = {} }
summary = Hash.new {|h, k| h[k] = Hash.new {|hh, kk| hh[kk] = {} } }
all_cops.each do |cop_name, spec|
items = {}
spec.each_key do |item_name|
m = /\AEnforcedStyle(.*)\z/.match(item_name)
next unless m
styles = spec["SupportedStyles#{m[1]}"]
next unless styles
items[m[0]] = styles
default_styles[cop_name][item_name] = spec[m[0]]
end
items.each do |item_name, styles|
styles.each_with_index do |style, idx|
configs[idx] ||= Hash.new {|h, k| h[k] = Hash.new {|hh, kk| hh[kk] = {} } }
configs[idx][cop_name][item_name] = style
summary[cop_name][item_name][style] = 0
end
end
end
configs.each_with_index do |config, idx|
warn "#{idx + 1} / #{configs.size} ..."
Tempfile.open('start_rubocop') do |tf|
YAML.dump(config, tf)
tf.close
cops = config.keys
result = run_rubocop_with_targets[
'--config', tf.path,
'--only', cops.join(','),
'--format', 'json',
] {|io| JSON.parse(io.read) }
result['files'].each do |file_result|
file_result['offenses'].each do |offense|
cop_name = offense['cop_name']
item_name, style = config[cop_name].first
next unless item_name && style
summary[cop_name][item_name][style] += 1
end
end
end
end
summary.each do |cop_name, s|
s.each do |item_name, styles|
offense_counts = styles.values
next if offense_counts.all?(&:zero?)
min_offense_count = offense_counts.min
default_style = default_styles[cop_name][item_name]
next if styles[default_style] == min_offense_count
puts "#{cop_name}:"
w = styles.each_key.map(&:length).max
styles.sort_by {|_, offense_count| offense_count }.each do |style, offense_count|
printf " %s: %-#{w}s # %d offenses%s\n",
item_name, style, offense_count,
style == default_style ? ' (default)' : ''
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment