class RuboCop::Cop::Registry

Registry that tracks all cops by their badge and department.

Attributes

global[R]
options[R]

Public Class Methods

all() click to toggle source
# File lib/rubocop/cop/registry.rb, line 22
def self.all
  global.without_department(:Test).cops
end
new(cops = [], options = {}) click to toggle source
# File lib/rubocop/cop/registry.rb, line 51
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
qualified_cop?(name) click to toggle source
# File lib/rubocop/cop/registry.rb, line 44
def self.qualified_cop?(name)
  badge = Badge.parse(name)
  global.qualify_badge(badge).first == badge
end
qualified_cop_name(name, origin) click to toggle source
# File lib/rubocop/cop/registry.rb, line 26
def self.qualified_cop_name(name, origin)
  global.qualified_cop_name(name, origin)
end
reset!() click to toggle source
# File lib/rubocop/cop/registry.rb, line 40
def self.reset!
  @global = new
end
with_temporary_global(temp_global = global.dup) { || ... } click to toggle source

Changes momentarily the global registry Intended for testing purposes

# File lib/rubocop/cop/registry.rb, line 32
def self.with_temporary_global(temp_global = global.dup)
  previous = @global
  @global = temp_global
  yield
ensure
  @global = previous
end

Public Instance Methods

==(other) click to toggle source
# File lib/rubocop/cop/registry.rb, line 232
def ==(other)
  cops == other.cops
end
contains_cop_matching?(names) click to toggle source
# File lib/rubocop/cop/registry.rb, line 97
def contains_cop_matching?(names)
  cops.any? { |cop| cop.match?(names) }
end
cops() click to toggle source
# File lib/rubocop/cop/registry.rb, line 179
def cops
  clear_enrollment_queue
  @registry.values
end
cops_for_department(department) click to toggle source
# File lib/rubocop/cop/registry.rb, line 224
def cops_for_department(department)
  cops.select { |cop| cop.department == department.to_sym }
end
department?(name) click to toggle source

@return [Boolean] Checks if given name is department

# File lib/rubocop/cop/registry.rb, line 93
def department?(name)
  departments.include?(name.to_sym)
end
department_missing?(badge, name) click to toggle source
# File lib/rubocop/cop/registry.rb, line 147
def department_missing?(badge, name)
  !badge.qualified? && unqualified_cop_names.include?(name)
end
departments() click to toggle source

@return [Array<Symbol>] list of departments for current cops.

# File lib/rubocop/cop/registry.rb, line 72
def departments
  clear_enrollment_queue
  @departments.keys
end
disabled(config) click to toggle source
# File lib/rubocop/cop/registry.rb, line 193
def disabled(config)
  @disabled_cache[config] ||= reject { |cop| enabled?(cop, config) }
end
dismiss(cop) click to toggle source
# File lib/rubocop/cop/registry.rb, line 67
def dismiss(cop)
  raise "Cop #{cop} could not be dismissed" unless @enrollment_queue.delete(cop)
end
each(&block) click to toggle source
# File lib/rubocop/cop/registry.rb, line 247
def each(&block)
  cops.each(&block)
end
enabled(config) click to toggle source
# File lib/rubocop/cop/registry.rb, line 189
def enabled(config)
  @enabled_cache[config] ||= select { |cop| enabled?(cop, config) }
end
enabled?(cop, config) click to toggle source
# File lib/rubocop/cop/registry.rb, line 197
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
enabled_pending_cop?(cop_cfg, config) click to toggle source
# File lib/rubocop/cop/registry.rb, line 213
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
enlist(cop) click to toggle source
# File lib/rubocop/cop/registry.rb, line 63
def enlist(cop)
  @enrollment_queue << cop
end
find_by_cop_name(cop_name) click to toggle source

@param [String] cop_name @return [Class, nil]

# File lib/rubocop/cop/registry.rb, line 253
def find_by_cop_name(cop_name)
  to_h[cop_name].first
end
find_cops_by_directive(directive) click to toggle source

When a cop name is given returns a single-element array with the cop class. When a department name is given returns an array with all the cop classes for that department.

# File lib/rubocop/cop/registry.rb, line 260
def find_cops_by_directive(directive)
  cop = find_by_cop_name(directive)
  cop ? [cop] : cops_for_department(directive)
end
freeze() click to toggle source
Calls superclass method
# File lib/rubocop/cop/registry.rb, line 265
def freeze
  clear_enrollment_queue
  unqualified_cop_names # build cache
  super
end
length() click to toggle source
# File lib/rubocop/cop/registry.rb, line 184
def length
  clear_enrollment_queue
  @registry.size
end
names() click to toggle source
# File lib/rubocop/cop/registry.rb, line 220
def names
  cops.map(&:cop_name)
end
names_for_department(department) click to toggle source
# File lib/rubocop/cop/registry.rb, line 228
def names_for_department(department)
  cops_for_department(department).map(&:cop_name)
end
print_warning(name, path) click to toggle source
qualified_cop_name(name, path, warn: true) click to toggle source

Convert a user provided cop name into a properly namespaced name

@example gives back a correctly qualified cop name

registry = RuboCop::Cop::Registry
registry.qualified_cop_name('Layout/EndOfLine', '') # => 'Layout/EndOfLine'

@example fixes incorrect namespaces

registry = RuboCop::Cop::Registry
registry.qualified_cop_name('Lint/EndOfLine', '') # => 'Layout/EndOfLine'

@example namespaces bare cop identifiers

registry = RuboCop::Cop::Registry
registry.qualified_cop_name('EndOfLine', '') # => 'Layout/EndOfLine'

@example passes back unrecognized cop names

registry = RuboCop::Cop::Registry
registry.qualified_cop_name('NotACop', '') # => 'NotACop'

@param name [String] Cop name extracted from config @param path [String, nil] Path of file that ‘name` was extracted from @param warn [Boolean] Print a warning if no department given for `name`

@raise [AmbiguousCopName]

if a bare identifier with two possible namespaces is provided

@note Emits a warning if the provided name has an incorrect namespace

@return [String] Qualified cop name

# File lib/rubocop/cop/registry.rb, line 133
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
qualify_badge(badge) click to toggle source
# File lib/rubocop/cop/registry.rb, line 166
def qualify_badge(badge)
  clear_enrollment_queue
  @departments
    .map { |department, _| badge.with_department(department) }
    .select { |potential_badge| registered?(potential_badge) }
end
select(&block) click to toggle source
# File lib/rubocop/cop/registry.rb, line 243
def select(&block)
  cops.select(&block)
end
sort!() click to toggle source
# File lib/rubocop/cop/registry.rb, line 236
def sort!
  clear_enrollment_queue
  @registry = @registry.sort_by { |badge, _| badge.cop_name }.to_h

  self
end
to_h() click to toggle source

@return [Hash{String => Array<Class>}]

# File lib/rubocop/cop/registry.rb, line 174
def to_h
  clear_enrollment_queue
  @cops_by_cop_name
end
unqualified_cop_names() click to toggle source
# File lib/rubocop/cop/registry.rb, line 159
def unqualified_cop_names
  clear_enrollment_queue
  @unqualified_cop_names ||=
    Set.new(@cops_by_cop_name.keys.map { |qn| File.basename(qn) }) <<
    'RedundantCopDisableDirective'
end
with_department(department) click to toggle source

@return [Registry] Cops for that specific department.

# File lib/rubocop/cop/registry.rb, line 78
def with_department(department)
  clear_enrollment_queue
  with(@departments.fetch(department, []))
end
without_department(department) click to toggle source

@return [Registry] Cops not for a specific department.

# File lib/rubocop/cop/registry.rb, line 84
def without_department(department)
  clear_enrollment_queue
  without_department = @departments.dup
  without_department.delete(department)

  with(without_department.values.flatten)
end

Private Instance Methods

clear_enrollment_queue() click to toggle source
# File lib/rubocop/cop/registry.rb, line 283
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
initialize_copy(reg) click to toggle source
# File lib/rubocop/cop/registry.rb, line 279
def initialize_copy(reg)
  initialize(reg.cops, reg.options)
end
registered?(badge) click to toggle source
# File lib/rubocop/cop/registry.rb, line 309
def registered?(badge)
  clear_enrollment_queue
  @registry.key?(badge)
end
resolve_badge(given_badge, real_badge, source_path) click to toggle source
# File lib/rubocop/cop/registry.rb, line 299
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
with(cops) click to toggle source
# File lib/rubocop/cop/registry.rb, line 295
def with(cops)
  self.class.new(cops)
end