Last active
November 19, 2020 16:43
-
-
Save arika/9c945d9a452aed3eebff0bcd6f2b7f3d to your computer and use it in GitHub Desktop.
This file contains 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 "yaml" | |
require "json" | |
require "tempfile" | |
module RuboCopAutoCollrect | |
class << self | |
def run_all!(targets, *cop_names, commit_log_format:, fixup_commit_log_format:) | |
plan(targets, *cop_names).each do |cop_name| | |
run!(targets, cop_name, commit_log_format: commit_log_format) | |
end | |
run!(targets, *cop_names, commit_log_format: fixup_commit_log_format) | |
end | |
def run!(targets, *cop_names, commit_log_format:) | |
cop_list = cop_names.join(",") unless cop_names.empty? | |
print "\n*** auto-correct by #{cop_list || 'AllCops'}...\n\n" | |
only_cops = cop_list ? ["--only", cop_list] : [] | |
begin | |
rubocop_auto_correct("--format", "autogenconf", *only_cops, *targets) | |
rescue | |
print "\n** try to detect errors...\n\n" | |
rubocop_check(*only_cops, *targets) | |
abort | |
end | |
return unless git_diff? | |
git("add", ".") | |
git("commit", "-q", "-m", format(commit_log_format, cop_list: cop_list)) | |
print "\n** commit changes\n\n" | |
end | |
def plan(targets, *cop_names) | |
print "*** calculate auto-correct plan...\n\n" | |
only_cops = cop_names.empty? ? [] : ["--only", cop_names.join(",")] | |
begin | |
output = Tempfile.open("auto_correct_plan") do |tf| | |
rubocop_auto_correct( | |
*only_cops, | |
"--display-cop-names", | |
"--format", "fuubar", | |
"--format", "json", | |
"--out", tf.path, | |
*targets, | |
) | |
tf.read | |
end | |
rescue | |
print "\n** try to detect errors...\n\n" | |
rubocop_check(*only_cops, *targets) | |
abort | |
end | |
git("restore", ".") | |
categories = cop_names.map {|cop_name| cop_name[%r{\A[^/]*}] }.uniq | |
corrected_cops = corrected_cops(JSON.parse(output)) | |
corrected_cops.keys.sort_by do |cop_name| | |
count = corrected_cops[cop_name] | |
idx = categories.index {|category| cop_name.start_with?(category) } | |
[idx || categories.size, -count] | |
end | |
end | |
private | |
def corrected_cops(rubocop_output) | |
rubocop_output["files"] | |
.map {|f| f["offenses"].select {|o| o["corrected"] } } | |
.flatten | |
.group_by {|o| o["cop_name"] } | |
.transform_values(&:size) | |
end | |
def rubocop(*args, on_failure: :raise) | |
command("rubocop", "--safe", *args) | |
rescue => e | |
warn "\n#{e}" | |
abort if on_failure == :abort | |
raise | |
end | |
def rubocop_auto_correct(*args) | |
rubocop( | |
"--fail-level", "E", | |
"--safe-auto-correct", | |
*args, | |
) | |
end | |
def rubocop_check(*args) | |
rubocop( | |
"--fail-level", "E", | |
"--display-only-fail-level-offenses", | |
*args, | |
on_failure: :abort, | |
) | |
end | |
def git(*args) | |
command("git", *args) | |
rescue => e | |
warn e | |
abort | |
end | |
def git_diff? | |
command("git", "diff", "--quiet") | |
false | |
rescue | |
true | |
end | |
def command(*cmd) | |
system(*cmd) | |
raise "failed: #{cmd.join(' ')}" unless $?.success? | |
end | |
end | |
end | |
sep_idx = ARGV.index("--") || 0 | |
targets = ARGV[(sep_idx + 1)..-1] | |
commit_log_prefix, = ARGV[0, sep_idx] | |
commit_log_format = "#{commit_log_prefix}auto-correct by RuboCop %<cop_list>s" | |
cop_names = %w(Layout Style) | |
RuboCopAutoCollrect.run_all!( | |
targets, *cop_names, | |
commit_log_format: commit_log_format, | |
fixup_commit_log_format: "#{commit_log_format} (fix-up)", | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment