Class: RuboCop::Cop::Registry

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/rubocop/cop/registry.rb

Overview

Registry that tracks all cops by their badge and department.

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cops = [], options = {}) ⇒ Registry

Returns a new instance of Registry.



51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/rubocop/cop/registry.rb', line 51

def initialize(cops = [], options = {})
  @departments = Set.new
  @cops_by_badge = {}
  @lazy_loaded_cops_by_badge = {}

  @enrollment_queue = cops
  @options = options

  @enabled_cache = {}.compare_by_identity
  @disabled_cache = {}.compare_by_identity
  @warnings = {}
end

Class Attribute Details

.globalObject (readonly)

Returns the value of attribute global.



283
284
285
# File 'lib/rubocop/cop/registry.rb', line 283

def global
  @global
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



49
50
51
# File 'lib/rubocop/cop/registry.rb', line 49

def options
  @options
end

#warningsObject (readonly)

Returns the value of attribute warnings.



49
50
51
# File 'lib/rubocop/cop/registry.rb', line 49

def warnings
  @warnings
end

Class Method Details

.allObject



22
23
24
# File 'lib/rubocop/cop/registry.rb', line 22

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

.qualified_cop?(name) ⇒ Boolean

Returns:

  • (Boolean)


44
45
46
47
# 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, warn: true) ⇒ Object



26
27
28
# File 'lib/rubocop/cop/registry.rb', line 26

def self.qualified_cop_name(name, origin, warn: true)
  global.qualified_cop_name(name, origin, warn: warn)
end

.reset!Object



40
41
42
# File 'lib/rubocop/cop/registry.rb', line 40

def self.reset!
  @global = new
end

.with_temporary_global(temp_global = global.dup) ⇒ Object

Changes momentarily the global registry Intended for testing purposes



32
33
34
35
36
37
38
# 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

Instance Method Details

#==(other) ⇒ Object



237
238
239
# File 'lib/rubocop/cop/registry.rb', line 237

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

#contains_cop_matching?(names) ⇒ Boolean

Returns:

  • (Boolean)


99
100
101
# File 'lib/rubocop/cop/registry.rb', line 99

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

#copsObject



182
183
184
185
186
# File 'lib/rubocop/cop/registry.rb', line 182

def cops
  clear_enrollment_queue
  load_all_lazy_cops
  @cops_by_badge.values
end

#cops_for_department(department) ⇒ Object



229
230
231
# File 'lib/rubocop/cop/registry.rb', line 229

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

#department?(name) ⇒ Boolean

Returns Checks if given name is department.

Returns:

  • (Boolean)

    Checks if given name is department



95
96
97
# File 'lib/rubocop/cop/registry.rb', line 95

def department?(name)
  departments.include?(name.to_sym)
end

#department_missing?(badge, name) ⇒ Boolean

Returns:

  • (Boolean)


149
150
151
# File 'lib/rubocop/cop/registry.rb', line 149

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

#departmentsArray<Symbol>

Returns list of departments for current cops.

Returns:

  • (Array<Symbol>)

    list of departments for current cops.



79
80
81
82
# File 'lib/rubocop/cop/registry.rb', line 79

def departments
  clear_enrollment_queue
  @departments.to_a
end

#disabled(config) ⇒ Object



197
198
199
# File 'lib/rubocop/cop/registry.rb', line 197

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

#dismiss(cop) ⇒ Object



74
75
76
# File 'lib/rubocop/cop/registry.rb', line 74

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

#each(&block) ⇒ Object



253
254
255
# File 'lib/rubocop/cop/registry.rb', line 253

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

#enabled(config) ⇒ Object



193
194
195
# File 'lib/rubocop/cop/registry.rb', line 193

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

#enabled?(cop, config) ⇒ Boolean

Returns:

  • (Boolean)


201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/rubocop/cop/registry.rb', line 201

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) ⇒ Boolean

Returns:

  • (Boolean)


217
218
219
220
221
222
# File 'lib/rubocop/cop/registry.rb', line 217

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) ⇒ Object



70
71
72
# File 'lib/rubocop/cop/registry.rb', line 70

def enlist(cop)
  @enrollment_queue << cop
end

#find_by_cop_name(cop_name) ⇒ Class?

Parameters:

Returns:

  • (Class, nil)


259
260
261
262
263
# File 'lib/rubocop/cop/registry.rb', line 259

def find_by_cop_name(cop_name)
  clear_enrollment_queue
  badge = Badge.parse(cop_name)
  @cops_by_badge[badge] || load_lazy_cop(badge)
end

#find_cops_by_directive(directive) ⇒ Object

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.



268
269
270
271
# File 'lib/rubocop/cop/registry.rb', line 268

def find_cops_by_directive(directive)
  cop = find_by_cop_name(directive)
  cop ? [cop] : cops_for_department(directive)
end

#freezeObject



273
274
275
276
277
278
# File 'lib/rubocop/cop/registry.rb', line 273

def freeze
  clear_enrollment_queue
  load_all_lazy_cops
  unqualified_cop_names # build cache
  super
end

#lazy_load(cop_name, constant_name) ⇒ Object



64
65
66
67
68
# File 'lib/rubocop/cop/registry.rb', line 64

def lazy_load(cop_name, constant_name)
  badge = Badge.parse(cop_name)
  @departments << badge.department
  @lazy_loaded_cops_by_badge[badge] = constant_name
end

#lengthObject



188
189
190
191
# File 'lib/rubocop/cop/registry.rb', line 188

def length
  clear_enrollment_queue
  @cops_by_badge.size + @lazy_loaded_cops_by_badge.size
end

#namesObject



224
225
226
227
# File 'lib/rubocop/cop/registry.rb', line 224

def names
  clear_enrollment_queue
  @cops_by_badge.keys.map(&:to_s) | @lazy_loaded_cops_by_badge.keys.map(&:to_s)
end

#names_for_department(department) ⇒ Object



233
234
235
# File 'lib/rubocop/cop/registry.rb', line 233

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


153
154
155
156
157
158
159
# File 'lib/rubocop/cop/registry.rb', line 153

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

#qualified_cop_name(name, path, warn: true) ⇒ String

Note:

Emits a warning if the provided name has an incorrect namespace

Convert a user provided cop name into a properly namespaced name

Examples:

gives back a correctly qualified cop name


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

fixes incorrect namespaces


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

namespaces bare cop identifiers


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

passes back unrecognized cop names


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

Parameters:

  • name (String)

    Cop name extracted from config

  • path (String, nil)

    Path of file that ‘name` was extracted from

  • warn (Boolean) (defaults to: true)

    Print a warning if no department given for ‘name`

Returns:

  • (String)

    Qualified cop name

Raises:

  • (AmbiguousCopName)

    if a bare identifier with two possible namespaces is provided



135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/rubocop/cop/registry.rb', line 135

def qualified_cop_name(name, path, warn: true)
  badge = Badge.parse(name)
  print_department_missing_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, warn: warn)
  else raise AmbiguousCopName.new(badge, path, potential_badges)
  end
end

#qualify_badge(badge) ⇒ Object



168
169
170
171
172
173
# File 'lib/rubocop/cop/registry.rb', line 168

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

#select(&block) ⇒ Object



249
250
251
# File 'lib/rubocop/cop/registry.rb', line 249

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

#sort!Object



241
242
243
244
245
246
247
# File 'lib/rubocop/cop/registry.rb', line 241

def sort!
  clear_enrollment_queue
  load_all_lazy_cops
  @cops_by_badge = @cops_by_badge.sort_by { |badge, _cop| badge.cop_name }.to_h

  self
end

#to_hHash{String => Array<Class>}

Returns:

  • (Hash{String => Array<Class>})


176
177
178
179
180
# File 'lib/rubocop/cop/registry.rb', line 176

def to_h
  clear_enrollment_queue
  load_all_lazy_cops
  @cops_by_badge.to_h { |_badge, cop| [cop.cop_name, [cop]] }
end

#unqualified_cop_namesObject



161
162
163
164
165
166
# File 'lib/rubocop/cop/registry.rb', line 161

def unqualified_cop_names
  clear_enrollment_queue
  @unqualified_cop_names ||=
    (@cops_by_badge.keys | @lazy_loaded_cops_by_badge.keys)
    .to_set { |badge| File.basename(badge.to_s) } << 'RedundantCopDisableDirective'
end

#warnings?(path) ⇒ Boolean

Returns:

  • (Boolean)


286
287
288
# File 'lib/rubocop/cop/registry.rb', line 286

def warnings?(path)
  @warnings[path]
end

#with_department(department) ⇒ Registry

Returns Cops for that specific department.

Returns:

  • (Registry)

    Cops for that specific department.



85
86
87
# File 'lib/rubocop/cop/registry.rb', line 85

def with_department(department)
  with(cops.select { |cop| cop.department == department })
end

#without_department(department) ⇒ Registry

Returns Cops not for a specific department.

Returns:

  • (Registry)

    Cops not for a specific department.



90
91
92
# File 'lib/rubocop/cop/registry.rb', line 90

def without_department(department)
  with(cops.reject { |cop| cop.department == department })
end