rubocop 1.50.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 (290) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -3
  3. data/config/default.yml +153 -16
  4. data/config/obsoletion.yml +5 -0
  5. data/lib/rubocop/cli/command/auto_generate_config.rb +10 -5
  6. data/lib/rubocop/cli/command/lsp.rb +19 -0
  7. data/lib/rubocop/cli.rb +4 -1
  8. data/lib/rubocop/config.rb +4 -0
  9. data/lib/rubocop/config_finder.rb +2 -2
  10. data/lib/rubocop/config_loader_resolver.rb +4 -3
  11. data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
  12. data/lib/rubocop/config_obsoletion.rb +13 -10
  13. data/lib/rubocop/cop/autocorrect_logic.rb +3 -1
  14. data/lib/rubocop/cop/base.rb +6 -2
  15. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -0
  16. data/lib/rubocop/cop/bundler/duplicated_group.rb +127 -0
  17. data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
  18. data/lib/rubocop/cop/bundler/gem_version.rb +2 -2
  19. data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
  20. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
  21. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
  22. data/lib/rubocop/cop/gemspec/dependency_version.rb +2 -2
  23. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +2 -2
  24. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  25. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
  26. data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
  27. data/lib/rubocop/cop/internal_affairs/cop_description.rb +32 -8
  28. data/lib/rubocop/cop/internal_affairs/example_description.rb +42 -21
  29. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -1
  30. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +19 -20
  31. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
  32. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +7 -7
  33. data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
  34. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
  35. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  36. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  37. data/lib/rubocop/cop/layout/class_structure.rb +7 -0
  38. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -2
  39. data/lib/rubocop/cop/layout/dot_position.rb +1 -5
  40. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +42 -9
  41. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +27 -4
  42. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
  43. data/lib/rubocop/cop/layout/end_alignment.rb +7 -1
  44. data/lib/rubocop/cop/layout/extra_spacing.rb +4 -10
  45. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +6 -6
  46. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  47. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +4 -4
  48. data/lib/rubocop/cop/layout/heredoc_indentation.rb +4 -1
  49. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  50. data/lib/rubocop/cop/layout/indentation_width.rb +3 -3
  51. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  52. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +17 -9
  53. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  54. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -0
  55. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
  56. data/lib/rubocop/cop/layout/redundant_line_break.rb +16 -5
  57. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -4
  58. data/lib/rubocop/cop/layout/single_line_block_chain.rb +5 -0
  59. data/lib/rubocop/cop/layout/space_after_comma.rb +9 -1
  60. data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
  61. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +2 -2
  62. data/lib/rubocop/cop/layout/space_around_operators.rb +53 -21
  63. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -0
  64. data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
  65. data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
  66. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +5 -0
  67. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +13 -1
  68. data/lib/rubocop/cop/lint/assignment_in_condition.rb +4 -4
  69. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
  70. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
  71. data/lib/rubocop/cop/lint/debugger.rb +19 -5
  72. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +2 -1
  73. data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
  74. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +46 -19
  75. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  76. data/lib/rubocop/cop/lint/erb_new_arguments.rb +6 -7
  77. data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
  78. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
  79. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +1 -1
  80. data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
  81. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -3
  82. data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
  83. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
  84. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  85. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +78 -0
  86. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  87. data/lib/rubocop/cop/lint/missing_super.rb +34 -5
  88. data/lib/rubocop/cop/lint/mixed_case_range.rb +111 -0
  89. data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
  90. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -7
  91. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -5
  92. data/lib/rubocop/cop/lint/number_conversion.rb +14 -4
  93. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
  94. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
  95. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -2
  96. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +130 -0
  97. data/lib/rubocop/cop/lint/redundant_require_statement.rb +12 -3
  98. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +63 -4
  99. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -1
  100. data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
  101. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  102. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +14 -8
  103. data/lib/rubocop/cop/lint/self_assignment.rb +38 -0
  104. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -2
  105. data/lib/rubocop/cop/lint/shadowed_exception.rb +5 -11
  106. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +7 -1
  107. data/lib/rubocop/cop/lint/struct_new_override.rb +12 -12
  108. data/lib/rubocop/cop/lint/suppressed_exception.rb +2 -2
  109. data/lib/rubocop/cop/lint/symbol_conversion.rb +8 -3
  110. data/lib/rubocop/cop/lint/to_enum_arguments.rb +5 -3
  111. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
  112. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
  113. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
  114. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  115. data/lib/rubocop/cop/lint/useless_assignment.rb +94 -10
  116. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  117. data/lib/rubocop/cop/lint/void.rb +92 -11
  118. data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
  119. data/lib/rubocop/cop/metrics/block_length.rb +1 -1
  120. data/lib/rubocop/cop/metrics/class_length.rb +8 -3
  121. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  122. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -2
  123. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +32 -4
  124. data/lib/rubocop/cop/migration/department_name.rb +2 -2
  125. data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
  126. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  127. data/lib/rubocop/cop/mixin/comments_help.rb +19 -11
  128. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  129. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
  130. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +14 -11
  131. data/lib/rubocop/cop/mixin/heredoc.rb +6 -2
  132. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -2
  133. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  134. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -8
  135. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  136. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  137. data/lib/rubocop/cop/mixin/string_help.rb +4 -2
  138. data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
  139. data/lib/rubocop/cop/naming/block_forwarding.rb +3 -3
  140. data/lib/rubocop/cop/naming/constant_name.rb +2 -3
  141. data/lib/rubocop/cop/naming/file_name.rb +1 -1
  142. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +3 -1
  143. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +26 -11
  144. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -3
  145. data/lib/rubocop/cop/naming/variable_name.rb +6 -1
  146. data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -2
  147. data/lib/rubocop/cop/style/accessor_grouping.rb +6 -2
  148. data/lib/rubocop/cop/style/alias.rb +9 -8
  149. data/lib/rubocop/cop/style/arguments_forwarding.rb +342 -63
  150. data/lib/rubocop/cop/style/array_first_last.rb +64 -0
  151. data/lib/rubocop/cop/style/array_intersect.rb +13 -5
  152. data/lib/rubocop/cop/style/attr.rb +11 -1
  153. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
  154. data/lib/rubocop/cop/style/begin_block.rb +1 -2
  155. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
  156. data/lib/rubocop/cop/style/block_comments.rb +1 -1
  157. data/lib/rubocop/cop/style/block_delimiters.rb +5 -4
  158. data/lib/rubocop/cop/style/case_like_if.rb +4 -4
  159. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  160. data/lib/rubocop/cop/style/class_check.rb +1 -0
  161. data/lib/rubocop/cop/style/class_equality_comparison.rb +24 -39
  162. data/lib/rubocop/cop/style/collection_compact.rb +22 -11
  163. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  164. data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
  165. data/lib/rubocop/cop/style/combinable_loops.rb +36 -8
  166. data/lib/rubocop/cop/style/concat_array_literals.rb +2 -1
  167. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
  168. data/lib/rubocop/cop/style/copyright.rb +5 -2
  169. data/lib/rubocop/cop/style/date_time.rb +5 -4
  170. data/lib/rubocop/cop/style/dir.rb +1 -1
  171. data/lib/rubocop/cop/style/dir_empty.rb +8 -14
  172. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
  173. data/lib/rubocop/cop/style/documentation.rb +1 -1
  174. data/lib/rubocop/cop/style/each_with_object.rb +2 -2
  175. data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
  176. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  177. data/lib/rubocop/cop/style/eval_with_location.rb +8 -8
  178. data/lib/rubocop/cop/style/exact_regexp_match.rb +69 -0
  179. data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
  180. data/lib/rubocop/cop/style/file_read.rb +2 -2
  181. data/lib/rubocop/cop/style/for.rb +1 -1
  182. data/lib/rubocop/cop/style/format_string.rb +24 -3
  183. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -1
  184. data/lib/rubocop/cop/style/guard_clause.rb +28 -0
  185. data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
  186. data/lib/rubocop/cop/style/hash_each_methods.rb +84 -32
  187. data/lib/rubocop/cop/style/hash_except.rb +21 -9
  188. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  189. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  190. data/lib/rubocop/cop/style/identical_conditional_branches.rb +31 -5
  191. data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
  192. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -0
  193. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  194. data/lib/rubocop/cop/style/inverse_methods.rb +6 -5
  195. data/lib/rubocop/cop/style/invertible_unless_condition.rb +10 -6
  196. data/lib/rubocop/cop/style/lambda.rb +3 -3
  197. data/lib/rubocop/cop/style/lambda_call.rb +5 -0
  198. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +3 -2
  199. data/lib/rubocop/cop/style/map_to_hash.rb +10 -4
  200. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +12 -5
  201. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
  202. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +20 -0
  203. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  204. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
  205. data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
  206. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  207. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
  208. data/lib/rubocop/cop/style/multiple_comparison.rb +14 -0
  209. data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
  210. data/lib/rubocop/cop/style/next.rb +1 -1
  211. data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
  212. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  213. data/lib/rubocop/cop/style/operator_method_call.rb +8 -2
  214. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  215. data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
  216. data/lib/rubocop/cop/style/redundant_argument.rb +9 -3
  217. data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
  218. data/lib/rubocop/cop/style/redundant_begin.rb +10 -2
  219. data/lib/rubocop/cop/style/redundant_conditional.rb +2 -10
  220. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +38 -0
  221. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +93 -5
  222. data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
  223. data/lib/rubocop/cop/style/redundant_fetch_block.rb +3 -3
  224. data/lib/rubocop/cop/style/redundant_filter_chain.rb +118 -0
  225. data/lib/rubocop/cop/style/redundant_line_continuation.rb +9 -3
  226. data/lib/rubocop/cop/style/redundant_parentheses.rb +54 -21
  227. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +100 -0
  228. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
  229. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
  230. data/lib/rubocop/cop/style/redundant_return.rb +8 -3
  231. data/lib/rubocop/cop/style/redundant_self.rb +17 -2
  232. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +8 -1
  233. data/lib/rubocop/cop/style/redundant_sort.rb +10 -9
  234. data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
  235. data/lib/rubocop/cop/style/redundant_string_escape.rb +3 -1
  236. data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
  237. data/lib/rubocop/cop/style/require_order.rb +11 -5
  238. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
  239. data/lib/rubocop/cop/style/return_nil.rb +6 -2
  240. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +95 -0
  241. data/lib/rubocop/cop/style/sample.rb +2 -1
  242. data/lib/rubocop/cop/style/select_by_regexp.rb +22 -11
  243. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  244. data/lib/rubocop/cop/style/semicolon.rb +20 -4
  245. data/lib/rubocop/cop/style/signal_exception.rb +1 -1
  246. data/lib/rubocop/cop/style/single_argument_dig.rb +7 -3
  247. data/lib/rubocop/cop/style/single_line_do_end_block.rb +67 -0
  248. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  249. data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
  250. data/lib/rubocop/cop/style/sole_nested_conditional.rb +6 -2
  251. data/lib/rubocop/cop/style/special_global_vars.rb +3 -4
  252. data/lib/rubocop/cop/style/string_chars.rb +1 -0
  253. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
  254. data/lib/rubocop/cop/style/strip.rb +7 -4
  255. data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
  256. data/lib/rubocop/cop/style/symbol_array.rb +35 -15
  257. data/lib/rubocop/cop/style/unpack_first.rb +11 -14
  258. data/lib/rubocop/cop/style/yaml_file_read.rb +66 -0
  259. data/lib/rubocop/cop/style/yoda_condition.rb +4 -2
  260. data/lib/rubocop/cop/style/yoda_expression.rb +8 -7
  261. data/lib/rubocop/cop/team.rb +1 -1
  262. data/lib/rubocop/cop/util.rb +1 -1
  263. data/lib/rubocop/cop/utils/regexp_ranges.rb +113 -0
  264. data/lib/rubocop/cop/variable_force/assignment.rb +45 -4
  265. data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
  266. data/lib/rubocop/cop/variable_force.rb +1 -0
  267. data/lib/rubocop/cops_documentation_generator.rb +1 -1
  268. data/lib/rubocop/ext/regexp_parser.rb +4 -1
  269. data/lib/rubocop/file_finder.rb +4 -7
  270. data/lib/rubocop/formatter/html_formatter.rb +5 -4
  271. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  272. data/lib/rubocop/lsp/logger.rb +22 -0
  273. data/lib/rubocop/lsp/routes.rb +246 -0
  274. data/lib/rubocop/lsp/runtime.rb +99 -0
  275. data/lib/rubocop/lsp/server.rb +68 -0
  276. data/lib/rubocop/lsp/severity.rb +27 -0
  277. data/lib/rubocop/magic_comment.rb +12 -10
  278. data/lib/rubocop/options.rb +11 -1
  279. data/lib/rubocop/result_cache.rb +5 -2
  280. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  281. data/lib/rubocop/rspec/shared_contexts.rb +2 -3
  282. data/lib/rubocop/runner.rb +6 -4
  283. data/lib/rubocop/server/cache.rb +1 -0
  284. data/lib/rubocop/server/client_command/exec.rb +3 -2
  285. data/lib/rubocop/string_interpreter.rb +3 -3
  286. data/lib/rubocop/target_finder.rb +7 -3
  287. data/lib/rubocop/target_ruby.rb +12 -7
  288. data/lib/rubocop/version.rb +10 -6
  289. data/lib/rubocop.rb +19 -0
  290. metadata +54 -15
@@ -35,7 +35,7 @@ module RuboCop
35
35
  unless contents.empty?
36
36
  corrector.replace(
37
37
  contents,
38
- contents.source.gsub(/\A/, '# ').gsub(/\n\n/, "\n#\n").gsub(/\n(?=[^#])/, "\n# ")
38
+ contents.source.gsub(/\A/, '# ').gsub("\n\n", "\n#\n").gsub(/\n(?=[^#])/, "\n# ")
39
39
  )
40
40
  end
41
41
  corrector.remove(eq_end)
@@ -370,7 +370,8 @@ module RuboCop
370
370
  def special_method_proper_block_style?(node)
371
371
  method_name = node.method_name
372
372
  return true if allowed_method?(method_name) || matches_allowed_pattern?(method_name)
373
- return node.braces? if braces_required_method?(method_name)
373
+
374
+ node.braces? if braces_required_method?(method_name)
374
375
  end
375
376
 
376
377
  def braces_required_method?(method_name)
@@ -411,7 +412,7 @@ module RuboCop
411
412
  end
412
413
 
413
414
  def correction_would_break_code?(node)
414
- return unless node.keywords?
415
+ return false unless node.keywords?
415
416
 
416
417
  node.send_node.arguments? && !node.send_node.parenthesized?
417
418
  end
@@ -433,7 +434,7 @@ module RuboCop
433
434
  end
434
435
 
435
436
  def return_value_used?(node)
436
- return unless node.parent
437
+ return false unless node.parent
437
438
 
438
439
  # If there are parentheses around the block, check if that
439
440
  # is being used.
@@ -445,7 +446,7 @@ module RuboCop
445
446
  end
446
447
 
447
448
  def return_value_of_scope?(node)
448
- return unless node.parent
449
+ return false unless node.parent
449
450
 
450
451
  conditional?(node.parent) || array_or_range?(node.parent) ||
451
452
  node.parent.children.last == node
@@ -125,7 +125,7 @@ module RuboCop
125
125
  when :==, :eql?, :equal?
126
126
  find_target_in_equality_node(node)
127
127
  when :===
128
- node.arguments.first
128
+ node.first_argument
129
129
  when :include?, :cover?
130
130
  find_target_in_include_or_cover_node(node)
131
131
  when :match, :match?, :=~
@@ -134,7 +134,7 @@ module RuboCop
134
134
  end
135
135
 
136
136
  def find_target_in_equality_node(node)
137
- argument = node.arguments.first
137
+ argument = node.first_argument
138
138
  receiver = node.receiver
139
139
  return unless argument && receiver
140
140
 
@@ -152,7 +152,7 @@ module RuboCop
152
152
  end
153
153
 
154
154
  def find_target_in_match_node(node)
155
- argument = node.arguments.first
155
+ argument = node.first_argument
156
156
  receiver = node.receiver
157
157
  return unless receiver
158
158
 
@@ -185,7 +185,7 @@ module RuboCop
185
185
  def condition_from_send_node(node, target)
186
186
  case node.method_name
187
187
  when :is_a?
188
- node.arguments.first if node.receiver == target
188
+ node.first_argument if node.receiver == target
189
189
  when :==, :eql?, :equal?
190
190
  condition_from_equality_node(node, target)
191
191
  when :=~, :match, :match?
@@ -139,7 +139,7 @@ module RuboCop
139
139
  end
140
140
 
141
141
  def check_style(node, body)
142
- return if node.identifier.children[0]&.cbase_type?
142
+ return if node.identifier.namespace&.cbase_type?
143
143
 
144
144
  if style == :nested
145
145
  check_nested_style(node)
@@ -40,6 +40,7 @@ module RuboCop
40
40
  corrector.replace(node.loc.selector, replacement)
41
41
  end
42
42
  end
43
+ alias on_csend on_send
43
44
 
44
45
  def message(node)
45
46
  if node.method?(:is_a?)
@@ -5,9 +5,14 @@ module RuboCop
5
5
  module Style
6
6
  # Enforces the use of `Object#instance_of?` instead of class comparison
7
7
  # for equality.
8
- # `==`, `equal?`, and `eql?` methods are allowed by default.
8
+ # `==`, `equal?`, and `eql?` custom method definitions are allowed by default.
9
9
  # These are customizable with `AllowedMethods` option.
10
10
  #
11
+ # @safety
12
+ # This cop's autocorrection is unsafe because there is no guarantee that
13
+ # the constant `Foo` exists when autocorrecting `var.class.name == 'Foo'` to
14
+ # `var.instance_of?(Foo)`.
15
+ #
11
16
  # @example
12
17
  # # bad
13
18
  # var.class == Date
@@ -18,53 +23,31 @@ module RuboCop
18
23
  # # good
19
24
  # var.instance_of?(Date)
20
25
  #
21
- # @example AllowedMethods: [] (default)
26
+ # @example AllowedMethods: ['==', 'equal?', 'eql?'] (default)
22
27
  # # good
23
- # var.instance_of?(Date)
28
+ # def ==(other)
29
+ # self.class == other.class && name == other.name
30
+ # end
24
31
  #
25
- # # bad
26
- # var.class == Date
27
- # var.class.equal?(Date)
28
- # var.class.eql?(Date)
29
- # var.class.name == 'Date'
30
- # var.class.to_s == 'Date'
31
- # var.class.inspect == 'Date'
32
+ # def equal?(other)
33
+ # self.class.equal?(other.class) && name.equal?(other.name)
34
+ # end
32
35
  #
33
- # @example AllowedMethods: [`==`]
34
- # # good
35
- # var.instance_of?(Date)
36
- # var.class == Date
37
- # var.class.name == 'Date'
38
- # var.class.to_s == 'Date'
39
- # var.class.inspect == 'Date'
40
- #
41
- # # bad
42
- # var.class.equal?(Date)
43
- # var.class.eql?(Date)
36
+ # def eql?(other)
37
+ # self.class.eql?(other.class) && name.eql?(other.name)
38
+ # end
44
39
  #
45
40
  # @example AllowedPatterns: [] (default)
46
- # # good
47
- # var.instance_of?(Date)
48
- #
49
41
  # # bad
50
- # var.class == Date
51
- # var.class.equal?(Date)
52
- # var.class.eql?(Date)
53
- # var.class.name == 'Date'
54
- # var.class.to_s == 'Date'
55
- # var.class.inspect == 'Date'
42
+ # def eq(other)
43
+ # self.class.eq(other.class) && name.eq(other.name)
44
+ # end
56
45
  #
57
46
  # @example AllowedPatterns: ['eq']
58
47
  # # good
59
- # var.instance_of?(Date)
60
- # var.class.equal?(Date)
61
- # var.class.eql?(Date)
62
- #
63
- # # bad
64
- # var.class == Date
65
- # var.class.name == 'Date'
66
- # var.class.to_s == 'Date'
67
- # var.class.inspect == 'Date'
48
+ # def eq(other)
49
+ # self.class.eq(other.class) && name.eq(other.name)
50
+ # end
68
51
  #
69
52
  class ClassEqualityComparison < Base
70
53
  include RangeHelp
@@ -91,6 +74,8 @@ module RuboCop
91
74
  matches_allowed_pattern?(def_node.method_name))
92
75
 
93
76
  class_comparison_candidate?(node) do |receiver_node, class_node|
77
+ return if class_node.dstr_type?
78
+
94
79
  range = offense_range(receiver_node, node)
95
80
  class_argument = (class_name = class_name(class_node, node)) ? "(#{class_name})" : ''
96
81
 
@@ -9,8 +9,8 @@ module RuboCop
9
9
  # @safety
10
10
  # It is unsafe by default because false positives may occur in the
11
11
  # `nil` check of block arguments to the receiver object. Additionally,
12
- # we can't know the type of the receiver object for sure, which may
13
- # result in false positives as well.
12
+ # we can't know the type of the receiver object for sure, which may
13
+ # result in false positives as well.
14
14
  #
15
15
  # For example, `[[1, 2], [3, nil]].reject { |first, second| second.nil? }`
16
16
  # and `[[1, 2], [3, nil]].compact` are not compatible. This will work fine
@@ -19,7 +19,9 @@ module RuboCop
19
19
  # @example
20
20
  # # bad
21
21
  # array.reject(&:nil?)
22
+ # array.delete_if(&:nil?)
22
23
  # array.reject { |e| e.nil? }
24
+ # array.delete_if { |e| e.nil? }
23
25
  # array.select { |e| !e.nil? }
24
26
  #
25
27
  # # good
@@ -33,20 +35,25 @@ module RuboCop
33
35
  # # good
34
36
  # hash.compact!
35
37
  #
38
+ # @example AllowedReceivers: ['params']
39
+ # # good
40
+ # params.reject(&:nil?)
41
+ #
36
42
  class CollectionCompact < Base
43
+ include AllowedReceivers
37
44
  include RangeHelp
38
45
  extend AutoCorrector
39
46
  extend TargetRubyVersion
40
47
 
41
48
  MSG = 'Use `%<good>s` instead of `%<bad>s`.'
42
- RESTRICT_ON_SEND = %i[reject reject! select select!].freeze
49
+ RESTRICT_ON_SEND = %i[reject delete_if reject! select select!].freeze
43
50
  TO_ENUM_METHODS = %i[to_enum lazy].freeze
44
51
 
45
52
  minimum_target_ruby_version 2.4
46
53
 
47
54
  # @!method reject_method_with_block_pass?(node)
48
55
  def_node_matcher :reject_method_with_block_pass?, <<~PATTERN
49
- (send !nil? {:reject :reject!}
56
+ (call !nil? {:reject :delete_if :reject!}
50
57
  (block_pass
51
58
  (sym :nil?)))
52
59
  PATTERN
@@ -54,33 +61,37 @@ module RuboCop
54
61
  # @!method reject_method?(node)
55
62
  def_node_matcher :reject_method?, <<~PATTERN
56
63
  (block
57
- (send
58
- !nil? {:reject :reject!})
64
+ (call
65
+ !nil? {:reject :delete_if :reject!})
59
66
  $(args ...)
60
- (send
67
+ (call
61
68
  $(lvar _) :nil?))
62
69
  PATTERN
63
70
 
64
71
  # @!method select_method?(node)
65
72
  def_node_matcher :select_method?, <<~PATTERN
66
73
  (block
67
- (send
74
+ (call
68
75
  !nil? {:select :select!})
69
76
  $(args ...)
70
- (send
71
- (send
77
+ (call
78
+ (call
72
79
  $(lvar _) :nil?) :!))
73
80
  PATTERN
74
81
 
75
82
  def on_send(node)
76
83
  return unless (range = offense_range(node))
77
- return if target_ruby_version <= 3.0 && to_enum_method?(node)
84
+ return if allowed_receiver?(node.receiver)
85
+ if (target_ruby_version <= 3.0 || node.method?(:delete_if)) && to_enum_method?(node)
86
+ return
87
+ end
78
88
 
79
89
  good = good_method_name(node)
80
90
  message = format(MSG, good: good, bad: range.source)
81
91
 
82
92
  add_offense(range, message: message) { |corrector| corrector.replace(range, good) }
83
93
  end
94
+ alias on_csend on_send
84
95
 
85
96
  private
86
97
 
@@ -25,6 +25,7 @@ module RuboCop
25
25
  # # bad
26
26
  # items.collect
27
27
  # items.collect!
28
+ # items.collect_concat
28
29
  # items.inject
29
30
  # items.detect
30
31
  # items.find_all
@@ -33,6 +34,7 @@ module RuboCop
33
34
  # # good
34
35
  # items.map
35
36
  # items.map!
37
+ # items.flat_map
36
38
  # items.reduce
37
39
  # items.find
38
40
  # items.select
@@ -3,8 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for methods invoked via the :: operator instead
7
- # of the . operator (like FileUtils::rmdir instead of FileUtils.rmdir).
6
+ # Checks for methods invoked via the `::` operator instead
7
+ # of the `.` operator (like `FileUtils::rmdir` instead of `FileUtils.rmdir`).
8
8
  #
9
9
  # @example
10
10
  # # bad
@@ -57,38 +57,66 @@ module RuboCop
57
57
  # end
58
58
  #
59
59
  class CombinableLoops < Base
60
+ extend AutoCorrector
61
+
60
62
  MSG = 'Combine this loop with the previous loop.'
61
63
 
62
64
  def on_block(node)
63
65
  return unless node.parent&.begin_type?
64
66
  return unless collection_looping_method?(node)
67
+ return unless same_collection_looping_block?(node, node.left_sibling)
68
+ return unless node.body && node.left_sibling.body
65
69
 
66
- add_offense(node) if same_collection_looping?(node, node.left_sibling)
70
+ add_offense(node) do |corrector|
71
+ combine_with_left_sibling(corrector, node)
72
+ end
67
73
  end
68
74
 
69
75
  alias on_numblock on_block
70
76
 
71
77
  def on_for(node)
72
78
  return unless node.parent&.begin_type?
79
+ return unless same_collection_looping_for?(node, node.left_sibling)
73
80
 
74
- sibling = node.left_sibling
75
- add_offense(node) if sibling&.for_type? && node.collection == sibling.collection
81
+ add_offense(node) do |corrector|
82
+ combine_with_left_sibling(corrector, node)
83
+ end
76
84
  end
77
85
 
78
86
  private
79
87
 
80
88
  def collection_looping_method?(node)
81
- # TODO: Remove `Symbol#to_s` after supporting only Ruby >= 2.7.
82
- method_name = node.method_name.to_s
89
+ method_name = node.method_name
83
90
  method_name.start_with?('each') || method_name.end_with?('_each')
84
91
  end
85
92
 
86
- def same_collection_looping?(node, sibling)
87
- (sibling&.block_type? || sibling&.numblock_type?) &&
88
- sibling.send_node.method?(node.method_name) &&
93
+ def same_collection_looping_block?(node, sibling)
94
+ return false if sibling.nil? || (!sibling.block_type? && !sibling.numblock_type?)
95
+
96
+ sibling.method?(node.method_name) &&
89
97
  sibling.receiver == node.receiver &&
90
98
  sibling.send_node.arguments == node.send_node.arguments
91
99
  end
100
+
101
+ def same_collection_looping_for?(node, sibling)
102
+ sibling&.for_type? && node.collection == sibling.collection
103
+ end
104
+
105
+ def combine_with_left_sibling(corrector, node)
106
+ corrector.remove(node.left_sibling.body.source_range.end.join(node.left_sibling.loc.end))
107
+ corrector.remove(node.source_range.begin.join(node.body.source_range.begin))
108
+
109
+ correct_end_of_block(corrector, node)
110
+ end
111
+
112
+ def correct_end_of_block(corrector, node)
113
+ return unless node.left_sibling.respond_to?(:braces?)
114
+ return if node.right_sibling&.block_type? || node.right_sibling&.numblock_type?
115
+
116
+ end_of_block = node.left_sibling.braces? ? '}' : ' end'
117
+ corrector.remove(node.loc.end)
118
+ corrector.insert_before(node.source_range.end, end_of_block)
119
+ end
92
120
  end
93
121
  end
94
122
  end
@@ -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
 
@@ -74,7 +75,7 @@ module RuboCop
74
75
  new_arguments =
75
76
  node.arguments.map do |arg|
76
77
  if arg.percent_literal?
77
- arg.children.map(&:value).map(&:inspect)
78
+ arg.children.map { |child| child.value.inspect }
78
79
  else
79
80
  arg.children.map(&:source)
80
81
  end
@@ -350,7 +350,7 @@ module RuboCop
350
350
  end
351
351
 
352
352
  def ternary_condition?(node)
353
- [node, node.children.first].any? { |n| n.if_type? && n.ternary? }
353
+ [node, node.children.first].compact.any? { |n| n.if_type? && n.ternary? }
354
354
  end
355
355
 
356
356
  def lhs_all_match?(branches)
@@ -361,7 +361,7 @@ module RuboCop
361
361
  end
362
362
 
363
363
  def assignment_types_match?(*nodes)
364
- return unless assignment_type?(nodes.first)
364
+ return false unless assignment_type?(nodes.first)
365
365
 
366
366
  nodes.map(&:type).uniq.one?
367
367
  end
@@ -386,7 +386,7 @@ module RuboCop
386
386
  def allowed_statements?(branches)
387
387
  return false unless branches.all?
388
388
 
389
- statements = branches.map { |branch| tail(branch) }.compact
389
+ statements = branches.filter_map { |branch| tail(branch) }
390
390
 
391
391
  lhs_all_match?(statements) && statements.none?(&:masgn_type?) &&
392
392
  assignment_types_match?(*statements)
@@ -440,6 +440,8 @@ module RuboCop
440
440
  module ConditionalCorrectorHelper
441
441
  def remove_whitespace_in_branches(corrector, branch, condition, column)
442
442
  branch.each_node do |child|
443
+ next if child.source_range.nil?
444
+
443
445
  white_space = white_space_range(child, column)
444
446
  corrector.remove(white_space) if white_space.source.strip.empty?
445
447
  end
@@ -532,7 +534,7 @@ module RuboCop
532
534
  end
533
535
 
534
536
  def element_assignment?(node)
535
- node.send_type? && node.method_name != :[]=
537
+ node.send_type? && !node.method?(:[]=)
536
538
  end
537
539
 
538
540
  def extract_branches(node)
@@ -8,8 +8,11 @@ module RuboCop
8
8
  # The default regexp for an acceptable copyright notice can be found in
9
9
  # config/default.yml. The default can be changed as follows:
10
10
  #
11
- # Style/Copyright:
12
- # Notice: '^Copyright (\(c\) )?2\d{3} Acme Inc'
11
+ # [source,yaml]
12
+ # ----
13
+ # Style/Copyright:
14
+ # Notice: '^Copyright (\(c\) )?2\d{3} Acme Inc'
15
+ # ----
13
16
  #
14
17
  # This regex string is treated as an unanchored regex. For each file
15
18
  # that RuboCop scans, a comment that matches this regex must be found or
@@ -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
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for places where the `#__dir__` method can replace more
6
+ # Checks for places where the `#\_\_dir\_\_` method can replace more
7
7
  # complex constructs to retrieve a canonicalized absolute path to the
8
8
  # current file.
9
9
  #
@@ -19,18 +19,16 @@ module RuboCop
19
19
  extend AutoCorrector
20
20
  extend TargetRubyVersion
21
21
 
22
- MSG = 'Use `Dir.empty?(%<arg>s)` instead.'
23
- RESTRICT_ON_SEND = %i[== > empty? none?].freeze
22
+ MSG = 'Use `%<replacement>s` instead.'
23
+ RESTRICT_ON_SEND = %i[== != > empty? none?].freeze
24
24
 
25
25
  minimum_target_ruby_version 2.4
26
26
 
27
27
  # @!method offensive?(node)
28
28
  def_node_matcher :offensive?, <<~PATTERN
29
29
  {
30
- (send (send (send $(const {nil? cbase} :Dir) :entries $_) :size) {:== :>} (int 2))
31
- (send (send (send $(const {nil? cbase} :Dir) :children $_) :size) {:== :>} (int 0))
32
- (send (send (send (send $(const {nil? cbase} :Dir) :entries $_) :size) :!) {:== :>} (int 2))
33
- (send (send (send (send $(const {nil? cbase} :Dir) :children $_) :size) :!) {:== :>} (int 0))
30
+ (send (send (send $(const {nil? cbase} :Dir) :entries $_) :size) {:== :!= :>} (int 2))
31
+ (send (send (send $(const {nil? cbase} :Dir) :children $_) :size) {:== :!= :>} (int 0))
34
32
  (send (send $(const {nil? cbase} :Dir) :children $_) :empty?)
35
33
  (send (send $(const {nil? cbase} :Dir) :each_child $_) :none?)
36
34
  }
@@ -38,10 +36,9 @@ module RuboCop
38
36
 
39
37
  def on_send(node)
40
38
  offensive?(node) do |const_node, arg_node|
41
- add_offense(node, message: format(MSG, arg: arg_node.source)) do |corrector|
42
- bang(node)
43
- corrector.replace(node,
44
- "#{bang(node)}#{const_node.source}.empty?(#{arg_node.source})")
39
+ replacement = "#{bang(node)}#{const_node.source}.empty?(#{arg_node.source})"
40
+ add_offense(node, message: format(MSG, replacement: replacement)) do |corrector|
41
+ corrector.replace(node, replacement)
45
42
  end
46
43
  end
47
44
  end
@@ -49,10 +46,7 @@ module RuboCop
49
46
  private
50
47
 
51
48
  def bang(node)
52
- if (node.method?(:==) && node.child_nodes.first.method?(:!)) ||
53
- (node.method?(:>) && !node.child_nodes.first.method?(:!))
54
- '!'
55
- end
49
+ '!' if %i[!= >].include? node.method_name
56
50
  end
57
51
  end
58
52
  end
@@ -108,7 +108,7 @@ module RuboCop
108
108
  comments = heredoc_comment_blocks(arg_node.loc.heredoc_body.line_span)
109
109
  .concat(preceding_comment_blocks(arg_node.parent))
110
110
 
111
- return if comments.none?
111
+ return false if comments.none?
112
112
 
113
113
  regexp = comment_regexp(arg_node)
114
114
  comments.any?(regexp) || regexp.match?(comments.join)
@@ -10,7 +10,7 @@ module RuboCop
10
10
  # declarations.
11
11
  #
12
12
  # The documentation requirement is annulled if the class or module has
13
- # a "#:nodoc:" comment next to it. Likewise, "#:nodoc: all" does the
13
+ # a `#:nodoc:` comment next to it. Likewise, `#:nodoc: all` does the
14
14
  # same for all its children.
15
15
  #
16
16
  # @example
@@ -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)
@@ -40,9 +40,13 @@ module RuboCop
40
40
  extend AutoCorrector
41
41
 
42
42
  MSG = 'Do not use empty `case` condition, instead use an `if` expression.'
43
+ NOT_SUPPORTED_PARENT_TYPES = %i[return break next send csend].freeze
43
44
 
45
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
44
46
  def on_case(case_node)
45
- return if case_node.condition
47
+ if case_node.condition || NOT_SUPPORTED_PARENT_TYPES.include?(case_node.parent&.type)
48
+ return
49
+ end
46
50
 
47
51
  branch_bodies = [*case_node.when_branches.map(&:body), case_node.else_branch].compact
48
52
 
@@ -52,6 +56,7 @@ module RuboCop
52
56
 
53
57
  add_offense(case_node.loc.keyword) { |corrector| autocorrect(corrector, case_node) }
54
58
  end
59
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
55
60
 
56
61
  private
57
62
 
@@ -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)