rubocop 1.57.2 → 1.62.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +4 -4
  4. data/assets/output.css.erb +159 -0
  5. data/assets/output.html.erb +1 -160
  6. data/config/default.yml +87 -15
  7. data/lib/rubocop/cli/command/auto_generate_config.rb +12 -3
  8. data/lib/rubocop/cli/command/lsp.rb +2 -2
  9. data/lib/rubocop/cli.rb +6 -1
  10. data/lib/rubocop/config.rb +4 -2
  11. data/lib/rubocop/config_finder.rb +12 -2
  12. data/lib/rubocop/config_loader.rb +0 -1
  13. data/lib/rubocop/config_obsoletion.rb +11 -8
  14. data/lib/rubocop/config_validator.rb +14 -7
  15. data/lib/rubocop/cop/autocorrect_logic.rb +6 -1
  16. data/lib/rubocop/cop/base.rb +17 -2
  17. data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
  18. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
  19. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +5 -13
  20. data/lib/rubocop/cop/exclude_limit.rb +1 -1
  21. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +2 -2
  22. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +5 -1
  23. data/lib/rubocop/cop/internal_affairs/example_description.rb +4 -4
  24. data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
  25. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +19 -20
  26. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
  27. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +123 -29
  28. data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
  29. data/lib/rubocop/cop/internal_affairs.rb +2 -0
  30. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  31. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +14 -7
  32. data/lib/rubocop/cop/layout/end_alignment.rb +8 -2
  33. data/lib/rubocop/cop/layout/extra_spacing.rb +4 -10
  34. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +22 -7
  35. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  36. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  37. data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -1
  38. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +1 -1
  39. data/lib/rubocop/cop/layout/redundant_line_break.rb +16 -3
  40. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -4
  41. data/lib/rubocop/cop/layout/single_line_block_chain.rb +5 -0
  42. data/lib/rubocop/cop/layout/space_around_operators.rb +50 -20
  43. data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
  44. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
  45. data/lib/rubocop/cop/lint/assignment_in_condition.rb +4 -4
  46. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
  47. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
  48. data/lib/rubocop/cop/lint/debugger.rb +2 -1
  49. data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
  50. data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
  51. data/lib/rubocop/cop/lint/erb_new_arguments.rb +3 -3
  52. data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
  53. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
  54. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
  55. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +85 -0
  56. data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
  57. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -5
  58. data/lib/rubocop/cop/lint/number_conversion.rb +9 -4
  59. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +54 -6
  60. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -2
  61. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  62. data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
  63. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -4
  64. data/lib/rubocop/cop/lint/script_permission.rb +3 -3
  65. data/lib/rubocop/cop/lint/self_assignment.rb +38 -0
  66. data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
  67. data/lib/rubocop/cop/lint/symbol_conversion.rb +7 -2
  68. data/lib/rubocop/cop/lint/syntax.rb +6 -3
  69. data/lib/rubocop/cop/lint/to_enum_arguments.rb +7 -2
  70. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
  71. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
  72. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  73. data/lib/rubocop/cop/lint/useless_times.rb +2 -2
  74. data/lib/rubocop/cop/lint/void.rb +20 -2
  75. data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
  76. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  77. data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -0
  78. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  79. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
  80. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  81. data/lib/rubocop/cop/naming/block_forwarding.rb +12 -4
  82. data/lib/rubocop/cop/naming/constant_name.rb +1 -2
  83. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  84. data/lib/rubocop/cop/naming/predicate_name.rb +2 -2
  85. data/lib/rubocop/cop/registry.rb +1 -1
  86. data/lib/rubocop/cop/security/open.rb +2 -2
  87. data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -2
  88. data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
  89. data/lib/rubocop/cop/style/arguments_forwarding.rb +152 -21
  90. data/lib/rubocop/cop/style/array_first_last.rb +64 -0
  91. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
  92. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
  93. data/lib/rubocop/cop/style/case_like_if.rb +5 -5
  94. data/lib/rubocop/cop/style/class_check.rb +1 -0
  95. data/lib/rubocop/cop/style/class_vars.rb +3 -3
  96. data/lib/rubocop/cop/style/collection_compact.rb +18 -8
  97. data/lib/rubocop/cop/style/combinable_loops.rb +13 -7
  98. data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
  99. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -0
  100. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -7
  101. data/lib/rubocop/cop/style/date_time.rb +5 -4
  102. data/lib/rubocop/cop/style/each_for_simple_loop.rb +7 -7
  103. data/lib/rubocop/cop/style/each_with_object.rb +2 -2
  104. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  105. data/lib/rubocop/cop/style/eval_with_location.rb +3 -14
  106. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -1
  107. data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
  108. data/lib/rubocop/cop/style/for.rb +2 -0
  109. data/lib/rubocop/cop/style/hash_each_methods.rb +105 -11
  110. data/lib/rubocop/cop/style/hash_except.rb +2 -1
  111. data/lib/rubocop/cop/style/hash_syntax.rb +6 -2
  112. data/lib/rubocop/cop/style/identical_conditional_branches.rb +4 -1
  113. data/lib/rubocop/cop/style/inverse_methods.rb +14 -13
  114. data/lib/rubocop/cop/style/invertible_unless_condition.rb +44 -2
  115. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +8 -10
  116. data/lib/rubocop/cop/style/map_to_hash.rb +17 -7
  117. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +14 -5
  118. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -4
  119. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +20 -0
  120. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  121. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
  122. data/lib/rubocop/cop/style/multiline_method_signature.rb +10 -1
  123. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +5 -3
  124. data/lib/rubocop/cop/style/next.rb +1 -1
  125. data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
  126. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +1 -1
  127. data/lib/rubocop/cop/style/object_then.rb +5 -3
  128. data/lib/rubocop/cop/style/operator_method_call.rb +2 -2
  129. data/lib/rubocop/cop/style/parallel_assignment.rb +3 -5
  130. data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -0
  131. data/lib/rubocop/cop/style/raise_args.rb +4 -1
  132. data/lib/rubocop/cop/style/redundant_argument.rb +4 -3
  133. data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
  134. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +4 -3
  135. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +3 -3
  136. data/lib/rubocop/cop/style/redundant_each.rb +7 -4
  137. data/lib/rubocop/cop/style/redundant_fetch_block.rb +3 -3
  138. data/lib/rubocop/cop/style/redundant_line_continuation.rb +27 -7
  139. data/lib/rubocop/cop/style/redundant_parentheses.rb +33 -10
  140. data/lib/rubocop/cop/style/redundant_return.rb +7 -1
  141. data/lib/rubocop/cop/style/redundant_self.rb +17 -2
  142. data/lib/rubocop/cop/style/redundant_sort.rb +9 -8
  143. data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
  144. data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -1
  145. data/lib/rubocop/cop/style/sample.rb +3 -4
  146. data/lib/rubocop/cop/style/select_by_regexp.rb +7 -6
  147. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  148. data/lib/rubocop/cop/style/semicolon.rb +8 -0
  149. data/lib/rubocop/cop/style/single_argument_dig.rb +5 -2
  150. data/lib/rubocop/cop/style/slicing_with_range.rb +76 -10
  151. data/lib/rubocop/cop/style/string_chars.rb +1 -0
  152. data/lib/rubocop/cop/style/strip.rb +7 -4
  153. data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
  154. data/lib/rubocop/cop/style/symbol_proc.rb +36 -0
  155. data/lib/rubocop/cop/style/unpack_first.rb +11 -14
  156. data/lib/rubocop/cop/utils/regexp_ranges.rb +1 -1
  157. data/lib/rubocop/cops_documentation_generator.rb +15 -3
  158. data/lib/rubocop/directive_comment.rb +10 -8
  159. data/lib/rubocop/ext/regexp_node.rb +9 -4
  160. data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
  161. data/lib/rubocop/formatter/html_formatter.rb +31 -12
  162. data/lib/rubocop/formatter/json_formatter.rb +0 -1
  163. data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
  164. data/lib/rubocop/formatter.rb +1 -1
  165. data/lib/rubocop/lsp/logger.rb +1 -1
  166. data/lib/rubocop/lsp/routes.rb +2 -2
  167. data/lib/rubocop/lsp/runtime.rb +1 -1
  168. data/lib/rubocop/lsp/server.rb +5 -2
  169. data/lib/rubocop/lsp/severity.rb +1 -1
  170. data/lib/rubocop/lsp.rb +29 -0
  171. data/lib/rubocop/magic_comment.rb +1 -1
  172. data/lib/rubocop/options.rb +11 -8
  173. data/lib/rubocop/path_util.rb +6 -2
  174. data/lib/rubocop/result_cache.rb +0 -1
  175. data/lib/rubocop/rspec/cop_helper.rb +8 -2
  176. data/lib/rubocop/rspec/expect_offense.rb +8 -8
  177. data/lib/rubocop/rspec/shared_contexts.rb +40 -15
  178. data/lib/rubocop/rspec/support.rb +2 -0
  179. data/lib/rubocop/runner.rb +10 -3
  180. data/lib/rubocop/server/cache.rb +1 -2
  181. data/lib/rubocop/server/client_command/exec.rb +0 -1
  182. data/lib/rubocop/server/server_command/exec.rb +0 -1
  183. data/lib/rubocop/target_finder.rb +84 -78
  184. data/lib/rubocop/target_ruby.rb +82 -80
  185. data/lib/rubocop/version.rb +18 -3
  186. data/lib/rubocop.rb +4 -0
  187. metadata +18 -10
  188. /data/lib/rubocop/formatter/{git_hub_actions_formatter.rb → github_actions_formatter.rb} +0 -0
@@ -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) ||
@@ -126,23 +127,31 @@ module RuboCop
126
127
 
127
128
  def call_with_ambiguous_arguments?(node) # rubocop:disable Metrics/PerceivedComplexity
128
129
  call_with_braced_block?(node) ||
130
+ call_in_argument_with_block?(node) ||
129
131
  call_as_argument_or_chain?(node) ||
130
132
  call_in_match_pattern?(node) ||
131
133
  hash_literal_in_arguments?(node) ||
132
134
  node.descendants.any? do |n|
133
- n.forwarded_args_type? || ambiguous_literal?(n) || logical_operator?(n) ||
134
- call_with_braced_block?(n)
135
+ n.forwarded_args_type? || n.block_type? || n.numblock_type? ||
136
+ ambiguous_literal?(n) || logical_operator?(n)
135
137
  end
136
138
  end
137
139
 
138
140
  def call_with_braced_block?(node)
139
- (node.send_type? || node.super_type?) && node.block_node&.braces?
141
+ (node.call_type? || node.super_type?) && node.block_node&.braces?
142
+ end
143
+
144
+ def call_in_argument_with_block?(node)
145
+ parent = node.parent&.block_type? && node.parent&.parent
146
+ return false unless parent
147
+
148
+ parent.call_type? || parent.super_type? || parent.yield_type?
140
149
  end
141
150
 
142
151
  def call_as_argument_or_chain?(node)
143
152
  node.parent &&
144
- ((node.parent.send_type? && !assigned_before?(node.parent, node)) ||
145
- node.parent.csend_type? || node.parent.super_type? || node.parent.yield_type?)
153
+ (node.parent.call_type? || node.parent.super_type? || node.parent.yield_type?) &&
154
+ !assigned_before?(node.parent, node)
146
155
  end
147
156
 
148
157
  def call_in_match_pattern?(node)
@@ -218,15 +218,13 @@ module RuboCop
218
218
  send(style, node) # call require_parentheses or omit_parentheses
219
219
  end
220
220
  alias on_csend on_send
221
- alias on_super on_send
222
221
  alias on_yield on_send
223
222
 
224
223
  private
225
224
 
226
225
  def args_begin(node)
227
226
  loc = node.loc
228
- selector =
229
- node.super_type? || node.yield_type? ? loc.keyword : loc.selector
227
+ selector = node.yield_type? ? loc.keyword : loc.selector
230
228
 
231
229
  resize_by = args_parenthesized?(node) ? 2 : 1
232
230
  selector.end.resize(resize_by)
@@ -239,7 +237,7 @@ module RuboCop
239
237
  def args_parenthesized?(node)
240
238
  return false unless node.arguments.one?
241
239
 
242
- first_node = node.arguments.first
240
+ first_node = node.first_argument
243
241
  first_node.begin_type? && first_node.parenthesized_call?
244
242
  end
245
243
  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
@@ -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
@@ -47,19 +47,21 @@ module RuboCop
47
47
  message = enforce_single_line_ternary_operator?(node) ? MSG_SINGLE_LINE : MSG_IF
48
48
 
49
49
  add_offense(node, message: message) do |corrector|
50
+ next if part_of_ignored_node?(node)
51
+
50
52
  autocorrect(corrector, node)
53
+
54
+ ignore_node(node)
51
55
  end
52
56
  end
53
57
 
54
58
  private
55
59
 
56
60
  def offense?(node)
57
- node.ternary? && node.multiline?
61
+ node.ternary? && node.multiline? && node.source != replacement(node)
58
62
  end
59
63
 
60
64
  def autocorrect(corrector, node)
61
- return unless offense?(node)
62
-
63
65
  corrector.replace(node, replacement(node))
64
66
  return unless (parent = node.parent)
65
67
  return unless (comments_in_condition = comments_in_condition(node))
@@ -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
@@ -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?
@@ -62,7 +62,7 @@ module RuboCop
62
62
  private
63
63
 
64
64
  def message(node)
65
- self.class.const_get("#{literal_type(node).upcase}_MSG")
65
+ self.class.const_get(:"#{literal_type(node).upcase}_MSG")
66
66
  end
67
67
 
68
68
  def literal_type(node)
@@ -46,15 +46,17 @@ module RuboCop
46
46
  private
47
47
 
48
48
  def check_method_node(node)
49
- return unless preferred_method(node)
49
+ return unless preferred_method?(node)
50
50
 
51
51
  message = message(node)
52
52
  add_offense(node.loc.selector, message: message) do |corrector|
53
- corrector.replace(node.loc.selector, style.to_s)
53
+ prefer = style == :then && node.receiver.nil? ? 'self.then' : style
54
+
55
+ corrector.replace(node.loc.selector, prefer)
54
56
  end
55
57
  end
56
58
 
57
- def preferred_method(node)
59
+ def preferred_method?(node)
58
60
  case style
59
61
  when :then
60
62
  node.method?(:yield_self)
@@ -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
  #
@@ -142,8 +142,8 @@ module RuboCop
142
142
  @assignments = assignments
143
143
  end
144
144
 
145
- def tsort_each_node(&block)
146
- @assignments.each(&block)
145
+ def tsort_each_node(...)
146
+ @assignments.each(...)
147
147
  end
148
148
 
149
149
  def tsort_each_child(assignment)
@@ -289,9 +289,7 @@ module RuboCop
289
289
  private
290
290
 
291
291
  def modifier_range(node)
292
- Parser::Source::Range.new(node.source_range.source_buffer,
293
- node.loc.keyword.begin_pos,
294
- node.source_range.end_pos)
292
+ node.loc.keyword.join(node.source_range.end)
295
293
  end
296
294
  end
297
295
  end
@@ -81,6 +81,7 @@ module RuboCop
81
81
  cond = node.condition
82
82
 
83
83
  control_op_condition(cond) do |first_child, rest_children|
84
+ return if require_parentheses?(node, first_child)
84
85
  return if semicolon_separated_expressions?(first_child, rest_children)
85
86
  return if modifier_op?(first_child)
86
87
  return if parens_allowed?(cond)
@@ -92,6 +93,13 @@ module RuboCop
92
93
  end
93
94
  end
94
95
 
96
+ def require_parentheses?(node, condition_body)
97
+ return false if !node.while_type? && !node.until_type?
98
+ return false if !condition_body.block_type? && !condition_body.numblock_type?
99
+
100
+ condition_body.send_node.block_literal? && condition_body.keywords?
101
+ end
102
+
95
103
  def semicolon_separated_expressions?(first_exp, rest_exps)
96
104
  return false unless (second_exp = rest_exps.first)
97
105
 
@@ -16,6 +16,9 @@ module RuboCop
16
16
  # The exploded style has an `AllowedCompactTypes` configuration
17
17
  # option that takes an Array of exception name Strings.
18
18
  #
19
+ # @safety
20
+ # This cop is unsafe because `raise Foo` calls `Foo.exception`, not `Foo.new`.
21
+ #
19
22
  # @example EnforcedStyle: exploded (default)
20
23
  # # bad
21
24
  # raise StandardError.new('message')
@@ -77,7 +80,7 @@ module RuboCop
77
80
 
78
81
  def correction_exploded_to_compact(node)
79
82
  exception_node, *message_nodes = *node.arguments
80
- return node.source if message_nodes.size > 1
83
+ return if message_nodes.size > 1
81
84
 
82
85
  argument = message_nodes.first.source
83
86
  exception_class = exception_node.receiver&.source || exception_node.source
@@ -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,14 +81,14 @@ 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.source.sub(/\A'/, '"').sub(/'\z/, '"') == redundant_argument
84
85
  end
85
86
 
86
87
  def redundant_arg_for_method(method_name)
87
88
  arg = cop_config['Methods'].fetch(method_name) { return }
88
89
 
89
90
  @mem ||= {}
90
- @mem[method_name] ||= parse(arg.inspect).ast
91
+ @mem[method_name] ||= arg.inspect
91
92
  end
92
93
 
93
94
  def argument_range(node)
@@ -54,12 +54,14 @@ module RuboCop
54
54
 
55
55
  private
56
56
 
57
+ # rubocop:disable Metrics/CyclomaticComplexity
57
58
  def check_branch(node)
58
59
  return unless node
59
60
 
60
61
  case node.type
61
- when :case then check_case_node(node)
62
- when :if then check_if_node(node)
62
+ when :case then check_case_node(node)
63
+ when :case_match then check_case_match_node(node)
64
+ when :if then check_if_node(node)
63
65
  when :rescue, :resbody
64
66
  check_rescue_node(node)
65
67
  when :ensure then check_ensure_node(node)
@@ -67,12 +69,18 @@ module RuboCop
67
69
  check_begin_node(node)
68
70
  end
69
71
  end
72
+ # rubocop:enable Metrics/CyclomaticComplexity
70
73
 
71
74
  def check_case_node(node)
72
75
  node.when_branches.each { |when_node| check_branch(when_node.body) }
73
76
  check_branch(node.else_branch)
74
77
  end
75
78
 
79
+ def check_case_match_node(node)
80
+ node.in_pattern_branches.each { |in_pattern_node| check_branch(in_pattern_node.body) }
81
+ check_branch(node.else_branch)
82
+ end
83
+
76
84
  def check_if_node(node)
77
85
  return if node.modifier_form? || node.ternary?
78
86
 
@@ -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|
@@ -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
 
@@ -56,6 +56,7 @@ module RuboCop
56
56
  end
57
57
  end
58
58
  end
59
+ alias on_csend on_send
59
60
 
60
61
  private
61
62
 
@@ -64,7 +65,7 @@ module RuboCop
64
65
  return if node.last_argument&.block_pass_type?
65
66
 
66
67
  if node.method?(:each) && !node.parent&.block_type?
67
- ancestor_node = node.each_ancestor(:send).detect do |ancestor|
68
+ ancestor_node = node.each_ancestor(:send, :csend).detect do |ancestor|
68
69
  ancestor.receiver == node &&
69
70
  (RESTRICT_ON_SEND.include?(ancestor.method_name) || ancestor.method?(:reverse_each))
70
71
  end
@@ -83,10 +84,12 @@ module RuboCop
83
84
  # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
84
85
 
85
86
  def range(node)
86
- if node.method?(:each)
87
- node.loc.dot.join(node.loc.selector)
87
+ return node.selector unless node.method?(:each)
88
+
89
+ if node.parent.call_type?
90
+ node.selector.join(node.parent.loc.dot)
88
91
  else
89
- node.loc.selector
92
+ node.loc.dot.join(node.selector)
90
93
  end
91
94
  end
92
95
 
@@ -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
@@ -72,7 +72,7 @@ module RuboCop
72
72
  ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
73
73
  ARGUMENT_TYPES = %i[
74
74
  kFALSE kNIL kSELF kTRUE tCONSTANT tCVAR tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR
75
- tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
75
+ tLABEL tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
76
76
  ].freeze
77
77
 
78
78
  def on_new_investigation
@@ -94,7 +94,8 @@ module RuboCop
94
94
  !ends_with_backslash_without_comment?(range.source_line) ||
95
95
  string_concatenation?(range.source_line) ||
96
96
  start_with_arithmetic_operator?(processed_source[range.line]) ||
97
- inside_string_literal_or_method_with_argument?(range)
97
+ inside_string_literal_or_method_with_argument?(range) ||
98
+ leading_dot_method_chain_with_blank_line?(range)
98
99
  end
99
100
 
100
101
  def ends_with_backslash_without_comment?(source_line)
@@ -107,16 +108,26 @@ module RuboCop
107
108
 
108
109
  def inside_string_literal_or_method_with_argument?(range)
109
110
  processed_source.tokens.each_cons(2).any? do |token, next_token|
111
+ next if token.line == next_token.line
112
+
110
113
  inside_string_literal?(range, token) || method_with_argument?(token, next_token)
111
114
  end
112
115
  end
113
116
 
117
+ def leading_dot_method_chain_with_blank_line?(range)
118
+ return false unless range.source_line.strip.start_with?('.', '&.')
119
+
120
+ processed_source[range.line].strip.empty?
121
+ end
122
+
114
123
  def redundant_line_continuation?(range)
115
124
  return true unless (node = find_node_for_line(range.line))
116
125
  return false if argument_newline?(node)
117
126
 
118
- source = node.parent ? node.parent.source : node.source
119
- parse(source.gsub("\\\n", "\n")).valid_syntax?
127
+ continuation_node = node.parent || node
128
+ return false if allowed_type?(node) || allowed_type?(continuation_node)
129
+
130
+ continuation_node.source.include?("\n") || continuation_node.source.include?("\\\n")
120
131
  end
121
132
 
122
133
  def inside_string_literal?(range, token)
@@ -131,17 +142,22 @@ module RuboCop
131
142
  current_token.type == :tIDENTIFIER && ARGUMENT_TYPES.include?(next_token.type)
132
143
  end
133
144
 
145
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
134
146
  def argument_newline?(node)
147
+ node = node.to_a.last if node.assignment?
148
+ return false if node.parenthesized_call?
149
+
135
150
  node = node.children.first if node.root? && node.begin_type?
136
151
 
137
- if argument_is_method?(node)
138
- argument_newline?(node.first_argument)
152
+ if argument_is_method?(node) || node.begin_type?
153
+ argument_newline?(node.children.first)
139
154
  else
140
155
  return false unless method_call_with_arguments?(node)
141
156
 
142
- node.loc.selector.line != node.first_argument.loc.line
157
+ !same_line?(node, node.first_argument)
143
158
  end
144
159
  end
160
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
145
161
 
146
162
  def find_node_for_line(line)
147
163
  processed_source.ast.each_node do |node|
@@ -149,6 +165,10 @@ module RuboCop
149
165
  end
150
166
  end
151
167
 
168
+ def allowed_type?(node)
169
+ node.and_type? || node.or_type? || (node.if_type? && node.ternary?)
170
+ end
171
+
152
172
  def same_line?(node, line)
153
173
  return false unless (source_range = node.source_range)
154
174