rubocop 1.68.0 → 1.71.2

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 (361) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +77 -8
  5. data/lib/rubocop/cli/command/execute_runner.rb +3 -3
  6. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  7. data/lib/rubocop/comment_config.rb +1 -1
  8. data/lib/rubocop/config.rb +13 -4
  9. data/lib/rubocop/config_loader.rb +4 -0
  10. data/lib/rubocop/config_loader_resolver.rb +14 -3
  11. data/lib/rubocop/config_validator.rb +18 -8
  12. data/lib/rubocop/cop/autocorrect_logic.rb +32 -35
  13. data/lib/rubocop/cop/base.rb +7 -1
  14. data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
  15. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  16. data/lib/rubocop/cop/bundler/gem_filename.rb +0 -1
  17. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +0 -1
  18. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +1 -1
  19. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
  20. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
  21. data/lib/rubocop/cop/generator.rb +6 -0
  22. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  23. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  24. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -4
  25. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  26. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  27. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  28. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  29. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +229 -0
  30. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  31. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  32. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
  33. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  34. data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +48 -0
  35. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  36. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  37. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
  38. data/lib/rubocop/cop/internal_affairs.rb +5 -0
  39. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  40. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -9
  41. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  42. data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
  43. data/lib/rubocop/cop/layout/block_alignment.rb +1 -2
  44. data/lib/rubocop/cop/layout/class_structure.rb +9 -9
  45. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  46. data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
  47. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  48. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  49. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +3 -3
  50. data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
  51. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +4 -5
  52. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +3 -1
  53. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  54. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  55. data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
  56. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  57. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  58. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  59. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  60. data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
  61. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -0
  62. data/lib/rubocop/cop/layout/indentation_width.rb +7 -7
  63. data/lib/rubocop/cop/layout/leading_comment_space.rb +15 -0
  64. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +11 -2
  65. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  66. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  67. data/lib/rubocop/cop/layout/line_length.rb +119 -4
  68. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  69. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  70. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +2 -1
  71. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
  72. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
  73. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -3
  74. data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
  75. data/lib/rubocop/cop/layout/redundant_line_break.rb +10 -41
  76. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -3
  77. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  78. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  79. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  80. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  81. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  82. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -1
  83. data/lib/rubocop/cop/layout/space_around_operators.rb +19 -20
  84. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  85. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  86. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +6 -0
  87. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +4 -0
  88. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
  89. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  90. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  91. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
  92. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  93. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +10 -12
  94. data/lib/rubocop/cop/lint/circular_argument_reference.rb +6 -0
  95. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  96. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  97. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  98. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +2 -1
  99. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  100. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  101. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  102. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
  103. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  104. data/lib/rubocop/cop/lint/empty_file.rb +0 -2
  105. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  106. data/lib/rubocop/cop/lint/float_comparison.rb +19 -8
  107. data/lib/rubocop/cop/lint/float_out_of_range.rb +2 -4
  108. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  109. data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
  110. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  111. data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
  112. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +3 -0
  113. data/lib/rubocop/cop/lint/literal_as_condition.rb +1 -0
  114. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  115. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
  116. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  117. data/lib/rubocop/cop/lint/mixed_case_range.rb +3 -6
  118. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  119. data/lib/rubocop/cop/lint/nested_method_definition.rb +9 -5
  120. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  121. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
  122. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +5 -3
  123. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -3
  124. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  125. data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
  126. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
  127. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +93 -0
  128. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -2
  129. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +3 -2
  130. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  131. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  132. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  133. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +12 -7
  134. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
  135. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  136. data/lib/rubocop/cop/lint/refinement_import_methods.rb +1 -1
  137. data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
  138. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  139. data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
  140. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -1
  141. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +2 -0
  142. data/lib/rubocop/cop/lint/self_assignment.rb +8 -10
  143. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  144. data/lib/rubocop/cop/lint/shared_mutable_default.rb +65 -0
  145. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  146. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  147. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  148. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -1
  149. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +1 -1
  150. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  151. data/lib/rubocop/cop/lint/unreachable_code.rb +51 -2
  152. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
  153. data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
  154. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -4
  155. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  156. data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
  157. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +4 -0
  158. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  159. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  160. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
  161. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  162. data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
  163. data/lib/rubocop/cop/lint/void.rb +8 -11
  164. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  165. data/lib/rubocop/cop/metrics/class_length.rb +9 -9
  166. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  167. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  168. data/lib/rubocop/cop/metrics/method_length.rb +8 -1
  169. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  170. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  171. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  172. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -3
  173. data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
  174. data/lib/rubocop/cop/mixin/check_line_breakable.rb +11 -11
  175. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
  176. data/lib/rubocop/cop/mixin/comments_help.rb +7 -2
  177. data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
  178. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  179. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +4 -4
  180. data/lib/rubocop/cop/mixin/hash_subset.rb +188 -0
  181. data/lib/rubocop/cop/mixin/line_length_help.rb +5 -4
  182. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  183. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +5 -9
  184. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +68 -30
  185. data/lib/rubocop/cop/mixin/range_help.rb +0 -1
  186. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  187. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
  188. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  189. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  190. data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
  191. data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
  192. data/lib/rubocop/cop/naming/accessor_method_name.rb +6 -6
  193. data/lib/rubocop/cop/naming/block_forwarding.rb +19 -15
  194. data/lib/rubocop/cop/naming/constant_name.rb +6 -7
  195. data/lib/rubocop/cop/naming/file_name.rb +0 -2
  196. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +11 -12
  197. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +6 -14
  198. data/lib/rubocop/cop/naming/variable_name.rb +3 -4
  199. data/lib/rubocop/cop/naming/variable_number.rb +2 -3
  200. data/lib/rubocop/cop/security/compound_hash.rb +2 -0
  201. data/lib/rubocop/cop/security/yaml_load.rb +3 -2
  202. data/lib/rubocop/cop/style/access_modifier_declarations.rb +86 -28
  203. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +1 -1
  204. data/lib/rubocop/cop/style/and_or.rb +1 -1
  205. data/lib/rubocop/cop/style/arguments_forwarding.rb +39 -23
  206. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  207. data/lib/rubocop/cop/style/array_intersect.rb +5 -4
  208. data/lib/rubocop/cop/style/bitwise_predicate.rb +1 -1
  209. data/lib/rubocop/cop/style/block_delimiters.rb +24 -22
  210. data/lib/rubocop/cop/style/case_like_if.rb +8 -11
  211. data/lib/rubocop/cop/style/class_and_module_children.rb +6 -3
  212. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  213. data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
  214. data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
  215. data/lib/rubocop/cop/style/commented_keyword.rb +11 -1
  216. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  217. data/lib/rubocop/cop/style/conditional_assignment.rb +25 -25
  218. data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
  219. data/lib/rubocop/cop/style/dig_chain.rb +89 -0
  220. data/lib/rubocop/cop/style/documentation.rb +1 -1
  221. data/lib/rubocop/cop/style/double_negation.rb +3 -3
  222. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  223. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  224. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  225. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  226. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  227. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  228. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -3
  229. data/lib/rubocop/cop/style/explicit_block_argument.rb +15 -2
  230. data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
  231. data/lib/rubocop/cop/style/fetch_env_var.rb +2 -1
  232. data/lib/rubocop/cop/style/file_null.rb +89 -0
  233. data/lib/rubocop/cop/style/file_touch.rb +75 -0
  234. data/lib/rubocop/cop/style/float_division.rb +8 -4
  235. data/lib/rubocop/cop/style/for.rb +0 -1
  236. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  237. data/lib/rubocop/cop/style/global_vars.rb +1 -3
  238. data/lib/rubocop/cop/style/guard_clause.rb +1 -1
  239. data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
  240. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -6
  241. data/lib/rubocop/cop/style/hash_except.rb +35 -147
  242. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  243. data/lib/rubocop/cop/style/hash_syntax.rb +6 -3
  244. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  245. data/lib/rubocop/cop/style/if_inside_else.rb +0 -1
  246. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  247. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +2 -3
  248. data/lib/rubocop/cop/style/if_with_semicolon.rb +20 -9
  249. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  250. data/lib/rubocop/cop/style/inverse_methods.rb +6 -7
  251. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  252. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +2 -2
  253. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  254. data/lib/rubocop/cop/style/lambda_call.rb +3 -2
  255. data/lib/rubocop/cop/style/map_into_array.rb +1 -1
  256. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  257. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  258. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +20 -13
  259. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  260. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +8 -11
  261. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -4
  262. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  263. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  264. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
  265. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  266. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  267. data/lib/rubocop/cop/style/multiple_comparison.rb +34 -22
  268. data/lib/rubocop/cop/style/mutable_constant.rb +7 -8
  269. data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -5
  270. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  271. data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
  272. data/lib/rubocop/cop/style/not.rb +1 -1
  273. data/lib/rubocop/cop/style/object_then.rb +14 -15
  274. data/lib/rubocop/cop/style/one_line_conditional.rb +25 -4
  275. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  276. data/lib/rubocop/cop/style/operator_method_call.rb +5 -6
  277. data/lib/rubocop/cop/style/or_assignment.rb +3 -6
  278. data/lib/rubocop/cop/style/parallel_assignment.rb +9 -18
  279. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  280. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  281. data/lib/rubocop/cop/style/proc.rb +1 -2
  282. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  283. data/lib/rubocop/cop/style/raise_args.rb +7 -5
  284. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  285. data/lib/rubocop/cop/style/redundant_argument.rb +3 -1
  286. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
  287. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  288. data/lib/rubocop/cop/style/redundant_condition.rb +38 -23
  289. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
  290. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  291. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  292. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  293. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
  294. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  295. data/lib/rubocop/cop/style/redundant_line_continuation.rb +44 -23
  296. data/lib/rubocop/cop/style/redundant_parentheses.rb +12 -12
  297. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -0
  298. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  299. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  300. data/lib/rubocop/cop/style/redundant_return.rb +2 -2
  301. data/lib/rubocop/cop/style/redundant_self.rb +8 -15
  302. data/lib/rubocop/cop/style/redundant_self_assignment.rb +20 -32
  303. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
  304. data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
  305. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  306. data/lib/rubocop/cop/style/rescue_modifier.rb +2 -3
  307. data/lib/rubocop/cop/style/return_nil.rb +1 -1
  308. data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
  309. data/lib/rubocop/cop/style/select_by_regexp.rb +1 -1
  310. data/lib/rubocop/cop/style/self_assignment.rb +11 -17
  311. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  312. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  313. data/lib/rubocop/cop/style/signal_exception.rb +2 -3
  314. data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
  315. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  316. data/lib/rubocop/cop/style/single_line_do_end_block.rb +12 -3
  317. data/lib/rubocop/cop/style/single_line_methods.rb +3 -4
  318. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  319. data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -5
  320. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  321. data/lib/rubocop/cop/style/string_concatenation.rb +14 -13
  322. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  323. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  324. data/lib/rubocop/cop/style/super_arguments.rb +65 -17
  325. data/lib/rubocop/cop/style/swap_values.rb +4 -15
  326. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  327. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  328. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
  329. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
  330. data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
  331. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  332. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  333. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  334. data/lib/rubocop/cop/util.rb +11 -4
  335. data/lib/rubocop/cop/variable_force/variable.rb +14 -2
  336. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  337. data/lib/rubocop/cop/variable_force.rb +4 -10
  338. data/lib/rubocop/cops_documentation_generator.rb +22 -14
  339. data/lib/rubocop/directive_comment.rb +9 -8
  340. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  341. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  342. data/lib/rubocop/lsp/logger.rb +2 -2
  343. data/lib/rubocop/lsp/routes.rb +7 -23
  344. data/lib/rubocop/lsp/runtime.rb +15 -49
  345. data/lib/rubocop/lsp/stdin_runner.rb +83 -0
  346. data/lib/rubocop/magic_comment.rb +3 -3
  347. data/lib/rubocop/options.rb +2 -1
  348. data/lib/rubocop/path_util.rb +11 -8
  349. data/lib/rubocop/result_cache.rb +13 -13
  350. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  351. data/lib/rubocop/rspec/shared_contexts.rb +4 -1
  352. data/lib/rubocop/rspec/support.rb +1 -2
  353. data/lib/rubocop/runner.rb +5 -6
  354. data/lib/rubocop/target_finder.rb +1 -0
  355. data/lib/rubocop/target_ruby.rb +15 -0
  356. data/lib/rubocop/version.rb +1 -1
  357. data/lib/rubocop.rb +14 -0
  358. data/lib/ruby_lsp/rubocop/addon.rb +78 -0
  359. data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +50 -0
  360. metadata +36 -15
  361. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for usage of `File.open` in append mode with empty block.
7
+ #
8
+ # Such a usage only creates a new file, but it doesn't update
9
+ # timestamps for an existing file, which might have been the intention.
10
+ #
11
+ # For example, for an existing file `foo.txt`:
12
+ #
13
+ # ruby -e "puts File.mtime('foo.txt')"
14
+ # # 2024-11-26 12:17:23 +0100
15
+ #
16
+ # ruby -e "File.open('foo.txt', 'a') {}"
17
+ #
18
+ # ruby -e "puts File.mtime('foo.txt')"
19
+ # # 2024-11-26 12:17:23 +0100 -> unchanged
20
+ #
21
+ # If the intention was to update timestamps, `FileUtils.touch('foo.txt')`
22
+ # should be used instead.
23
+ #
24
+ # @safety
25
+ # Autocorrection is unsafe for this cop because unlike `File.open`,
26
+ # `FileUtils.touch` updates an existing file's timestamps.
27
+ #
28
+ # @example
29
+ # # bad
30
+ # File.open(filename, 'a') {}
31
+ # File.open(filename, 'a+') {}
32
+ #
33
+ # # good
34
+ # FileUtils.touch(filename)
35
+ #
36
+ class FileTouch < Base
37
+ extend AutoCorrector
38
+
39
+ MSG = 'Use `FileUtils.touch(%<argument>s)` instead of `File.open` in ' \
40
+ 'append mode with empty block.'
41
+
42
+ RESTRICT_ON_SEND = %i[open].freeze
43
+
44
+ APPEND_FILE_MODES = %w[a a+ ab a+b at a+t].to_set.freeze
45
+
46
+ # @!method file_open?(node)
47
+ def_node_matcher :file_open?, <<~PATTERN
48
+ (send
49
+ (const {nil? cbase} :File) :open
50
+ $(...)
51
+ (str %APPEND_FILE_MODES))
52
+ PATTERN
53
+
54
+ def on_send(node)
55
+ filename = file_open?(node)
56
+ parent = node.parent
57
+
58
+ return unless filename
59
+ return unless parent && empty_block?(parent)
60
+
61
+ message = format(MSG, argument: filename.source)
62
+ add_offense(parent, message: message) do |corrector|
63
+ corrector.replace(parent, "FileUtils.touch(#{filename.source})")
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def empty_block?(node)
70
+ node.block_type? && !node.body
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -65,19 +65,23 @@ module RuboCop
65
65
 
66
66
  # @!method right_coerce?(node)
67
67
  def_node_matcher :right_coerce?, <<~PATTERN
68
- (send _ :/ (send _ :to_f))
68
+ (send _ :/ #to_f_method?)
69
69
  PATTERN
70
70
  # @!method left_coerce?(node)
71
71
  def_node_matcher :left_coerce?, <<~PATTERN
72
- (send (send _ :to_f) :/ _)
72
+ (send #to_f_method? :/ _)
73
73
  PATTERN
74
74
  # @!method both_coerce?(node)
75
75
  def_node_matcher :both_coerce?, <<~PATTERN
76
- (send (send _ :to_f) :/ (send _ :to_f))
76
+ (send #to_f_method? :/ #to_f_method?)
77
77
  PATTERN
78
78
  # @!method any_coerce?(node)
79
79
  def_node_matcher :any_coerce?, <<~PATTERN
80
- {(send _ :/ (send _ :to_f)) (send (send _ :to_f) :/ _)}
80
+ {(send _ :/ #to_f_method?) (send #to_f_method? :/ _)}
81
+ PATTERN
82
+ # @!method to_f_method?(node)
83
+ def_node_matcher :to_f_method?, <<~PATTERN
84
+ (send !nil? :to_f)
81
85
  PATTERN
82
86
 
83
87
  def on_send(node)
@@ -44,7 +44,6 @@ module RuboCop
44
44
  #
45
45
  class For < Base
46
46
  include ConfigurableEnforcedStyle
47
- include RangeHelp
48
47
  extend AutoCorrector
49
48
 
50
49
  EACH_LENGTH = 'each'.length
@@ -151,7 +151,7 @@ module RuboCop
151
151
 
152
152
  def frozen_string_literal_comment(processed_source)
153
153
  processed_source.tokens.find do |token|
154
- token.text.start_with?(FROZEN_STRING_LITERAL)
154
+ token.text.start_with?(FROZEN_STRING_LITERAL_REGEXP)
155
155
  end
156
156
  end
157
157
 
@@ -70,9 +70,7 @@ module RuboCop
70
70
  end
71
71
 
72
72
  def check(node)
73
- global_var, = *node
74
-
75
- add_offense(node.loc.name) unless allowed_var?(global_var)
73
+ add_offense(node.loc.name) unless allowed_var?(node.name)
76
74
  end
77
75
  end
78
76
  end
@@ -264,7 +264,7 @@ module RuboCop
264
264
 
265
265
  def and_or_guard_clause?(guard_clause)
266
266
  parent = guard_clause.parent
267
- parent.and_type? || parent.or_type?
267
+ parent.operator_keyword?
268
268
  end
269
269
 
270
270
  def too_long_for_single_line?(node, example)
@@ -111,8 +111,7 @@ module RuboCop
111
111
  end
112
112
 
113
113
  def requires_parens?(node)
114
- (node.call_type? && node.arguments.any? && !node.parenthesized?) ||
115
- node.or_type? || node.and_type?
114
+ (node.call_type? && node.arguments.any? && !node.parenthesized?) || node.operator_keyword?
116
115
  end
117
116
 
118
117
  def multi_argument(node)
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for uses of `each_key` and `each_value` Hash methods.
6
+ # Checks for uses of `each_key` and `each_value` `Hash` methods.
7
7
  #
8
8
  # NOTE: If you have an array of two-element arrays, you can put
9
9
  # parentheses around the block arguments to indicate that you're not
@@ -44,7 +44,7 @@ module RuboCop
44
44
 
45
45
  # @!method kv_each(node)
46
46
  def_node_matcher :kv_each, <<~PATTERN
47
- ({block numblock} $(call (call _ ${:keys :values}) :each) ...)
47
+ (any_block $(call (call _ ${:keys :values}) :each) ...)
48
48
  PATTERN
49
49
 
50
50
  # @!method each_arguments(node)
@@ -162,10 +162,7 @@ module RuboCop
162
162
 
163
163
  def use_array_converter_method_as_preceding?(node)
164
164
  return false unless (preceding_method = node.children.first.children.first)
165
- unless preceding_method.call_type? ||
166
- preceding_method.block_type? || preceding_method.numblock_type?
167
- return false
168
- end
165
+ return false unless preceding_method.type?(:call, :any_block)
169
166
 
170
167
  ARRAY_CONVERTER_METHODS.include?(preceding_method.method_name)
171
168
  end
@@ -10,8 +10,10 @@ module RuboCop
10
10
  # (`Hash#except` was added in Ruby 3.0.)
11
11
  #
12
12
  # For safe detection, it is limited to commonly used string and symbol comparisons
13
- # when used `==`.
14
- # And do not check `Hash#delete_if` and `Hash#keep_if` to change receiver object.
13
+ # when using `==` or `!=`.
14
+ #
15
+ # This cop doesn't check for `Hash#delete_if` and `Hash#keep_if` because they
16
+ # modify the receiver.
15
17
  #
16
18
  # @safety
17
19
  # This cop is unsafe because it cannot be guaranteed that the receiver
@@ -23,6 +25,9 @@ module RuboCop
23
25
  # {foo: 1, bar: 2, baz: 3}.reject {|k, v| k == :bar }
24
26
  # {foo: 1, bar: 2, baz: 3}.select {|k, v| k != :bar }
25
27
  # {foo: 1, bar: 2, baz: 3}.filter {|k, v| k != :bar }
28
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| k.eql?(:bar) }
29
+ #
30
+ # # bad
26
31
  # {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].include?(k) }
27
32
  # {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].include?(k) }
28
33
  # {foo: 1, bar: 2, baz: 3}.filter {|k, v| !%i[bar].include?(k) }
@@ -30,161 +35,44 @@ module RuboCop
30
35
  # # good
31
36
  # {foo: 1, bar: 2, baz: 3}.except(:bar)
32
37
  #
38
+ # @example AllCops:ActiveSupportExtensionsEnabled: false (default)
39
+ #
40
+ # # good
41
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].exclude?(k) }
42
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].exclude?(k) }
43
+ #
44
+ # # good
45
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| k.in?(%i[bar]) }
46
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| !k.in?(%i[bar]) }
47
+ #
48
+ # @example AllCops:ActiveSupportExtensionsEnabled: true
49
+ #
50
+ # # bad
51
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].exclude?(k) }
52
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].exclude?(k) }
53
+ #
54
+ # # bad
55
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| k.in?(%i[bar]) }
56
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| !k.in?(%i[bar]) }
57
+ #
58
+ # # good
59
+ # {foo: 1, bar: 2, baz: 3}.except(:bar)
60
+ #
33
61
  class HashExcept < Base
34
- include RangeHelp
62
+ include HashSubset
35
63
  extend TargetRubyVersion
36
64
  extend AutoCorrector
37
65
 
38
66
  minimum_target_ruby_version 3.0
39
67
 
40
- MSG = 'Use `%<prefer>s` instead.'
41
- RESTRICT_ON_SEND = %i[reject select filter].freeze
42
-
43
- # @!method bad_method_with_poro?(node)
44
- def_node_matcher :bad_method_with_poro?, <<~PATTERN
45
- (block
46
- (call _ _)
47
- (args
48
- $(arg _)
49
- (arg _))
50
- {
51
- $(send
52
- _ {:== :!= :eql? :include?} _)
53
- (send
54
- $(send
55
- _ {:== :!= :eql? :include?} _) :!)
56
- })
57
- PATTERN
58
-
59
- # @!method bad_method_with_active_support?(node)
60
- def_node_matcher :bad_method_with_active_support?, <<~PATTERN
61
- (block
62
- (send _ _)
63
- (args
64
- $(arg _)
65
- (arg _))
66
- {
67
- $(send
68
- _ {:== :!= :eql? :in? :include? :exclude?} _)
69
- (send
70
- $(send
71
- _ {:== :!= :eql? :in? :include? :exclude?} _) :!)
72
- })
73
- PATTERN
74
-
75
- def on_send(node)
76
- method_name = node.method_name
77
- block = node.parent
78
- return unless bad_method?(method_name, block) && semantically_except_method?(node, block)
79
-
80
- except_key = except_key(block)
81
- return if except_key.nil? || !safe_to_register_offense?(block, except_key)
82
-
83
- range = offense_range(node)
84
- preferred_method = "except(#{except_key_source(except_key)})"
85
-
86
- add_offense(range, message: format(MSG, prefer: preferred_method)) do |corrector|
87
- corrector.replace(range, preferred_method)
88
- end
89
- end
90
- alias on_csend on_send
91
-
92
68
  private
93
69
 
94
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
95
- def bad_method?(method_name, block)
96
- if active_support_extensions_enabled?
97
- bad_method_with_active_support?(block) do |key_arg, send_node|
98
- if send_node.method?(:in?) && send_node.receiver&.source != key_arg.source
99
- return false
100
- end
101
- return true if !send_node.method?(:include?) && !send_node.method?(:exclude?)
102
-
103
- send_node.first_argument&.source == key_arg.source
104
- end
105
- else
106
- bad_method_with_poro?(block) do |key_arg, send_node|
107
- return false if method_name == :reject && block.body.method?(:!)
108
-
109
- !send_node.method?(:include?) || send_node.first_argument&.source == key_arg.source
110
- end
111
- end
112
- end
113
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
114
-
115
- def semantically_except_method?(send, block)
116
- body = block.body
117
-
118
- negated = body.method?('!')
119
- body = body.receiver if negated
120
-
121
- case send.method_name
122
- when :reject
123
- body.method?('==') || body.method?('eql?') || included?(negated, body)
124
- when :select, :filter
125
- body.method?('!=') || not_included?(negated, body)
126
- else
127
- false
128
- end
129
- end
130
-
131
- def included?(negated, body)
132
- body.method?('include?') || body.method?('in?') || (negated && body.method?('exclude?'))
133
- end
134
-
135
- def not_included?(negated, body)
136
- body.method?('exclude?') || (negated && (body.method?('include?') || body.method?('in?')))
137
- end
138
-
139
- def safe_to_register_offense?(block, except_key)
140
- extracted = extract_body_if_negated(block.body)
141
- if extracted.method?('in?') || extracted.method?('include?') ||
142
- extracted.method?('exclude?')
143
- return true
144
- end
145
- return true if block.body.method?('eql?')
146
-
147
- except_key.sym_type? || except_key.str_type?
148
- end
149
-
150
- def extract_body_if_negated(body)
151
- return body unless body.method?('!')
152
-
153
- body.receiver
154
- end
155
-
156
- def except_key_source(key)
157
- if key.array_type?
158
- key = if key.percent_literal?
159
- key.each_value.map { |v| decorate_source(v) }
160
- else
161
- key.each_value.map(&:source)
162
- end
163
- return key.join(', ')
164
- end
165
-
166
- key.literal? ? key.source : "*#{key.source}"
167
- end
168
-
169
- def decorate_source(value)
170
- return ":\"#{value.source}\"" if value.dsym_type?
171
- return "\"#{value.source}\"" if value.dstr_type?
172
- return ":#{value.source}" if value.sym_type?
173
-
174
- "'#{value.source}'"
175
- end
176
-
177
- def except_key(node)
178
- key_argument = node.argument_list.first.source
179
- body = extract_body_if_negated(node.body)
180
- lhs, _method_name, rhs = *body
181
- return if [lhs, rhs].map(&:source).none?(key_argument)
182
-
183
- [lhs, rhs].find { |operand| operand.source != key_argument }
70
+ def semantically_subset_method?(node)
71
+ semantically_except_method?(node)
184
72
  end
185
73
 
186
- def offense_range(node)
187
- range_between(node.loc.selector.begin_pos, node.parent.loc.end.end_pos)
74
+ def preferred_method_name
75
+ 'except'
188
76
  end
189
77
  end
190
78
  end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for usages of `Hash#reject`, `Hash#select`, and `Hash#filter` methods
7
+ # that can be replaced with `Hash#slice` method.
8
+ #
9
+ # This cop should only be enabled on Ruby version 2.5 or higher.
10
+ # (`Hash#slice` was added in Ruby 2.5.)
11
+ #
12
+ # For safe detection, it is limited to commonly used string and symbol comparisons
13
+ # when using `==` or `!=`.
14
+ #
15
+ # This cop doesn't check for `Hash#delete_if` and `Hash#keep_if` because they
16
+ # modify the receiver.
17
+ #
18
+ # @safety
19
+ # This cop is unsafe because it cannot be guaranteed that the receiver
20
+ # is a `Hash` or responds to the replacement method.
21
+ #
22
+ # @example
23
+ #
24
+ # # bad
25
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k == :bar }
26
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| k != :bar }
27
+ # {foo: 1, bar: 2, baz: 3}.filter {|k, v| k == :bar }
28
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k.eql?(:bar) }
29
+ #
30
+ # # bad
31
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].include?(k) }
32
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].include?(k) }
33
+ # {foo: 1, bar: 2, baz: 3}.filter {|k, v| %i[bar].include?(k) }
34
+ #
35
+ # # good
36
+ # {foo: 1, bar: 2, baz: 3}.slice(:bar)
37
+ #
38
+ # @example AllCops:ActiveSupportExtensionsEnabled: false (default)
39
+ #
40
+ # # good
41
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].exclude?(k) }
42
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].exclude?(k) }
43
+ #
44
+ # # good
45
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k.in?(%i[bar]) }
46
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !k.in?(%i[bar]) }
47
+ #
48
+ # @example AllCops:ActiveSupportExtensionsEnabled: true
49
+ #
50
+ # # bad
51
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].exclude?(k) }
52
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].exclude?(k) }
53
+ #
54
+ # # bad
55
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k.in?(%i[bar]) }
56
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !k.in?(%i[bar]) }
57
+ #
58
+ # # good
59
+ # {foo: 1, bar: 2, baz: 3}.slice(:bar)
60
+ #
61
+ class HashSlice < Base
62
+ include HashSubset
63
+ extend TargetRubyVersion
64
+ extend AutoCorrector
65
+
66
+ minimum_target_ruby_version 2.5
67
+
68
+ private
69
+
70
+ def semantically_subset_method?(node)
71
+ semantically_slice_method?(node)
72
+ end
73
+
74
+ def preferred_method_name
75
+ 'slice'
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -137,6 +137,7 @@ module RuboCop
137
137
  MSG_19 = 'Use the new Ruby 1.9 hash syntax.'
138
138
  MSG_NO_MIXED_KEYS = "Don't mix styles in the same hash."
139
139
  MSG_HASH_ROCKETS = 'Use hash rockets syntax.'
140
+ NO_MIXED_KEYS_STYLES = %i[ruby19_no_mixed_keys no_mixed_keys].freeze
140
141
 
141
142
  def on_hash(node)
142
143
  pairs = node.pairs
@@ -196,7 +197,7 @@ module RuboCop
196
197
  def autocorrect(corrector, node)
197
198
  if style == :hash_rockets || force_hash_rockets?(node.parent.pairs)
198
199
  autocorrect_hash_rockets(corrector, node)
199
- elsif style == :ruby19_no_mixed_keys || style == :no_mixed_keys
200
+ elsif NO_MIXED_KEYS_STYLES.include?(style)
200
201
  autocorrect_no_mixed_keys(corrector, node)
201
202
  else
202
203
  autocorrect_ruby19(corrector, node)
@@ -208,7 +209,7 @@ module RuboCop
208
209
  end
209
210
 
210
211
  def word_symbol_pair?(pair)
211
- return false unless pair.key.sym_type? || pair.key.dsym_type?
212
+ return false unless pair.key.type?(:sym, :dsym)
212
213
 
213
214
  acceptable_19_syntax_symbol?(pair.key.source)
214
215
  end
@@ -272,7 +273,9 @@ module RuboCop
272
273
  end
273
274
 
274
275
  def argument_without_space?(node)
275
- node.argument? && node.source_range.begin_pos == node.parent.loc.selector.end_pos
276
+ return false if !node.argument? || !node.parent.loc.selector
277
+
278
+ node.source_range.begin_pos == node.parent.loc.selector.end_pos
276
279
  end
277
280
 
278
281
  def autocorrect_hash_rockets(corrector, pair_node)
@@ -203,17 +203,36 @@ module RuboCop
203
203
  corrector.remove(range)
204
204
  next if inserted_expression
205
205
 
206
- if insert_position == :after_condition
207
- corrector.insert_after(node, "\n#{expression.source}")
206
+ if node.parent&.assignment?
207
+ correct_assignment(corrector, node, expression, insert_position)
208
208
  else
209
- corrector.insert_before(node, "#{expression.source}\n")
209
+ correct_no_assignment(corrector, node, expression, insert_position)
210
210
  end
211
+
211
212
  inserted_expression = true
212
213
  end
213
214
  end
214
215
  end
215
216
  # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
216
217
 
218
+ def correct_assignment(corrector, node, expression, insert_position)
219
+ if insert_position == :after_condition
220
+ assignment = node.parent.source_range.with(end_pos: node.source_range.begin_pos)
221
+ corrector.remove(assignment)
222
+ corrector.insert_after(node, "\n#{assignment.source}#{expression.source}")
223
+ else
224
+ corrector.insert_before(node.parent, "#{expression.source}\n")
225
+ end
226
+ end
227
+
228
+ def correct_no_assignment(corrector, node, expression, insert_position)
229
+ if insert_position == :after_condition
230
+ corrector.insert_after(node, "\n#{expression.source}")
231
+ else
232
+ corrector.insert_before(node, "#{expression.source}\n")
233
+ end
234
+ end
235
+
217
236
  def last_child_of_parent?(node)
218
237
  return true unless (parent = node.parent)
219
238
 
@@ -59,7 +59,6 @@ module RuboCop
59
59
  # end
60
60
  #
61
61
  class IfInsideElse < Base
62
- include IgnoredNode
63
62
  include RangeHelp
64
63
  extend AutoCorrector
65
64
 
@@ -103,7 +103,7 @@ module RuboCop
103
103
 
104
104
  def defined_argument_is_undefined?(if_node, defined_node)
105
105
  defined_argument = defined_node.first_argument
106
- return false unless defined_argument.lvar_type? || defined_argument.send_type?
106
+ return false unless defined_argument.type?(:lvar, :send)
107
107
 
108
108
  if_node.left_siblings.none? do |sibling|
109
109
  sibling.respond_to?(:lvasgn_type?) && sibling.lvasgn_type? &&
@@ -112,11 +112,11 @@ module RuboCop
112
112
  end
113
113
 
114
114
  def pattern_matching_nodes(condition)
115
- if condition.match_pattern_type? || condition.match_pattern_p_type?
115
+ if condition.type?(:match_pattern, :match_pattern_p)
116
116
  [condition]
117
117
  else
118
118
  condition.each_descendant.select do |node|
119
- node.match_pattern_type? || node.match_pattern_p_type?
119
+ node.type?(:match_pattern, :match_pattern_p)
120
120
  end
121
121
  end
122
122
  end
@@ -67,7 +67,7 @@ module RuboCop
67
67
 
68
68
  # @!method if_with_boolean_literal_branches?(node)
69
69
  def_node_matcher :if_with_boolean_literal_branches?, <<~PATTERN
70
- (if #return_boolean_value? {(true) (false) | (false) (true)})
70
+ (if #return_boolean_value? <true false>)
71
71
  PATTERN
72
72
  # @!method double_negative?(node)
73
73
  def_node_matcher :double_negative?, '(send (send _ :!) :!)'
@@ -155,8 +155,7 @@ module RuboCop
155
155
  end
156
156
 
157
157
  def require_parentheses?(condition)
158
- condition.and_type? || condition.or_type? ||
159
- (condition.send_type? && condition.comparison_method?)
158
+ condition.operator_keyword? || (condition.send_type? && condition.comparison_method?)
160
159
  end
161
160
  end
162
161
  end
@@ -23,6 +23,7 @@ module RuboCop
23
23
 
24
24
  def on_normal_if_unless(node)
25
25
  return if node.parent&.if_type?
26
+ return if part_of_ignored_node?(node)
26
27
 
27
28
  beginning = node.loc.begin
28
29
  return unless beginning&.is?(';')
@@ -32,16 +33,17 @@ module RuboCop
32
33
  add_offense(node, message: message) do |corrector|
33
34
  autocorrect(corrector, node)
34
35
  end
36
+
37
+ ignore_node(node)
35
38
  end
36
39
 
37
40
  private
38
41
 
39
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
40
42
  def message(node)
41
- template = if node.if_branch&.begin_type?
43
+ template = if require_newline?(node)
42
44
  MSG_NEWLINE
43
- elsif node.else_branch&.if_type? || node.else_branch&.begin_type? ||
44
- use_block_in_branches?(node)
45
+ elsif node.else_branch&.type?(:if, :begin) ||
46
+ use_masgn_or_block_in_branches?(node)
45
47
  MSG_IF_ELSE
46
48
  else
47
49
  MSG_TERNARY
@@ -49,18 +51,27 @@ module RuboCop
49
51
 
50
52
  format(template, expr: node.condition.source)
51
53
  end
52
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
53
54
 
54
55
  def autocorrect(corrector, node)
55
- if node.branches.compact.any?(&:begin_type?) || use_block_in_branches?(node)
56
+ if require_newline?(node) || use_masgn_or_block_in_branches?(node)
56
57
  corrector.replace(node.loc.begin, "\n")
57
58
  else
58
59
  corrector.replace(node, replacement(node))
59
60
  end
60
61
  end
61
62
 
62
- def use_block_in_branches?(node)
63
- node.branches.compact.any? { |branch| branch.block_type? || branch.numblock_type? }
63
+ def require_newline?(node)
64
+ node.branches.compact.any?(&:begin_type?) || use_return_with_argument?(node)
65
+ end
66
+
67
+ def use_masgn_or_block_in_branches?(node)
68
+ node.branches.compact.any? do |branch|
69
+ branch.type?(:masgn, :any_block)
70
+ end
71
+ end
72
+
73
+ def use_return_with_argument?(node)
74
+ node.if_branch&.return_type? && node.if_branch&.arguments&.any?
64
75
  end
65
76
 
66
77
  def replacement(node)
@@ -111,7 +122,7 @@ module RuboCop
111
122
  end
112
123
 
113
124
  def require_argument_parentheses?(node)
114
- return false unless node.call_type?
125
+ return false if !node.call_type? || node.arithmetic_operation?
115
126
 
116
127
  !node.parenthesized? && node.arguments.any? && !node.method?(:[]) && !node.method?(:[]=)
117
128
  end