Last active
October 8, 2016 23:24
-
-
Save backus/00f0a34857208bf356af to your computer and use it in GitHub Desktop.
Rubocop's --auto-gen-config changes your settings for certain cops. For example, if you have one line of code which has a LineLength of 150 characters then it is going to set your Metrics/LineLength config to Max: 150. This script instead generates a list of files to exclude only and does not lower your standards
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
#!/usr/bin/env ruby | |
gem 'slop', '4.2.1' | |
require 'slop' | |
require 'pathname' | |
require 'json' | |
require 'yaml' | |
module SlopExt | |
class PathOption < Slop::Option | |
def call(value) | |
Pathname(value).expand_path.freeze.tap do |path| | |
fail "Invalid path #{path}" unless path.exist? && path.file? | |
end | |
end | |
end | |
end | |
Slop.include(SlopExt) | |
module CLI | |
def self.parse(args) | |
options = Slop.parse(args) do |switch| | |
# Print and display help | |
switch.on('-h', '--help') { puts switch } | |
# Accept configuration file | |
switch.path '-c', '--config', 'Specify configuration file.' | |
end | |
fail "You must specify a config file" unless options.get(:config) | |
options.to_hash | |
end | |
end | |
SETTINGS = CLI.parse(ARGV) | |
# Note: comment out any existing excludes in your current config file | |
CONFIG_LOCATION = SETTINGS.fetch(:config) | |
json = `bundle exec rubocop -c #{CONFIG_LOCATION} -f json` | |
OUTPUT = JSON.parse(json, symbolize_names: true) | |
FILES = OUTPUT.fetch(:files) | |
OFFENSES = FILES.map do |file| | |
file.fetch(:offenses).map do |offense| | |
offense.merge(path: file.fetch(:path)) | |
end | |
end.flatten | |
GROUPS = OFFENSES.group_by { |item| item.fetch(:cop_name) } | |
CONF = GROUPS.each.with_object({}) do |(key, offense), config| | |
config[key] ||= {} | |
config[key]['Exclude'] ||= [] | |
offense.each { |o| config[key]['Exclude'] << o.fetch(:path) } | |
end | |
RUBOCOP_IGNORES = CONF.map do |key, settings| | |
[key, { 'Exclude' => settings.fetch('Exclude').sort.uniq }] | |
end.to_h | |
modified_yaml = CONFIG_LOCATION.readlines.each.with_index.map do |line, index| | |
line.gsub(/^#(.+)$/, ":yaml_comment#{index}:\\1") | |
end.join | |
CURRENT_CONFIG = YAML.load(modified_yaml) | |
CONFIGURATION_KEYS = (CURRENT_CONFIG.keys + RUBOCOP_IGNORES.keys).uniq | |
MERGED = CONFIGURATION_KEYS.each.with_object({}) do |key, memo| | |
if key.to_s.start_with?('yaml_comment') | |
next memo[key] = CURRENT_CONFIG.fetch(key) | |
end | |
existing = CURRENT_CONFIG.fetch(key, {}) | |
additions = RUBOCOP_IGNORES.fetch(key, {}) | |
excludes = (existing.fetch('Exclude', []) + additions.fetch('Exclude', [])).uniq | |
merged = existing.merge(additions) | |
merged = merged.merge('Exclude' => excludes) if excludes.any? | |
memo[key] = merged | |
end.to_h | |
updated_yaml = YAML.dump(MERGED) | |
final_yaml = updated_yaml.gsub(/^:yaml_comment\d+:(.+)$/, '#\1') | |
CONFIG_LOCATION.write(final_yaml) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment