Class: RuboCop::ConfigValidator
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
|
Class Chain:
self,
SimpleForwardable
|
|
| Inherits: | Object |
| Defined in: | lib/rubocop/config_validator.rb |
Overview
Handles validation of configuration, for example cop names, parameter names, and Ruby versions.
Constant Summary
-
COMMON_PARAMS =
# File 'lib/rubocop/config_validator.rb', line 11%w[Exclude Include Severity inherit_mode AutoCorrect StyleGuide Details Enabled Reference References Safe SafeAutoCorrect].freeze
-
CONFIG_CHECK_AUTOCORRECTS =
# File 'lib/rubocop/config_validator.rb', line 25%w[always contextual disabled].freeze
-
CONFIG_CHECK_DEPARTMENTS =
private
# File 'lib/rubocop/config_validator.rb', line 24%w[pending override_department].freeze
-
CONFIG_CHECK_KEYS =
private
# File 'lib/rubocop/config_validator.rb', line 23%w[Enabled Safe SafeAutoCorrect AutoCorrect References].to_set.freeze
-
INTERNAL_PARAMS =
# File 'lib/rubocop/config_validator.rb', line 14%w[Description StyleGuide VersionAdded VersionChanged VersionRemoved Reference References Safe SafeAutoCorrect].freeze
-
NEW_COPS_VALUES =
# File 'lib/rubocop/config_validator.rb', line 18%w[pending disable enable].freeze
-
NEW_COPS_VERSION_PATTERN =
# File 'lib/rubocop/config_validator.rb', line 20/\A\d+(\.\d+)*\z/.freeze
Class Method Summary
- .new(config) ⇒ ConfigValidator constructor
Instance Attribute Summary
- #target_ruby readonly private
Instance Method Summary
- #target_ruby_version
- #validate
-
#validate_after_resolution
Validations that should only be run after all config resolving has taken place: * The target ruby version is only checked once the entire inheritance chain has been loaded so that only the final value is validated, and any obsolete but overridden values are ignored.
- #alert_about_unrecognized_cops(invalid_cop_names) private
-
#check_cop_config_value(hash, parent = nil)
private
Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity.
- #check_obsoletions private
- #check_target_ruby private
- #each_invalid_parameter(cop_name) private
- #list_unknown_cops(invalid_cop_names) private
- #new_cops_value_for_department(name, section) private
- #new_cops_version_value?(value) ⇒ Boolean private
-
#param_error_message(parent, key, value, supposed_values)
private
FIXME: Handling colors in exception messages like this is ugly.
- #reject_conflicting_safe_settings private
- #reject_mutually_exclusive_defaults private
- #suggestion(name) private
- #validate_all_cops_new_cops_parameter private
- #validate_department_new_cops_parameters private
-
#validate_enforced_styles(valid_cop_names)
private
rubocop:todo Metrics/AbcSize.
- #validate_new_cops_parameter private
- #validate_parameter_names(valid_cop_names) private
- #validate_parameter_shape(valid_cop_names) private
- #validate_support_and_has_list(name, formats, valid) private
- #validate_syntax_cop private
Constructor Details
.new(config) ⇒ ConfigValidator
# File 'lib/rubocop/config_validator.rb', line 30
def initialize(config) @config = config @config_obsoletion = ConfigObsoletion.new(config) @target_ruby = TargetRuby.new(config) end
Instance Attribute Details
#target_ruby (readonly, private)
[ GitHub ]# File 'lib/rubocop/config_validator.rb', line 73
attr_reader :target_ruby
Instance Method Details
#alert_about_unrecognized_cops(invalid_cop_names) (private)
# File 'lib/rubocop/config_validator.rb', line 102
def alert_about_unrecognized_cops(invalid_cop_names) unknown_cops = list_unknown_cops(invalid_cop_names) return if unknown_cops.empty? if ConfigLoader.ignore_unrecognized_cops warn Rainbow('The following cops or departments are not ' \ 'recognized and will be ignored:').yellow warn unknown_cops.join("\n") return end raise ValidationError, unknown_cops.join("\n") end
#check_cop_config_value(hash, parent = nil) (private)
Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
# File 'lib/rubocop/config_validator.rb', line 300
def check_cop_config_value(hash, parent = nil) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity hash.each do |key, value| check_cop_config_value(value, key) if value.is_a?(Hash) next unless CONFIG_CHECK_KEYS.include?(key) && value.is_a?(String) if key == 'Enabled' && !CONFIG_CHECK_DEPARTMENTS.include?(value) supposed_values = 'a boolean' elsif key == 'AutoCorrect' && !CONFIG_CHECK_AUTOCORRECTS.include?(value) supposed_values = '`always`, `contextual`, `disabled`, or a boolean' elsif key == 'References' supposed_values = 'an array of strings' else next end raise ValidationError, (parent, key, value, supposed_values) end end
#check_obsoletions (private)
[ GitHub ]# File 'lib/rubocop/config_validator.rb', line 75
def check_obsoletions @config_obsoletion.reject_obsolete! return unless @config_obsoletion.warnings.any? warn Rainbow("Warning: #{@config_obsoletion.warnings.join("\n")}").yellow end
#check_target_ruby (private)
# File 'lib/rubocop/config_validator.rb', line 82
def check_target_ruby return if target_ruby.supported? source = target_ruby.source last_version = target_ruby.rubocop_version_with_support msg = if last_version "RuboCop found unsupported Ruby version #{target_ruby_version} " \ "in #{source}. #{target_ruby_version}-compatible " \ "analysis was dropped after version #{last_version}." else 'RuboCop found unknown Ruby version ' \ "#{target_ruby_version.inspect} in #{source}." end msg += "\nSupported versions: #{TargetRuby.supported_versions.join(', ')}" raise ValidationError, msg end
#each_invalid_parameter(cop_name) (private)
[ GitHub ]# File 'lib/rubocop/config_validator.rb', line 239
def each_invalid_parameter(cop_name) default_config = ConfigLoader.default_configuration[cop_name] @config[cop_name].each_key do |param| next if COMMON_PARAMS.include?(param) || default_config.key?(param) # Departments shipped as top-level sections in an extension's default configuration accept # `NewCops`, like any other department. next if param == 'NewCops' && Cop::Registry.global.department?(cop_name) supported_params = default_config.keys - INTERNAL_PARAMS yield param, supported_params end end
#list_unknown_cops(invalid_cop_names) (private)
[ GitHub ]# File 'lib/rubocop/config_validator.rb', line 118
def list_unknown_cops(invalid_cop_names) unknown_cops = [] invalid_cop_names.each do |name| # There could be a custom cop with this name. If so, don't warn next if Cop::Registry.global.contains_cop_matching?([name]) next if ConfigObsoletion.deprecated_cop_name?(name) # Special case for inherit_mode, which is a directive that we keep in # the configuration (even though it's not a cop), because it's easier # to do so than to pass the value around to various methods. next if name == 'inherit_mode' = <<~MESSAGE.rstrip unrecognized cop or department #{name} found in #{smart_loaded_path} #{suggestion(name)} MESSAGE unknown_cops << end unknown_cops end
#new_cops_value_for_department(name, section) (private)
[ GitHub ]
#new_cops_version_value?(value) ⇒ Boolean (private)
# File 'lib/rubocop/config_validator.rb', line 203
def new_cops_version_value?(value) case value when Float, Integer then true when String then NEW_COPS_VERSION_PATTERN.match?(value) else false end end
#param_error_message(parent, key, value, supposed_values) (private)
FIXME: Handling colors in exception messages like this is ugly.
# File 'lib/rubocop/config_validator.rb', line 321
def (parent, key, value, supposed_values) "#{Rainbow('').reset}" \ "Property #{Rainbow(key).yellow} of #{Rainbow(parent).yellow} cop " \ "is supposed to be #{supposed_values} and #{Rainbow(value).yellow} is not." end
#reject_conflicting_safe_settings (private)
[ GitHub ]# File 'lib/rubocop/config_validator.rb', line 289
def reject_conflicting_safe_settings @config.each do |name, cop_config| next unless cop_config.is_a?(Hash) next unless cop_config['Safe'] == false && cop_config['SafeAutoCorrect'] == true msg = 'Unsafe cops cannot have a safe autocorrection ' \ "(section #{name} in #{smart_loaded_path})" raise ValidationError, msg end end
#reject_mutually_exclusive_defaults (private)
# File 'lib/rubocop/config_validator.rb', line 280
def reject_mutually_exclusive_defaults disabled_by_default = for_all_cops['DisabledByDefault'] enabled_by_default = for_all_cops['EnabledByDefault'] return unless disabled_by_default && enabled_by_default msg = 'Cops cannot be both enabled by default and disabled by default' raise ValidationError, msg end
#suggestion(name) (private)
[ GitHub ]# File 'lib/rubocop/config_validator.rb', line 141
def suggestion(name) registry = Cop::Registry.global departments = registry.departments.map(&:to_s) suggestions = NameSimilarity.find_similar_names(name, departments + registry.map(&:cop_name)) if suggestions.any? "Did you mean `#{suggestions.join('`, `')}`?" else # Department names can contain slashes, e.g. Chef/Correctness, but there's no support for # the concept of higher level departments in RuboCop. It's a flat structure. So if the user # tries to configure a "top level department", we hint that it's the bottom level # departments that should be configured. suggestions = departments.select { |department| department.start_with?("#{name}/") } "#{name} is not a department. Use `#{suggestions.join('`, `')}`." if suggestions.any? end end
#target_ruby_version
[ GitHub ]# File 'lib/rubocop/config_validator.rb', line 67
def target_ruby_version target_ruby.version end
#validate
[ GitHub ]# File 'lib/rubocop/config_validator.rb', line 36
def validate check_cop_config_value(@config) reject_conflicting_safe_settings # Don't validate RuboCop's own files further. Avoids infinite recursion. return if @config.internal? valid_cop_names, invalid_cop_names = @config.keys.partition do |key| ConfigLoader.default_configuration.key?(key) end validate_parameter_shape(valid_cop_names) check_obsoletions alert_about_unrecognized_cops(invalid_cop_names) validate_new_cops_parameter validate_parameter_names(valid_cop_names) validate_enforced_styles(valid_cop_names) validate_syntax_cop reject_mutually_exclusive_defaults end
#validate_after_resolution
Validations that should only be run after all config resolving has taken place: * The target ruby version is only checked once the entire inheritance chain has been loaded so that only the final value is validated, and any obsolete but overridden values are ignored.
# File 'lib/rubocop/config_validator.rb', line 63
def validate_after_resolution check_target_ruby end
#validate_all_cops_new_cops_parameter (private)
# File 'lib/rubocop/config_validator.rb', line 173
def validate_all_cops_new_cops_parameter new_cop_parameter = @config.for_all_cops['NewCops'] return if new_cop_parameter.nil? || NEW_COPS_VALUES.include?(new_cop_parameter) = "invalid #{new_cop_parameter} for `NewCops` found in " \ "#{smart_loaded_path}\n" \ "Valid choices are: #{NEW_COPS_VALUES.join(', ')}" raise ValidationError, end
#validate_department_new_cops_parameters (private)
[ GitHub ]# File 'lib/rubocop/config_validator.rb', line 184
def validate_department_new_cops_parameters @config.each do |name, section| value = new_cops_value_for_department(name, section) next if value.nil? || NEW_COPS_VALUES.include?(value) || new_cops_version_value?(value) raise ValidationError, "invalid #{value} for `NewCops` found in #{smart_loaded_path}\n" \ "Valid choices for a department are: #{NEW_COPS_VALUES.join(', ')}, " \ "or a version string like '1.50'" end end
#validate_enforced_styles(valid_cop_names) (private)
rubocop:todo Metrics/AbcSize
# File 'lib/rubocop/config_validator.rb', line 254
def validate_enforced_styles(valid_cop_names) # rubocop:todo Metrics/AbcSize valid_cop_names.each do |name| styles = @config[name].select { |key, _| key.start_with?('Enforced') } styles.each do |style_name, style| supported_key = RuboCop::Cop::Util.to_supported_styles(style_name) valid = ConfigLoader.default_configuration[name][supported_key] next unless valid next if valid.include?(style) next if validate_support_and_has_list(name, style, valid) msg = "invalid #{style_name} '#{style}' for #{name} found in " \ "#{smart_loaded_path}\n" \ "Valid choices are: #{valid.join(', ')}" raise ValidationError, msg end end end
#validate_new_cops_parameter (private)
[ GitHub ]# File 'lib/rubocop/config_validator.rb', line 168
def validate_new_cops_parameter validate_all_cops_new_cops_parameter validate_department_new_cops_parameters end
#validate_parameter_names(valid_cop_names) (private)
[ GitHub ]# File 'lib/rubocop/config_validator.rb', line 225
def validate_parameter_names(valid_cop_names) valid_cop_names.each do |name| each_invalid_parameter(name) do |param, supported_params| warn Rainbow(<<~MESSAGE).yellow Warning: #{name} does not support #{param} parameter. Supported parameters are: - #{supported_params.join("\n - ")} MESSAGE end end end
#validate_parameter_shape(valid_cop_names) (private)
[ GitHub ]# File 'lib/rubocop/config_validator.rb', line 211
def validate_parameter_shape(valid_cop_names) valid_cop_names.each do |name| if @config[name].nil? raise ValidationError, "empty section #{name.inspect} found in #{smart_loaded_path}" elsif !@config[name].is_a?(Hash) raise ValidationError, <<~MESSAGE The configuration for #{name.inspect} in #{smart_loaded_path} is not a Hash. Found: #{@config[name].inspect} MESSAGE end end end
#validate_support_and_has_list(name, formats, valid) (private)
[ GitHub ]# File 'lib/rubocop/config_validator.rb', line 274
def validate_support_and_has_list(name, formats, valid) ConfigLoader.default_configuration[name]['AllowMultipleStyles'] && formats.is_a?(Array) && formats.all? { |format| valid.include?(format) } end
#validate_syntax_cop (private)
# File 'lib/rubocop/config_validator.rb', line 157
def validate_syntax_cop syntax_config = @config['Lint/Syntax'] default_config = ConfigLoader.default_configuration['Lint/Syntax'] return unless syntax_config && default_config.merge(syntax_config) != default_config raise ValidationError, "configuration for Lint/Syntax cop found in #{smart_loaded_path}\n" \ 'It\'s not possible to disable this cop.' end