rubocop 1.91.0 → 1.92.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 (263) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +4 -1
  4. data/lib/rubocop/cached_data.rb +47 -7
  5. data/lib/rubocop/changed_files.rb +35 -13
  6. data/lib/rubocop/cli/command/cop_names.rb +57 -0
  7. data/lib/rubocop/cli/command/execute_runner.rb +2 -2
  8. data/lib/rubocop/cli/command/explain.rb +34 -0
  9. data/lib/rubocop/cli/command/show_cops.rb +6 -0
  10. data/lib/rubocop/cli/command/show_docs_url.rb +6 -4
  11. data/lib/rubocop/cli.rb +3 -2
  12. data/lib/rubocop/comment_config.rb +17 -8
  13. data/lib/rubocop/config_loader.rb +6 -3
  14. data/lib/rubocop/config_loader_resolver.rb +37 -12
  15. data/lib/rubocop/config_obsoletion/removed_cop.rb +1 -1
  16. data/lib/rubocop/config_validator.rb +11 -0
  17. data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
  18. data/lib/rubocop/cop/badge.rb +1 -1
  19. data/lib/rubocop/cop/base.rb +42 -21
  20. data/lib/rubocop/cop/bundler/gem_comment.rb +0 -1
  21. data/lib/rubocop/cop/bundler/ordered_gems.rb +0 -8
  22. data/lib/rubocop/cop/cop_documentation.rb +81 -0
  23. data/lib/rubocop/cop/cop_explanation.rb +140 -0
  24. data/lib/rubocop/cop/correctors/alignment_corrector.rb +13 -1
  25. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +37 -7
  26. data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
  27. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +25 -4
  28. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +34 -0
  29. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +45 -8
  30. data/lib/rubocop/cop/documentation.rb +1 -1
  31. data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
  32. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +0 -6
  33. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -5
  34. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +0 -7
  35. data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +1 -7
  36. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +1 -7
  37. data/lib/rubocop/cop/layout/argument_alignment.rb +5 -1
  38. data/lib/rubocop/cop/layout/block_alignment.rb +27 -0
  39. data/lib/rubocop/cop/layout/case_indentation.rb +25 -9
  40. data/lib/rubocop/cop/layout/class_structure.rb +29 -7
  41. data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
  42. data/lib/rubocop/cop/layout/dot_position.rb +25 -15
  43. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +21 -8
  44. data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
  45. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
  46. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +9 -3
  47. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
  48. data/lib/rubocop/cop/layout/end_alignment.rb +19 -17
  49. data/lib/rubocop/cop/layout/extra_spacing.rb +4 -0
  50. data/lib/rubocop/cop/layout/first_argument_indentation.rb +27 -1
  51. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +15 -0
  52. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +16 -8
  53. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +6 -0
  54. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
  55. data/lib/rubocop/cop/layout/hash_alignment.rb +16 -12
  56. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +7 -3
  57. data/lib/rubocop/cop/layout/heredoc_indentation.rb +15 -0
  58. data/lib/rubocop/cop/layout/indentation_consistency.rb +22 -5
  59. data/lib/rubocop/cop/layout/indentation_style.rb +4 -1
  60. data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
  61. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +8 -1
  62. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
  63. data/lib/rubocop/cop/layout/line_length.rb +153 -21
  64. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +12 -0
  65. data/lib/rubocop/cop/layout/multiline_block_layout.rb +8 -1
  66. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +9 -0
  67. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -0
  68. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +30 -5
  69. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
  70. data/lib/rubocop/cop/layout/redundant_line_break.rb +22 -1
  71. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +15 -2
  72. data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
  73. data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
  74. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +6 -11
  75. data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -0
  76. data/lib/rubocop/cop/layout/space_before_block_braces.rb +4 -1
  77. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +15 -2
  78. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +31 -8
  79. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +2 -12
  80. data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
  81. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +2 -1
  82. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +6 -1
  83. data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
  84. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +4 -0
  85. data/lib/rubocop/cop/lint/literal_as_condition.rb +15 -0
  86. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +63 -19
  87. data/lib/rubocop/cop/lint/loop.rb +24 -2
  88. data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +71 -11
  89. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
  90. data/lib/rubocop/cop/lint/number_conversion.rb +3 -1
  91. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +12 -1
  92. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +13 -2
  93. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +47 -1
  94. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -0
  95. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +18 -1
  96. data/lib/rubocop/cop/lint/useless_assignment.rb +14 -7
  97. data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
  98. data/lib/rubocop/cop/lint/void.rb +8 -1
  99. data/lib/rubocop/cop/metrics/class_length.rb +4 -2
  100. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
  101. data/lib/rubocop/cop/metrics/module_length.rb +4 -2
  102. data/lib/rubocop/cop/mixin/alignment.rb +4 -0
  103. data/lib/rubocop/cop/mixin/check_line_breakable.rb +23 -19
  104. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +8 -2
  105. data/lib/rubocop/cop/mixin/code_length.rb +10 -2
  106. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -1
  107. data/lib/rubocop/cop/mixin/endless_method_body_help.rb +105 -0
  108. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +2 -2
  109. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +24 -5
  110. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +26 -2
  111. data/lib/rubocop/cop/mixin/min_branches_count.rb +3 -1
  112. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
  113. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +9 -0
  114. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  115. data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
  116. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +17 -2
  117. data/lib/rubocop/cop/mixin/project_index_help.rb +15 -0
  118. data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +13 -3
  119. data/lib/rubocop/cop/mixin/statement_modifier.rb +25 -4
  120. data/lib/rubocop/cop/mixin/visibility_help.rb +2 -1
  121. data/lib/rubocop/cop/mixin.rb +2 -0
  122. data/lib/rubocop/cop/naming/accessor_method_name.rb +0 -16
  123. data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
  124. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +9 -2
  125. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
  126. data/lib/rubocop/cop/naming/predicate_prefix.rb +7 -22
  127. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
  128. data/lib/rubocop/cop/offense.rb +59 -3
  129. data/lib/rubocop/cop/registry.rb +1 -1
  130. data/lib/rubocop/cop/security/json_load.rb +16 -4
  131. data/lib/rubocop/cop/style/access_modifier_declarations.rb +37 -2
  132. data/lib/rubocop/cop/style/alias.rb +18 -5
  133. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
  134. data/lib/rubocop/cop/style/and_or.rb +6 -2
  135. data/lib/rubocop/cop/style/arguments_forwarding.rb +32 -3
  136. data/lib/rubocop/cop/style/attr.rb +3 -4
  137. data/lib/rubocop/cop/style/bitwise_predicate.rb +6 -4
  138. data/lib/rubocop/cop/style/block_delimiters.rb +35 -3
  139. data/lib/rubocop/cop/style/case_like_if.rb +6 -3
  140. data/lib/rubocop/cop/style/class_and_module_children.rb +56 -16
  141. data/lib/rubocop/cop/style/class_methods_definitions.rb +15 -0
  142. data/lib/rubocop/cop/style/collection_querying.rb +79 -46
  143. data/lib/rubocop/cop/style/combinable_loops.rb +89 -11
  144. data/lib/rubocop/cop/style/concat_array_literals.rb +58 -7
  145. data/lib/rubocop/cop/style/conditional_assignment.rb +4 -0
  146. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +65 -9
  147. data/lib/rubocop/cop/style/double_negation.rb +11 -0
  148. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  149. data/lib/rubocop/cop/style/empty_method.rb +3 -1
  150. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +53 -11
  151. data/lib/rubocop/cop/style/endless_method.rb +71 -6
  152. data/lib/rubocop/cop/style/exact_regexp_match.rb +45 -8
  153. data/lib/rubocop/cop/style/explicit_block_argument.rb +50 -10
  154. data/lib/rubocop/cop/style/float_division.rb +22 -2
  155. data/lib/rubocop/cop/style/for.rb +53 -2
  156. data/lib/rubocop/cop/style/format_string.rb +28 -6
  157. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
  158. data/lib/rubocop/cop/style/guard_clause.rb +31 -22
  159. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +4 -0
  160. data/lib/rubocop/cop/style/hash_conversion.rb +28 -8
  161. data/lib/rubocop/cop/style/hash_lookup_method.rb +32 -9
  162. data/lib/rubocop/cop/style/hash_syntax.rb +16 -3
  163. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  164. data/lib/rubocop/cop/style/if_inside_else.rb +21 -1
  165. data/lib/rubocop/cop/style/if_unless_modifier.rb +32 -26
  166. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -0
  167. data/lib/rubocop/cop/style/if_with_semicolon.rb +47 -4
  168. data/lib/rubocop/cop/style/inverse_methods.rb +24 -2
  169. data/lib/rubocop/cop/style/it_block_parameter.rb +94 -4
  170. data/lib/rubocop/cop/style/keyword_parameters_order.rb +3 -1
  171. data/lib/rubocop/cop/style/lambda.rb +34 -1
  172. data/lib/rubocop/cop/style/lambda_call.rb +7 -2
  173. data/lib/rubocop/cop/style/map_into_array.rb +1 -2
  174. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +80 -13
  175. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +25 -2
  176. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +26 -3
  177. data/lib/rubocop/cop/style/method_def_parentheses.rb +29 -3
  178. data/lib/rubocop/cop/style/missing_else.rb +7 -1
  179. data/lib/rubocop/cop/style/mixin_grouping.rb +12 -3
  180. data/lib/rubocop/cop/style/multiline_if_modifier.rb +45 -5
  181. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
  182. data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -5
  183. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
  184. data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
  185. data/lib/rubocop/cop/style/mutable_constant.rb +52 -7
  186. data/lib/rubocop/cop/style/negated_if_else_condition.rb +2 -1
  187. data/lib/rubocop/cop/style/negative_array_index.rb +9 -1
  188. data/lib/rubocop/cop/style/nested_modifier.rb +27 -8
  189. data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
  190. data/lib/rubocop/cop/style/next.rb +24 -10
  191. data/lib/rubocop/cop/style/nil_comparison.rb +16 -4
  192. data/lib/rubocop/cop/style/non_nil_check.rb +1 -1
  193. data/lib/rubocop/cop/style/not.rb +10 -5
  194. data/lib/rubocop/cop/style/numeric_predicate.rb +21 -5
  195. data/lib/rubocop/cop/style/one_line_conditional.rb +13 -2
  196. data/lib/rubocop/cop/style/parentheses_around_condition.rb +1 -1
  197. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +14 -3
  198. data/lib/rubocop/cop/style/raise_args.rb +19 -9
  199. data/lib/rubocop/cop/style/reduce_to_hash.rb +17 -1
  200. data/lib/rubocop/cop/style/redundant_begin.rb +22 -4
  201. data/lib/rubocop/cop/style/redundant_condition.rb +30 -13
  202. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -0
  203. data/lib/rubocop/cop/style/redundant_exception.rb +15 -3
  204. data/lib/rubocop/cop/style/redundant_fetch_block.rb +9 -1
  205. data/lib/rubocop/cop/style/redundant_freeze.rb +11 -3
  206. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +24 -1
  207. data/lib/rubocop/cop/style/redundant_parentheses.rb +12 -1
  208. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +7 -0
  209. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +20 -0
  210. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +4 -0
  211. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +28 -0
  212. data/lib/rubocop/cop/style/redundant_sort.rb +38 -4
  213. data/lib/rubocop/cop/style/regexp_literal.rb +75 -26
  214. data/lib/rubocop/cop/style/require_order.rb +25 -8
  215. data/lib/rubocop/cop/style/rescue_modifier.rb +11 -9
  216. data/lib/rubocop/cop/style/return_nil.rb +17 -2
  217. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
  218. data/lib/rubocop/cop/style/sample.rb +9 -8
  219. data/lib/rubocop/cop/style/self_assignment.rb +12 -15
  220. data/lib/rubocop/cop/style/semicolon.rb +16 -5
  221. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +4 -0
  222. data/lib/rubocop/cop/style/single_line_methods.rb +21 -4
  223. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +29 -5
  224. data/lib/rubocop/cop/style/string_concatenation.rb +9 -3
  225. data/lib/rubocop/cop/style/struct_inheritance.rb +6 -0
  226. data/lib/rubocop/cop/style/super_arguments.rb +3 -0
  227. data/lib/rubocop/cop/style/symbol_proc.rb +24 -6
  228. data/lib/rubocop/cop/style/ternary_parentheses.rb +23 -1
  229. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +23 -19
  230. data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
  231. data/lib/rubocop/cop/style/yoda_condition.rb +24 -9
  232. data/lib/rubocop/cop/style/yoda_expression.rb +10 -1
  233. data/lib/rubocop/cop/team.rb +10 -5
  234. data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
  235. data/lib/rubocop/cop/variable_force/variable.rb +14 -1
  236. data/lib/rubocop/formatter/base_formatter.rb +22 -0
  237. data/lib/rubocop/formatter/formatter_set.rb +4 -0
  238. data/lib/rubocop/formatter/json_formatter.rb +71 -1
  239. data/lib/rubocop/formatter/offense_count_formatter.rb +3 -1
  240. data/lib/rubocop/formatter/pacman_formatter.rb +3 -1
  241. data/lib/rubocop/formatter/sarif_formatter.rb +12 -7
  242. data/lib/rubocop/formatter/worst_offenders_formatter.rb +3 -1
  243. data/lib/rubocop/lsp/routes.rb +23 -23
  244. data/lib/rubocop/lsp/runtime.rb +47 -11
  245. data/lib/rubocop/lsp/stdin_runner.rb +11 -5
  246. data/lib/rubocop/lsp.rb +5 -2
  247. data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
  248. data/lib/rubocop/mcp/explain_tool.rb +68 -0
  249. data/lib/rubocop/mcp/scope.rb +65 -0
  250. data/lib/rubocop/mcp/server.rb +184 -76
  251. data/lib/rubocop/mcp/source_files.rb +35 -0
  252. data/lib/rubocop/offense_limit.rb +30 -0
  253. data/lib/rubocop/options.rb +45 -10
  254. data/lib/rubocop/plugin/configuration_integrator.rb +12 -5
  255. data/lib/rubocop/remote_config.rb +4 -1
  256. data/lib/rubocop/result_cache.rb +20 -13
  257. data/lib/rubocop/runner.rb +109 -41
  258. data/lib/rubocop/server/cache.rb +6 -6
  259. data/lib/rubocop/target_ruby.rb +21 -9
  260. data/lib/rubocop/util.rb +69 -0
  261. data/lib/rubocop/version.rb +1 -1
  262. data/lib/rubocop.rb +5 -0
  263. metadata +16 -5
@@ -96,15 +96,22 @@ module RuboCop
96
96
  [parenthesized, first_line_comment(node)].compact.join(' ')
97
97
  end
98
98
 
99
+ # rubocop:disable-next Metrics/AbcSize
99
100
  def if_body_source(if_body)
100
- if if_body.call_type? && !if_body.method?(:[]=) && omitted_value_in_last_hash_arg?(if_body)
101
+ if unparenthesized_call_with_omitted_value?(if_body)
101
102
  "#{method_source(if_body)}(#{if_body.arguments.map(&:source).join(', ')})"
103
+ elsif (value = wrapped_value(if_body))
104
+ prefix = if_body.source_range.begin.join(value.source_range.begin).source
105
+ suffix = value.source_range.end.join(if_body.source_range.end).source
106
+
107
+ "#{prefix}#{if_body_source(value)}#{suffix}"
102
108
  else
103
109
  if_body.source
104
110
  end
105
111
  end
106
112
 
107
- def omitted_value_in_last_hash_arg?(if_body)
113
+ def unparenthesized_call_with_omitted_value?(if_body)
114
+ return false if !if_body.call_type? || if_body.method?(:[]=) || if_body.parenthesized?
108
115
  return false unless (last_argument = if_body.last_argument)
109
116
 
110
117
  last_argument.hash_type? && last_argument.pairs.last&.value_omission?
@@ -116,6 +123,14 @@ module RuboCop
116
123
  if_body.source_range.begin.join(end_range).source
117
124
  end
118
125
 
126
+ def wrapped_value(if_body)
127
+ if if_body.type?(:return, :next, :break)
128
+ if_body.first_argument if if_body.arguments.one?
129
+ elsif if_body.type?(:lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn)
130
+ if_body.expression
131
+ end
132
+ end
133
+
119
134
  def first_line_comment(node)
120
135
  comment = processed_source.comment_at_line(node.first_line)
121
136
  return unless comment
@@ -137,9 +152,15 @@ module RuboCop
137
152
  parent = node.parent
138
153
  return false if parent.nil?
139
154
  return true if parent.assignment? || parent.operator_keyword?
140
- return true if %i[array pair].include?(parent.type)
155
+ return true if parent.type?(:array, :pair, :call, :yield, :super)
156
+
157
+ ternary_branch_or_endless_method_body?(parent)
158
+ end
159
+
160
+ def ternary_branch_or_endless_method_body?(parent)
161
+ return parent.ternary? if parent.if_type?
141
162
 
142
- node.parent.send_type?
163
+ parent.any_def_type? && parent.endless?
143
164
  end
144
165
 
145
166
  def comment_disables_cop?(comment)
@@ -63,9 +63,10 @@ module RuboCop
63
63
  (send nil? VISIBILITY_SCOPES def)
64
64
  PATTERN
65
65
 
66
+ # A modifier applies to every symbol it is given, not only to a sole argument.
66
67
  # @!method visibility_inline_on_method_name?(node, method_name:)
67
68
  def_node_matcher :visibility_inline_on_method_name?, <<~PATTERN
68
- (send nil? VISIBILITY_SCOPES (sym %method_name))
69
+ (send nil? VISIBILITY_SCOPES <(sym %method_name) ...>)
69
70
  PATTERN
70
71
  end
71
72
  end
@@ -32,6 +32,7 @@ module RuboCop
32
32
  autoload :AnnotationComment, "#{__dir__}/mixin/annotation_comment"
33
33
  autoload :EmptyParameter, "#{__dir__}/mixin/empty_parameter"
34
34
  autoload :EndKeywordAlignment, "#{__dir__}/mixin/end_keyword_alignment"
35
+ autoload :EndlessMethodBodyHelp, "#{__dir__}/mixin/endless_method_body_help"
35
36
  autoload :EndlessMethodRewriter, "#{__dir__}/mixin/endless_method_rewriter"
36
37
  autoload :EnforceSuperclass, "#{__dir__}/mixin/enforce_superclass"
37
38
  autoload :FirstElementLineBreak, "#{__dir__}/mixin/first_element_line_break"
@@ -64,6 +65,7 @@ module RuboCop
64
65
  autoload :OnNormalIfUnless, "#{__dir__}/mixin/on_normal_if_unless"
65
66
  autoload :OrderedGemNode, "#{__dir__}/mixin/ordered_gem_node"
66
67
  autoload :Parentheses, "#{__dir__}/mixin/parentheses"
68
+ autoload :PatternMatchingHelp, "#{__dir__}/mixin/pattern_matching_help"
67
69
  autoload :PercentArray, "#{__dir__}/mixin/percent_array"
68
70
  autoload :PercentLiteral, "#{__dir__}/mixin/percent_literal"
69
71
  autoload :PrecedingFollowingAlignment, "#{__dir__}/mixin/preceding_following_alignment"
@@ -80,22 +80,6 @@ module RuboCop
80
80
  node.arguments.one? &&
81
81
  node.first_argument.arg_type?
82
82
  end
83
-
84
- # When `AllCops/UseProjectIndex` is enabled, methods that override a
85
- # method defined by an ancestor elsewhere in the project are not
86
- # reported: renaming an override breaks the inherited contract.
87
- def overrides_inherited_method?(node)
88
- return false unless project_index
89
- return false unless (namespace_node = node.each_ancestor(:class, :module).first)
90
-
91
- declaration = resolve_constant_in_index(namespace_node.identifier)
92
- return false unless declaration.is_a?(Rubydex::Namespace)
93
-
94
- scope = node.defs_type? ? indexed_singleton_of(declaration) : declaration
95
- !scope.nil? && inherited_index_member?(scope, "#{node.method_name}()")
96
- rescue StandardError
97
- false
98
- end
99
83
  end
100
84
  end
101
85
  end
@@ -63,7 +63,7 @@ module RuboCop
63
63
 
64
64
  def self.autocorrect_incompatible_with
65
65
  [
66
- Lint::AmbiguousOperator, Style::ArgumentsForwarding,
66
+ Lint::AmbiguousOperator, Style::ArgumentsForwarding, Style::EndlessMethod,
67
67
  Style::ExplicitBlockArgument, Style::MethodDefParentheses
68
68
  ]
69
69
  end
@@ -35,7 +35,7 @@ module RuboCop
35
35
  MSG = 'Use %<style>s heredoc delimiters.'
36
36
 
37
37
  def on_heredoc(node)
38
- return if correct_case_delimiters?(node)
38
+ return if correct_case_delimiters?(node) || corrected_delimiter_in_body?(node)
39
39
 
40
40
  add_offense(node.loc.heredoc_end) do |corrector|
41
41
  expr = node.source_range
@@ -52,7 +52,14 @@ module RuboCop
52
52
  end
53
53
 
54
54
  def correct_case_delimiters?(node)
55
- delimiter_string(node) == correct_delimiters(delimiter_string(node))
55
+ delimiters = delimiter_string(node)
56
+ delimiters == correct_delimiters(delimiters)
57
+ end
58
+
59
+ def corrected_delimiter_in_body?(node)
60
+ corrected = correct_delimiters(delimiter_string(node))
61
+
62
+ node.loc.heredoc_body.source.each_line.any? { |line| line.strip == corrected }
56
63
  end
57
64
 
58
65
  def correct_delimiters(source)
@@ -43,9 +43,11 @@ module RuboCop
43
43
 
44
44
  return false unless /\w/.match?(delimiters)
45
45
 
46
- forbidden_delimiters.none? do |forbidden_delimiter|
47
- Regexp.new(forbidden_delimiter).match?(delimiters)
48
- end
46
+ forbidden_delimiter_regexps.none? { |regexp| regexp.match?(delimiters) }
47
+ end
48
+
49
+ def forbidden_delimiter_regexps
50
+ @forbidden_delimiter_regexps ||= forbidden_delimiters.map { |d| Regexp.new(d) }
49
51
  end
50
52
 
51
53
  def forbidden_delimiters
@@ -142,12 +142,6 @@ module RuboCop
142
142
  end
143
143
  end
144
144
 
145
- def offending_prefixes_for(node, method_name)
146
- predicate_prefixes.reject do |prefix|
147
- allowed_method_name?(method_name, prefix) ||
148
- (use_sorbet_sigs? && !sorbet_sig?(node, return_type: 'T::Boolean'))
149
- end
150
- end
151
145
  alias on_defs on_def
152
146
 
153
147
  def validate_config
@@ -162,6 +156,13 @@ module RuboCop
162
156
 
163
157
  private
164
158
 
159
+ def offending_prefixes_for(node, method_name)
160
+ prefixes = predicate_prefixes.reject { |p| allowed_method_name?(method_name, p) }
161
+ return prefixes if prefixes.empty? || !use_sorbet_sigs?
162
+
163
+ sorbet_sig?(node, return_type: 'T::Boolean') ? prefixes : []
164
+ end
165
+
165
166
  # @!method sorbet_return_type(node)
166
167
  def_node_matcher :sorbet_return_type, <<~PATTERN
167
168
  (block (send nil? :sig) args (send _ :returns $_type))
@@ -210,22 +211,6 @@ module RuboCop
210
211
  def method_definition_macro?(macro_name)
211
212
  cop_config['MethodDefinitionMacros'].include?(macro_name.to_s)
212
213
  end
213
-
214
- # When `AllCops/UseProjectIndex` is enabled, methods that override a
215
- # method defined by an ancestor elsewhere in the project are not
216
- # reported: renaming an override breaks the inherited contract.
217
- def overrides_inherited_method?(node)
218
- return false unless project_index
219
- return false unless (namespace_node = node.each_ancestor(:class, :module).first)
220
-
221
- declaration = resolve_constant_in_index(namespace_node.identifier)
222
- return false unless declaration.is_a?(Rubydex::Namespace)
223
-
224
- scope = node.defs_type? ? indexed_singleton_of(declaration) : declaration
225
- !scope.nil? && inherited_index_member?(scope, "#{node.method_name}()")
226
- rescue StandardError
227
- false
228
- end
229
214
  end
230
215
  end
231
216
  end
@@ -128,7 +128,7 @@ module RuboCop
128
128
  if child_node.lvar_type?
129
129
  parent_node = child_node.parent
130
130
  if parent_node.respond_to?(:value_omission?) && parent_node.value_omission?
131
- corrector.insert_after(parent_node.loc.operator, " #{preferred_name}")
131
+ corrector.replace(parent_node.loc.operator, ": #{preferred_name}")
132
132
  else
133
133
  corrector.replace(child_node, preferred_name)
134
134
  end
@@ -86,6 +86,9 @@ module RuboCop
86
86
 
87
87
  NO_LOCATION = PseudoSourceRange.new(1, 0, '', 0, 0).freeze
88
88
 
89
+ EMPTY_CORRECTIONS = [].freeze
90
+ private_constant :EMPTY_CORRECTIONS
91
+
89
92
  # @api public
90
93
  #
91
94
  # @!attribute [r] justification
@@ -96,9 +99,43 @@ module RuboCop
96
99
  # or the directive carries no reason
97
100
  attr_reader :justification
98
101
 
102
+ # @api public
103
+ #
104
+ # @!attribute [r] corrections
105
+ #
106
+ # @return [Array<Correction>]
107
+ # the individual edits that autocorrecting this offense would make, in
108
+ # source order. Empty when the offense has no correction. Unlike
109
+ # {#corrector}, this survives serialization, so it is available on a
110
+ # cache hit and in parallel runs.
111
+ attr_reader :corrections
112
+
113
+ # @api public
114
+ #
115
+ # @!attribute [r] correction_safe
116
+ #
117
+ # @return [Boolean]
118
+ # whether autocorrection would apply {#corrections} in a normal `-a`
119
+ # run. A cop marked `Safe: false` or `SafeAutoCorrect: false` still
120
+ # builds its correction, but only `-A` applies it, so a consumer that
121
+ # applies edits itself has to make the same distinction.
122
+ attr_reader :correction_safe
123
+
124
+ # A single edit of an autocorrection: the source range it replaces and
125
+ # the text it replaces it with. An insertion has an empty range, a
126
+ # removal an empty replacement.
127
+ #
128
+ # @api public
129
+ Correction = Struct.new(:begin_pos, :end_pos, :replacement) do
130
+ def length
131
+ end_pos - begin_pos
132
+ end
133
+ end
134
+
99
135
  # @api private
100
136
  def initialize(severity, location, message, cop_name, # rubocop:disable Metrics/ParameterLists
101
- status = :uncorrected, corrector = nil, justification: nil)
137
+ status = :uncorrected, corrector = nil, justification: nil,
138
+ corrections: nil, correction_safe: true)
102
139
  @severity = RuboCop::Cop::Severity.new(severity)
103
140
  @location = location
104
141
 
@@ -112,15 +149,21 @@ module RuboCop
112
149
  @status = status
113
150
  @corrector = corrector
114
151
  @justification = justification.freeze
152
+ @corrections = (corrections || corrections_from(corrector)).freeze
153
+ @correction_safe = correction_safe
115
154
  freeze
116
155
  end
117
156
 
118
157
  def marshal_dump
119
- [@severity, @location, @message, @cop_name, @status, @justification]
158
+ [@severity, @location, @message, @cop_name, @status, @justification, @corrections,
159
+ @correction_safe]
120
160
  end
121
161
 
122
162
  def marshal_load(array)
123
- @severity, @location, @message, @cop_name, @status, @justification = array
163
+ @severity, @location, @message, @cop_name, @status, @justification, @corrections,
164
+ @correction_safe = array
165
+ @corrections ||= EMPTY_CORRECTIONS
166
+ @correction_safe = true if @correction_safe.nil?
124
167
  @line = @location.line
125
168
  @column = @location.column
126
169
  end
@@ -276,6 +319,19 @@ module RuboCop
276
319
  end
277
320
  0
278
321
  end
322
+
323
+ private
324
+
325
+ # Extracted eagerly rather than on demand because the offense is frozen,
326
+ # and because a corrector cannot be serialized - the cache and parallel
327
+ # workers would otherwise hand back offenses that have lost their edits.
328
+ def corrections_from(corrector)
329
+ return EMPTY_CORRECTIONS unless corrector
330
+
331
+ corrector.as_replacements.map do |range, replacement|
332
+ Correction.new(range.begin_pos, range.end_pos, replacement.freeze).freeze
333
+ end
334
+ end
279
335
  end
280
336
  end
281
337
  end
@@ -43,7 +43,7 @@ module RuboCop
43
43
 
44
44
  def self.qualified_cop?(name)
45
45
  badge = Badge.parse(name)
46
- global.qualify_badge(badge).first == badge
46
+ global.qualify_badge(badge).include?(badge)
47
47
  end
48
48
 
49
49
  attr_reader :options, :warnings
@@ -22,6 +22,13 @@ module RuboCop
22
22
  # passing the `create_additions` keyword argument emits a deprecation warning, with the
23
23
  # goal of being secure by default in the next major version 3.0.0.
24
24
  #
25
+ # NOTE: Before `json` gem version 2.17.0, `JSON.load` only takes options as its third
26
+ # argument. A hash passed as the second argument is taken as the `proc` argument, so
27
+ # its `create_additions` option is ignored. Which `json` version runs can't be told
28
+ # statically (the lockfile may resolve a newer one than the default gem loaded in
29
+ # production), so options passed as the second argument are always reported. Pass
30
+ # `nil` as the second argument instead.
31
+ #
25
32
  # @safety
26
33
  # This cop's autocorrection is unsafe because it's potentially dangerous.
27
34
  # If using a stream, like `JSON.load(open('file'))`, you will need to call
@@ -33,13 +40,16 @@ module RuboCop
33
40
  # JSON.load('{}')
34
41
  # JSON.restore('{}')
35
42
  #
43
+ # # bad - ignored by `json` older than 2.17.0
44
+ # JSON.load('{}', create_additions: false)
45
+ #
36
46
  # # good
37
47
  # JSON.parse('{}')
38
48
  # JSON.unsafe_load('{}')
39
49
  #
40
50
  # # good - explicit use of `create_additions` option
41
- # JSON.load('{}', create_additions: true)
42
- # JSON.load('{}', create_additions: false)
51
+ # JSON.load('{}', nil, create_additions: true)
52
+ # JSON.load('{}', nil, create_additions: false)
43
53
  #
44
54
  class JSONLoad < Base
45
55
  extend AutoCorrector
@@ -51,8 +61,10 @@ module RuboCop
51
61
  def_node_matcher :insecure_json_load, <<~PATTERN
52
62
  (
53
63
  send (const {nil? cbase} :JSON) ${:load :restore}
54
- ...
55
- !`(pair (sym :create_additions) _)
64
+ {
65
+ _ hash
66
+ | ... !`(pair (sym :create_additions) _)
67
+ }
56
68
  )
57
69
  PATTERN
58
70
 
@@ -132,10 +132,11 @@ module RuboCop
132
132
  # private alias_method :qux, :foo
133
133
  #
134
134
  # end
135
- class AccessModifierDeclarations < Base
135
+ class AccessModifierDeclarations < Base # rubocop:disable Metrics/ClassLength
136
136
  extend AutoCorrector
137
137
 
138
138
  include ConfigurableEnforcedStyle
139
+ include EndlessMethodBodyHelp
139
140
  include RangeHelp
140
141
 
141
142
  GROUP_STYLE_MESSAGE = [
@@ -169,6 +170,10 @@ module RuboCop
169
170
  (send nil? :alias_method _ _))
170
171
  PATTERN
171
172
 
173
+ def self.autocorrect_incompatible_with
174
+ [Style::EndlessMethod, Style::SingleLineMethods]
175
+ end
176
+
172
177
  def on_send(node)
173
178
  return if allowed?(node)
174
179
 
@@ -187,11 +192,18 @@ module RuboCop
187
192
  def allowed?(node)
188
193
  !node.access_modifier? ||
189
194
  node.parent&.type?(:pair, :any_block) ||
195
+ dynamic_method_list?(node) ||
190
196
  allow_modifiers_on_symbols?(node) ||
191
197
  allow_modifiers_on_attrs?(node) ||
192
198
  allow_modifiers_on_alias_method?(node)
193
199
  end
194
200
 
201
+ # `private(*names)` with a list computed at runtime names no definition
202
+ # the modifier could be grouped with.
203
+ def dynamic_method_list?(node)
204
+ node.arguments.any?(&:splat_type?) && !access_modifier_with_symbol?(node)
205
+ end
206
+
195
207
  def autocorrect(corrector, node)
196
208
  case style
197
209
  when :group
@@ -241,10 +253,33 @@ module RuboCop
241
253
 
242
254
  access_modifier_is_inlined?(node) && !right_siblings_same_inline_method?(node)
243
255
  else
244
- access_modifier_is_not_inlined?(node) && select_grouped_def_nodes(node).any?
256
+ access_modifier_is_not_inlined?(node) && inlinable?(select_grouped_def_nodes(node))
245
257
  end
246
258
  end
247
259
 
260
+ def inlinable?(def_nodes)
261
+ return false if def_nodes.empty?
262
+
263
+ def_nodes.none? { |def_node| def_node.endless? && body_unsafe_to_inline?(def_node.body) }
264
+ end
265
+
266
+ def body_unsafe_to_inline?(body)
267
+ return true if body.each_node(:any_block).any? { |block| do_end_block?(block) }
268
+
269
+ target_ruby_version < 4.0 && command_body?(body)
270
+ end
271
+
272
+ def do_end_block?(block)
273
+ block.keywords? && !block.send_node.lambda_literal?
274
+ end
275
+
276
+ def command_body?(body)
277
+ body = body.body while body.rescue_type?
278
+ return true if body.send_type? && body.prefix_not? && !body.parenthesized?
279
+
280
+ command_call?(body)
281
+ end
282
+
248
283
  def correctable_group_offense?(node)
249
284
  return false unless group_style?
250
285
  return false if allowed?(node)
@@ -60,7 +60,7 @@ module RuboCop
60
60
  add_offense(node.loc.keyword, message: MSG_ALIAS) do |corrector|
61
61
  autocorrect(corrector, node)
62
62
  end
63
- elsif node.children.none? { |arg| bareword?(arg) }
63
+ elsif node.children.all? { |arg| !bareword?(arg) && bareword_symbol?(arg) }
64
64
  add_offense_for_args(node) { |corrector| autocorrect(corrector, node) }
65
65
  end
66
66
  end
@@ -97,7 +97,7 @@ module RuboCop
97
97
 
98
98
  def add_offense_for_args(node, &block)
99
99
  existing_args = node.children.map(&:source).join(' ')
100
- preferred_args = node.children.map { |a| a.source[1..] }.join(' ')
100
+ preferred_args = node.children.map { |node| bareword_for(node) }.join(' ')
101
101
  arg_ranges = node.children.map(&:source_range)
102
102
  msg = format(MSG_SYMBOL_ARGS, prefer: preferred_args, current: existing_args)
103
103
  add_offense(arg_ranges.reduce(&:join), message: msg, &block)
@@ -138,6 +138,15 @@ module RuboCop
138
138
  !sym_node.source.start_with?(':') || sym_node.dsym_type?
139
139
  end
140
140
 
141
+ def bareword_symbol?(sym_node)
142
+ return false unless sym_node.sym_type?
143
+
144
+ value = sym_node.value.to_s
145
+ return true if value.match?(/\A[A-Za-z_]\w*[?!=]?\z/)
146
+
147
+ !sym_node.source.start_with?(':"', ":'") && !value.start_with?('@', '$')
148
+ end
149
+
141
150
  def correct_alias_method_to_alias(corrector, send_node)
142
151
  new, old = *send_node.arguments
143
152
  replacement = "alias #{identifier(new)} #{identifier(old)}"
@@ -153,17 +162,21 @@ module RuboCop
153
162
  end
154
163
 
155
164
  def correct_alias_with_symbol_args(corrector, node)
156
- corrector.replace(node.new_identifier, node.new_identifier.source[1..])
157
- corrector.replace(node.old_identifier, node.old_identifier.source[1..])
165
+ corrector.replace(node.new_identifier, bareword_for(node.new_identifier))
166
+ corrector.replace(node.old_identifier, bareword_for(node.old_identifier))
158
167
  end
159
168
 
160
169
  def identifier(node)
161
- if node.sym_type?
170
+ if bareword_symbol?(node)
162
171
  ":#{node.children.first}"
163
172
  else
164
173
  node.source
165
174
  end
166
175
  end
176
+
177
+ def bareword_for(sym_node)
178
+ sym_node.value.to_s
179
+ end
167
180
  end
168
181
  end
169
182
  end
@@ -39,9 +39,9 @@ module RuboCop
39
39
  # @!method ambiguous_endless_method_body(node)
40
40
  def_node_matcher :ambiguous_endless_method_body, <<~PATTERN
41
41
  ^${
42
- (if _ <def _>)
43
- ({and or} def _)
44
- ({while until} _ def)
42
+ (if _ <any_def _>)
43
+ ({and or} any_def _)
44
+ ({while until} _ any_def)
45
45
  }
46
46
  PATTERN
47
47
 
@@ -57,6 +57,7 @@ module RuboCop
57
57
  correct_to_multiline(corrector, node)
58
58
  end
59
59
  end
60
+ alias on_defs on_def
60
61
 
61
62
  private
62
63
 
@@ -48,6 +48,10 @@ module RuboCop
48
48
 
49
49
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
50
50
 
51
+ def self.autocorrect_incompatible_with
52
+ [Style::MethodCallWithArgsParentheses, Style::ReturnNil, Style::ReturnNilInPredicateMethodDefinition]
53
+ end
54
+
51
55
  def on_and(node)
52
56
  process_logical_operator(node) if style == :always
53
57
  end
@@ -69,7 +73,7 @@ module RuboCop
69
73
  message = message(node)
70
74
  add_offense(node.loc.operator, message: message) do |corrector|
71
75
  node.each_child_node do |expr|
72
- if expr.send_type?
76
+ if expr.call_type?
73
77
  correct_send(expr, corrector)
74
78
  elsif expr.type?(:return, :next, :break, :yield) || expr.assignment?
75
79
  correct_other(expr, corrector)
@@ -116,7 +120,7 @@ module RuboCop
116
120
  # however, 'not x' also parses as (send x :!)
117
121
  def correct_not(node, receiver, corrector)
118
122
  if node.prefix_bang?
119
- return unless receiver.send_type?
123
+ return unless receiver.call_type?
120
124
 
121
125
  correct_send(receiver, corrector)
122
126
  elsif node.prefix_not?
@@ -153,7 +153,7 @@ module RuboCop
153
153
  BLOCK_MSG = 'Use anonymous block arguments forwarding (`&`).'
154
154
 
155
155
  def self.autocorrect_incompatible_with
156
- [Naming::BlockForwarding, Style::MethodDefParentheses]
156
+ [Naming::BlockForwarding, Style::EndlessMethod, Style::MethodDefParentheses]
157
157
  end
158
158
 
159
159
  def on_def(node)
@@ -169,7 +169,7 @@ module RuboCop
169
169
 
170
170
  return if send_classifications.empty?
171
171
 
172
- if only_forwards_all?(send_classifications)
172
+ if forward_all?(send_nodes, send_classifications)
173
173
  add_forward_all_offenses(node, send_classifications, forwardable_args)
174
174
  elsif target_ruby_version >= 3.2
175
175
  add_post_ruby_32_offenses(node, send_classifications, forwardable_args)
@@ -192,11 +192,33 @@ module RuboCop
192
192
  [restarg_node, kwrestarg_node, blockarg_node]
193
193
  end
194
194
 
195
+ def forward_all?(send_nodes, send_classifications)
196
+ only_forwards_all?(send_classifications) &&
197
+ !anonymous_forwarding_elsewhere?(send_nodes, send_classifications)
198
+ end
199
+
195
200
  def only_forwards_all?(send_classifications)
196
201
  all_classifications = %i[all all_anonymous].freeze
197
202
  send_classifications.all? { |_, c, _, _| all_classifications.include?(c) }
198
203
  end
199
204
 
205
+ def anonymous_forwarding_elsewhere?(send_nodes, send_classifications)
206
+ classified = send_classifications.map(&:first)
207
+
208
+ send_nodes.any? do |send_node|
209
+ classified.none? { |node| node.equal?(send_node) } &&
210
+ forwards_anonymous_args?(send_node)
211
+ end
212
+ end
213
+
214
+ def forwards_anonymous_args?(send_node)
215
+ send_node.arguments.any? do |arg|
216
+ next arg.children.any?(&:forwarded_kwrestarg_type?) if arg.hash_type?
217
+
218
+ arg.forwarded_restarg_type?
219
+ end
220
+ end
221
+
200
222
  # rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
201
223
  def add_forward_all_offenses(node, send_classifications, forwardable_args)
202
224
  rest_arg, kwrest_arg, block_arg = *forwardable_args
@@ -376,11 +398,16 @@ module RuboCop
376
398
 
377
399
  def add_parens_if_missing(node, corrector)
378
400
  return if parentheses?(node)
379
- return if node.send_type? && node.method?(:[])
401
+ return if node.call_type? && operator_or_setter_call?(node)
402
+ return unless (@parenthesized_nodes ||= Set.new.compare_by_identity).add?(node)
380
403
 
381
404
  add_parentheses(node, corrector)
382
405
  end
383
406
 
407
+ def operator_or_setter_call?(node)
408
+ node.setter_method? || (node.operator_method? && !node.loc.dot)
409
+ end
410
+
384
411
  # Classifies send nodes for possible rest/kwrest/all (including block) forwarding.
385
412
  class SendNodeClassifier
386
413
  extend NodePattern::Macros
@@ -499,6 +526,8 @@ module RuboCop
499
526
  end
500
527
 
501
528
  def offensive_block_forwarding?
529
+ return false if @send_node.block_literal?
530
+
502
531
  @block_arg ? forwarded_block_arg : allow_offense_for_no_block?
503
532
  end
504
533
 
@@ -50,10 +50,9 @@ module RuboCop
50
50
  def autocorrect(corrector, node)
51
51
  attr_name, setter = *node.arguments
52
52
 
53
- node_expr = node.source_range
54
- attr_expr = attr_name.source_range
55
-
56
- remove = range_between(attr_expr.end_pos, node_expr.end_pos) if setter&.boolean_type?
53
+ if setter&.boolean_type?
54
+ remove = range_between(attr_name.source_range.end_pos, setter.source_range.end_pos)
55
+ end
57
56
 
58
57
  corrector.replace(node.loc.selector, replacement_method(node))
59
58
  corrector.remove(remove) if remove