rubocop 1.15.0 → 1.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +104 -31
  4. data/lib/rubocop.rb +7 -0
  5. data/lib/rubocop/cli/command/suggest_extensions.rb +3 -3
  6. data/lib/rubocop/config_loader.rb +1 -1
  7. data/lib/rubocop/config_validator.rb +5 -5
  8. data/lib/rubocop/cop/base.rb +2 -2
  9. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  10. data/lib/rubocop/cop/bundler/gem_version.rb +38 -4
  11. data/lib/rubocop/cop/corrector.rb +4 -4
  12. data/lib/rubocop/cop/generator.rb +1 -1
  13. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  14. data/lib/rubocop/cop/layout/argument_alignment.rb +4 -3
  15. data/lib/rubocop/cop/layout/array_alignment.rb +2 -2
  16. data/lib/rubocop/cop/layout/block_alignment.rb +1 -1
  17. data/lib/rubocop/cop/layout/case_indentation.rb +57 -9
  18. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +7 -1
  19. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  20. data/lib/rubocop/cop/layout/dot_position.rb +7 -1
  21. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +13 -15
  22. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -2
  23. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -2
  24. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  25. data/lib/rubocop/cop/layout/hash_alignment.rb +26 -8
  26. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
  27. data/lib/rubocop/cop/layout/indentation_width.rb +8 -0
  28. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +122 -0
  29. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +6 -6
  30. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +2 -2
  31. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +6 -6
  32. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -6
  33. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +6 -6
  34. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +3 -3
  35. data/lib/rubocop/cop/layout/parameter_alignment.rb +2 -2
  36. data/lib/rubocop/cop/layout/redundant_line_break.rb +11 -9
  37. data/lib/rubocop/cop/layout/space_around_keyword.rb +28 -0
  38. data/lib/rubocop/cop/layout/space_around_operators.rb +7 -1
  39. data/lib/rubocop/cop/lint/empty_in_pattern.rb +62 -0
  40. data/lib/rubocop/cop/lint/literal_as_condition.rb +13 -1
  41. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +32 -17
  42. data/lib/rubocop/cop/lint/nested_percent_literal.rb +1 -1
  43. data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
  44. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  45. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +105 -74
  46. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +5 -0
  47. data/lib/rubocop/cop/lint/symbol_conversion.rb +3 -13
  48. data/lib/rubocop/cop/lint/unused_block_argument.rb +1 -1
  49. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  50. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  51. data/lib/rubocop/cop/migration/department_name.rb +3 -1
  52. data/lib/rubocop/cop/mixin/check_line_breakable.rb +10 -1
  53. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +14 -3
  54. data/lib/rubocop/cop/mixin/string_literals_help.rb +2 -4
  55. data/lib/rubocop/cop/mixin/symbol_help.rb +13 -0
  56. data/lib/rubocop/cop/naming/inclusive_language.rb +249 -0
  57. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +2 -2
  58. data/lib/rubocop/cop/style/class_and_module_children.rb +14 -0
  59. data/lib/rubocop/cop/style/hash_each_methods.rb +18 -1
  60. data/lib/rubocop/cop/style/identical_conditional_branches.rb +58 -8
  61. data/lib/rubocop/cop/style/in_pattern_then.rb +56 -0
  62. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -1
  63. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +62 -0
  64. data/lib/rubocop/cop/style/multiline_when_then.rb +2 -11
  65. data/lib/rubocop/cop/style/multiple_comparison.rb +1 -1
  66. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  67. data/lib/rubocop/cop/style/quoted_symbols.rb +110 -0
  68. data/lib/rubocop/cop/style/raise_args.rb +2 -0
  69. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  70. data/lib/rubocop/cop/style/redundant_self.rb +24 -2
  71. data/lib/rubocop/cop/style/regexp_literal.rb +10 -1
  72. data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
  73. data/lib/rubocop/cop/style/string_concatenation.rb +32 -5
  74. data/lib/rubocop/cop/style/string_literals.rb +3 -2
  75. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +1 -0
  76. data/lib/rubocop/cop/style/swap_values.rb +1 -1
  77. data/lib/rubocop/cop/style/top_level_method_definition.rb +10 -2
  78. data/lib/rubocop/cop/style/unpack_first.rb +1 -1
  79. data/lib/rubocop/cop/style/when_then.rb +6 -2
  80. data/lib/rubocop/cop/variable_force/variable_table.rb +1 -1
  81. data/lib/rubocop/directive_comment.rb +58 -6
  82. data/lib/rubocop/options.rb +4 -4
  83. data/lib/rubocop/rake_task.rb +1 -1
  84. data/lib/rubocop/remote_config.rb +10 -2
  85. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  86. data/lib/rubocop/rspec/expect_offense.rb +1 -1
  87. data/lib/rubocop/version.rb +1 -1
  88. metadata +12 -5
@@ -120,6 +120,12 @@ module RuboCop
120
120
  check_operator(:special_asgn, node.loc.operator, right.source_range)
121
121
  end
122
122
 
123
+ def on_match_pattern(node)
124
+ return if target_ruby_version < 3.0
125
+
126
+ check_operator(:match_pattern, node.loc.operator, node.source_range)
127
+ end
128
+
123
129
  alias on_or on_binary
124
130
  alias on_and on_binary
125
131
  alias on_lvasgn on_assignment
@@ -192,7 +198,7 @@ module RuboCop
192
198
  elsif excess_leading_space?(type, operator, with_space) ||
193
199
  excess_trailing_space?(right_operand, with_space)
194
200
  "Operator `#{operator.source}` should be surrounded " \
195
- 'by a single space.'
201
+ 'by a single space.'
196
202
  end
197
203
  end
198
204
 
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # This cop checks for the presence of `in` pattern branches without a body.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # case condition
12
+ # in [a]
13
+ # do_something
14
+ # in [a, b]
15
+ # end
16
+ #
17
+ # # good
18
+ # case condition
19
+ # in [a]
20
+ # do_something
21
+ # in [a, b]
22
+ # nil
23
+ # end
24
+ #
25
+ # @example AllowComments: true (default)
26
+ #
27
+ # # good
28
+ # case condition
29
+ # in [a]
30
+ # do_something
31
+ # in [a, b]
32
+ # # noop
33
+ # end
34
+ #
35
+ # @example AllowComments: false
36
+ #
37
+ # # bad
38
+ # case condition
39
+ # in [a]
40
+ # do_something
41
+ # in [a, b]
42
+ # # noop
43
+ # end
44
+ #
45
+ class EmptyInPattern < Base
46
+ extend TargetRubyVersion
47
+
48
+ MSG = 'Avoid `in` branches without a body.'
49
+
50
+ minimum_target_ruby_version 2.7
51
+
52
+ def on_case_match(node)
53
+ node.in_pattern_branches.each do |branch|
54
+ next if branch.body || cop_config['AllowComments'] && comment_lines?(node)
55
+
56
+ add_offense(branch)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Lint
6
6
  # This cop checks for literals used as the conditions or as
7
7
  # operands in and/or expressions serving as the conditions of
8
- # if/while/until.
8
+ # if/while/until/case-when/case-in.
9
9
  #
10
10
  # @example
11
11
  #
@@ -67,6 +67,18 @@ module RuboCop
67
67
  end
68
68
  end
69
69
 
70
+ def on_case_match(case_match_node)
71
+ if case_match_node.condition
72
+ check_case(case_match_node)
73
+ else
74
+ case_match_node.each_in_pattern do |in_pattern_node|
75
+ next unless in_pattern_node.condition.literal?
76
+
77
+ add_offense(in_pattern_node)
78
+ end
79
+ end
80
+ end
81
+
70
82
  def on_send(node)
71
83
  return unless node.negation_method?
72
84
 
@@ -45,37 +45,52 @@ module RuboCop
45
45
  class MissingCopEnableDirective < Base
46
46
  include RangeHelp
47
47
 
48
- MSG = 'Re-enable %<cop>s cop with `# rubocop:enable` after disabling it.'
49
- MSG_BOUND = 'Re-enable %<cop>s cop within %<max_range>s lines after disabling it.'
48
+ MSG = 'Re-enable %<cop>s %<type>s with `# rubocop:enable` after disabling it.'
49
+ MSG_BOUND = 'Re-enable %<cop>s %<type>s within %<max_range>s lines after disabling it.'
50
50
 
51
- # rubocop:disable Metrics/AbcSize
52
51
  def on_new_investigation
53
- max_range = cop_config['MaximumRangeSize']
54
- processed_source.disabled_line_ranges.each do |cop, line_ranges|
55
- line_ranges.each do |line_range|
56
- # This has to remain a strict inequality to handle
57
- # the case when max_range is Float::INFINITY
58
- next if line_range.max - line_range.min < max_range + 2
52
+ each_missing_enable do |cop, line_range|
53
+ # This has to remain a strict inequality to handle
54
+ # the case when max_range is Float::INFINITY
55
+ next if line_range.max - line_range.min < max_range + 2
59
56
 
60
- range = source_range(processed_source.buffer, line_range.min, (0..0))
57
+ range = source_range(processed_source.buffer, line_range.min, (0..0))
58
+ comment = processed_source.comment_at_line(line_range.begin)
61
59
 
62
- add_offense(range, message: message(max_range: max_range, cop: cop))
63
- end
60
+ add_offense(range, message: message(cop, comment))
64
61
  end
65
62
  end
66
- # rubocop:enable Metrics/AbcSize
67
63
 
68
64
  private
69
65
 
70
- def message(max_range:, cop:)
66
+ def each_missing_enable
67
+ processed_source.disabled_line_ranges.each do |cop, line_ranges|
68
+ line_ranges.each { |line_range| yield cop, line_range }
69
+ end
70
+ end
71
+
72
+ def max_range
73
+ @max_range ||= cop_config['MaximumRangeSize']
74
+ end
75
+
76
+ def message(cop, comment, type = 'cop')
77
+ if department_enabled?(cop, comment)
78
+ type = 'department'
79
+ cop = cop.split('/').first
80
+ end
81
+
71
82
  if max_range == Float::INFINITY
72
- format(MSG, cop: cop)
83
+ format(MSG, cop: cop, type: type)
73
84
  else
74
- format(MSG_BOUND, cop: cop, max_range: max_range)
85
+ format(MSG_BOUND, cop: cop, type: type, max_range: max_range)
75
86
  end
76
87
  end
88
+
89
+ def department_enabled?(cop, comment)
90
+ DirectiveComment.new(comment).in_directive_department?(cop)
91
+ end
77
92
  end
78
93
  end
79
94
  end
80
95
  end
81
- # rubocop:enable Lint/RedundantCopDisableDirective, Layout/SpaceAroundOperators
96
+ # rubocop:enable Lint/RedundantCopDisableDirective
@@ -33,7 +33,7 @@ module RuboCop
33
33
  include PercentLiteral
34
34
 
35
35
  MSG = 'Within percent literals, nested percent literals do not ' \
36
- 'function and may be unwanted in the result.'
36
+ 'function and may be unwanted in the result.'
37
37
 
38
38
  # The array of regular expressions representing percent literals that,
39
39
  # if found within a percent literal expression, will cause a
@@ -29,7 +29,7 @@ module RuboCop
29
29
  TRAILING_QUOTE = /['"]?,?$/.freeze
30
30
 
31
31
  MSG = "Within `%w`/`%W`, quotes and ',' are unnecessary and may be " \
32
- 'unwanted in the resulting strings.'
32
+ 'unwanted in the resulting strings.'
33
33
 
34
34
  def on_array(node)
35
35
  process(node, '%w', '%W')
@@ -25,7 +25,7 @@ module RuboCop
25
25
  extend AutoCorrector
26
26
 
27
27
  MSG = "Within `%i`/`%I`, ':' and ',' are unnecessary and may be " \
28
- 'unwanted in the resulting symbols.'
28
+ 'unwanted in the resulting symbols.'
29
29
 
30
30
  def on_array(node)
31
31
  process(node, '%i', '%I')
@@ -25,11 +25,12 @@ module RuboCop
25
25
  #
26
26
  # # good
27
27
  # x += 1
28
- class RedundantCopDisableDirective < Base
28
+ class RedundantCopDisableDirective < Base # rubocop:todo Metrics/ClassLength
29
29
  include RangeHelp
30
30
  extend AutoCorrector
31
31
 
32
32
  COP_NAME = 'Lint/RedundantCopDisableDirective'
33
+ DEPARTMENT_MARKER = 'DEPARTMENT'
33
34
 
34
35
  attr_accessor :offenses_to_check
35
36
 
@@ -41,12 +42,9 @@ module RuboCop
41
42
  def on_new_investigation
42
43
  return unless offenses_to_check
43
44
 
44
- cop_disabled_line_ranges = processed_source.disabled_line_ranges
45
-
46
45
  redundant_cops = Hash.new { |h, k| h[k] = Set.new }
47
46
 
48
- each_redundant_disable(cop_disabled_line_ranges,
49
- offenses_to_check) do |comment, redundant_cop|
47
+ each_redundant_disable do |comment, redundant_cop|
50
48
  redundant_cops[comment].add(redundant_cop)
51
49
  end
52
50
 
@@ -56,20 +54,31 @@ module RuboCop
56
54
 
57
55
  private
58
56
 
57
+ def cop_disabled_line_ranges
58
+ processed_source.disabled_line_ranges
59
+ end
60
+
61
+ def disabled_ranges
62
+ cop_disabled_line_ranges[COP_NAME] || [0..0]
63
+ end
64
+
59
65
  def previous_line_blank?(range)
60
66
  processed_source.buffer.source_line(range.line - 1).blank?
61
67
  end
62
68
 
63
- def comment_range_with_surrounding_space(range)
64
- if previous_line_blank?(range) &&
65
- processed_source.comment_config.comment_only_line?(range.line)
69
+ def comment_range_with_surrounding_space(directive_comment_range, line_comment_range)
70
+ if previous_line_blank?(directive_comment_range) &&
71
+ processed_source.comment_config.comment_only_line?(directive_comment_range.line) &&
72
+ directive_comment_range.begin_pos == line_comment_range.begin_pos
66
73
  # When the previous line is blank, it should be retained
67
- range_with_surrounding_space(range: range, side: :right)
74
+ range_with_surrounding_space(range: directive_comment_range, side: :right)
68
75
  else
69
76
  # Eat the entire comment, the preceding space, and the preceding
70
77
  # newline if there is one.
71
- original_begin = range.begin_pos
72
- range = range_with_surrounding_space(range: range, side: :left, newlines: true)
78
+ original_begin = directive_comment_range.begin_pos
79
+ range = range_with_surrounding_space(
80
+ range: directive_comment_range, side: :left, newlines: true
81
+ )
73
82
 
74
83
  range_with_surrounding_space(range: range,
75
84
  side: :right,
@@ -94,32 +103,34 @@ module RuboCop
94
103
  range_with_surrounding_space(range: range, side: :right, newlines: false)
95
104
  end
96
105
 
97
- def each_redundant_disable(cop_disabled_line_ranges, offenses,
98
- &block)
99
- disabled_ranges = cop_disabled_line_ranges[COP_NAME] || [0..0]
100
-
106
+ def each_redundant_disable(&block)
101
107
  cop_disabled_line_ranges.each do |cop, line_ranges|
102
- each_already_disabled(line_ranges, disabled_ranges) { |comment| yield comment, cop }
103
-
104
- each_line_range(line_ranges, disabled_ranges, offenses, cop, &block)
108
+ each_already_disabled(cop, line_ranges, &block)
109
+ each_line_range(cop, line_ranges, &block)
105
110
  end
106
111
  end
107
112
 
108
- def each_line_range(line_ranges, disabled_ranges, offenses,
109
- cop)
110
- line_ranges.each_with_index do |line_range, ix|
111
- comment = processed_source.comment_at_line(line_range.begin)
112
- next if ignore_offense?(disabled_ranges, line_range)
113
+ def each_line_range(cop, line_ranges)
114
+ line_ranges.each_with_index do |line_range, line_range_index|
115
+ next if ignore_offense?(line_range)
113
116
 
114
- redundant_cop = find_redundant(comment, offenses, cop, line_range, line_ranges[ix + 1])
115
- yield comment, redundant_cop if redundant_cop
117
+ comment = processed_source.comment_at_line(line_range.begin)
118
+ redundant = if all_disabled?(comment)
119
+ find_redundant_all(line_range, line_ranges[line_range_index + 1])
120
+ elsif department_disabled?(cop, comment)
121
+ find_redundant_department(cop, line_range)
122
+ else
123
+ find_redundant_cop(cop, line_range)
124
+ end
125
+
126
+ yield comment, redundant if redundant
116
127
  end
117
128
  end
118
129
 
119
- def each_already_disabled(line_ranges, disabled_ranges)
130
+ def each_already_disabled(cop, line_ranges)
120
131
  line_ranges.each_cons(2) do |previous_range, range|
121
- next if ignore_offense?(disabled_ranges, range)
122
- next if previous_range.end != range.begin
132
+ next if ignore_offense?(range)
133
+ next unless followed_ranges?(previous_range, range)
123
134
 
124
135
  # If a cop is disabled in a range that begins on the same line as
125
136
  # the end of the previous range, it means that the cop was
@@ -130,42 +141,56 @@ module RuboCop
130
141
  # Comments disabling all cops don't count since it's reasonable
131
142
  # to disable a few select cops first and then all cops further
132
143
  # down in the code.
133
- yield comment if comment && !all_disabled?(comment)
144
+ yield comment, cop if comment && !all_disabled?(comment)
134
145
  end
135
146
  end
136
147
 
137
- # rubocop:todo Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
138
- def find_redundant(comment, offenses, cop, line_range, next_line_range)
139
- if all_disabled?(comment)
140
- # If there's a disable all comment followed by a comment
141
- # specifically disabling `cop`, we don't report the `all`
142
- # comment. If the disable all comment is truly redundant, we will
143
- # detect that when examining the comments of another cop, and we
144
- # get the full line range for the disable all.
145
- if (next_line_range.nil? || line_range.last != next_line_range.first) &&
146
- offenses.none? { |o| line_range.cover?(o.line) }
147
- 'all'
148
- end
149
- else
150
- cop_offenses = offenses.select { |o| o.cop_name == cop }
151
- cop if cop_offenses.none? { |o| line_range.cover?(o.line) }
152
- end
148
+ def find_redundant_cop(cop, range)
149
+ cop_offenses = offenses_to_check.select { |offense| offense.cop_name == cop }
150
+ cop if range_with_offense?(range, cop_offenses)
151
+ end
152
+
153
+ def find_redundant_all(range, next_range)
154
+ # If there's a disable all comment followed by a comment
155
+ # specifically disabling `cop`, we don't report the `all`
156
+ # comment. If the disable all comment is truly redundant, we will
157
+ # detect that when examining the comments of another cop, and we
158
+ # get the full line range for the disable all.
159
+ has_no_next_range = next_range.nil? || !followed_ranges?(range, next_range)
160
+ 'all' if has_no_next_range && range_with_offense?(range)
161
+ end
162
+
163
+ def find_redundant_department(cop, range)
164
+ department = cop.split('/').first
165
+ offenses = offenses_to_check.select { |offense| offense.cop_name.start_with?(department) }
166
+ add_department_marker(department) if range_with_offense?(range, offenses)
167
+ end
168
+
169
+ def followed_ranges?(range, next_range)
170
+ range.end == next_range.begin
171
+ end
172
+
173
+ def range_with_offense?(range, offenses = offenses_to_check)
174
+ offenses.none? { |offense| range.cover?(offense.line) }
153
175
  end
154
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
155
176
 
156
177
  def all_disabled?(comment)
157
- /rubocop\s*:\s*(?:disable|todo)\s+all\b/.match?(comment.text)
178
+ DirectiveComment.new(comment).disabled_all?
158
179
  end
159
180
 
160
- def ignore_offense?(disabled_ranges, line_range)
181
+ def ignore_offense?(line_range)
161
182
  disabled_ranges.any? do |range|
162
183
  range.cover?(line_range.min) && range.cover?(line_range.max)
163
184
  end
164
185
  end
165
186
 
187
+ def department_disabled?(cop, comment)
188
+ directive = DirectiveComment.new(comment)
189
+ directive.in_directive_department?(cop) && !directive.overridden_by_department?(cop)
190
+ end
191
+
166
192
  def directive_count(comment)
167
- _, cops_string = DirectiveComment.new(comment).match_captures
168
- cops_string.split(/,\s*/).size
193
+ DirectiveComment.new(comment).directive_count
169
194
  end
170
195
 
171
196
  def add_offenses(redundant_cops)
@@ -179,14 +204,11 @@ module RuboCop
179
204
  end
180
205
 
181
206
  def add_offense_for_entire_comment(comment, cops)
182
- location = comment.loc.expression
183
- cop_list = cops.sort.map { |c| describe(c) }
184
-
185
- add_offense(
186
- location,
187
- message: "Unnecessary disabling of #{cop_list.join(', ')}."
188
- ) do |corrector|
189
- range = comment_range_with_surrounding_space(location)
207
+ location = DirectiveComment.new(comment).range
208
+ cop_names = cops.sort.map { |c| describe(c) }.join(', ')
209
+
210
+ add_offense(location, message: message(cop_names)) do |corrector|
211
+ range = comment_range_with_surrounding_space(location, comment.loc.expression)
190
212
  corrector.remove(range)
191
213
  end
192
214
  end
@@ -197,10 +219,8 @@ module RuboCop
197
219
  ranges = cop_ranges.map { |_, r| r }
198
220
 
199
221
  cop_ranges.each do |cop, range|
200
- add_offense(
201
- range,
202
- message: "Unnecessary disabling of #{describe(cop)}."
203
- ) do |corrector|
222
+ cop_name = describe(cop)
223
+ add_offense(range, message: message(cop_name)) do |corrector|
204
224
  range = directive_range_in_list(range, ranges)
205
225
  corrector.remove(range)
206
226
  end
@@ -208,6 +228,7 @@ module RuboCop
208
228
  end
209
229
 
210
230
  def cop_range(comment, cop)
231
+ cop = remove_department_marker(cop)
211
232
  matching_range(comment.loc.expression, cop) ||
212
233
  matching_range(comment.loc.expression, Badge.parse(cop).cop_name) ||
213
234
  raise("Couldn't find #{cop} in comment: #{comment.text}")
@@ -230,18 +251,16 @@ module RuboCop
230
251
  end
231
252
 
232
253
  def describe(cop)
233
- if cop == 'all'
234
- 'all cops'
235
- elsif all_cop_names.include?(cop)
236
- "`#{cop}`"
237
- else
238
- similar = NameSimilarity.find_similar_name(cop, all_cop_names)
239
- if similar
240
- "`#{cop}` (did you mean `#{similar}`?)"
241
- else
242
- "`#{cop}` (unknown cop)"
243
- end
244
- end
254
+ return 'all cops' if cop == 'all'
255
+ return "`#{remove_department_marker(cop)}` department" if department_marker?(cop)
256
+ return "`#{cop}`" if all_cop_names.include?(cop)
257
+
258
+ similar = NameSimilarity.find_similar_name(cop, all_cop_names)
259
+ similar ? "`#{cop}` (did you mean `#{similar}`?)" : "`#{cop}` (unknown cop)"
260
+ end
261
+
262
+ def message(cop_names)
263
+ "Unnecessary disabling of #{cop_names}."
245
264
  end
246
265
 
247
266
  def all_cop_names
@@ -252,6 +271,18 @@ module RuboCop
252
271
  line = range.source_buffer.source_line(range.last_line)
253
272
  (line =~ /\s*\z/) == range.last_column
254
273
  end
274
+
275
+ def department_marker?(department)
276
+ department.start_with?(DEPARTMENT_MARKER)
277
+ end
278
+
279
+ def remove_department_marker(department)
280
+ department.gsub(DEPARTMENT_MARKER, '')
281
+ end
282
+
283
+ def add_department_marker(department)
284
+ DEPARTMENT_MARKER + department
285
+ end
255
286
  end
256
287
  end
257
288
  end