class Rubocop::Config
directories are inspected.
during a run of the rubocop program, if files in several
file from which it was read. Several different Configs can be used
and all its cops. A Config is associated with a YAML configuration
This class represents the configuration of the RuboCop application
def add_excludes_from_higher_level(config, highest_config)
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?('/') path = File.join(File.dirname(highest_config.loaded_path), path) end config['AllCops']['Excludes'] << path end config['AllCops']['Excludes'].uniq! end end
def base_configs(path, inherit_from)
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?('/') print 'Inheriting ' if debug? load_file(f) end end
def config_files_in_path(target)
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
def configuration_file_for(target_dir)
user's home directory is checked. If there's no .rubocop.yml
inspected file is. If no .rubocop.yml is found there, the
directory structure starting at the given directory where the
Returns the path of .rubocop.yml searching upwards in the
def configuration_file_for(target_dir) config_files_in_path(target_dir).first || DEFAULT_FILE end
def configuration_from_file(config_file)
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 print 'AllCops/Excludes ' if debug? add_excludes_from_higher_level(config, load_file(found_files.last)) end make_excludes_absolute(config) merge_with_default(config, config_file) end
def cop_enabled?(cop)
def cop_enabled?(cop) self[cop].nil? || self[cop]['Enabled'] end
def default_configuration
def default_configuration @default_configuration ||= begin print 'Default ' if debug? load_file(DEFAULT_FILE) end end
def dirs_to_search(target_dir)
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
def file_to_exclude?(file)
def file_to_exclude?(file) file = File.join(Dir.pwd, file) unless file.start_with?('/') patterns_to_exclude.any? { |pattern| match_path?(pattern, file) } end
def file_to_include?(file)
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
def for_cop(cop)
def for_cop(cop) self[cop] end
def initialize(hash = {}, loaded_path = nil)
def initialize(hash = {}, loaded_path = nil) @hash = hash @loaded_path = loaded_path super(@hash) end
def load_file(path)
def load_file(path) path = File.absolute_path(path) hash = YAML.load_file(path) puts "configuration from #{path}" if debug? contains_auto_generated_config = false base_configs(path, hash['inherit_from']).reverse.each do |base_config| if File.basename(base_config.loaded_path) == DOTFILE make_excludes_absolute(base_config) end base_config.each do |key, value| if value.is_a?(Hash) hash[key] = hash.has_key?(key) ? merge(value, hash[key]) : value end end if base_config.loaded_path.include?(AUTO_GENERATED_FILE) contains_auto_generated_config = true end end hash.delete('inherit_from') config = new(hash, path) config.warn_unless_valid config.contains_auto_generated_config = contains_auto_generated_config config end
def loaded_dir_pathname
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
def make_excludes_absolute(config)
def make_excludes_absolute(config) if config['AllCops'] && config['AllCops']['Excludes'] config['AllCops']['Excludes'].map! do |exclude_elem| if exclude_elem.is_a?(String) && !exclude_elem.start_with?('/') File.join(File.dirname(config.loaded_path), exclude_elem) else exclude_elem end end end end
def match_path?(pattern, path)
def match_path?(pattern, path) case pattern when String File.basename(path) == pattern || File.fnmatch(pattern, path) when Regexp path =~ pattern end end
def merge(base_hash, derived_hash)
with the addition that any value that is a hash, and occurs in both
Return an extended merge of two hashes. That is, a normal hash merge,
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) value.merge(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
def merge_with_default(config, config_file)
def merge_with_default(config, config_file) result = new(merge(default_configuration, config), config_file) result.contains_auto_generated_config = config.contains_auto_generated_config result end
def patterns_to_exclude
def patterns_to_exclude @hash['AllCops']['Excludes'] end
def patterns_to_include
def patterns_to_include @hash['AllCops']['Includes'] end
def relative_path(path, base)
def relative_path(path, base) path_name = Pathname.new(File.expand_path(path)) path_name.relative_path_from(Pathname.new(base)).to_s end
def relative_path_to_loaded_dir(file)
def relative_path_to_loaded_dir(file) return file unless loaded_path Config.relative_path(file, loaded_dir_pathname) end
def validate
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
def warn_unless_valid
def warn_unless_valid validate rescue Config::ValidationError => e puts "Warning: #{e.message}".color(:red) end