rubocop 1.68.0 → 1.69.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 (162) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +41 -6
  4. data/lib/rubocop/cop/base.rb +1 -1
  5. data/lib/rubocop/cop/bundler/gem_filename.rb +0 -1
  6. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +0 -1
  7. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +1 -1
  8. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
  9. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
  10. data/lib/rubocop/cop/generator.rb +6 -0
  11. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -4
  12. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
  13. data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +46 -0
  14. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
  15. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  16. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -2
  17. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  18. data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
  19. data/lib/rubocop/cop/layout/block_alignment.rb +1 -2
  20. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  21. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +2 -3
  22. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +3 -4
  23. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +3 -1
  24. data/lib/rubocop/cop/layout/indentation_width.rb +7 -7
  25. data/lib/rubocop/cop/layout/leading_comment_space.rb +15 -0
  26. data/lib/rubocop/cop/layout/line_length.rb +118 -4
  27. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
  28. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
  29. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -3
  30. data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
  31. data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -35
  32. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -2
  33. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  34. data/lib/rubocop/cop/layout/space_around_operators.rb +16 -17
  35. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +6 -0
  36. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +4 -0
  37. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
  38. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +10 -12
  39. data/lib/rubocop/cop/lint/circular_argument_reference.rb +6 -0
  40. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +2 -1
  41. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
  42. data/lib/rubocop/cop/lint/empty_file.rb +0 -2
  43. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  44. data/lib/rubocop/cop/lint/float_comparison.rb +14 -6
  45. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -3
  46. data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
  47. data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
  48. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +3 -0
  49. data/lib/rubocop/cop/lint/literal_as_condition.rb +1 -0
  50. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  51. data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -5
  52. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  53. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
  54. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +1 -1
  55. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -3
  56. data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
  57. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
  58. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +106 -0
  59. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -2
  60. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
  61. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  62. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +12 -7
  63. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
  64. data/lib/rubocop/cop/lint/refinement_import_methods.rb +1 -1
  65. data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
  66. data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
  67. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +2 -0
  68. data/lib/rubocop/cop/lint/self_assignment.rb +8 -10
  69. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  70. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +3 -0
  71. data/lib/rubocop/cop/lint/unreachable_code.rb +51 -2
  72. data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
  73. data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
  74. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +4 -0
  75. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
  76. data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
  77. data/lib/rubocop/cop/lint/void.rb +3 -2
  78. data/lib/rubocop/cop/metrics/class_length.rb +7 -7
  79. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  80. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -3
  81. data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
  82. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
  83. data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
  84. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +5 -9
  85. data/lib/rubocop/cop/mixin/range_help.rb +0 -1
  86. data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
  87. data/lib/rubocop/cop/naming/accessor_method_name.rb +6 -6
  88. data/lib/rubocop/cop/naming/constant_name.rb +6 -7
  89. data/lib/rubocop/cop/naming/file_name.rb +0 -2
  90. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +11 -12
  91. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -11
  92. data/lib/rubocop/cop/naming/variable_name.rb +3 -4
  93. data/lib/rubocop/cop/naming/variable_number.rb +2 -3
  94. data/lib/rubocop/cop/security/compound_hash.rb +1 -0
  95. data/lib/rubocop/cop/security/yaml_load.rb +3 -2
  96. data/lib/rubocop/cop/style/access_modifier_declarations.rb +54 -25
  97. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +1 -1
  98. data/lib/rubocop/cop/style/array_intersect.rb +5 -4
  99. data/lib/rubocop/cop/style/bitwise_predicate.rb +1 -1
  100. data/lib/rubocop/cop/style/block_delimiters.rb +10 -2
  101. data/lib/rubocop/cop/style/case_like_if.rb +8 -11
  102. data/lib/rubocop/cop/style/commented_keyword.rb +11 -1
  103. data/lib/rubocop/cop/style/conditional_assignment.rb +19 -21
  104. data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
  105. data/lib/rubocop/cop/style/dig_chain.rb +89 -0
  106. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -0
  107. data/lib/rubocop/cop/style/file_null.rb +73 -0
  108. data/lib/rubocop/cop/style/file_touch.rb +75 -0
  109. data/lib/rubocop/cop/style/for.rb +0 -1
  110. data/lib/rubocop/cop/style/global_vars.rb +1 -3
  111. data/lib/rubocop/cop/style/guard_clause.rb +1 -1
  112. data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
  113. data/lib/rubocop/cop/style/hash_except.rb +19 -7
  114. data/lib/rubocop/cop/style/if_inside_else.rb +0 -1
  115. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -2
  116. data/lib/rubocop/cop/style/if_with_semicolon.rb +14 -5
  117. data/lib/rubocop/cop/style/inverse_methods.rb +0 -1
  118. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +2 -2
  119. data/lib/rubocop/cop/style/lambda_call.rb +3 -2
  120. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
  121. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +7 -11
  122. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
  123. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  124. data/lib/rubocop/cop/style/mutable_constant.rb +4 -5
  125. data/lib/rubocop/cop/style/negated_if_else_condition.rb +6 -4
  126. data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
  127. data/lib/rubocop/cop/style/not.rb +1 -1
  128. data/lib/rubocop/cop/style/object_then.rb +1 -0
  129. data/lib/rubocop/cop/style/one_line_conditional.rb +25 -4
  130. data/lib/rubocop/cop/style/operator_method_call.rb +5 -6
  131. data/lib/rubocop/cop/style/or_assignment.rb +3 -6
  132. data/lib/rubocop/cop/style/parallel_assignment.rb +8 -13
  133. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  134. data/lib/rubocop/cop/style/redundant_argument.rb +3 -1
  135. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
  136. data/lib/rubocop/cop/style/redundant_condition.rb +36 -21
  137. data/lib/rubocop/cop/style/redundant_line_continuation.rb +7 -6
  138. data/lib/rubocop/cop/style/redundant_parentheses.rb +2 -2
  139. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +1 -0
  140. data/lib/rubocop/cop/style/redundant_return.rb +2 -2
  141. data/lib/rubocop/cop/style/redundant_self.rb +8 -15
  142. data/lib/rubocop/cop/style/redundant_self_assignment.rb +7 -5
  143. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
  144. data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
  145. data/lib/rubocop/cop/style/rescue_modifier.rb +2 -3
  146. data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
  147. data/lib/rubocop/cop/style/select_by_regexp.rb +1 -1
  148. data/lib/rubocop/cop/style/self_assignment.rb +11 -17
  149. data/lib/rubocop/cop/style/signal_exception.rb +2 -3
  150. data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
  151. data/lib/rubocop/cop/style/single_line_do_end_block.rb +13 -3
  152. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -3
  153. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  154. data/lib/rubocop/cop/style/string_concatenation.rb +13 -12
  155. data/lib/rubocop/cop/style/swap_values.rb +4 -15
  156. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
  157. data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
  158. data/lib/rubocop/cop/variable_force.rb +4 -10
  159. data/lib/rubocop/cops_documentation_generator.rb +9 -1
  160. data/lib/rubocop/version.rb +1 -1
  161. data/lib/rubocop.rb +8 -0
  162. metadata +23 -14
@@ -38,7 +38,7 @@ module RuboCop
38
38
  # * `Layout/MultilineHashKeyLineBreaks`
39
39
  # * `Layout/MultilineMethodArgumentLineBreaks`
40
40
  # * `Layout/MultilineMethodParameterLineBreaks`
41
- # * `Layout//ParameterAlignment`
41
+ # * `Layout/ParameterAlignment`
42
42
  # * `Style/BlockDelimiters`
43
43
  #
44
44
  # Together, these cops will pretty print hashes, arrays,
@@ -60,7 +60,7 @@ module RuboCop
60
60
  # bar: "0000000000",
61
61
  # baz: "0000000000",
62
62
  # }
63
- class LineLength < Base
63
+ class LineLength < Base # rubocop:disable Metrics/ClassLength
64
64
  include CheckLineBreakable
65
65
  include AllowedPattern
66
66
  include RangeHelp
@@ -74,9 +74,16 @@ module RuboCop
74
74
  def on_block(node)
75
75
  check_for_breakable_block(node)
76
76
  end
77
-
78
77
  alias on_numblock on_block
79
78
 
79
+ def on_str(node)
80
+ check_for_breakable_str(node)
81
+ end
82
+
83
+ def on_dstr(node)
84
+ check_for_breakable_dstr(node)
85
+ end
86
+
80
87
  def on_potential_breakable_node(node)
81
88
  check_for_breakable_node(node)
82
89
  end
@@ -132,6 +139,42 @@ module RuboCop
132
139
  breakable_range_by_line_index[line_index] = range_between(pos, pos + 1)
133
140
  end
134
141
 
142
+ def check_for_breakable_str(node)
143
+ line_index = node.loc.line - 1
144
+ return if breakable_range_by_line_index[line_index]
145
+
146
+ return unless breakable_string?(node)
147
+ return unless (delimiter = string_delimiter(node))
148
+ return unless (pos = breakable_string_position(node))
149
+
150
+ breakable_range_by_line_index[line_index] = range_between(pos, pos + 1)
151
+ breakable_string_delimiters[line_index] = delimiter
152
+ end
153
+
154
+ def check_for_breakable_dstr(node) # rubocop:disable Metrics/AbcSize
155
+ line_index = node.loc.line - 1
156
+ return if breakable_range_by_line_index[line_index]
157
+
158
+ return unless breakable_dstr?(node)
159
+ return unless (delimiter = string_delimiter(node))
160
+
161
+ node.each_child_node(:begin).detect do |begin_node|
162
+ next unless (pos = breakable_dstr_begin_position(begin_node))
163
+
164
+ breakable_range_by_line_index[line_index] = range_between(pos, pos + 1)
165
+ breakable_string_delimiters[line_index] = delimiter
166
+ end
167
+ end
168
+
169
+ def breakable_string?(node)
170
+ allow_string_split? &&
171
+ node.single_line? &&
172
+ !node.heredoc? &&
173
+ # TODO: strings inside hashes, kwargs and arrays are currently ignored,
174
+ # but could be considered in the future
175
+ !node.parent&.type?(:pair, :kwoptarg, :array)
176
+ end
177
+
135
178
  def breakable_block_range(block_node)
136
179
  if block_node.arguments? && !block_node.lambda?
137
180
  block_node.arguments.loc.end
@@ -153,10 +196,47 @@ module RuboCop
153
196
  next_range
154
197
  end
155
198
 
199
+ def breakable_string_position(node)
200
+ source_range = node.source_range
201
+ return if source_range.last_column < max
202
+ return unless (pos = breakable_string_range(node))
203
+
204
+ pos.end_pos unless pos.end_pos == source_range.begin_pos
205
+ end
206
+
207
+ # Locate where to break a string that is too long, ensuring that escape characters
208
+ # are not bisected.
209
+ # If the string contains spaces, use them to determine a place for a clean break;
210
+ # otherwise, the string will be broken at the line length limit.
211
+ def breakable_string_range(node) # rubocop:disable Metrics/AbcSize
212
+ source_range = node.source_range
213
+ relevant_substr = largest_possible_string(node)
214
+
215
+ if (space_pos = relevant_substr.rindex(/\s/))
216
+ source_range.resize(space_pos + 1)
217
+ elsif (escape_pos = relevant_substr.rindex(/\\(u[\da-f]{0,4}|x[\da-f]{0,2})?\z/))
218
+ source_range.resize(escape_pos)
219
+ else
220
+ adjustment = max - source_range.last_column - 3
221
+ return if adjustment.abs > source_range.size
222
+
223
+ source_range.adjust(end_pos: max - source_range.last_column - 3)
224
+ end
225
+ end
226
+
227
+ def breakable_dstr_begin_position(node)
228
+ source_range = node.source_range
229
+ source_range.begin_pos if source_range.begin_pos < max && source_range.end_pos >= max
230
+ end
231
+
156
232
  def breakable_range_by_line_index
157
233
  @breakable_range_by_line_index ||= {}
158
234
  end
159
235
 
236
+ def breakable_string_delimiters
237
+ @breakable_string_delimiters ||= {}
238
+ end
239
+
160
240
  def heredocs
161
241
  @heredocs ||= extract_heredocs(processed_source.ast)
162
242
  end
@@ -197,7 +277,14 @@ module RuboCop
197
277
 
198
278
  add_offense(loc, message: message) do |corrector|
199
279
  self.max = line_length(line)
200
- corrector.insert_before(breakable_range, "\n") unless breakable_range.nil?
280
+
281
+ insertion = if (delimiter = breakable_string_delimiters[line_index])
282
+ [delimiter, " \\\n", delimiter].join
283
+ else
284
+ "\n"
285
+ end
286
+
287
+ corrector.insert_before(breakable_range, insertion) unless breakable_range.nil?
201
288
  end
202
289
  end
203
290
 
@@ -224,6 +311,10 @@ module RuboCop
224
311
  cop_config['AllowHeredoc']
225
312
  end
226
313
 
314
+ def allow_string_split?
315
+ cop_config['SplitStrings']
316
+ end
317
+
227
318
  def extract_heredocs(ast)
228
319
  return [] unless ast
229
320
 
@@ -270,6 +361,29 @@ module RuboCop
270
361
 
271
362
  register_offense(excess_range(uri_range, line, line_index), line, line_index)
272
363
  end
364
+
365
+ def breakable_dstr?(node)
366
+ # If the `dstr` only contains one child, it cannot be broken
367
+ breakable_string?(node) && !node.child_nodes.one?
368
+ end
369
+
370
+ def string_delimiter(node)
371
+ delimiter = node.loc.begin
372
+ delimiter ||= node.parent.loc.begin if node.parent&.dstr_type?
373
+ delimiter = delimiter&.source
374
+
375
+ delimiter if %w[' "].include?(delimiter)
376
+ end
377
+
378
+ # Find the largest possible substring of a string node to retain before a break
379
+ def largest_possible_string(node)
380
+ # The maximum allowed length of a string value is:
381
+ # `Max` - end delimiter (quote) - continuation characters (space and slash)
382
+ max_length = max - 3
383
+ # If the string doesn't start at the beginning of the line, the max length is offset
384
+ max_length -= column_offset_between(node.loc, node.parent.loc) if node.parent
385
+ node.source[0...(max_length)]
386
+ end
273
387
  end
274
388
  end
275
389
  end
@@ -12,7 +12,7 @@ module RuboCop
12
12
  # argument of the call, then the closing brace should be on the same
13
13
  # line as the last argument of the call.
14
14
  #
15
- # If an method call's opening brace is on the line above the first
15
+ # If a method call's opening brace is on the line above the first
16
16
  # argument of the call, then the closing brace should be on the line
17
17
  # below the last argument of the call.
18
18
  #
@@ -12,7 +12,7 @@ module RuboCop
12
12
  # first parameter of the definition, then the closing brace should be
13
13
  # on the same line as the last parameter of the definition.
14
14
  #
15
- # If an method definition's opening brace is on the line above the first
15
+ # If a method definition's opening brace is on the line above the first
16
16
  # parameter of the definition, then the closing brace should be on the
17
17
  # line below the last parameter of the definition.
18
18
  #
@@ -76,9 +76,8 @@ module RuboCop
76
76
  end
77
77
 
78
78
  def check_and_or(node)
79
- lhs, rhs = *node
80
- range = offending_range(node, lhs, rhs.source_range, style)
81
- check(range, node, lhs, rhs.source_range)
79
+ range = offending_range(node, node.lhs, node.rhs.source_range, style)
80
+ check(range, node, node.lhs, node.rhs.source_range)
82
81
  end
83
82
 
84
83
  def offending_range(node, lhs, rhs, given_style)
@@ -3,11 +3,10 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Here we check if the parameters on a multi-line method call or
7
- # definition are aligned.
6
+ # Check that the parameters on a multi-line method call or definition are aligned.
8
7
  #
9
- # To set the alignment of the first argument, use the cop
10
- # FirstParameterIndentation.
8
+ # To set the alignment of the first argument, use the
9
+ # `Layout/FirstParameterIndentation` cop.
11
10
  #
12
11
  # @example EnforcedStyle: with_first_parameter (default)
13
12
  # # good
@@ -44,6 +44,7 @@ module RuboCop
44
44
  #
45
45
  class RedundantLineBreak < Base
46
46
  include CheckAssignment
47
+ include CheckSingleLineSuitability
47
48
  extend AutoCorrector
48
49
 
49
50
  MSG = 'Redundant line break detected.'
@@ -84,8 +85,8 @@ module RuboCop
84
85
  end
85
86
 
86
87
  def offense?(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?
88
+ return false unless node.multiline? && suitable_as_single_line?(node)
89
+ return require_backslash?(node) if node.operator_keyword?
89
90
 
90
91
  !index_access_call_chained?(node) && !configured_to_not_be_inspected?(node)
91
92
  end
@@ -117,44 +118,11 @@ module RuboCop
117
118
  @config.for_cop('Layout/SingleLineBlockChain')['Enabled']
118
119
  end
119
120
 
120
- def suitable_as_single_line?(node)
121
- !comment_within?(node) &&
122
- node.each_descendant(:if, :case, :kwbegin, :def, :defs).none? &&
123
- node.each_descendant(:dstr, :str).none? { |n| n.heredoc? || n.value.include?("\n") } &&
124
- node.each_descendant(:begin, :sym).none? { |b| !b.single_line? }
125
- end
126
-
127
121
  def convertible_block?(node)
128
122
  parent = node.parent
129
123
  parent&.block_type? && node == parent.send_node &&
130
124
  (node.parenthesized? || !node.arguments?)
131
125
  end
132
-
133
- def comment_within?(node)
134
- comment_line_numbers = processed_source.comments.map { |comment| comment.loc.line }
135
-
136
- comment_line_numbers.any? do |comment_line_number|
137
- comment_line_number >= node.first_line && comment_line_number <= node.last_line
138
- end
139
- end
140
-
141
- def too_long?(node)
142
- lines = processed_source.lines[(node.first_line - 1)...node.last_line]
143
- to_single_line(lines.join("\n")).length > max_line_length
144
- end
145
-
146
- def to_single_line(source)
147
- source
148
- .gsub(/" *\\\n\s*'/, %q(" + ')) # Double quote, backslash, and then single quote
149
- .gsub(/' *\\\n\s*"/, %q(' + ")) # Single quote, backslash, and then double quote
150
- .gsub(/(["']) *\\\n\s*\1/, '') # Double or single quote, backslash, then same quote
151
- .gsub(/\n\s*(?=(&)?\.\w)/, '') # Extra space within method chaining which includes `&.`
152
- .gsub(/\s*\\?\n\s*/, ' ') # Any other line break, with or without backslash
153
- end
154
-
155
- def max_line_length
156
- config.for_cop('Layout/LineLength')['Max']
157
- end
158
126
  end
159
127
  end
160
128
  end
@@ -92,6 +92,7 @@ module RuboCop
92
92
  )
93
93
  end
94
94
 
95
+ # rubocop:disable Metrics/AbcSize
95
96
  def alignment_source(node, starting_loc)
96
97
  ending_loc =
97
98
  case node.type
@@ -101,8 +102,7 @@ module RuboCop
101
102
  :lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn
102
103
  node.loc.name
103
104
  when :masgn
104
- mlhs_node, = *node
105
- mlhs_node.source_range
105
+ node.lhs.source_range
106
106
  else
107
107
  # It is a wrapper with receiver of object attribute or access modifier.
108
108
  node.receiver&.source_range || node.child_nodes.first.loc.name
@@ -110,6 +110,7 @@ module RuboCop
110
110
 
111
111
  range_between(starting_loc.begin_pos, ending_loc.end_pos).source
112
112
  end
113
+ # rubocop:enable Metrics/AbcSize
113
114
 
114
115
  # We will use ancestor or wrapper with access modifier.
115
116
 
@@ -256,7 +256,7 @@ module RuboCop
256
256
  # regular dotted method calls bind more tightly than operators
257
257
  # so we need to climb up the AST past them
258
258
  node.each_ancestor do |ancestor|
259
- return true if ancestor.and_type? || ancestor.or_type? || ancestor.range_type?
259
+ return true if ancestor.operator_keyword? || ancestor.range_type?
260
260
  return false unless ancestor.send_type?
261
261
  return true if ancestor.operator_method?
262
262
  end
@@ -99,51 +99,50 @@ module RuboCop
99
99
  def on_resbody(node)
100
100
  return unless node.loc.assoc
101
101
 
102
- _, variable, = *node
103
-
104
- check_operator(:resbody, node.loc.assoc, variable)
102
+ check_operator(:resbody, node.loc.assoc, node.exception_variable)
105
103
  end
106
104
 
107
105
  def on_send(node)
108
106
  return if rational_literal?(node)
109
107
 
110
108
  if node.setter_method?
111
- on_special_asgn(node)
109
+ on_setter_method(node)
112
110
  elsif regular_operator?(node)
113
111
  check_operator(:send, node.loc.selector, node.first_argument)
114
112
  end
115
113
  end
116
114
 
117
115
  def on_assignment(node)
118
- _, rhs, = *node
116
+ rhs = node.rhs
119
117
 
120
118
  return unless rhs
121
119
 
122
- check_operator(:assignment, node.loc.operator, rhs)
120
+ type = node.op_asgn_type? ? :special_asgn : :assignment
121
+ check_operator(type, node.loc.operator, rhs)
123
122
  end
124
123
 
125
- def on_casgn(node)
126
- _, _, right, = *node
124
+ def on_class(node)
125
+ rhs = node.parent_class
127
126
 
128
- return unless right
127
+ return unless rhs
129
128
 
130
- check_operator(:assignment, node.loc.operator, right)
129
+ check_operator(:class, node.loc.operator, rhs)
131
130
  end
132
131
 
133
132
  def on_binary(node)
134
- _, rhs, = *node
133
+ rhs = node.rhs
135
134
 
136
135
  return unless rhs
137
136
 
138
137
  check_operator(:binary, node.loc.operator, rhs)
139
138
  end
140
139
 
141
- def on_special_asgn(node)
142
- _, _, right, = *node
140
+ def on_setter_method(node)
141
+ rhs = node.first_argument
143
142
 
144
- return unless right
143
+ return unless rhs
145
144
 
146
- check_operator(:special_asgn, node.loc.operator, right)
145
+ check_operator(:special_asgn, node.loc.operator, node.first_argument)
147
146
  end
148
147
 
149
148
  def on_match_pattern(node)
@@ -155,14 +154,14 @@ module RuboCop
155
154
  alias on_or on_binary
156
155
  alias on_and on_binary
157
156
  alias on_lvasgn on_assignment
157
+ alias on_casgn on_assignment
158
158
  alias on_masgn on_assignment
159
159
  alias on_ivasgn on_assignment
160
160
  alias on_cvasgn on_assignment
161
161
  alias on_gvasgn on_assignment
162
- alias on_class on_binary
163
162
  alias on_or_asgn on_assignment
164
163
  alias on_and_asgn on_assignment
165
- alias on_op_asgn on_special_asgn
164
+ alias on_op_asgn on_assignment
166
165
 
167
166
  private
168
167
 
@@ -12,9 +12,11 @@ module RuboCop
12
12
  #
13
13
  # # bad
14
14
  # array = [ a, b, c, d ]
15
+ # array = [ a, [ b, c ]]
15
16
  #
16
17
  # # good
17
18
  # array = [a, b, c, d]
19
+ # array = [a, [b, c]]
18
20
  #
19
21
  # @example EnforcedStyle: space
20
22
  # # The `space` style enforces that array literals have
@@ -22,9 +24,11 @@ module RuboCop
22
24
  #
23
25
  # # bad
24
26
  # array = [a, b, c, d]
27
+ # array = [ a, [ b, c ]]
25
28
  #
26
29
  # # good
27
30
  # array = [ a, b, c, d ]
31
+ # array = [ a, [ b, c ] ]
28
32
  #
29
33
  # @example EnforcedStyle: compact
30
34
  # # The `compact` style normally requires a space inside
@@ -32,6 +36,7 @@ module RuboCop
32
36
  # # or right brackets are collapsed together in nested arrays.
33
37
  #
34
38
  # # bad
39
+ # array = [a, b, c, d]
35
40
  # array = [ a, [ b, c ] ]
36
41
  # array = [
37
42
  # [ a ],
@@ -39,6 +44,7 @@ module RuboCop
39
44
  # ]
40
45
  #
41
46
  # # good
47
+ # array = [ a, b, c, d ]
42
48
  # array = [ a, [ b, c ]]
43
49
  # array = [[ a ],
44
50
  # [ b, c ]]
@@ -12,9 +12,11 @@ module RuboCop
12
12
  #
13
13
  # # bad
14
14
  # h = {a: 1, b: 2}
15
+ # foo = {{ a: 1 } => { b: { c: 2 }}}
15
16
  #
16
17
  # # good
17
18
  # h = { a: 1, b: 2 }
19
+ # foo = { { a: 1 } => { b: { c: 2 } } }
18
20
  #
19
21
  # @example EnforcedStyle: no_space
20
22
  # # The `no_space` style enforces that hash literals have
@@ -22,9 +24,11 @@ module RuboCop
22
24
  #
23
25
  # # bad
24
26
  # h = { a: 1, b: 2 }
27
+ # foo = {{ a: 1 } => { b: { c: 2 }}}
25
28
  #
26
29
  # # good
27
30
  # h = {a: 1, b: 2}
31
+ # foo = {{a: 1} => {b: {c: 2}}}
28
32
  #
29
33
  # @example EnforcedStyle: compact
30
34
  # # The `compact` style normally requires a space inside
@@ -22,7 +22,6 @@ module RuboCop
22
22
  include Interpolation
23
23
  include SurroundingSpace
24
24
  include ConfigurableEnforcedStyle
25
- include RangeHelp
26
25
  extend AutoCorrector
27
26
 
28
27
  MSG = '%<command>s space inside string interpolation.'
@@ -5,17 +5,16 @@ module RuboCop
5
5
  module Lint
6
6
  # Checks for places where binary operator has identical operands.
7
7
  #
8
- # It covers arithmetic operators: `-`, `/`, `%`;
9
- # comparison operators: `==`, `===`, `=~`, `>`, `>=`, `<`, ``<=``;
8
+ # It covers comparison operators: `==`, `===`, `=~`, `>`, `>=`, `<`, ``<=``;
10
9
  # bitwise operators: `|`, `^`, `&`;
11
10
  # boolean operators: `&&`, `||`
12
11
  # and "spaceship" operator - ``<=>``.
13
12
  #
14
13
  # Simple arithmetic operations are allowed by this cop: `+`, `*`, `**`, `<<` and `>>`.
15
14
  # Although these can be rewritten in a different way, it should not be necessary to
16
- # do so. This does not include operations such as `-` or `/` where the result will
17
- # always be the same (`x - x` will always be 0; `x / x` will always be 1), and
18
- # thus are legitimate offenses.
15
+ # do so. Operations such as `-` or `/` where the result will always be the same
16
+ # (`x - x` will always be 0; `x / x` will always be 1) are offenses, but these
17
+ # are covered by Lint/NumericOperationWithConstantResult instead.
19
18
  #
20
19
  # @safety
21
20
  # This cop is unsafe as it does not consider side effects when calling methods
@@ -30,7 +29,6 @@ module RuboCop
30
29
  #
31
30
  # @example
32
31
  # # bad
33
- # x / x
34
32
  # x.top >= x.top
35
33
  #
36
34
  # if a.x != 0 && a.x != 0
@@ -47,19 +45,19 @@ module RuboCop
47
45
  #
48
46
  class BinaryOperatorWithIdenticalOperands < Base
49
47
  MSG = 'Binary operator `%<op>s` has identical operands.'
50
- ALLOWED_MATH_OPERATORS = %i[+ * ** << >>].to_set.freeze
48
+ RESTRICT_ON_SEND = %i[== != === <=> =~ && || > >= < <= | ^].freeze
51
49
 
52
50
  def on_send(node)
53
51
  return unless node.binary_operation?
52
+ return unless node.receiver == node.first_argument
54
53
 
55
- lhs, operation, rhs = *node
56
- return if ALLOWED_MATH_OPERATORS.include?(node.method_name)
57
-
58
- add_offense(node, message: format(MSG, op: operation)) if lhs == rhs
54
+ add_offense(node, message: format(MSG, op: node.method_name))
59
55
  end
60
56
 
61
57
  def on_and(node)
62
- add_offense(node, message: format(MSG, op: node.operator)) if node.lhs == node.rhs
58
+ return unless node.lhs == node.rhs
59
+
60
+ add_offense(node, message: format(MSG, op: node.operator))
63
61
  end
64
62
  alias on_or on_and
65
63
  end
@@ -8,6 +8,8 @@ module RuboCop
8
8
  #
9
9
  # This cop mirrors a warning produced by MRI since 2.2.
10
10
  #
11
+ # NOTE: This syntax is no longer valid on Ruby 2.7 or higher.
12
+ #
11
13
  # @example
12
14
  #
13
15
  # # bad
@@ -35,8 +37,12 @@ module RuboCop
35
37
  # dry_ingredients.combine
36
38
  # end
37
39
  class CircularArgumentReference < Base
40
+ extend TargetRubyVersion
41
+
38
42
  MSG = 'Circular argument reference - `%<arg_name>s`.'
39
43
 
44
+ maximum_target_ruby_version 2.6
45
+
40
46
  def on_kwoptarg(node)
41
47
  check_for_circular_argument_references(*node)
42
48
  end
@@ -33,6 +33,7 @@ module RuboCop
33
33
 
34
34
  MSG = 'Use `%<constant>s.%<method>s(%<replacement_args>s)` instead of `%<original>s`.'
35
35
 
36
+ RESTRICT_ON_SEND = %i[new digest].freeze
36
37
  NO_ARG_ALGORITHM = %w[BF DES IDEA RC4].freeze
37
38
 
38
39
  # @!method algorithm_const(node)
@@ -51,7 +52,7 @@ module RuboCop
51
52
  PATTERN
52
53
 
53
54
  def on_send(node)
54
- return if node.arguments.any? { |arg| arg.variable? || arg.send_type? || arg.const_type? }
55
+ return if node.arguments.any? { |arg| arg.variable? || arg.call_type? || arg.const_type? }
55
56
  return if digest_const?(node.receiver)
56
57
  return unless algorithm_const(node)
57
58
 
@@ -38,7 +38,7 @@ module RuboCop
38
38
  MSG = 'Empty `ensure` block detected.'
39
39
 
40
40
  def on_ensure(node)
41
- return if node.body
41
+ return if node.branch
42
42
 
43
43
  add_offense(node.loc.keyword) { |corrector| corrector.remove(node.loc.keyword) }
44
44
  end
@@ -21,8 +21,6 @@ module RuboCop
21
21
  # # File consisting only of comments
22
22
  #
23
23
  class EmptyFile < Base
24
- include RangeHelp
25
-
26
24
  MSG = 'Empty file detected.'
27
25
 
28
26
  def on_new_investigation
@@ -43,7 +43,7 @@ module RuboCop
43
43
  MSG = 'Do not return from an `ensure` block.'
44
44
 
45
45
  def on_ensure(node)
46
- node.body&.each_node(:return) { |return_node| add_offense(return_node) }
46
+ node.branch&.each_node(:return) { |return_node| add_offense(return_node) }
47
47
  end
48
48
  end
49
49
  end
@@ -29,6 +29,9 @@ module RuboCop
29
29
  # tolerance = 0.0001
30
30
  # (x - 0.1).abs < tolerance
31
31
  #
32
+ # # good - comparing against nil
33
+ # Float(x, exception: false) == nil
34
+ #
32
35
  # # Or some other epsilon based type of comparison:
33
36
  # # https://www.embeddeduse.com/2019/08/26/qt-compare-two-floats/
34
37
  #
@@ -42,8 +45,12 @@ module RuboCop
42
45
  RESTRICT_ON_SEND = EQUALITY_METHODS
43
46
 
44
47
  def on_send(node)
45
- lhs, _method, rhs = *node
46
- return if literal_zero?(lhs) || literal_zero?(rhs)
48
+ return unless node.arguments.one?
49
+
50
+ lhs = node.receiver
51
+ rhs = node.first_argument
52
+
53
+ return if literal_safe?(lhs) || literal_safe?(rhs)
47
54
 
48
55
  add_offense(node) if float?(lhs) || float?(rhs)
49
56
  end
@@ -65,15 +72,16 @@ module RuboCop
65
72
  end
66
73
  end
67
74
 
68
- def literal_zero?(node)
69
- node&.numeric_type? && node.value.zero?
75
+ def literal_safe?(node)
76
+ return false unless node
77
+
78
+ (node.numeric_type? && node.value.zero?) || node.nil_type?
70
79
  end
71
80
 
72
81
  # rubocop:disable Metrics/PerceivedComplexity
73
82
  def check_send(node)
74
83
  if node.arithmetic_operation?
75
- lhs, _operation, rhs = *node
76
- float?(lhs) || float?(rhs)
84
+ float?(node.receiver) || float?(node.first_argument)
77
85
  elsif FLOAT_RETURNING_METHODS.include?(node.method_name)
78
86
  true
79
87
  elsif node.receiver&.float_type?
@@ -18,9 +18,7 @@ module RuboCop
18
18
  MSG = 'Float out of range.'
19
19
 
20
20
  def on_float(node)
21
- value, = *node
22
-
23
- return unless value.infinite? || (value.zero? && /[1-9]/.match?(node.source))
21
+ return unless node.value.infinite? || (node.value.zero? && /[1-9]/.match?(node.source))
24
22
 
25
23
  add_offense(node)
26
24
  end