jekyll/rake/task_utils/rubocop_config_formatter.rb

119 lines
3.2 KiB
Ruby

# frozen_string_literal: true
require "yaml"
module Jekyll
module TaskUtils
class RuboCopConfigFormatter
def initialize(config_file)
@registry = Hash.new { |hsh, k| hsh[k] = [] }
@buffer = +""
@config = sort_hash_by_key(YAML.safe_load_file(config_file))
@config_file = config_file
end
def format!
inject_banner
consume :key => "inherit_from"
consume :key => "require"
consume :key => "AllCops", :comment => "Directive for all cops" do |key, conf|
format_all_cops_config(key, conf)
end
consume :key => "Jekyll/NoPutsAllowed", :comment => "Configure custom cop"
stream_builtin_cops
File.write(@config_file, @buffer.chomp)
end
private
def inject_banner
@buffer << <<~MSG
# -----------------------------------------------------------------------------
# This file has been formatted via a Rake Task configuring cops from
# RuboCop v#{rubocop_version}.
#
# To add more cops, paste configurations at the end of the file and run
# the rake task via `bundle exec rake rubocop:format_config`.
# -----------------------------------------------------------------------------
MSG
end
def rubocop_version
`bundle exec rubocop --version`.chomp
end
def consume(key:, comment: nil)
conf = @config.delete(key)
@buffer << "# #{comment}\n" if comment
entry = block_given? ? yield(key, conf) : normalize_entry(key => conf)
@buffer << entry
@buffer << "\n"
end
def stream_cops_banner
@buffer << <<~MSG
# Configure built-in cops
# =======================
MSG
end
def group_cops_by_department
@config.each_with_object(@registry) do |(key, conf), registry|
department = key.split("/", 2)[0]
registry[department] << { key => conf }
end
end
def stream_builtin_cops
stream_cops_banner
group_cops_by_department
@registry.each do |(dept, cops)|
@buffer << <<~MSG
# #{dept} cops
# #{"-" * 40}
MSG
while (entry = cops.shift)
@buffer << normalize_entry(entry)
end
@buffer << "\n"
end
end
def normalize_entry(entry)
YAML.dump(entry).delete_prefix("---\n")
end
def format_all_cops_config(key, conf)
all_cops_config = %w(TargetRubyVersion Include Exclude).each_with_object({}) do |k, res|
res[k] = conf.delete(k)
end
normalize_entry(key => all_cops_config)
end
def sort_hash_by_key(hsh)
sorted = hsh.sort_by { |key, _v| key }.to_h
sorted.each_pair.with_object({}) do |(key, value), result|
new_val = case value
when Array
value.sort
when Hash
sort_hash_by_key(value)
else
value
end
result[key] = new_val
end
end
end
end
end