rubocop 1.68.0 → 1.69.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.
Files changed (148) 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/internal_affairs/location_line_equality_comparison.rb +2 -4
  11. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
  12. data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +46 -0
  13. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
  14. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  15. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -2
  16. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  17. data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
  18. data/lib/rubocop/cop/layout/block_alignment.rb +1 -2
  19. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  20. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +2 -3
  21. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +3 -4
  22. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +3 -1
  23. data/lib/rubocop/cop/layout/indentation_width.rb +7 -7
  24. data/lib/rubocop/cop/layout/leading_comment_space.rb +15 -0
  25. data/lib/rubocop/cop/layout/line_length.rb +118 -4
  26. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
  27. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
  28. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -3
  29. data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
  30. data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -35
  31. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -2
  32. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  33. data/lib/rubocop/cop/layout/space_around_operators.rb +16 -17
  34. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +6 -0
  35. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +4 -0
  36. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
  37. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +11 -12
  38. data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -0
  39. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  40. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
  41. data/lib/rubocop/cop/lint/empty_file.rb +0 -2
  42. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  43. data/lib/rubocop/cop/lint/float_comparison.rb +14 -6
  44. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -3
  45. data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
  46. data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
  47. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +3 -0
  48. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  49. data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -5
  50. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  51. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
  52. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +1 -1
  53. data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
  54. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
  55. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +106 -0
  56. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -2
  57. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
  58. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  59. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +12 -7
  60. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
  61. data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
  62. data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
  63. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +2 -0
  64. data/lib/rubocop/cop/lint/self_assignment.rb +8 -10
  65. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  66. data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
  67. data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
  68. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
  69. data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
  70. data/lib/rubocop/cop/lint/void.rb +3 -2
  71. data/lib/rubocop/cop/metrics/class_length.rb +7 -7
  72. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  73. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -2
  74. data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
  75. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
  76. data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
  77. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +5 -9
  78. data/lib/rubocop/cop/mixin/range_help.rb +0 -1
  79. data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
  80. data/lib/rubocop/cop/naming/constant_name.rb +6 -7
  81. data/lib/rubocop/cop/naming/file_name.rb +0 -2
  82. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +11 -12
  83. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -11
  84. data/lib/rubocop/cop/naming/variable_name.rb +3 -4
  85. data/lib/rubocop/cop/naming/variable_number.rb +2 -3
  86. data/lib/rubocop/cop/style/access_modifier_declarations.rb +53 -24
  87. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +1 -1
  88. data/lib/rubocop/cop/style/array_intersect.rb +5 -4
  89. data/lib/rubocop/cop/style/bitwise_predicate.rb +1 -1
  90. data/lib/rubocop/cop/style/block_delimiters.rb +1 -1
  91. data/lib/rubocop/cop/style/case_like_if.rb +8 -11
  92. data/lib/rubocop/cop/style/commented_keyword.rb +11 -1
  93. data/lib/rubocop/cop/style/conditional_assignment.rb +19 -21
  94. data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
  95. data/lib/rubocop/cop/style/dig_chain.rb +90 -0
  96. data/lib/rubocop/cop/style/file_null.rb +73 -0
  97. data/lib/rubocop/cop/style/file_touch.rb +75 -0
  98. data/lib/rubocop/cop/style/for.rb +0 -1
  99. data/lib/rubocop/cop/style/global_vars.rb +1 -3
  100. data/lib/rubocop/cop/style/guard_clause.rb +1 -1
  101. data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
  102. data/lib/rubocop/cop/style/if_inside_else.rb +0 -1
  103. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -2
  104. data/lib/rubocop/cop/style/if_with_semicolon.rb +14 -5
  105. data/lib/rubocop/cop/style/inverse_methods.rb +0 -1
  106. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +2 -2
  107. data/lib/rubocop/cop/style/lambda_call.rb +0 -1
  108. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
  109. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +7 -11
  110. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
  111. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  112. data/lib/rubocop/cop/style/mutable_constant.rb +4 -5
  113. data/lib/rubocop/cop/style/negated_if_else_condition.rb +6 -4
  114. data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
  115. data/lib/rubocop/cop/style/not.rb +1 -1
  116. data/lib/rubocop/cop/style/one_line_conditional.rb +25 -4
  117. data/lib/rubocop/cop/style/operator_method_call.rb +5 -6
  118. data/lib/rubocop/cop/style/or_assignment.rb +3 -6
  119. data/lib/rubocop/cop/style/parallel_assignment.rb +8 -13
  120. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  121. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
  122. data/lib/rubocop/cop/style/redundant_condition.rb +36 -21
  123. data/lib/rubocop/cop/style/redundant_line_continuation.rb +7 -6
  124. data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
  125. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +1 -0
  126. data/lib/rubocop/cop/style/redundant_return.rb +2 -2
  127. data/lib/rubocop/cop/style/redundant_self.rb +7 -14
  128. data/lib/rubocop/cop/style/redundant_self_assignment.rb +7 -5
  129. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
  130. data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
  131. data/lib/rubocop/cop/style/rescue_modifier.rb +2 -3
  132. data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
  133. data/lib/rubocop/cop/style/select_by_regexp.rb +1 -1
  134. data/lib/rubocop/cop/style/self_assignment.rb +11 -17
  135. data/lib/rubocop/cop/style/signal_exception.rb +2 -3
  136. data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
  137. data/lib/rubocop/cop/style/single_line_do_end_block.rb +13 -3
  138. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -3
  139. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  140. data/lib/rubocop/cop/style/string_concatenation.rb +0 -1
  141. data/lib/rubocop/cop/style/swap_values.rb +4 -15
  142. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
  143. data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
  144. data/lib/rubocop/cop/variable_force.rb +4 -10
  145. data/lib/rubocop/cops_documentation_generator.rb +9 -1
  146. data/lib/rubocop/version.rb +1 -1
  147. data/lib/rubocop.rb +8 -0
  148. metadata +17 -8
@@ -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,20 @@ 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
+ MATH_OPERATORS = %i[- + * / ** << >>].to_set.freeze
51
49
 
52
50
  def on_send(node)
53
51
  return unless node.binary_operation?
52
+ return if MATH_OPERATORS.include?(node.method_name)
53
+ return unless node.receiver == node.first_argument
54
54
 
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
55
+ add_offense(node, message: format(MSG, op: node.method_name))
59
56
  end
60
57
 
61
58
  def on_and(node)
62
- add_offense(node, message: format(MSG, op: node.operator)) if node.lhs == node.rhs
59
+ return unless node.lhs == node.rhs
60
+
61
+ add_offense(node, message: format(MSG, op: node.operator))
63
62
  end
64
63
  alias on_or on_and
65
64
  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
@@ -51,7 +51,7 @@ module RuboCop
51
51
  PATTERN
52
52
 
53
53
  def on_send(node)
54
- return if node.arguments.any? { |arg| arg.variable? || arg.send_type? || arg.const_type? }
54
+ return if node.arguments.any? { |arg| arg.variable? || arg.call_type? || arg.const_type? }
55
55
  return if digest_const?(node.receiver)
56
56
  return unless algorithm_const(node)
57
57
 
@@ -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
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for the deprecated use of keyword arguments as a default in `Hash.new`.
7
+ #
8
+ # This usage raises a warning in Ruby 3.3 and results in an error in Ruby 3.4.
9
+ # In Ruby 3.4, keyword arguments will instead be used to change the behavior of a hash.
10
+ # For example, the capacity option can be passed to create a hash with a certain size
11
+ # if you know it in advance, for better performance.
12
+ #
13
+ # NOTE: The following corner case may result in a false negative when upgrading from Ruby 3.3
14
+ # or earlier, but it is intentionally not detected to respect the expected usage in Ruby 3.4.
15
+ #
16
+ # [source,ruby]
17
+ # ----
18
+ # Hash.new(capacity: 42)
19
+ # ----
20
+ #
21
+ # @example
22
+ #
23
+ # # bad
24
+ # Hash.new(key: :value)
25
+ #
26
+ # # good
27
+ # Hash.new({key: :value})
28
+ #
29
+ class HashNewWithKeywordArgumentsAsDefault < Base
30
+ extend AutoCorrector
31
+
32
+ MSG = 'Use a hash literal instead of keyword arguments.'
33
+ RESTRICT_ON_SEND = %i[new].freeze
34
+
35
+ # @!method hash_new(node)
36
+ def_node_matcher :hash_new, <<~PATTERN
37
+ (send (const {nil? (cbase)} :Hash) :new $[hash !braces?])
38
+ PATTERN
39
+
40
+ def on_send(node)
41
+ return unless (first_argument = hash_new(node))
42
+
43
+ if first_argument.pairs.one?
44
+ key = first_argument.pairs.first.key
45
+ return if key.respond_to?(:value) && key.value == :capacity
46
+ end
47
+
48
+ add_offense(first_argument) do |corrector|
49
+ corrector.wrap(first_argument, '{', '}')
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -24,14 +24,17 @@ module RuboCop
24
24
  MSG = 'Interpolation in single quoted string detected. ' \
25
25
  'Use double quoted strings if you need interpolation.'
26
26
 
27
+ # rubocop:disable Metrics/CyclomaticComplexity
27
28
  def on_str(node)
28
29
  return if node.parent&.regexp_type?
29
30
  return unless /(?<!\\)#\{.*\}/.match?(node.source)
30
31
  return if heredoc?(node)
31
32
  return unless node.loc.begin && node.loc.end
33
+ return unless valid_syntax?(node)
32
34
 
33
35
  add_offense(node) { |corrector| autocorrect(corrector, node) }
34
36
  end
37
+ # rubocop:enable Metrics/CyclomaticComplexity
35
38
 
36
39
  private
37
40
 
@@ -49,6 +52,12 @@ module RuboCop
49
52
  def heredoc?(node)
50
53
  node.loc.is_a?(Parser::Source::Map::Heredoc) || (node.parent && heredoc?(node.parent))
51
54
  end
55
+
56
+ def valid_syntax?(node)
57
+ double_quoted_string = node.source.gsub(/\A'|'\z/, '"')
58
+
59
+ parse(double_quoted_string).valid_syntax?
60
+ end
52
61
  end
53
62
  end
54
63
  end
@@ -26,6 +26,9 @@ module RuboCop
26
26
  #
27
27
  class ItWithoutArgumentsInBlock < Base
28
28
  include NodePattern::Macros
29
+ extend TargetRubyVersion
30
+
31
+ maximum_target_ruby_version 3.3
29
32
 
30
33
  MSG = '`it` calls without arguments will refer to the first block param in Ruby 3.4; ' \
31
34
  'use `it()` or `self.it`.'
@@ -40,7 +40,7 @@ module RuboCop
40
40
  traverse_node(node.condition) do |asgn_node|
41
41
  next unless asgn_node.loc.operator
42
42
 
43
- rhs = asgn_node.to_a.last
43
+ rhs = asgn_node.rhs
44
44
  next if !all_literals?(rhs) || parallel_assignment_with_splat_operator?(rhs)
45
45
 
46
46
  range = offense_range(asgn_node, rhs)
@@ -36,12 +36,9 @@ module RuboCop
36
36
 
37
37
  def on_irange(node)
38
38
  return unless node.children.compact.all?(&:str_type?)
39
+ return if node.begin.nil? || node.end.nil?
39
40
 
40
- range_start, range_end = node.children
41
-
42
- return if range_start.nil? || range_end.nil?
43
-
44
- add_offense(node) if unsafe_range?(range_start.value, range_end.value)
41
+ add_offense(node) if unsafe_range?(node.begin.value, node.end.value)
45
42
  end
46
43
  alias on_erange on_irange
47
44
 
@@ -95,7 +95,7 @@ module RuboCop
95
95
  MSG = 'Method definitions must not be nested. Use `lambda` instead.'
96
96
 
97
97
  def on_def(node)
98
- subject, = *node
98
+ subject, = *node # rubocop:disable InternalAffairs/NodeDestructuring
99
99
  return if node.defs_type? && subject.variable?
100
100
 
101
101
  def_ancestor = node.each_ancestor(:def, :defs).first
@@ -45,8 +45,8 @@ module RuboCop
45
45
  end
46
46
  end
47
47
  end
48
- alias on_or_asgn on_lvasgn
49
- alias on_op_asgn on_lvasgn
48
+ alias on_or_asgn on_lvasgn
49
+ alias on_op_asgn on_lvasgn
50
50
  end
51
51
  end
52
52
  end
@@ -95,7 +95,7 @@ module RuboCop
95
95
  end
96
96
 
97
97
  def allowable_use_with_if?(if_node)
98
- if_node.condition.and_type? || if_node.condition.or_type? || if_node.else_branch
98
+ if_node.condition.operator_keyword? || if_node.else_branch
99
99
  end
100
100
 
101
101
  def register_offense(node, exist_node)
@@ -74,7 +74,6 @@ module RuboCop
74
74
  extend AutoCorrector
75
75
  include AllowedMethods
76
76
  include AllowedPattern
77
- include IgnoredNode
78
77
 
79
78
  CONVERSION_METHOD_CLASS_MAPPING = {
80
79
  to_i: "#{Integer.name}(%<number_object>s, 10)",
@@ -33,8 +33,7 @@ module RuboCop
33
33
  NUMBERED_PARAMETER_RANGE = (1..9).freeze
34
34
 
35
35
  def on_lvasgn(node)
36
- lhs, _rhs = *node
37
- return unless /\A_(\d+)\z/ =~ lhs
36
+ return unless /\A_(\d+)\z/ =~ node.name
38
37
 
39
38
  number = Regexp.last_match(1).to_i
40
39
  template = NUMBERED_PARAMETER_RANGE.include?(number) ? NUM_PARAM_MSG : LVAR_MSG