class RuboCop::Plugin::ConfigurationIntegrator
A class for integrating plugin configurations into RuboCop
. Handles configuration merging, validation, and compatibility for plugins. @api private
Public Class Methods
Source
# File lib/rubocop/plugin/configuration_integrator.rb, line 13 def integrate_plugins_into_rubocop_config(rubocop_config, plugins) default_config = ConfigLoader.default_configuration runner_context = create_context(rubocop_config) validate_plugins!(plugins, runner_context) plugin_config = combine_rubocop_configs(default_config, runner_context, plugins).to_h merge_plugin_config_into_all_cops!(default_config, plugin_config) merge_plugin_config_into_default_config!(default_config, plugin_config) end
Private Class Methods
Source
# File lib/rubocop/plugin/configuration_integrator.rb, line 44 def combine_rubocop_configs(default_config, runner_context, plugins) fake_out_rubocop_default_configuration(default_config) do |fake_config| all_cop_keys_configured_by_plugins = [] plugins.reduce(fake_config) do |combined_config, plugin| RuboCop::ConfigLoader.instance_variable_set(:@default_configuration, combined_config) print 'Plugin ' if ConfigLoader.debug plugin_config, plugin_config_path = load_plugin_rubocop_config(plugin, runner_context) plugin_config['AllCops'], all_cop_keys_configured_by_plugins = merge_all_cop_settings( combined_config['AllCops'], plugin_config['AllCops'], all_cop_keys_configured_by_plugins ) plugin_config.make_excludes_absolute ConfigLoader.merge_with_default(plugin_config, plugin_config_path) end end end
Source
# File lib/rubocop/plugin/configuration_integrator.rb, line 27 def create_context(rubocop_config) LintRoller::Context.new( runner: :rubocop, runner_version: Version.version, engine: :rubocop, engine_version: Version.version, target_ruby_version: rubocop_config.target_ruby_version ) end
Source
# File lib/rubocop/plugin/configuration_integrator.rb, line 81 def fake_out_rubocop_default_configuration(default_config) orig_default_config = ConfigLoader.instance_variable_get(:@default_configuration) result = yield default_config ConfigLoader.instance_variable_set(:@default_configuration, orig_default_config) result end
Source
# File lib/rubocop/plugin/configuration_integrator.rb, line 92 def load_plugin_rubocop_config(plugin, runner_context) rules = plugin.rules(runner_context) case rules.type when :path [ConfigLoader.load_file(rules.value, check: false), rules.value] when :object path = plugin.method(:rules).source_location[0] [Config.create(rules.value, path, check: true), path] when :error plugin_name = plugin.about&.name || plugin.inspect error_message = rules.value.respond_to?(:message) ? rules.value.message : rules.value raise "Plugin `#{plugin_name}' failed to load with error: #{error_message}" end end
rubocop:disable Metrics/AbcSize
Source
# File lib/rubocop/plugin/configuration_integrator.rb, line 118 def merge_all_cop_settings(existing_all_cops, new_all_cops, already_configured_keys) return [existing_all_cops, already_configured_keys] unless new_all_cops.is_a?(Hash) combined_all_cops = existing_all_cops.dup combined_configured_keys = already_configured_keys.dup new_all_cops.each do |key, value| if combined_all_cops[key].is_a?(Array) && value.is_a?(Array) combined_all_cops[key] |= value combined_configured_keys |= [key] elsif !combined_configured_keys.include?(key) combined_all_cops[key] = value combined_configured_keys << key end end [combined_all_cops, combined_configured_keys] end
This is how we ensure “first-in wins”: plugins can override AllCops settings that are set by RuboCop’s default configuration, but once a plugin sets an AllCop setting, they have exclusive first-in-wins rights to that setting.
The one exception to this are array fields, because we don’t want to overwrite the AllCops defaults but rather munge the arrays (‘existing | new`) to allow plugins to add to the array, for example Include and Exclude paths and patterns.
Source
# File lib/rubocop/plugin/configuration_integrator.rb, line 67 def merge_plugin_config_into_all_cops!(rubocop_config, plugin_config) rubocop_config['AllCops'].merge!(plugin_config['AllCops']) end
Source
# File lib/rubocop/plugin/configuration_integrator.rb, line 71 def merge_plugin_config_into_default_config!(default_config, plugin_config) plugin_config.each do |key, value| default_config[key] = if default_config[key].is_a?(Hash) resolver.merge(default_config[key], value) else value end end end
Source
# File lib/rubocop/plugin/configuration_integrator.rb, line 137 def resolver @resolver ||= ConfigLoaderResolver.new end
Source
# File lib/rubocop/plugin/configuration_integrator.rb, line 37 def validate_plugins!(plugins, runner_context) unsupported_plugins = plugins.reject { |plugin| plugin.supported?(runner_context) } return if unsupported_plugins.none? raise Plugin::NotSupportedError, unsupported_plugins end