rubocop 1.57.2 → 1.59.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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/config/default.yml +43 -2
  4. data/lib/rubocop/config_obsoletion.rb +11 -8
  5. data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
  6. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +2 -2
  7. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +19 -20
  8. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
  9. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -2
  10. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  11. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  12. data/lib/rubocop/cop/layout/extra_spacing.rb +4 -10
  13. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +6 -6
  14. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  15. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  16. data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -1
  17. data/lib/rubocop/cop/layout/redundant_line_break.rb +2 -1
  18. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -4
  19. data/lib/rubocop/cop/layout/single_line_block_chain.rb +5 -0
  20. data/lib/rubocop/cop/layout/space_around_operators.rb +50 -20
  21. data/lib/rubocop/cop/lint/assignment_in_condition.rb +4 -4
  22. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
  23. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
  24. data/lib/rubocop/cop/lint/debugger.rb +2 -1
  25. data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
  26. data/lib/rubocop/cop/lint/erb_new_arguments.rb +3 -3
  27. data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
  28. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
  29. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
  30. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +78 -0
  31. data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
  32. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -5
  33. data/lib/rubocop/cop/lint/number_conversion.rb +9 -4
  34. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +43 -0
  35. data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
  36. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  37. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -4
  38. data/lib/rubocop/cop/lint/self_assignment.rb +38 -0
  39. data/lib/rubocop/cop/lint/symbol_conversion.rb +7 -2
  40. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
  41. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
  42. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  43. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  44. data/lib/rubocop/cop/lint/void.rb +14 -1
  45. data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
  46. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  47. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
  48. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  49. data/lib/rubocop/cop/naming/block_forwarding.rb +2 -2
  50. data/lib/rubocop/cop/naming/constant_name.rb +1 -2
  51. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  52. data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -2
  53. data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
  54. data/lib/rubocop/cop/style/arguments_forwarding.rb +68 -6
  55. data/lib/rubocop/cop/style/array_first_last.rb +64 -0
  56. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
  57. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
  58. data/lib/rubocop/cop/style/case_like_if.rb +4 -4
  59. data/lib/rubocop/cop/style/class_check.rb +1 -0
  60. data/lib/rubocop/cop/style/collection_compact.rb +7 -6
  61. data/lib/rubocop/cop/style/combinable_loops.rb +13 -7
  62. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -0
  63. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
  64. data/lib/rubocop/cop/style/date_time.rb +5 -4
  65. data/lib/rubocop/cop/style/each_with_object.rb +2 -2
  66. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  67. data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
  68. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -1
  69. data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
  70. data/lib/rubocop/cop/style/hash_each_methods.rb +83 -10
  71. data/lib/rubocop/cop/style/hash_except.rb +2 -1
  72. data/lib/rubocop/cop/style/inverse_methods.rb +6 -5
  73. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +3 -2
  74. data/lib/rubocop/cop/style/map_to_hash.rb +10 -4
  75. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -0
  76. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
  77. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +20 -0
  78. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  79. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
  80. data/lib/rubocop/cop/style/next.rb +1 -1
  81. data/lib/rubocop/cop/style/operator_method_call.rb +2 -2
  82. data/lib/rubocop/cop/style/redundant_argument.rb +3 -2
  83. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +3 -3
  84. data/lib/rubocop/cop/style/redundant_fetch_block.rb +3 -3
  85. data/lib/rubocop/cop/style/redundant_line_continuation.rb +2 -0
  86. data/lib/rubocop/cop/style/redundant_parentheses.rb +15 -8
  87. data/lib/rubocop/cop/style/redundant_return.rb +1 -1
  88. data/lib/rubocop/cop/style/redundant_self.rb +17 -2
  89. data/lib/rubocop/cop/style/redundant_sort.rb +9 -8
  90. data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
  91. data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -1
  92. data/lib/rubocop/cop/style/sample.rb +2 -1
  93. data/lib/rubocop/cop/style/select_by_regexp.rb +7 -6
  94. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  95. data/lib/rubocop/cop/style/semicolon.rb +8 -0
  96. data/lib/rubocop/cop/style/single_argument_dig.rb +5 -2
  97. data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
  98. data/lib/rubocop/cop/style/string_chars.rb +1 -0
  99. data/lib/rubocop/cop/style/strip.rb +7 -4
  100. data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
  101. data/lib/rubocop/cop/style/unpack_first.rb +11 -14
  102. data/lib/rubocop/formatter/html_formatter.rb +1 -2
  103. data/lib/rubocop/result_cache.rb +0 -1
  104. data/lib/rubocop/runner.rb +1 -1
  105. data/lib/rubocop/version.rb +1 -1
  106. data/lib/rubocop.rb +4 -0
  107. metadata +14 -9
@@ -63,6 +63,7 @@ module RuboCop
63
63
  end
64
64
  end
65
65
  # rubocop:enable Metrics
66
+ alias on_csend on_send
66
67
 
67
68
  private
68
69
 
@@ -534,7 +534,7 @@ module RuboCop
534
534
  end
535
535
 
536
536
  def element_assignment?(node)
537
- node.send_type? && node.method_name != :[]=
537
+ node.send_type? && !node.method?(:[]=)
538
538
  end
539
539
 
540
540
  def extract_branches(node)
@@ -49,12 +49,12 @@ module RuboCop
49
49
  class DateTime < Base
50
50
  extend AutoCorrector
51
51
 
52
- CLASS_MSG = 'Prefer Time over DateTime.'
53
- COERCION_MSG = 'Do not use #to_datetime.'
52
+ CLASS_MSG = 'Prefer `Time` over `DateTime`.'
53
+ COERCION_MSG = 'Do not use `#to_datetime`.'
54
54
 
55
55
  # @!method date_time?(node)
56
56
  def_node_matcher :date_time?, <<~PATTERN
57
- (send (const {nil? (cbase)} :DateTime) ...)
57
+ (call (const {nil? (cbase)} :DateTime) ...)
58
58
  PATTERN
59
59
 
60
60
  # @!method historic_date?(node)
@@ -64,7 +64,7 @@ module RuboCop
64
64
 
65
65
  # @!method to_datetime?(node)
66
66
  def_node_matcher :to_datetime?, <<~PATTERN
67
- (send _ :to_datetime)
67
+ (call _ :to_datetime)
68
68
  PATTERN
69
69
 
70
70
  def on_send(node)
@@ -75,6 +75,7 @@ module RuboCop
75
75
 
76
76
  add_offense(node, message: message) { |corrector| autocorrect(corrector, node) }
77
77
  end
78
+ alias on_csend on_send
78
79
 
79
80
  private
80
81
 
@@ -58,12 +58,12 @@ module RuboCop
58
58
 
59
59
  # @!method each_with_object_block_candidate?(node)
60
60
  def_node_matcher :each_with_object_block_candidate?, <<~PATTERN
61
- (block $(send _ {:inject :reduce} _) $_ $_)
61
+ (block $(call _ {:inject :reduce} _) $_ $_)
62
62
  PATTERN
63
63
 
64
64
  # @!method each_with_object_numblock_candidate?(node)
65
65
  def_node_matcher :each_with_object_numblock_candidate?, <<~PATTERN
66
- (numblock $(send _ {:inject :reduce} _) 2 $_)
66
+ (numblock $(call _ {:inject :reduce} _) 2 $_)
67
67
  PATTERN
68
68
 
69
69
  def autocorrect_block(corrector, node, return_value)
@@ -83,7 +83,7 @@ module RuboCop
83
83
  parent = node.parent
84
84
  return false unless parent && %i[send super zsuper].include?(parent.type)
85
85
 
86
- node.equal?(parent.arguments.first) && !parentheses?(node.parent)
86
+ node.equal?(parent.first_argument) && !parentheses?(node.parent)
87
87
  end
88
88
 
89
89
  def replacement_range(node)
@@ -84,7 +84,7 @@ module RuboCop
84
84
  # are considered.
85
85
  return if node.method?(:eval) && !valid_eval_receiver?(node.receiver)
86
86
 
87
- code = node.arguments.first
87
+ code = node.first_argument
88
88
  return unless code && (code.str_type? || code.dstr_type?)
89
89
 
90
90
  check_location(node, code)
@@ -165,7 +165,7 @@ module RuboCop
165
165
  end
166
166
 
167
167
  def check_line(node, code)
168
- line_node = node.arguments.last
168
+ line_node = node.last_argument
169
169
  line_diff = line_difference(line_node, code)
170
170
  if line_diff.zero?
171
171
  add_offense_for_same_line(node, line_node)
@@ -227,7 +227,7 @@ module RuboCop
227
227
  end
228
228
 
229
229
  def missing_line(node, code)
230
- line_diff = line_difference(node.arguments.last, code)
230
+ line_diff = line_difference(node.last_argument, code)
231
231
  sign = line_diff.positive? ? :+ : :-
232
232
  expected_line(sign, line_diff)
233
233
  end
@@ -30,7 +30,7 @@ module RuboCop
30
30
 
31
31
  # @!method exact_regexp_match(node)
32
32
  def_node_matcher :exact_regexp_match, <<~PATTERN
33
- (send
33
+ (call
34
34
  _ {:=~ :=== :!~ :match :match?}
35
35
  (regexp
36
36
  (str $_)
@@ -49,6 +49,7 @@ module RuboCop
49
49
  corrector.replace(node, prefer)
50
50
  end
51
51
  end
52
+ alias on_csend on_send
52
53
 
53
54
  private
54
55
 
@@ -86,7 +86,7 @@ module RuboCop
86
86
 
87
87
  def extract_block_name(def_node)
88
88
  if def_node.block_argument?
89
- def_node.arguments.last.name
89
+ def_node.last_argument.name
90
90
  else
91
91
  'block'
92
92
  end
@@ -127,7 +127,7 @@ module RuboCop
127
127
  end
128
128
 
129
129
  def insert_argument(node, corrector, block_name)
130
- last_arg = node.arguments.last
130
+ last_arg = node.last_argument
131
131
  arg_range = range_with_surrounding_comma(last_arg.source_range, :right)
132
132
  replacement = " &#{block_name}"
133
133
  replacement = ",#{replacement}" unless arg_range.source.end_with?(',')
@@ -17,10 +17,16 @@ module RuboCop
17
17
  # @example
18
18
  # # bad
19
19
  # hash.keys.each { |k| p k }
20
- # hash.values.each { |v| p v }
20
+ # hash.each { |k, unused_value| p k }
21
21
  #
22
22
  # # good
23
23
  # hash.each_key { |k| p k }
24
+ #
25
+ # # bad
26
+ # hash.values.each { |v| p v }
27
+ # hash.each { |unused_key, v| p v }
28
+ #
29
+ # # good
24
30
  # hash.each_value { |v| p v }
25
31
  #
26
32
  # @example AllowedReceivers: ['execute']
@@ -33,22 +39,46 @@ module RuboCop
33
39
  extend AutoCorrector
34
40
 
35
41
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
42
+ UNUSED_BLOCK_ARG_MSG = "#{MSG.chop} and remove the unused `%<unused_code>s` block argument."
36
43
 
37
44
  # @!method kv_each(node)
38
45
  def_node_matcher :kv_each, <<~PATTERN
39
- ({block numblock} $(send (send _ ${:keys :values}) :each) ...)
46
+ ({block numblock} $(call (call _ ${:keys :values}) :each) ...)
47
+ PATTERN
48
+
49
+ # @!method each_arguments(node)
50
+ def_node_matcher :each_arguments, <<~PATTERN
51
+ (block (call _ :each)(args $_key $_value) ...)
40
52
  PATTERN
41
53
 
42
54
  # @!method kv_each_with_block_pass(node)
43
55
  def_node_matcher :kv_each_with_block_pass, <<~PATTERN
44
- (send $(send _ ${:keys :values}) :each (block_pass (sym _)))
56
+ (call $(call _ ${:keys :values}) :each (block_pass (sym _)))
45
57
  PATTERN
46
58
 
59
+ # rubocop:disable Metrics/AbcSize
47
60
  def on_block(node)
61
+ return unless handleable?(node)
62
+
48
63
  kv_each(node) do |target, method|
49
- register_kv_offense(target, method)
64
+ register_kv_offense(target, method) and return
65
+ end
66
+
67
+ return unless (key, value = each_arguments(node))
68
+
69
+ if unused_block_arg_exist?(node, value)
70
+ message = message('each_key', node.method_name, value.source)
71
+ unused_range = key.source_range.end.join(value.source_range.end)
72
+
73
+ register_each_args_offense(node, message, 'each_key', unused_range)
74
+ elsif unused_block_arg_exist?(node, key)
75
+ message = message('each_value', node.method_name, key.source)
76
+ unused_range = key.source_range.begin.join(value.source_range.begin)
77
+
78
+ register_each_args_offense(node, message, 'each_value', unused_range)
50
79
  end
51
80
  end
81
+ # rubocop:enable Metrics/AbcSize
52
82
 
53
83
  alias on_numblock on_block
54
84
 
@@ -60,27 +90,70 @@ module RuboCop
60
90
 
61
91
  private
62
92
 
93
+ def handleable?(node)
94
+ return false unless (root_receiver = root_receiver(node))
95
+
96
+ !root_receiver.literal? || root_receiver.hash_type?
97
+ end
98
+
63
99
  def register_kv_offense(target, method)
64
100
  return unless (parent_receiver = target.receiver.receiver)
65
101
  return if allowed_receiver?(parent_receiver)
66
102
 
67
- add_offense(kv_range(target), message: format_message(method)) do |corrector|
103
+ current = target.receiver.loc.selector.join(target.source_range.end).source
104
+
105
+ add_offense(kv_range(target), message: format_message(method, current)) do |corrector|
68
106
  correct_key_value_each(target, corrector)
69
107
  end
70
108
  end
71
109
 
110
+ def unused_block_arg_exist?(node, block_arg)
111
+ lvar_sources = node.body.each_descendant(:lvar).map(&:source)
112
+
113
+ if block_arg.mlhs_type?
114
+ block_arg.each_descendant(:arg).all? do |block_arg|
115
+ lvar_sources.none?(block_arg.source)
116
+ end
117
+ else
118
+ lvar_sources.none?(block_arg.source)
119
+ end
120
+ end
121
+
122
+ def message(prefer, method_name, unused_code)
123
+ format(
124
+ UNUSED_BLOCK_ARG_MSG, prefer: prefer, current: method_name, unused_code: unused_code
125
+ )
126
+ end
127
+
128
+ def register_each_args_offense(node, message, prefer, unused_range)
129
+ add_offense(node, message: message) do |corrector|
130
+ corrector.replace(node.send_node.loc.selector, prefer)
131
+ corrector.remove(unused_range)
132
+ end
133
+ end
134
+
72
135
  def register_kv_with_block_pass_offense(node, target, method)
73
136
  return unless (parent_receiver = node.parent.receiver.receiver)
74
137
  return if allowed_receiver?(parent_receiver)
75
138
 
76
- range = target.loc.selector.with(end_pos: node.parent.loc.selector.end_pos)
77
- add_offense(range, message: format_message(method)) do |corrector|
139
+ range = target.loc.selector.join(node.parent.loc.selector.end)
140
+
141
+ add_offense(range, message: format_message(method, range.source)) do |corrector|
78
142
  corrector.replace(range, "each_#{method[0..-2]}")
79
143
  end
80
144
  end
81
145
 
82
- def format_message(method_name)
83
- format(MSG, prefer: "each_#{method_name[0..-2]}", current: "#{method_name}.each")
146
+ def root_receiver(node)
147
+ receiver = node.receiver
148
+ if receiver&.receiver
149
+ root_receiver(receiver)
150
+ else
151
+ receiver
152
+ end
153
+ end
154
+
155
+ def format_message(method_name, current)
156
+ format(MSG, prefer: "each_#{method_name[0..-2]}", current: current)
84
157
  end
85
158
 
86
159
  def check_argument(variable)
@@ -103,7 +176,7 @@ module RuboCop
103
176
  name = "each_#{node.receiver.method_name.to_s.chop}"
104
177
  return correct_implicit(node, corrector, name) unless receiver
105
178
 
106
- new_source = receiver.source + ".#{name}"
179
+ new_source = receiver.source + "#{node.loc.dot.source}#{name}"
107
180
  corrector.replace(node, new_source)
108
181
  end
109
182
 
@@ -43,7 +43,7 @@ module RuboCop
43
43
  # @!method bad_method_with_poro?(node)
44
44
  def_node_matcher :bad_method_with_poro?, <<~PATTERN
45
45
  (block
46
- (send _ _)
46
+ (call _ _)
47
47
  (args
48
48
  $(arg _)
49
49
  (arg _))
@@ -86,6 +86,7 @@ module RuboCop
86
86
  corrector.replace(range, preferred_method)
87
87
  end
88
88
  end
89
+ alias on_csend on_send
89
90
 
90
91
  private
91
92
 
@@ -60,17 +60,17 @@ module RuboCop
60
60
  # @!method inverse_candidate?(node)
61
61
  def_node_matcher :inverse_candidate?, <<~PATTERN
62
62
  {
63
- (send $(send $(...) $_ $...) :!)
64
- (send ({block numblock} $(send $(...) $_) $...) :!)
65
- (send (begin $(send $(...) $_ $...)) :!)
63
+ (send $(call $(...) $_ $...) :!)
64
+ (send ({block numblock} $(call $(...) $_) $...) :!)
65
+ (send (begin $(call $(...) $_ $...)) :!)
66
66
  }
67
67
  PATTERN
68
68
 
69
69
  # @!method inverse_block?(node)
70
70
  def_node_matcher :inverse_block?, <<~PATTERN
71
- ({block numblock} $(send (...) $_) ... { $(send ... :!)
71
+ ({block numblock} $(call (...) $_) ... { $(call ... :!)
72
72
  $(send (...) {:!= :!~} ...)
73
- (begin ... $(send ... :!))
73
+ (begin ... $(call ... :!))
74
74
  (begin ... $(send (...) {:!= :!~} ...))
75
75
  })
76
76
  PATTERN
@@ -87,6 +87,7 @@ module RuboCop
87
87
  end
88
88
  end
89
89
  end
90
+ alias on_csend on_send
90
91
 
91
92
  def on_block(node)
92
93
  inverse_block?(node) do |_method_call, method, block|
@@ -44,9 +44,9 @@ module RuboCop
44
44
 
45
45
  # @!method map_and_compact?(node)
46
46
  def_node_matcher :map_and_compact?, <<~RUBY
47
- (send
47
+ (call
48
48
  (block
49
- (send _ :map)
49
+ (call _ :map)
50
50
  (args
51
51
  $(arg _))
52
52
  {
@@ -85,6 +85,7 @@ module RuboCop
85
85
  end
86
86
  end
87
87
  end
88
+ alias on_csend on_send
88
89
 
89
90
  private
90
91
 
@@ -34,21 +34,25 @@ module RuboCop
34
34
 
35
35
  minimum_target_ruby_version 2.6
36
36
 
37
- MSG = 'Pass a block to `to_h` instead of calling `%<method>s.to_h`.'
37
+ MSG = 'Pass a block to `to_h` instead of calling `%<method>s%<dot>sto_h`.'
38
38
  RESTRICT_ON_SEND = %i[to_h].freeze
39
39
 
40
40
  # @!method map_to_h?(node)
41
41
  def_node_matcher :map_to_h?, <<~PATTERN
42
42
  {
43
- $(send ({block numblock} $(send _ {:map :collect}) ...) :to_h)
44
- $(send $(send _ {:map :collect} (block_pass sym)) :to_h)
43
+ $(call ({block numblock} $(call _ {:map :collect}) ...) :to_h)
44
+ $(call $(call _ {:map :collect} (block_pass sym)) :to_h)
45
45
  }
46
46
  PATTERN
47
47
 
48
+ def self.autocorrect_incompatible_with
49
+ [Layout::SingleLineBlockChain]
50
+ end
51
+
48
52
  def on_send(node)
49
53
  return unless (to_h_node, map_node = map_to_h?(node))
50
54
 
51
- message = format(MSG, method: map_node.loc.selector.source)
55
+ message = format(MSG, method: map_node.loc.selector.source, dot: map_node.loc.dot.source)
52
56
  add_offense(map_node.loc.selector, message: message) do |corrector|
53
57
  # If the `to_h` call already has a block, do not autocorrect.
54
58
  next if to_h_node.block_node
@@ -56,6 +60,7 @@ module RuboCop
56
60
  autocorrect(corrector, to_h_node, map_node)
57
61
  end
58
62
  end
63
+ alias on_csend on_send
59
64
 
60
65
  private
61
66
 
@@ -63,6 +68,7 @@ module RuboCop
63
68
  removal_range = range_between(to_h.loc.dot.begin_pos, to_h.loc.selector.end_pos)
64
69
 
65
70
  corrector.remove(range_with_surrounding_space(removal_range, side: :left))
71
+ corrector.replace(map.loc.dot, '.') if to_h.dot?
66
72
  corrector.replace(map.loc.selector, 'to_h')
67
73
  end
68
74
  end
@@ -86,6 +86,7 @@ module RuboCop
86
86
 
87
87
  def legitimate_call_with_parentheses?(node) # rubocop:disable Metrics/PerceivedComplexity
88
88
  call_in_literals?(node) ||
89
+ node.parent&.when_type? ||
89
90
  call_with_ambiguous_arguments?(node) ||
90
91
  call_in_logical_operators?(node) ||
91
92
  call_in_optional_arguments?(node) ||
@@ -239,7 +239,7 @@ module RuboCop
239
239
  def args_parenthesized?(node)
240
240
  return false unless node.arguments.one?
241
241
 
242
- first_node = node.arguments.first
242
+ first_node = node.first_argument
243
243
  first_node.begin_type? && first_node.parenthesized_call?
244
244
  end
245
245
  end
@@ -8,6 +8,9 @@ module RuboCop
8
8
  # This cop can be customized allowed methods with `AllowedMethods`.
9
9
  # By default, there are no methods to allowed.
10
10
  #
11
+ # NOTE: This cop allows the use of `it()` without arguments in blocks,
12
+ # as in `0.times { it() }`, following `Lint/ItWithoutArgumentsInBlock` cop.
13
+ #
11
14
  # @example
12
15
  # # bad
13
16
  # object.some_method()
@@ -30,15 +33,18 @@ module RuboCop
30
33
 
31
34
  MSG = 'Do not use parentheses for method calls with no arguments.'
32
35
 
36
+ # rubocop:disable Metrics/CyclomaticComplexity
33
37
  def on_send(node)
34
38
  return unless !node.arguments? && node.parenthesized?
35
39
  return if ineligible_node?(node)
36
40
  return if default_argument?(node)
37
41
  return if allowed_method_name?(node.method_name)
38
42
  return if same_name_assignment?(node)
43
+ return if parenthesized_it_method_in_block?(node)
39
44
 
40
45
  register_offense(node)
41
46
  end
47
+ # rubocop:enable Metrics/CyclomaticComplexity
42
48
 
43
49
  private
44
50
 
@@ -71,6 +77,20 @@ module RuboCop
71
77
  end
72
78
  end
73
79
 
80
+ # Respects `Lint/ItWithoutArgumentsInBlock` cop and the following Ruby 3.3's warning:
81
+ #
82
+ # $ ruby -e '0.times { begin; it; end }'
83
+ # -e:1: warning: `it` calls without arguments will refer to the first block param in
84
+ # Ruby 3.4; use it() or self.it
85
+ #
86
+ def parenthesized_it_method_in_block?(node)
87
+ return false unless node.method?(:it)
88
+ return false unless (block_node = node.each_ancestor(:block).first)
89
+ return false unless block_node.arguments.empty_and_without_delimiters?
90
+
91
+ !node.receiver && node.arguments.empty? && !node.block_literal?
92
+ end
93
+
74
94
  def any_assignment?(node)
75
95
  node.each_ancestor(*AST::Node::ASSIGNMENTS).any? do |asgn_node|
76
96
  # `obj.method = value` parses as (send ... :method= ...), and will
@@ -170,7 +170,7 @@ module RuboCop
170
170
  return true if node.arguments.any? do |arg|
171
171
  arg.forward_arg_type? || arg.restarg_type? || arg.kwrestarg_type?
172
172
  end
173
- return false unless (last_argument = node.arguments.last)
173
+ return false unless (last_argument = node.last_argument)
174
174
 
175
175
  last_argument.blockarg_type? && last_argument.name.nil?
176
176
  end
@@ -7,12 +7,12 @@ module RuboCop
7
7
  # defining `respond_to_missing?`.
8
8
  #
9
9
  # @example
10
- # #bad
10
+ # # bad
11
11
  # def method_missing(name, *args)
12
12
  # # ...
13
13
  # end
14
14
  #
15
- # #good
15
+ # # good
16
16
  # def respond_to_missing?(name, include_private)
17
17
  # # ...
18
18
  # end
@@ -66,7 +66,7 @@ module RuboCop
66
66
  end
67
67
 
68
68
  def on_block(node)
69
- return unless node.send_node.send_type? && node.send_node.enumerator_method?
69
+ return unless node.send_node.call_type? && node.send_node.enumerator_method?
70
70
 
71
71
  check(node)
72
72
  end
@@ -4,8 +4,8 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # Checks for redundant dot before operator method call.
7
- # The target operator methods are `|`, `^`, `&`, `<=>`, `==`, `===`, `=~`, `>`, `>=`, `<`,
8
- # `<=`, `<<`, `>>`, `+`, `-`, `*`, `/`, `%`, `**`, `~`, `!`, `!=`, and `!~`.
7
+ # The target operator methods are `|`, `^`, `&`, ``<=>``, `==`, `===`, `=~`, `>`, `>=`, `<`,
8
+ # ``<=``, `<<`, `>>`, `+`, `-`, `*`, `/`, `%`, `**`, `~`, `!`, `!=`, and `!~`.
9
9
  #
10
10
  # @example
11
11
  #
@@ -67,12 +67,13 @@ module RuboCop
67
67
  return unless redundant_argument?(node)
68
68
 
69
69
  offense_range = argument_range(node)
70
- message = format(MSG, arg: node.arguments.first.source)
70
+ message = format(MSG, arg: node.first_argument.source)
71
71
 
72
72
  add_offense(offense_range, message: message) do |corrector|
73
73
  corrector.remove(offense_range)
74
74
  end
75
75
  end
76
+ alias on_csend on_send
76
77
 
77
78
  private
78
79
 
@@ -80,7 +81,7 @@ module RuboCop
80
81
  redundant_argument = redundant_arg_for_method(node.method_name.to_s)
81
82
  return false if redundant_argument.nil?
82
83
 
83
- node.arguments.first == redundant_argument
84
+ node.first_argument == redundant_argument
84
85
  end
85
86
 
86
87
  def redundant_arg_for_method(method_name)
@@ -25,20 +25,20 @@ module RuboCop
25
25
  MSG = 'Remove the redundant double splat and braces, use keyword arguments directly.'
26
26
  MERGE_METHODS = %i[merge merge!].freeze
27
27
 
28
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
28
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
29
29
  def on_hash(node)
30
30
  return if node.pairs.empty? || node.pairs.any?(&:hash_rocket?)
31
31
  return unless (parent = node.parent)
32
32
  return unless parent.call_type? || parent.kwsplat_type?
33
33
  return unless mergeable?(parent)
34
34
  return unless (kwsplat = node.each_ancestor(:kwsplat).first)
35
- return if allowed_double_splat_receiver?(kwsplat)
35
+ return if !node.braces? || allowed_double_splat_receiver?(kwsplat)
36
36
 
37
37
  add_offense(kwsplat) do |corrector|
38
38
  autocorrect(corrector, node, kwsplat)
39
39
  end
40
40
  end
41
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
41
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
42
42
 
43
43
  private
44
44
 
@@ -47,7 +47,7 @@ module RuboCop
47
47
  # @!method redundant_fetch_block_candidate?(node)
48
48
  def_node_matcher :redundant_fetch_block_candidate?, <<~PATTERN
49
49
  (block
50
- $(send _ :fetch _)
50
+ $(call _ :fetch _)
51
51
  (args)
52
52
  ${nil? #basic_literal? #const_type?})
53
53
  PATTERN
@@ -61,10 +61,10 @@ module RuboCop
61
61
  bad = build_bad_method(send, body)
62
62
 
63
63
  add_offense(range, message: format(MSG, good: good, bad: bad)) do |corrector|
64
- receiver, _, key = send.children
64
+ _, _, key = send.children
65
65
  default_value = body ? body.source : 'nil'
66
66
 
67
- corrector.replace(node, "#{receiver.source}.fetch(#{key.source}, #{default_value})")
67
+ corrector.replace(range, "fetch(#{key.source}, #{default_value})")
68
68
  end
69
69
  end
70
70
  end
@@ -107,6 +107,8 @@ module RuboCop
107
107
 
108
108
  def inside_string_literal_or_method_with_argument?(range)
109
109
  processed_source.tokens.each_cons(2).any? do |token, next_token|
110
+ next if token.line == next_token.line
111
+
110
112
  inside_string_literal?(range, token) || method_with_argument?(token, next_token)
111
113
  end
112
114
  end