class Rubocop::Config
This class represents the configuration of the RuboCop application and all its cops. A Config
is associated with a YAML configuration file from which it was read. Several different Configs can be used during a run of the rubocop program, if files in several directories are inspected.
Constants
- DEFAULT_FILE
- DOTFILE
- RUBOCOP_HOME
Attributes
Public Class Methods
# File lib/rubocop/config.rb, line 113 def add_excludes_from_higher_level(config, highest_config) if highest_config['AllCops'] && highest_config['AllCops']['Excludes'] config['AllCops'] ||= {} config['AllCops']['Excludes'] ||= [] highest_config['AllCops']['Excludes'].each do |path| unless path.is_a?(Regexp) || path.start_with?('/') diff_in_level = config.loaded_path.count('/') - highest_config.loaded_path.count('/') path = '../' * diff_in_level + path end config['AllCops']['Excludes'] << path end config['AllCops']['Excludes'].uniq! end end
# File lib/rubocop/config.rb, line 83 def base_configs(path, inherit_from) base_files = case inherit_from when nil then [] when String then [inherit_from] when Array then inherit_from end base_files.map do |f| f = File.join(File.dirname(path), f) unless f.start_with?('/') load_file(f) end end
Returns the path of .rubocop.yml searching upwards in the directory structure starting at the given directory where the inspected file is. If no .rubocop.yml is found there, the user’s home directory is checked. If there’s no .rubocop.yml there either, the path to the default file is returned.
# File lib/rubocop/config.rb, line 100 def configuration_file_for(target_dir) config_files_in_path(target_dir).first || DEFAULT_FILE end
# File lib/rubocop/config.rb, line 104 def configuration_from_file(config_file) config = load_file(config_file) found_files = config_files_in_path(config_file) if found_files.any? && found_files.last != config_file add_excludes_from_higher_level(config, load_file(found_files.last)) end merge_with_default(config, config_file) end
# File lib/rubocop/config.rb, line 44 def correct_relative_excludes(all_cops, base_config, path) all_cops['Excludes'].map! do |exclude_elem| if exclude_elem.is_a?(String) && exclude_elem =~ %r([^/].*/) rel_path = relative_path(base_config.loaded_path, File.dirname(path)) rel_path.to_s.sub(/#{DOTFILE}$/, '') + exclude_elem else exclude_elem end end end
# File lib/rubocop/config.rb, line 129 def default_configuration @default_configuration ||= load_file(DEFAULT_FILE) end
# File lib/rubocop/config.rb, line 23 def load_file(path) path = File.absolute_path(path) hash = YAML.load_file(path) base_configs(path, hash['inherit_from']).reverse.each do |base_config| base_config.each do |key, value| if value.is_a?(Hash) if key == 'AllCops' && value['Excludes'] correct_relative_excludes(value, base_config, path) end hash[key] = hash.has_key?(key) ? merge(value, hash[key]) : value end end end hash.delete('inherit_from') config = new(hash, path) config.warn_unless_valid config end
Return a recursive merge of two hashes. That is, a normal hash merge, with the addition that any value that is a hash, and occurs in both arguments, will also be merged. And so on.
# File lib/rubocop/config.rb, line 64 def merge(base_hash, derived_hash) result = {} base_hash.each do |key, value| result[key] = if derived_hash.has_key?(key) if value.is_a?(Hash) merge(value, derived_hash[key]) else derived_hash[key] end else base_hash[key] end end derived_hash.each do |key, value| result[key] = value unless base_hash.has_key?(key) end result end
# File lib/rubocop/config.rb, line 133 def merge_with_default(config, config_file) new(merge(default_configuration, config), config_file) end
# File lib/rubocop/config.rb, line 157 def initialize(hash = {}, loaded_path = nil) @hash = hash @loaded_path = loaded_path super(@hash) end
# File lib/rubocop/config.rb, line 56 def relative_path(path, base) path_name = Pathname.new(File.expand_path(path)) path_name.relative_path_from(Pathname.new(base)).to_s end
Private Class Methods
# File lib/rubocop/config.rb, line 139 def config_files_in_path(target) possible_config_files = dirs_to_search(target).map do |dir| File.join(dir, DOTFILE) end possible_config_files.select { |config_file| File.exist?(config_file) } end
# File lib/rubocop/config.rb, line 146 def dirs_to_search(target_dir) dirs_to_search = [] target_dir_pathname = Pathname.new(File.expand_path(target_dir)) target_dir_pathname.ascend do |dir_pathname| dirs_to_search << dir_pathname.to_s end dirs_to_search << Dir.home dirs_to_search end
Public Instance Methods
# File lib/rubocop/config.rb, line 167 def cop_enabled?(cop) self[cop].nil? || self[cop]['Enabled'] end
# File lib/rubocop/config.rb, line 211 def file_to_exclude?(file) relative_file_path = relative_path_to_loaded_dir(file) patterns_to_exclude.any? do |pattern| match_path?(pattern, relative_file_path) end end
# File lib/rubocop/config.rb, line 204 def file_to_include?(file) relative_file_path = relative_path_to_loaded_dir(file) patterns_to_include.any? do |pattern| match_path?(pattern, relative_file_path) end end
# File lib/rubocop/config.rb, line 163 def for_cop(cop) self[cop] end
# File lib/rubocop/config.rb, line 222 def patterns_to_exclude @hash['AllCops']['Excludes'] end
# File lib/rubocop/config.rb, line 218 def patterns_to_include @hash['AllCops']['Includes'] end
TODO: This should be a private method
# File lib/rubocop/config.rb, line 178 def validate # Don't validate RuboCop's own files. Avoids inifinite recursion. return if @loaded_path.start_with?(RUBOCOP_HOME) default_config = self.class.default_configuration valid_cop_names, invalid_cop_names = @hash.keys.partition do |key| default_config.has_key?(key) end invalid_cop_names.each do |name| fail ValidationError, "unrecognized cop #{name} found in #{loaded_path || self}" end valid_cop_names.each do |name| @hash[name].each_key do |param| unless default_config[name].has_key?(param) fail ValidationError, "unrecognized parameter #{name}:#{param} found " + "in #{loaded_path || self}" end end end end
# File lib/rubocop/config.rb, line 171 def warn_unless_valid validate rescue Config::ValidationError => e puts "Warning: #{e.message}".color(:red) end
Private Instance Methods
# File lib/rubocop/config.rb, line 233 def loaded_dir_pathname return nil unless loaded_path @loaded_dir ||= begin loaded_dir = File.expand_path(File.dirname(loaded_path)) Pathname.new(loaded_dir) end end
# File lib/rubocop/config.rb, line 241 def match_path?(pattern, path) case pattern when String File.basename(path) == pattern || File.fnmatch(pattern, path) when Regexp path =~ pattern end end
# File lib/rubocop/config.rb, line 228 def relative_path_to_loaded_dir(file) return file unless loaded_path Config.relative_path(file, loaded_dir_pathname) end