rubocop 1.16.1 → 1.17.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 336b4f09242c5130a3e66be9c17bb23a1d884d0e9d788799f3ff3291616367d7
4
- data.tar.gz: 2bbcb0fed39b66808dac5bf4c4df3f6bf4fbf606fcb6f0136acdaff5a1212d42
3
+ metadata.gz: f038acc03307acfc14ddf1dd971bf78978fac3401b4588b78b6bab4f4b7d8e13
4
+ data.tar.gz: 4f5da9053cce2f82b955f15d311d4b0d1f78396b2d49c8672c27d380804d5ba8
5
5
  SHA512:
6
- metadata.gz: 006de603e9c559a6c34fb1e25d7c7b255ca8231773e4e8f4c99a6f31a2914ba11069597e66806564bd761a493581f62e0028bd0e47d470fc28ff7822bd9e90d9
7
- data.tar.gz: e5fb0bf4851cd7273834f1b89e952406942379298b93ac130dcfc254e3fe427dfdae8adca3666ac45db9314645e74f3bb86aae9fe199f1bb0fe3e0e21047fcb6
6
+ metadata.gz: 6c4b743259b607ed588066f260b69cfdfd03772cd89f533eaf80705e689005a771ef76cf29873d73c0e5f97e3b7b4be6e6080a5890a63ebb19150d951ae272e1
7
+ data.tar.gz: 7505601eb0e34cc563cb8b7efdec9b6340e709f6a29eec7a7b952f84386df60fe8912b8ebd0849d9ba59e22e7701b980276f8bd728330985d5fa9bdf99c2d9ad
data/README.md CHANGED
@@ -54,7 +54,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
54
54
  in your `Gemfile`:
55
55
 
56
56
  ```rb
57
- gem 'rubocop', '~> 1.16', require: false
57
+ gem 'rubocop', '~> 1.17', require: false
58
58
  ```
59
59
 
60
60
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
@@ -24,6 +24,7 @@ module RuboCop
24
24
  # method
25
25
  class DotPosition < Base
26
26
  include ConfigurableEnforcedStyle
27
+ include RangeHelp
27
28
  extend AutoCorrector
28
29
 
29
30
  def on_send(node)
@@ -42,7 +43,12 @@ module RuboCop
42
43
  private
43
44
 
44
45
  def autocorrect(corrector, dot, node)
45
- corrector.remove(dot)
46
+ dot_range = if processed_source[dot.line - 1].strip == '.'
47
+ range_by_whole_lines(dot, include_final_newline: true)
48
+ else
49
+ dot
50
+ end
51
+ corrector.remove(dot_range)
46
52
  case style
47
53
  when :leading
48
54
  corrector.insert_before(selector_range(node), dot.source)
@@ -45,8 +45,7 @@ module RuboCop
45
45
  def on_if(node)
46
46
  return if correct_style?(node)
47
47
 
48
- if node.modifier_form? && last_argument_is_heredoc?(node)
49
- heredoc_node = last_heredoc_argument(node)
48
+ if node.modifier_form? && (heredoc_node = last_heredoc_argument(node))
50
49
  return if next_line_empty_or_enable_directive_comment?(heredoc_line(node, heredoc_node))
51
50
 
52
51
  add_offense(heredoc_node.loc.heredoc_end) do |corrector|
@@ -62,7 +61,7 @@ module RuboCop
62
61
  private
63
62
 
64
63
  def autocorrect(corrector, node)
65
- node_range = if node.respond_to?(:heredoc?) && node.heredoc?
64
+ node_range = if heredoc?(node)
66
65
  range_by_whole_lines(node.loc.heredoc_body)
67
66
  else
68
67
  range_by_whole_lines(node.source_range)
@@ -125,19 +124,8 @@ module RuboCop
125
124
  next_sibling.if_type? && contains_guard_clause?(next_sibling)
126
125
  end
127
126
 
128
- def last_argument_is_heredoc?(node)
129
- last_children = node.if_branch
130
- return false unless last_children&.send_type?
131
-
132
- heredoc?(last_heredoc_argument(node))
133
- end
134
-
135
127
  def last_heredoc_argument(node)
136
- n = if node.respond_to?(:if_branch)
137
- node.if_branch.children.last
138
- else
139
- node
140
- end
128
+ n = last_heredoc_argument_node(node)
141
129
 
142
130
  return n if heredoc?(n)
143
131
  return unless n.respond_to?(:arguments)
@@ -150,6 +138,16 @@ module RuboCop
150
138
  return last_heredoc_argument(n.receiver) if n.respond_to?(:receiver)
151
139
  end
152
140
 
141
+ def last_heredoc_argument_node(node)
142
+ return node unless node.respond_to?(:if_branch)
143
+
144
+ if node.if_branch.and_type?
145
+ node.if_branch.children.first
146
+ else
147
+ node.if_branch.children.last
148
+ end
149
+ end
150
+
153
151
  def heredoc_line(node, heredoc_node)
154
152
  heredoc_body = heredoc_node.loc.heredoc_body
155
153
  num_of_heredoc_lines = heredoc_body.last_line - heredoc_body.first_line
@@ -218,6 +218,7 @@ module RuboCop
218
218
 
219
219
  def autocorrect_incompatible_with_other_cops?(node)
220
220
  enforce_first_argument_with_fixed_indentation? &&
221
+ node.pairs.any? &&
221
222
  node.parent&.call_type? && node.parent.loc.line == node.pairs.first.loc.line
222
223
  end
223
224
 
@@ -138,6 +138,14 @@ module RuboCop
138
138
  check_indentation(case_node.when_branches.last.loc.keyword, case_node.else_branch)
139
139
  end
140
140
 
141
+ def on_case_match(case_match)
142
+ case_match.each_in_pattern do |in_pattern_node|
143
+ check_indentation(in_pattern_node.loc.keyword, in_pattern_node.body)
144
+ end
145
+
146
+ check_indentation(case_match.in_pattern_branches.last.loc.keyword, case_match.else_branch)
147
+ end
148
+
141
149
  def on_if(node, base = node)
142
150
  return if ignored_node?(node)
143
151
  return if node.ternary? || node.modifier_form?
@@ -42,8 +42,9 @@ module RuboCop
42
42
  # # good
43
43
  # foo(a) { |x| puts x }
44
44
  #
45
- class RedundantLineBreak < Cop
45
+ class RedundantLineBreak < Base
46
46
  include CheckAssignment
47
+ extend AutoCorrector
47
48
 
48
49
  MSG = 'Redundant line break detected.'
49
50
 
@@ -55,23 +56,24 @@ module RuboCop
55
56
 
56
57
  return unless offense?(node) && !part_of_ignored_node?(node)
57
58
 
58
- add_offense(node)
59
- ignore_node(node)
59
+ register_offense(node)
60
60
  end
61
61
 
62
+ private
63
+
62
64
  def check_assignment(node, _rhs)
63
65
  return unless offense?(node)
64
66
 
65
- add_offense(node)
66
- ignore_node(node)
67
+ register_offense(node)
67
68
  end
68
69
 
69
- def autocorrect(node)
70
- ->(corrector) { corrector.replace(node.source_range, to_single_line(node.source).strip) }
70
+ def register_offense(node)
71
+ add_offense(node) do |corrector|
72
+ corrector.replace(node.source_range, to_single_line(node.source).strip)
73
+ end
74
+ ignore_node(node)
71
75
  end
72
76
 
73
- private
74
-
75
77
  def offense?(node)
76
78
  return false if configured_to_not_be_inspected?(node)
77
79
 
@@ -81,6 +81,18 @@ module RuboCop
81
81
  check(node, %i[begin end].freeze, nil)
82
82
  end
83
83
 
84
+ # Handle one-line pattern matching syntax (`in`) with `Parser::Ruby27`.
85
+ def on_match_pattern(node)
86
+ return if target_ruby_version >= 3.0
87
+
88
+ check(node, [:operator].freeze)
89
+ end
90
+
91
+ # Handle one-line pattern matching syntax (`in`) with `Parser::Ruby30`.
92
+ def on_match_pattern_p(node)
93
+ check(node, [:operator].freeze)
94
+ end
95
+
84
96
  def on_next(node)
85
97
  check(node, [:keyword].freeze)
86
98
  end
@@ -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
@@ -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
@@ -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,6 +54,14 @@ 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
@@ -97,32 +103,34 @@ module RuboCop
97
103
  range_with_surrounding_space(range: range, side: :right, newlines: false)
98
104
  end
99
105
 
100
- def each_redundant_disable(cop_disabled_line_ranges, offenses,
101
- &block)
102
- disabled_ranges = cop_disabled_line_ranges[COP_NAME] || [0..0]
103
-
106
+ def each_redundant_disable(&block)
104
107
  cop_disabled_line_ranges.each do |cop, line_ranges|
105
- each_already_disabled(line_ranges, disabled_ranges) { |comment| yield comment, cop }
106
-
107
- 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)
108
110
  end
109
111
  end
110
112
 
111
- def each_line_range(line_ranges, disabled_ranges, offenses,
112
- cop)
113
- line_ranges.each_with_index do |line_range, ix|
114
- comment = processed_source.comment_at_line(line_range.begin)
115
- 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)
116
116
 
117
- redundant_cop = find_redundant(comment, offenses, cop, line_range, line_ranges[ix + 1])
118
- 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
119
127
  end
120
128
  end
121
129
 
122
- def each_already_disabled(line_ranges, disabled_ranges)
130
+ def each_already_disabled(cop, line_ranges)
123
131
  line_ranges.each_cons(2) do |previous_range, range|
124
- next if ignore_offense?(disabled_ranges, range)
125
- next if previous_range.end != range.begin
132
+ next if ignore_offense?(range)
133
+ next unless followed_ranges?(previous_range, range)
126
134
 
127
135
  # If a cop is disabled in a range that begins on the same line as
128
136
  # the end of the previous range, it means that the cop was
@@ -133,42 +141,56 @@ module RuboCop
133
141
  # Comments disabling all cops don't count since it's reasonable
134
142
  # to disable a few select cops first and then all cops further
135
143
  # down in the code.
136
- yield comment if comment && !all_disabled?(comment)
144
+ yield comment, cop if comment && !all_disabled?(comment)
137
145
  end
138
146
  end
139
147
 
140
- # rubocop:todo Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
141
- def find_redundant(comment, offenses, cop, line_range, next_line_range)
142
- if all_disabled?(comment)
143
- # If there's a disable all comment followed by a comment
144
- # specifically disabling `cop`, we don't report the `all`
145
- # comment. If the disable all comment is truly redundant, we will
146
- # detect that when examining the comments of another cop, and we
147
- # get the full line range for the disable all.
148
- if (next_line_range.nil? || line_range.last != next_line_range.first) &&
149
- offenses.none? { |o| line_range.cover?(o.line) }
150
- 'all'
151
- end
152
- else
153
- cop_offenses = offenses.select { |o| o.cop_name == cop }
154
- cop if cop_offenses.none? { |o| line_range.cover?(o.line) }
155
- 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) }
156
175
  end
157
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
158
176
 
159
177
  def all_disabled?(comment)
160
- /rubocop\s*:\s*(?:disable|todo)\s+all\b/.match?(comment.text)
178
+ DirectiveComment.new(comment).disabled_all?
161
179
  end
162
180
 
163
- def ignore_offense?(disabled_ranges, line_range)
181
+ def ignore_offense?(line_range)
164
182
  disabled_ranges.any? do |range|
165
183
  range.cover?(line_range.min) && range.cover?(line_range.max)
166
184
  end
167
185
  end
168
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
+
169
192
  def directive_count(comment)
170
- _, cops_string = DirectiveComment.new(comment).match_captures
171
- cops_string.split(/,\s*/).size
193
+ DirectiveComment.new(comment).directive_count
172
194
  end
173
195
 
174
196
  def add_offenses(redundant_cops)
@@ -183,12 +205,9 @@ module RuboCop
183
205
 
184
206
  def add_offense_for_entire_comment(comment, cops)
185
207
  location = DirectiveComment.new(comment).range
186
- cop_list = cops.sort.map { |c| describe(c) }
208
+ cop_names = cops.sort.map { |c| describe(c) }.join(', ')
187
209
 
188
- add_offense(
189
- location,
190
- message: "Unnecessary disabling of #{cop_list.join(', ')}."
191
- ) do |corrector|
210
+ add_offense(location, message: message(cop_names)) do |corrector|
192
211
  range = comment_range_with_surrounding_space(location, comment.loc.expression)
193
212
  corrector.remove(range)
194
213
  end
@@ -200,10 +219,8 @@ module RuboCop
200
219
  ranges = cop_ranges.map { |_, r| r }
201
220
 
202
221
  cop_ranges.each do |cop, range|
203
- add_offense(
204
- range,
205
- message: "Unnecessary disabling of #{describe(cop)}."
206
- ) do |corrector|
222
+ cop_name = describe(cop)
223
+ add_offense(range, message: message(cop_name)) do |corrector|
207
224
  range = directive_range_in_list(range, ranges)
208
225
  corrector.remove(range)
209
226
  end
@@ -211,6 +228,7 @@ module RuboCop
211
228
  end
212
229
 
213
230
  def cop_range(comment, cop)
231
+ cop = remove_department_marker(cop)
214
232
  matching_range(comment.loc.expression, cop) ||
215
233
  matching_range(comment.loc.expression, Badge.parse(cop).cop_name) ||
216
234
  raise("Couldn't find #{cop} in comment: #{comment.text}")
@@ -233,18 +251,16 @@ module RuboCop
233
251
  end
234
252
 
235
253
  def describe(cop)
236
- if cop == 'all'
237
- 'all cops'
238
- elsif all_cop_names.include?(cop)
239
- "`#{cop}`"
240
- else
241
- similar = NameSimilarity.find_similar_name(cop, all_cop_names)
242
- if similar
243
- "`#{cop}` (did you mean `#{similar}`?)"
244
- else
245
- "`#{cop}` (unknown cop)"
246
- end
247
- 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}."
248
264
  end
249
265
 
250
266
  def all_cop_names
@@ -255,6 +271,18 @@ module RuboCop
255
271
  line = range.source_buffer.source_line(range.last_line)
256
272
  (line =~ /\s*\z/) == range.last_column
257
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
258
286
  end
259
287
  end
260
288
  end
@@ -54,6 +54,7 @@ module RuboCop
54
54
  directive = DirectiveComment.new(comment)
55
55
 
56
56
  cop_names.each do |name|
57
+ name = name.split('/').first if department?(directive, name)
57
58
  add_offense(
58
59
  range_of_offense(comment, name),
59
60
  message: format(MSG, cop: all_or_name(name))
@@ -119,6 +120,10 @@ module RuboCop
119
120
  def all_or_name(name)
120
121
  name == 'all' ? 'all cops' : name
121
122
  end
123
+
124
+ def department?(directive, name)
125
+ directive.in_directive_department?(name) && !directive.overridden_by_department?(name)
126
+ end
122
127
  end
123
128
  end
124
129
  end
@@ -61,7 +61,9 @@ module RuboCop
61
61
  end
62
62
 
63
63
  def valid_content_token?(content_token)
64
- /\W+/.match?(content_token) || DISABLING_COPS_CONTENT_TOKEN.match?(content_token)
64
+ /\W+/.match?(content_token) ||
65
+ DISABLING_COPS_CONTENT_TOKEN.match?(content_token) ||
66
+ Registry.global.department?(content_token)
65
67
  end
66
68
 
67
69
  def contain_unexpected_character_for_department_name?(name)
@@ -67,6 +67,28 @@ module RuboCop
67
67
  # do_x
68
68
  # do_z
69
69
  # end
70
+ #
71
+ # # bad
72
+ # case foo
73
+ # in 1
74
+ # do_x
75
+ # in 2
76
+ # do_x
77
+ # else
78
+ # do_x
79
+ # end
80
+ #
81
+ # # good
82
+ # case foo
83
+ # in 1
84
+ # do_x
85
+ # do_y
86
+ # in 2
87
+ # # nothing
88
+ # else
89
+ # do_x
90
+ # do_z
91
+ # end
70
92
  class IdenticalConditionalBranches < Base
71
93
  include RangeHelp
72
94
  extend AutoCorrector
@@ -87,6 +109,13 @@ module RuboCop
87
109
  check_branches(node, branches)
88
110
  end
89
111
 
112
+ def on_case_match(node)
113
+ return unless node.else? && node.else_branch
114
+
115
+ branches = node.in_pattern_branches.map(&:body).push(node.else_branch)
116
+ check_branches(node, branches)
117
+ end
118
+
90
119
  private
91
120
 
92
121
  def check_branches(node, branches)
@@ -23,6 +23,7 @@ module RuboCop
23
23
  # # good
24
24
  # raise StandardError, 'message'
25
25
  # fail 'message'
26
+ # raise MyCustomError
26
27
  # raise MyCustomError.new(arg1, arg2, arg3)
27
28
  # raise MyKwArgError.new(key1: val1, key2: val2)
28
29
  #
@@ -37,6 +38,7 @@ module RuboCop
37
38
  #
38
39
  # # good
39
40
  # raise StandardError.new('message')
41
+ # raise MyCustomError
40
42
  # raise MyCustomError.new(arg1, arg2, arg3)
41
43
  # fail 'message'
42
44
  class RaiseArgs < Base
@@ -117,7 +117,7 @@ module RuboCop
117
117
  def allowed_percent_r_literal?(node)
118
118
  style == :slashes && contains_disallowed_slash?(node) ||
119
119
  style == :percent_r ||
120
- allowed_mixed_percent_r?(node)
120
+ allowed_mixed_percent_r?(node) || omit_parentheses_style?(node)
121
121
  end
122
122
 
123
123
  def allowed_mixed_percent_r?(node)
@@ -149,6 +149,14 @@ module RuboCop
149
149
  config.for_cop('Style/PercentLiteralDelimiters') ['PreferredDelimiters']['%r'].chars
150
150
  end
151
151
 
152
+ def omit_parentheses_style?(node)
153
+ return false unless node.parent&.call_type?
154
+
155
+ enforced_style = config.for_cop('Style/MethodCallWithArgsParentheses')['EnforcedStyle']
156
+
157
+ enforced_style == 'omit_parentheses'
158
+ end
159
+
152
160
  def correct_delimiters(node, corrector)
153
161
  replacement = calculate_replacement(node)
154
162
  corrector.replace(node.loc.begin, replacement.first)
@@ -6,7 +6,9 @@ module RuboCop
6
6
  # cops it contains.
7
7
  class DirectiveComment
8
8
  # @api private
9
- REDUNDANT_COP = 'Lint/RedundantCopDisableDirective'
9
+ REDUNDANT_DIRECTIVE_COP_DEPARTMENT = 'Lint'
10
+ # @api private
11
+ REDUNDANT_DIRECTIVE_COP = "#{REDUNDANT_DIRECTIVE_COP_DEPARTMENT}/RedundantCopDisableDirective"
10
12
  # @api private
11
13
  COP_NAME_PATTERN = '([A-Z]\w+/)*(?:[A-Z]\w+)'
12
14
  # @api private
@@ -23,10 +25,11 @@ module RuboCop
23
25
  line.split(DIRECTIVE_COMMENT_REGEXP).first
24
26
  end
25
27
 
26
- attr_reader :comment, :mode, :cops
28
+ attr_reader :comment, :cop_registry, :mode, :cops
27
29
 
28
- def initialize(comment)
30
+ def initialize(comment, cop_registry = Cop::Registry.global)
29
31
  @comment = comment
32
+ @cop_registry = cop_registry
30
33
  @mode, @cops = match_captures
31
34
  end
32
35
 
@@ -68,6 +71,11 @@ module RuboCop
68
71
  !disabled? && all_cops?
69
72
  end
70
73
 
74
+ # Checks if this directive disables all cops
75
+ def disabled_all?
76
+ disabled? && all_cops?
77
+ end
78
+
71
79
  # Checks if all cops specified in this directive
72
80
  def all_cops?
73
81
  cops == 'all'
@@ -78,6 +86,26 @@ module RuboCop
78
86
  @cop_names ||= all_cops? ? all_cop_names : parsed_cop_names
79
87
  end
80
88
 
89
+ # Returns array of specified in this directive department names
90
+ # when all department disabled
91
+ def department_names
92
+ splitted_cops_string.select { |cop| department?(cop) }
93
+ end
94
+
95
+ # Checks if directive departments include cop
96
+ def in_directive_department?(cop)
97
+ department_names.any? { |department| cop.start_with?(department) }
98
+ end
99
+
100
+ # Checks if cop department has already used in directive comment
101
+ def overridden_by_department?(cop)
102
+ in_directive_department?(cop) && splitted_cops_string.include?(cop)
103
+ end
104
+
105
+ def directive_count
106
+ splitted_cops_string.count
107
+ end
108
+
81
109
  # Returns line number for directive
82
110
  def line_number
83
111
  comment.loc.expression.line
@@ -85,12 +113,32 @@ module RuboCop
85
113
 
86
114
  private
87
115
 
88
- def parsed_cop_names
116
+ def splitted_cops_string
89
117
  (cops || '').split(/,\s*/)
90
118
  end
91
119
 
120
+ def parsed_cop_names
121
+ splitted_cops_string.map do |name|
122
+ department?(name) ? cop_names_for_department(name) : name
123
+ end.flatten
124
+ end
125
+
126
+ def department?(name)
127
+ cop_registry.department?(name)
128
+ end
129
+
92
130
  def all_cop_names
93
- Cop::Registry.global.names - [REDUNDANT_COP]
131
+ exclude_redundant_directive_cop(cop_registry.names)
132
+ end
133
+
134
+ def cop_names_for_department(department)
135
+ names = cop_registry.names_for_department(department)
136
+ has_redundant_directive_cop = department == REDUNDANT_DIRECTIVE_COP_DEPARTMENT
137
+ has_redundant_directive_cop ? exclude_redundant_directive_cop(names) : names
138
+ end
139
+
140
+ def exclude_redundant_directive_cop(cops)
141
+ cops - [REDUNDANT_DIRECTIVE_COP]
94
142
  end
95
143
  end
96
144
  end
@@ -55,6 +55,7 @@ module RuboCop
55
55
  def generate_request(uri)
56
56
  request = Net::HTTP::Get.new(uri.request_uri)
57
57
 
58
+ request.basic_auth(uri.user, uri.password) if uri.user
58
59
  request['If-Modified-Since'] = File.stat(cache_path).mtime.rfc2822 if cache_path_exists?
59
60
 
60
61
  yield request
@@ -70,7 +71,7 @@ module RuboCop
70
71
  begin
71
72
  response.error!
72
73
  rescue StandardError => e
73
- message = "#{e.message} while downloading remote config file #{uri}"
74
+ message = "#{e.message} while downloading remote config file #{cloned_url}"
74
75
  raise e, message
75
76
  end
76
77
  end
@@ -94,9 +95,16 @@ module RuboCop
94
95
  end
95
96
 
96
97
  def cache_name_from_uri
97
- uri = @uri.clone
98
+ uri = cloned_url
98
99
  uri.query = nil
99
100
  uri.to_s.gsub!(/[^0-9A-Za-z]/, '-')
100
101
  end
102
+
103
+ def cloned_url
104
+ uri = @uri.clone
105
+ uri.user = nil if uri.user
106
+ uri.password = nil if uri.password
107
+ uri
108
+ end
101
109
  end
102
110
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.16.1'
6
+ STRING = '1.17.0'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, '\
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.16.1
4
+ version: 1.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
8
8
  - Jonas Arvidsson
9
9
  - Yuji Nakayama
10
- autorequire:
10
+ autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2021-06-09 00:00:00.000000000 Z
13
+ date: 2021-06-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: parallel
@@ -881,9 +881,9 @@ metadata:
881
881
  homepage_uri: https://rubocop.org/
882
882
  changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
883
883
  source_code_uri: https://github.com/rubocop/rubocop/
884
- documentation_uri: https://docs.rubocop.org/rubocop/1.16/
884
+ documentation_uri: https://docs.rubocop.org/rubocop/1.17/
885
885
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
886
- post_install_message:
886
+ post_install_message:
887
887
  rdoc_options: []
888
888
  require_paths:
889
889
  - lib
@@ -898,8 +898,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
898
898
  - !ruby/object:Gem::Version
899
899
  version: '0'
900
900
  requirements: []
901
- rubygems_version: 3.1.2
902
- signing_key:
901
+ rubygems_version: 3.2.18
902
+ signing_key:
903
903
  specification_version: 4
904
904
  summary: Automatic Ruby code style checking tool.
905
905
  test_files: []