class RuboCop::Cop::Registry

Registry that tracks all cops by their badge and department.

def self.all

def self.all
  global.without_department(:Test).cops
end

def self.qualified_cop?(name)

def self.qualified_cop?(name)
  badge = Badge.parse(name)
  global.qualify_badge(badge).first == badge
end

def self.qualified_cop_name(name, origin)

def self.qualified_cop_name(name, origin)
  global.qualified_cop_name(name, origin)
end

def self.reset!

def self.reset!
  @global = new
end

def self.with_temporary_global(temp_global = global.dup)

Intended for testing purposes
Changes momentarily the global registry
def self.with_temporary_global(temp_global = global.dup)
  previous = @global
  @global = temp_global
  yield
ensure
  @global = previous
end

def ==(other)

def ==(other)
  cops == other.cops
end

def clear_enrollment_queue

def clear_enrollment_queue
  return if @enrollment_queue.empty?
  @enrollment_queue.each do |cop|
    @registry[cop.badge] = cop
    @departments[cop.department] ||= []
    @departments[cop.department] << cop
    @cops_by_cop_name[cop.cop_name] << cop
  end
  @enrollment_queue = []
end

def contains_cop_matching?(names)

def contains_cop_matching?(names)
  cops.any? { |cop| cop.match?(names) }
end

def cops

def cops
  clear_enrollment_queue
  @registry.values
end

def cops_for_department(department)

def cops_for_department(department)
  cops.select { |cop| cop.department == department.to_sym }
end

def department?(name)

Returns:
  • (Boolean) - Checks if given name is department
def department?(name)
  departments.include?(name.to_sym)
end

def department_missing?(badge, name)

def department_missing?(badge, name)
  !badge.qualified? && unqualified_cop_names.include?(name)
end

def departments

Returns:
  • (Array) - list of departments for current cops.
def departments
  clear_enrollment_queue
  @departments.keys
end

def disabled(config)

def disabled(config)
  @disabled_cache[config] ||= reject { |cop| enabled?(cop, config) }
end

def dismiss(cop)

def dismiss(cop)
  raise "Cop #{cop} could not be dismissed" unless @enrollment_queue.delete(cop)
end

def each(&block)

def each(&block)
  cops.each(&block)
end

def enabled(config)

def enabled(config)
  @enabled_cache[config] ||= select { |cop| enabled?(cop, config) }
end

def enabled?(cop, config)

def enabled?(cop, config)
  return true if options[:only]&.include?(cop.cop_name)
  # We need to use `cop_name` in this case, because `for_cop` uses caching
  # which expects cop names or cop classes as keys.
  cfg = config.for_cop(cop.cop_name)
  cop_enabled = cfg.fetch('Enabled') == true || enabled_pending_cop?(cfg, config)
  if options.fetch(:safe, false)
    cop_enabled && cfg.fetch('Safe', true)
  else
    cop_enabled
  end
end

def enabled_pending_cop?(cop_cfg, config)

def enabled_pending_cop?(cop_cfg, config)
  return false if @options[:disable_pending_cops]
  cop_cfg.fetch('Enabled') == 'pending' &&
    (@options[:enable_pending_cops] || config.enabled_new_cops?)
end

def enlist(cop)

def enlist(cop)
  @enrollment_queue << cop
end

def find_by_cop_name(cop_name)

Returns:
  • (Class, nil) -

Parameters:
  • cop_name (String) --
def find_by_cop_name(cop_name)
  to_h[cop_name].first
end

def find_cops_by_directive(directive)

for that department.
When a department name is given returns an array with all the cop classes
When a cop name is given returns a single-element array with the cop class.
def find_cops_by_directive(directive)
  cop = find_by_cop_name(directive)
  cop ? [cop] : cops_for_department(directive)
end

def freeze

def freeze
  clear_enrollment_queue
  unqualified_cop_names # build cache
  super
end

def initialize(cops = [], options = {})

def initialize(cops = [], options = {})
  @registry = {}
  @departments = {}
  @cops_by_cop_name = Hash.new { |hash, key| hash[key] = [] }
  @enrollment_queue = cops
  @options = options
  @enabled_cache = {}.compare_by_identity
  @disabled_cache = {}.compare_by_identity
end

def initialize_copy(reg)

def initialize_copy(reg)
  initialize(reg.cops, reg.options)
end

def length

def length
  clear_enrollment_queue
  @registry.size
end

def names

def names
  cops.map(&:cop_name)
end

def names_for_department(department)

def names_for_department(department)
  cops_for_department(department).map(&:cop_name)
end

def print_warning(name, path)

def print_warning(name, path)
  message = "#{path}: Warning: no department given for #{name}."
  if path.end_with?('.rb')
    message += ' Run `rubocop -a --only Migration/DepartmentName` to fix.'
  end
  warn message
end

def qualified_cop_name(name, path, warn: true)

Returns:
  • (String) - Qualified cop name

Other tags:
    Note: - Emits a warning if the provided name has an incorrect namespace

Raises:
  • (AmbiguousCopName) -

Parameters:
  • warn (Boolean) -- Print a warning if no department given for `name`
  • path (String, nil) -- Path of file that `name` was extracted from
  • name (String) -- Cop name extracted from config

Other tags:
    Example: passes back unrecognized cop names -
    Example: namespaces bare cop identifiers -
    Example: fixes incorrect namespaces -
    Example: gives back a correctly qualified cop name -
def qualified_cop_name(name, path, warn: true)
  badge = Badge.parse(name)
  print_warning(name, path) if warn && department_missing?(badge, name)
  return name if registered?(badge)
  potential_badges = qualify_badge(badge)
  case potential_badges.size
  when 0 then name # No namespace found. Deal with it later in caller.
  when 1 then resolve_badge(badge, potential_badges.first, path)
  else raise AmbiguousCopName.new(badge, path, potential_badges)
  end
end

def qualify_badge(badge)

def qualify_badge(badge)
  clear_enrollment_queue
  @departments
    .map { |department, _| badge.with_department(department) }
    .select { |potential_badge| registered?(potential_badge) }
end

def registered?(badge)

def registered?(badge)
  clear_enrollment_queue
  @registry.key?(badge)
end

def resolve_badge(given_badge, real_badge, source_path)

def resolve_badge(given_badge, real_badge, source_path)
  unless given_badge.match?(real_badge)
    path = PathUtil.smart_path(source_path)
    warn "#{path}: #{given_badge} has the wrong namespace - " \
         "replace it with #{given_badge.with_department(real_badge.department)}"
  end
  real_badge.to_s
end

def select(&block)

def select(&block)
  cops.select(&block)
end

def sort!

def sort!
  clear_enrollment_queue
  @registry = @registry.sort_by { |badge, _| badge.cop_name }.to_h
  self
end

def to_h

Returns:
  • (Hash{String => Array}) -
def to_h
  clear_enrollment_queue
  @cops_by_cop_name
end

def unqualified_cop_names

def unqualified_cop_names
  clear_enrollment_queue
  @unqualified_cop_names ||=
    Set.new(@cops_by_cop_name.keys.map { |qn| File.basename(qn) }) <<
    'RedundantCopDisableDirective'
end

def with(cops)

def with(cops)
  self.class.new(cops)
end

def with_department(department)

Returns:
  • (Registry) - Cops for that specific department.
def with_department(department)
  clear_enrollment_queue
  with(@departments.fetch(department, []))
end

def without_department(department)

Returns:
  • (Registry) - Cops not for a specific department.
def without_department(department)
  clear_enrollment_queue
  without_department = @departments.dup
  without_department.delete(department)
  with(without_department.values.flatten)
end