rubocop 1.62.0 → 1.62.1

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: 71f9543fd4a2366245df52234cec7a2492a2e4df631fec99e466de8b82cde5d7
4
- data.tar.gz: 99bf7b324f099186e5918469d3fd5d954e91317cb572e96f48a253c4d4ace709
3
+ metadata.gz: 8daa4ef7dd74b8608039d7dfda5f1e3fe739738949390a6f1347acaccf7bd1c4
4
+ data.tar.gz: 271a978db956def596a5b06a7fd69d189d807b27db0acdda03fd6200b95ef541
5
5
  SHA512:
6
- metadata.gz: a0128453654e2f6c5b5000c70931edb3dcccc2d1eb54c08b4e1af6ea393f7192ad0aeaaf9c07a136138fee6be7702caa22cdd3e0f3a46a25a6508102ac0759a1
7
- data.tar.gz: 989aade51c2112e02b3d4e130b99d1096116fca3a8cc0d47e8c25de8eea419afb242969f9a48c7a8d04ab1b9a8563dc138b65e9b364d89758ebcdd3444147893
6
+ metadata.gz: 484294f43781f114ba01470b22331ef17648219e26dc4ba2f28073f609c909af2997c47e1f1aad62860124f6f4594a2e536cd793f05352a78d588f979732a290
7
+ data.tar.gz: 6a8313e61422bcd568eea747c0f9a88f61f50620b4dd4f478da0bdd3e067c1aa8bcf70e15744e02118d4c525eb0632fae3cc19caf73db6db1f63ea76dbb84b45
@@ -17,7 +17,10 @@ module RuboCop
17
17
 
18
18
  PHASE_1_OVERRIDDEN = '(skipped because the default Layout/LineLength:Max is overridden)'
19
19
  PHASE_1_DISABLED = '(skipped because Layout/LineLength is disabled)'
20
- PHASE_1_SKIPPED = '(skipped because a list of cops is passed to the `--only` flag)'
20
+ PHASE_1_SKIPPED_ONLY_COPS =
21
+ '(skipped because a list of cops is passed to the `--only` flag)'
22
+ PHASE_1_SKIPPED_ONLY_EXCLUDE =
23
+ '(skipped because only excludes will be generated due to `--auto-gen-only-exclude` flag)'
21
24
 
22
25
  def run
23
26
  add_formatter
@@ -29,12 +32,14 @@ module RuboCop
29
32
  private
30
33
 
31
34
  def maybe_run_line_length_cop
32
- if !line_length_enabled?(@config_store.for_pwd)
35
+ if only_exclude?
36
+ skip_line_length_cop(PHASE_1_SKIPPED_ONLY_EXCLUDE)
37
+ elsif !line_length_enabled?(@config_store.for_pwd)
33
38
  skip_line_length_cop(PHASE_1_DISABLED)
34
39
  elsif !same_max_line_length?(@config_store.for_pwd, ConfigLoader.default_configuration)
35
40
  skip_line_length_cop(PHASE_1_OVERRIDDEN)
36
41
  elsif options_has_only_flag?
37
- skip_line_length_cop(PHASE_1_SKIPPED)
42
+ skip_line_length_cop(PHASE_1_SKIPPED_ONLY_COPS)
38
43
  else
39
44
  run_line_length_cop
40
45
  end
@@ -65,6 +70,10 @@ module RuboCop
65
70
  @options[:only]
66
71
  end
67
72
 
73
+ def only_exclude?
74
+ @options[:auto_gen_only_exclude]
75
+ end
76
+
68
77
  # Do an initial run with only Layout/LineLength so that cops that
69
78
  # depend on Layout/LineLength:Max get the correct value for that
70
79
  # parameter.
@@ -76,7 +76,9 @@ module RuboCop
76
76
  PATTERN
77
77
 
78
78
  def on_new_investigation
79
- add_global_offense(MISSING_MSG) unless required_ruby_version?(processed_source.ast)
79
+ return if processed_source.ast && required_ruby_version?(processed_source.ast)
80
+
81
+ add_global_offense(MISSING_MSG)
80
82
  end
81
83
 
82
84
  def on_send(node)
@@ -26,10 +26,18 @@ module RuboCop
26
26
  MSG = 'Precede `%<method>s` with a `@!method` YARD directive.'
27
27
  MSG_WRONG_NAME = '`@!method` YARD directive has invalid method name, ' \
28
28
  'use `%<expected>s` instead of `%<actual>s`.'
29
+ MSG_MISSING_SCOPE_SELF = 'Follow the `@!method` YARD directive with ' \
30
+ '`@!scope class` if it is a class method.'
31
+ MSG_WRONG_SCOPE_SELF = 'Do not use the `@!scope class` YARD directive if it ' \
32
+ 'is not a class method.'
29
33
  MSG_TOO_MANY = 'Multiple `@!method` YARD directives found for this matcher.'
30
34
 
31
35
  RESTRICT_ON_SEND = %i[def_node_matcher def_node_search].to_set.freeze
32
- REGEXP = /^\s*#\s*@!method\s+(?<method_name>[a-z0-9_]+[?!]?)(?:\((?<args>.*)\))?/.freeze
36
+ REGEXP_METHOD = /
37
+ ^\s*\#\s*
38
+ @!method\s+(?<receiver>self\.)?(?<method_name>[a-z0-9_]+[?!]?)(?:\((?<args>.*)\))?
39
+ /x.freeze
40
+ REGEXP_SCOPE = /^\s*\#\s*@!scope class/.freeze
33
41
 
34
42
  # @!method pattern_matcher?(node)
35
43
  def_node_matcher :pattern_matcher?, <<~PATTERN
@@ -40,14 +48,15 @@ module RuboCop
40
48
  return if node.arguments.none?
41
49
  return unless valid_method_name?(node)
42
50
 
43
- actual_name = node.first_argument.value
51
+ actual_name = node.first_argument.value.to_s
52
+
53
+ # Ignore cases where the method has a receiver that isn't self
54
+ return if actual_name.include?('.') && !actual_name.start_with?('self.')
55
+
44
56
  directives = method_directives(node)
45
57
  return too_many_directives(node) if directives.size > 1
46
58
 
47
- directive = directives.first
48
- return if directive_correct?(directive, actual_name)
49
-
50
- register_offense(node, directive, actual_name)
59
+ process_directive(node, actual_name, directives.first)
51
60
  end
52
61
 
53
62
  private
@@ -58,44 +67,112 @@ module RuboCop
58
67
 
59
68
  def method_directives(node)
60
69
  comments = processed_source.ast_with_comments[node]
61
-
62
- comments.filter_map do |comment|
63
- match = comment.text.match(REGEXP)
70
+ group_comments(comments).filter_map do |comment_method, comment_scope|
71
+ match = comment_method.text.match(REGEXP_METHOD)
64
72
  next unless match
65
73
 
66
- { node: comment, method_name: match[:method_name], args: match[:args] }
74
+ {
75
+ node_method: comment_method,
76
+ node_scope: comment_scope,
77
+ method_name: match[:method_name],
78
+ args: match[:args],
79
+ receiver: match[:receiver],
80
+ has_scope_directive: comment_scope&.text&.match?(REGEXP_SCOPE)
81
+ }
82
+ end
83
+ end
84
+
85
+ def group_comments(comments)
86
+ result = []
87
+ comments.each.with_index do |comment, index|
88
+ # Grab the scope directive if it is preceded by a method directive
89
+ if comment.text.include?('@!method')
90
+ result << if (next_comment = comments[index + 1])&.text&.include?('@!scope')
91
+ [comment, next_comment]
92
+ else
93
+ [comment, nil]
94
+ end
95
+ end
67
96
  end
97
+ result
68
98
  end
69
99
 
70
100
  def too_many_directives(node)
71
101
  add_offense(node, message: MSG_TOO_MANY)
72
102
  end
73
103
 
74
- def directive_correct?(directive, actual_name)
75
- directive && directive[:method_name] == actual_name.to_s
104
+ def process_directive(node, actual_name, directive)
105
+ return unless (offense_type = directive_offense_type(directive, actual_name))
106
+
107
+ register_offense(offense_type, node, directive, actual_name)
108
+ end
109
+
110
+ def directive_offense_type(directive, actual_name)
111
+ return :missing_directive unless directive
112
+
113
+ return :wrong_scope if wrong_scope(directive, actual_name)
114
+ return :no_scope if no_scope(directive, actual_name)
115
+
116
+ # The method directive being prefixed by 'self.' is always an offense.
117
+ # The matched method_name does not contain the receiver but the
118
+ # def_node_match method name may so it must be removed.
119
+ if directive[:method_name] != remove_receiver(actual_name) || directive[:receiver]
120
+ :wrong_name
121
+ end
122
+ end
123
+
124
+ def wrong_scope(directive, actual_name)
125
+ !actual_name.start_with?('self.') && directive[:has_scope_directive]
126
+ end
127
+
128
+ def no_scope(directive, actual_name)
129
+ actual_name.start_with?('self.') && !directive[:has_scope_directive]
76
130
  end
77
131
 
78
- def register_offense(node, directive, actual_name)
79
- message = formatted_message(directive, actual_name, node.method_name)
132
+ def register_offense(offense_type, node, directive, actual_name)
133
+ message = formatted_message(offense_type, directive, actual_name, node.method_name)
80
134
 
81
135
  add_offense(node, message: message) do |corrector|
82
- if directive
83
- correct_directive(corrector, directive, actual_name)
84
- else
85
- insert_directive(corrector, node, actual_name)
136
+ case offense_type
137
+ when :wrong_name
138
+ correct_method_directive(corrector, directive, actual_name)
139
+ when :wrong_scope
140
+ remove_scope_directive(corrector, directive)
141
+ when :no_scope
142
+ insert_scope_directive(corrector, directive[:node_method])
143
+ when :missing_directive
144
+ insert_method_directive(corrector, node, actual_name)
86
145
  end
87
146
  end
88
147
  end
89
148
 
90
- def formatted_message(directive, actual_name, method_name)
91
- if directive
92
- format(MSG_WRONG_NAME, expected: actual_name, actual: directive[:method_name])
93
- else
149
+ # rubocop:disable Metrics/MethodLength
150
+ def formatted_message(offense_type, directive, actual_name, method_name)
151
+ case offense_type
152
+ when :wrong_name
153
+ # Add the receiver to the name when showing an offense
154
+ current_name = if directive[:receiver]
155
+ directive[:receiver] + directive[:method_name]
156
+ else
157
+ directive[:method_name]
158
+ end
159
+ # The correct name will never include a receiver, remove it
160
+ format(MSG_WRONG_NAME, expected: remove_receiver(actual_name), actual: current_name)
161
+ when :wrong_scope
162
+ MSG_WRONG_SCOPE_SELF
163
+ when :no_scope
164
+ MSG_MISSING_SCOPE_SELF
165
+ when :missing_directive
94
166
  format(MSG, method: method_name)
95
167
  end
96
168
  end
169
+ # rubocop:enable Metrics/MethodLength
170
+
171
+ def remove_receiver(current)
172
+ current.delete_prefix('self.')
173
+ end
97
174
 
98
- def insert_directive(corrector, node, actual_name)
175
+ def insert_method_directive(corrector, node, actual_name)
99
176
  # If the pattern matcher uses arguments (`%1`, `%2`, etc.), include them in the directive
100
177
  arguments = pattern_arguments(node.arguments[1].source)
101
178
 
@@ -107,6 +184,14 @@ module RuboCop
107
184
  corrector.insert_before(range, directive)
108
185
  end
109
186
 
187
+ def insert_scope_directive(corrector, node)
188
+ range = range_with_surrounding_space(node.source_range, side: :left, newlines: false)
189
+ indentation = range.source.match(/^\s*/)[0]
190
+ directive = "\n#{indentation}# @!scope class"
191
+
192
+ corrector.insert_after(node, directive)
193
+ end
194
+
110
195
  def pattern_arguments(pattern)
111
196
  arguments = %w[node]
112
197
  max_pattern_var = pattern.scan(/(?<=%)\d+/).map(&:to_i).max
@@ -134,12 +219,21 @@ module RuboCop
134
219
  end
135
220
  end
136
221
 
137
- def correct_directive(corrector, directive, actual_name)
138
- correct = "@!method #{actual_name}"
139
- regexp = /@!method\s+#{Regexp.escape(directive[:method_name])}/
222
+ def correct_method_directive(corrector, directive, actual_name)
223
+ correct = "@!method #{remove_receiver(actual_name)}"
224
+ current_name = (directive[:receiver] || '') + directive[:method_name]
225
+ regexp = /@!method\s+#{Regexp.escape(current_name)}/
226
+
227
+ replacement = directive[:node_method].text.gsub(regexp, correct)
228
+ corrector.replace(directive[:node_method], replacement)
229
+ end
140
230
 
141
- replacement = directive[:node].text.gsub(regexp, correct)
142
- corrector.replace(directive[:node], replacement)
231
+ def remove_scope_directive(corrector, directive)
232
+ range = range_by_whole_lines(
233
+ directive[:node_scope].source_range,
234
+ include_final_newline: true
235
+ )
236
+ corrector.remove(range)
143
237
  end
144
238
  end
145
239
  end
@@ -27,9 +27,9 @@ module RuboCop
27
27
  MSG = 'Add an empty line after magic comments.'
28
28
 
29
29
  def on_new_investigation
30
- return unless processed_source.ast &&
31
- (last_magic_comment = last_magic_comment(processed_source))
32
- return if processed_source[last_magic_comment.loc.line].strip.empty?
30
+ return unless (last_magic_comment = last_magic_comment(processed_source))
31
+ return unless (next_line = processed_source[last_magic_comment.loc.line])
32
+ return if next_line.strip.empty?
33
33
 
34
34
  offending_range = offending_range(last_magic_comment)
35
35
 
@@ -46,18 +46,25 @@ module RuboCop
46
46
 
47
47
  # Find the last magic comment in the source file.
48
48
  #
49
- # Take all comments that precede the first line of code, select the
49
+ # Take all comments that precede the first line of code (or just take
50
+ # them all in the case when there is no code), select the
50
51
  # magic comments, and return the last magic comment in the file.
51
52
  #
52
53
  # @return [Parser::Source::Comment] if magic comments exist before code
53
54
  # @return [nil] otherwise
54
55
  def last_magic_comment(source)
55
- source
56
- .comments
57
- .take_while { |comment| comment.loc.line < source.ast.loc.line }
56
+ comments_before_code(source)
58
57
  .reverse
59
58
  .find { |comment| MagicComment.parse(comment.text).any? }
60
59
  end
60
+
61
+ def comments_before_code(source)
62
+ if source.ast
63
+ source.comments.take_while { |comment| comment.loc.line < source.ast.loc.line }
64
+ else
65
+ source.comments
66
+ end
67
+ end
61
68
  end
62
69
  end
63
70
  end
@@ -84,8 +84,14 @@ module RuboCop
84
84
  end
85
85
 
86
86
  def offense?(node)
87
- node.multiline? && !too_long?(node) && suitable_as_single_line?(node) &&
88
- !index_access_call_chained?(node) && !configured_to_not_be_inspected?(node)
87
+ return false if !node.multiline? || too_long?(node) || !suitable_as_single_line?(node)
88
+ return require_backslash?(node) if node.and_type? || node.or_type?
89
+
90
+ !index_access_call_chained?(node) && !configured_to_not_be_inspected?(node)
91
+ end
92
+
93
+ def require_backslash?(node)
94
+ processed_source.lines[node.loc.operator.line - 1].end_with?('\\')
89
95
  end
90
96
 
91
97
  def index_access_call_chained?(node)
@@ -34,6 +34,7 @@ module RuboCop
34
34
  MSG_WITH_INDEX = 'Remove redundant `with_index`.'
35
35
 
36
36
  def on_block(node)
37
+ return unless node.receiver
37
38
  return unless (send = redundant_with_index?(node))
38
39
 
39
40
  range = with_index_range(send)
@@ -64,7 +64,7 @@ module RuboCop
64
64
  remove_node(corrector, node)
65
65
  elsif !proc_name.empty?
66
66
  autocorrect_block_pass(corrector, node, proc_name)
67
- else
67
+ elsif node.block_type?
68
68
  autocorrect_block(corrector, node)
69
69
  end
70
70
  end
@@ -189,7 +189,7 @@ module RuboCop
189
189
  case node.type
190
190
  when :casgn then _scope, _lhs, rhs = *node
191
191
  when :op_asgn then _lhs, _op, rhs = *node
192
- when :send then rhs = node.last_argument
192
+ when :send, :csend then rhs = node.last_argument
193
193
  else _lhs, rhs = *node
194
194
  end
195
195
  rhs
@@ -54,9 +54,9 @@ module RuboCop
54
54
  end
55
55
 
56
56
  def on_send(node)
57
- add_offense(
58
- node.first_argument, message: format(MSG, class_var: node.first_argument.source)
59
- )
57
+ return unless (first_argument = node.first_argument)
58
+
59
+ add_offense(first_argument, message: format(MSG, class_var: first_argument.source))
60
60
  end
61
61
  end
62
62
  end
@@ -66,6 +66,8 @@ module RuboCop
66
66
  return unless suspect_enumerable?(node)
67
67
 
68
68
  if style == :for
69
+ return unless node.receiver
70
+
69
71
  add_offense(node, message: PREFER_FOR) do |corrector|
70
72
  EachToForCorrector.new(node).call(corrector)
71
73
  opposite_style_detected
@@ -40,7 +40,7 @@ module RuboCop
40
40
 
41
41
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
42
42
  UNUSED_BLOCK_ARG_MSG = "#{MSG.chop} and remove the unused `%<unused_code>s` block argument."
43
- ARRAY_CONVERTER_METHODS = %i[assoc flatten rassoc sort sort_by to_a].freeze
43
+ ARRAY_CONVERTER_METHODS = %i[assoc chunk flatten rassoc sort sort_by to_a].freeze
44
44
 
45
45
  # @!method kv_each(node)
46
46
  def_node_matcher :kv_each, <<~PATTERN
@@ -38,6 +38,7 @@ module RuboCop
38
38
 
39
39
  private
40
40
 
41
+ # rubocop:disable Metrics/AbcSize
41
42
  def autocorrect(corrector, node, begin_of_arguments)
42
43
  arguments = node.arguments
43
44
  joined_arguments = arguments.map(&:source).join(', ')
@@ -49,9 +50,17 @@ module RuboCop
49
50
  corrector.remove(range_by_whole_lines(arguments.loc.end, include_final_newline: true))
50
51
  end
51
52
 
52
- corrector.remove(arguments_range(node))
53
+ arguments_range = arguments_range(node)
54
+ # If the method name isn't on the same line as def, move it directly after def
55
+ if arguments_range.first_line != opening_line(node)
56
+ corrector.remove(node.loc.name)
57
+ corrector.insert_after(node.loc.keyword, " #{node.loc.name.source}")
58
+ end
59
+
60
+ corrector.remove(arguments_range)
53
61
  corrector.insert_after(begin_of_arguments, joined_arguments)
54
62
  end
63
+ # rubocop:enable Metrics/AbcSize
55
64
 
56
65
  def last_line_source_of_arguments(arguments)
57
66
  processed_source[arguments.last_line - 1].strip
@@ -44,6 +44,8 @@ module RuboCop
44
44
  def_node_matcher :nil_check?, '(send _ :nil?)'
45
45
 
46
46
  def on_send(node)
47
+ return unless node.receiver
48
+
47
49
  style_check?(node) do
48
50
  add_offense(node.loc.selector) do |corrector|
49
51
  new_code = if prefer_comparison?
@@ -80,7 +80,7 @@ module RuboCop
80
80
 
81
81
  def correction_exploded_to_compact(node)
82
82
  exception_node, *message_nodes = *node.arguments
83
- return node.source if message_nodes.size > 1
83
+ return if message_nodes.size > 1
84
84
 
85
85
  argument = message_nodes.first.source
86
86
  exception_class = exception_node.receiver&.source || exception_node.source
@@ -22,10 +22,11 @@ module RuboCop
22
22
 
23
23
  def on_send(node)
24
24
  return unless node.method?(:require_relative)
25
- return unless node.first_argument.str_content&.start_with?(CURRENT_DIRECTORY_PATH)
26
- return unless (index = node.first_argument.source.index(CURRENT_DIRECTORY_PATH))
25
+ return unless (first_argument = node.first_argument)
26
+ return unless first_argument.str_content&.start_with?(CURRENT_DIRECTORY_PATH)
27
+ return unless (index = first_argument.source.index(CURRENT_DIRECTORY_PATH))
27
28
 
28
- begin_pos = node.first_argument.source_range.begin.begin_pos + index
29
+ begin_pos = first_argument.source_range.begin.begin_pos + index
29
30
  range = range_between(begin_pos, begin_pos + 2)
30
31
 
31
32
  add_offense(range) do |corrector|
@@ -88,7 +88,7 @@ module RuboCop
88
88
  end
89
89
 
90
90
  def escaped_octal?(expr)
91
- expr.text =~ /^\\[0-7]$/
91
+ expr.text.valid_encoding? && expr.text =~ /^\\[0-7]$/
92
92
  end
93
93
 
94
94
  def octal_digit?(char)
@@ -6,9 +6,11 @@ module RuboCop
6
6
  # cops it contains.
7
7
  class DirectiveComment
8
8
  # @api private
9
- REDUNDANT_DIRECTIVE_COP_DEPARTMENT = 'Lint'
9
+ LINT_DEPARTMENT = 'Lint'
10
10
  # @api private
11
- REDUNDANT_DIRECTIVE_COP = "#{REDUNDANT_DIRECTIVE_COP_DEPARTMENT}/RedundantCopDisableDirective"
11
+ LINT_REDUNDANT_DIRECTIVE_COP = "#{LINT_DEPARTMENT}/RedundantCopDisableDirective"
12
+ # @api private
13
+ LINT_SYNTAX_COP = "#{LINT_DEPARTMENT}/Syntax"
12
14
  # @api private
13
15
  COP_NAME_PATTERN = '([A-Z]\w+/)*(?:[A-Z]\w+)'
14
16
  # @api private
@@ -118,9 +120,10 @@ module RuboCop
118
120
  end
119
121
 
120
122
  def parsed_cop_names
121
- splitted_cops_string.map do |name|
123
+ cops = splitted_cops_string.map do |name|
122
124
  department?(name) ? cop_names_for_department(name) : name
123
125
  end.flatten
126
+ cops - [LINT_SYNTAX_COP]
124
127
  end
125
128
 
126
129
  def department?(name)
@@ -128,17 +131,16 @@ module RuboCop
128
131
  end
129
132
 
130
133
  def all_cop_names
131
- exclude_redundant_directive_cop(cop_registry.names)
134
+ exclude_lint_department_cops(cop_registry.names)
132
135
  end
133
136
 
134
137
  def cop_names_for_department(department)
135
138
  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
139
+ department == LINT_DEPARTMENT ? exclude_lint_department_cops(names) : names
138
140
  end
139
141
 
140
- def exclude_redundant_directive_cop(cops)
141
- cops - [REDUNDANT_DIRECTIVE_COP]
142
+ def exclude_lint_department_cops(cops)
143
+ cops - [LINT_REDUNDANT_DIRECTIVE_COP, LINT_SYNTAX_COP]
142
144
  end
143
145
  end
144
146
  end
@@ -126,7 +126,7 @@ module RuboCop
126
126
  @offenses
127
127
  end
128
128
 
129
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
129
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
130
130
  def expect_correction(correction, loop: true, source: nil)
131
131
  if source
132
132
  expected_annotations = parse_annotations(source, raise_error: false)
@@ -148,7 +148,6 @@ module RuboCop
148
148
 
149
149
  break corrected_source unless loop
150
150
  break corrected_source if @last_corrector.empty?
151
- break corrected_source if corrected_source == @processed_source.buffer.source
152
151
 
153
152
  if iteration > RuboCop::Runner::MAX_ITERATIONS
154
153
  raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [@offenses])
@@ -163,19 +162,20 @@ module RuboCop
163
162
 
164
163
  expect(new_source).to eq(correction)
165
164
  end
166
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
165
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
167
166
 
168
167
  def expect_no_corrections
169
168
  raise '`expect_no_corrections` must follow `expect_offense`' unless @processed_source
170
169
 
171
170
  return if @last_corrector.empty?
172
171
 
173
- # In order to print a nice diff, e.g. what source got corrected to,
174
- # we need to run the actual corrections
175
-
172
+ # This is just here for a pretty diff if the source actually got changed
176
173
  new_source = @last_corrector.rewrite
177
-
178
174
  expect(new_source).to eq(@processed_source.buffer.source)
175
+
176
+ # There is an infinite loop if a corrector is present that did not make
177
+ # any changes. It will cause the same offense/correction on the next loop.
178
+ raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [@offenses])
179
179
  end
180
180
 
181
181
  def expect_no_offenses(source, file = nil)
@@ -105,7 +105,7 @@ module RuboCop
105
105
  def version_from_right_hand_side(right_hand_side)
106
106
  gem_requirement_versions = gem_requirement_versions(right_hand_side)
107
107
 
108
- if right_hand_side.array_type?
108
+ if right_hand_side.array_type? && right_hand_side.children.all?(&:str_type?)
109
109
  version_from_array(right_hand_side)
110
110
  elsif gem_requirement_versions
111
111
  gem_requirement_versions.map(&:value)
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.62.0'
6
+ STRING = '1.62.1'
7
7
 
8
8
  MSG = '%<version>s (using %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.62.0
4
+ version: 1.62.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2024-03-06 00:00:00.000000000 Z
13
+ date: 2024-03-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -1031,7 +1031,7 @@ licenses:
1031
1031
  - MIT
1032
1032
  metadata:
1033
1033
  homepage_uri: https://rubocop.org/
1034
- changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.62.0
1034
+ changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.62.1
1035
1035
  source_code_uri: https://github.com/rubocop/rubocop/
1036
1036
  documentation_uri: https://docs.rubocop.org/rubocop/1.62/
1037
1037
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues