rubocop 1.16.1 → 1.17.0

Sign up to get free protection for your applications and to get access to all the features.
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: []