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,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for `Hash` creation with a mutable default value.
7
+ # Creating a `Hash` in such a way will share the default value
8
+ # across all keys, causing unexpected behavior when modifying it.
9
+ #
10
+ # For example, when the `Hash` was created with an `Array` as the argument,
11
+ # calling `hash[:foo] << 'bar'` will also change the value of all
12
+ # other keys that have not been explicitly assigned to.
13
+ #
14
+ # @example
15
+ # # bad
16
+ # Hash.new([])
17
+ # Hash.new({})
18
+ # Hash.new(Array.new)
19
+ # Hash.new(Hash.new)
20
+ #
21
+ # # okay -- In rare cases that intentionally have this behavior,
22
+ # # without disabling the cop, you can set the default explicitly.
23
+ # h = Hash.new
24
+ # h.default = []
25
+ # h[:a] << 1
26
+ # h[:b] << 2
27
+ # h # => {:a => [1, 2], :b => [1, 2]}
28
+ #
29
+ # # okay -- beware this will discard mutations and only remember assignments
30
+ # Hash.new { Array.new }
31
+ # Hash.new { Hash.new }
32
+ # Hash.new { {} }
33
+ # Hash.new { [] }
34
+ #
35
+ # # good - frozen solution will raise an error when mutation attempted
36
+ # Hash.new([].freeze)
37
+ # Hash.new({}.freeze)
38
+ #
39
+ # # good - using a proc will create a new object for each key
40
+ # h = Hash.new
41
+ # h.default_proc = ->(h, k) { [] }
42
+ # h.default_proc = ->(h, k) { {} }
43
+ #
44
+ # # good - using a block will create a new object for each key
45
+ # Hash.new { |h, k| h[k] = [] }
46
+ # Hash.new { |h, k| h[k] = {} }
47
+ class SharedMutableDefault < Base
48
+ MSG = 'Do not create a Hash with a mutable default value ' \
49
+ 'as the default value can accidentally be changed.'
50
+ RESTRICT_ON_SEND = %i[new].freeze
51
+
52
+ # @!method hash_initialized_with_mutable_shared_object?(node)
53
+ def_node_matcher :hash_initialized_with_mutable_shared_object?, <<~PATTERN
54
+ (send (const {nil? cbase} :Hash) :new {array hash (send (const {nil? cbase} {:Array :Hash}) :new)})
55
+ PATTERN
56
+
57
+ def on_send(node)
58
+ return unless hash_initialized_with_mutable_shared_object?(node)
59
+
60
+ add_offense(node)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -116,7 +116,7 @@ module RuboCop
116
116
  private
117
117
 
118
118
  def comment_between_rescue_and_end?(node)
119
- ancestor = node.each_ancestor(:kwbegin, :def, :defs, :block, :numblock).first
119
+ ancestor = node.each_ancestor(:kwbegin, :def, :defs, :any_block).first
120
120
  return false unless ancestor
121
121
 
122
122
  end_line = ancestor.loc.end&.line || ancestor.loc.last_line
@@ -78,7 +78,7 @@ module RuboCop
78
78
  def on_send(node)
79
79
  return unless node.receiver
80
80
 
81
- if node.receiver.str_type? || node.receiver.sym_type?
81
+ if node.receiver.type?(:str, :sym)
82
82
  register_offense(node, correction: node.receiver.value.to_sym.inspect)
83
83
  elsif node.receiver.dstr_type?
84
84
  register_offense(node, correction: ":\"#{node.receiver.value.to_sym}\"")
@@ -6,9 +6,12 @@ module RuboCop
6
6
  # Repacks Parser's diagnostics/errors
7
7
  # into RuboCop's offenses.
8
8
  class Syntax < Base
9
+ LEVELS = %i[error fatal].freeze
10
+
9
11
  def on_other_file
10
12
  add_offense_from_error(processed_source.parser_error) if processed_source.parser_error
11
- processed_source.diagnostics.each do |diagnostic|
13
+ syntax_errors = processed_source.diagnostics.select { |d| LEVELS.include?(d.level) }
14
+ syntax_errors.each do |diagnostic|
12
15
  add_offense_from_diagnostic(diagnostic, processed_source.ruby_version)
13
16
  end
14
17
  super
@@ -55,7 +55,7 @@ module RuboCop
55
55
  return if node.each_descendant(:dstr).any?
56
56
 
57
57
  regexp_constructor(node) do |text|
58
- Regexp::Parser.parse(text.value)&.each_expression do |expr|
58
+ parse_regexp(text.value)&.each_expression do |expr|
59
59
  detect_offenses(text, expr)
60
60
  end
61
61
  end
@@ -81,7 +81,7 @@ module RuboCop
81
81
  node.arguments.count do |arg|
82
82
  return Float::INFINITY if arg.restarg_type?
83
83
 
84
- arg.arg_type? || arg.optarg_type? || arg.mlhs_type?
84
+ arg.type?(:arg, :optarg, :mlhs)
85
85
  end
86
86
  end
87
87
  end
@@ -130,7 +130,7 @@ module RuboCop
130
130
 
131
131
  block_body_node.each_descendant(:next, :break) do |n|
132
132
  # Ignore `next`/`break` inside an inner block
133
- next if n.each_ancestor(:block).first != block_body_node.parent
133
+ next if n.each_ancestor(:any_block).first != block_body_node.parent
134
134
  next unless n.first_argument
135
135
 
136
136
  nodes << n.first_argument
@@ -32,6 +32,22 @@ module RuboCop
32
32
  class UnreachableCode < Base
33
33
  MSG = 'Unreachable code detected.'
34
34
 
35
+ def initialize(config = nil, options = nil)
36
+ super
37
+ @redefined = []
38
+ @instance_eval_count = 0
39
+ end
40
+
41
+ def on_block(node)
42
+ @instance_eval_count += 1 if instance_eval_block?(node)
43
+ end
44
+
45
+ alias on_numblock on_block
46
+
47
+ def after_block(node)
48
+ @instance_eval_count -= 1 if instance_eval_block?(node)
49
+ end
50
+
35
51
  def on_begin(node)
36
52
  expressions = *node
37
53
 
@@ -46,19 +62,23 @@ module RuboCop
46
62
 
47
63
  private
48
64
 
65
+ def redefinable_flow_method?(method)
66
+ %i[raise fail throw exit exit! abort].include? method
67
+ end
68
+
49
69
  # @!method flow_command?(node)
50
70
  def_node_matcher :flow_command?, <<~PATTERN
51
71
  {
52
72
  return next break retry redo
53
73
  (send
54
74
  {nil? (const {nil? cbase} :Kernel)}
55
- {:raise :fail :throw :exit :exit! :abort}
75
+ #redefinable_flow_method?
56
76
  ...)
57
77
  }
58
78
  PATTERN
59
79
 
60
80
  def flow_expression?(node)
61
- return true if flow_command?(node)
81
+ return report_on_flow_command?(node) if flow_command?(node)
62
82
 
63
83
  case node.type
64
84
  when :begin, :kwbegin
@@ -68,6 +88,8 @@ module RuboCop
68
88
  check_if(node)
69
89
  when :case, :case_match
70
90
  check_case(node)
91
+ when :def
92
+ register_redefinition(node)
71
93
  else
72
94
  false
73
95
  end
@@ -88,6 +110,33 @@ module RuboCop
88
110
 
89
111
  branches.all? { |branch| branch.body && flow_expression?(branch.body) }
90
112
  end
113
+
114
+ def register_redefinition(node)
115
+ @redefined << node.method_name if redefinable_flow_method? node.method_name
116
+ false
117
+ end
118
+
119
+ def instance_eval_block?(node)
120
+ node.any_block_type? && node.method?(:instance_eval)
121
+ end
122
+
123
+ def report_on_flow_command?(node)
124
+ return true unless node.send_type?
125
+
126
+ # By the contract of this function, this case means that
127
+ # the method is called on `Kernel` in which case we
128
+ # always want to report a warning.
129
+ return true if node.receiver
130
+
131
+ # Inside an `instance_eval` we have no way to tell the
132
+ # type of `self` just by looking at the AST, so we can't
133
+ # tell if the give function that's called has been
134
+ # redefined or not, so to avoid false positives, we silence
135
+ # the warning.
136
+ return false if @instance_eval_count.positive?
137
+
138
+ !@redefined.include? node.method_name
139
+ end
91
140
  end
92
141
  end
93
142
  end
@@ -108,7 +108,7 @@ module RuboCop
108
108
  private
109
109
 
110
110
  def loop_method?(node)
111
- return false unless node.block_type? || node.numblock_type?
111
+ return false unless node.any_block_type?
112
112
 
113
113
  send_node = node.send_node
114
114
  loopable = send_node.enumerable_method? || send_node.enumerator_method? ||
@@ -39,6 +39,8 @@ module RuboCop
39
39
  # end
40
40
  #
41
41
  # @example IgnoreNotImplementedMethods: true (default)
42
+ # # with default value of `NotImplementedExceptions: ['NotImplementedError']`
43
+ #
42
44
  # # good
43
45
  # def do_something(unused)
44
46
  # raise NotImplementedError
@@ -48,6 +50,14 @@ module RuboCop
48
50
  # fail "TODO"
49
51
  # end
50
52
  #
53
+ # @example IgnoreNotImplementedMethods: true
54
+ # # with `NotImplementedExceptions: ['AbstractMethodError']`
55
+ #
56
+ # # good
57
+ # def do_something(unused)
58
+ # raise AbstractMethodError
59
+ # end
60
+ #
51
61
  # @example IgnoreNotImplementedMethods: false
52
62
  # # bad
53
63
  # def do_something(unused)
@@ -57,14 +67,13 @@ module RuboCop
57
67
  # def do_something_else(unused)
58
68
  # fail "TODO"
59
69
  # end
60
- #
61
70
  class UnusedMethodArgument < Base
62
71
  include UnusedArgument
63
72
  extend AutoCorrector
64
73
 
65
74
  # @!method not_implemented?(node)
66
75
  def_node_matcher :not_implemented?, <<~PATTERN
67
- {(send nil? :raise (const {nil? cbase} :NotImplementedError) ...)
76
+ {(send nil? :raise #allowed_exception_class? ...)
68
77
  (send nil? :fail ...)}
69
78
  PATTERN
70
79
 
@@ -115,6 +124,13 @@ module RuboCop
115
124
 
116
125
  message
117
126
  end
127
+
128
+ def allowed_exception_class?(node)
129
+ return false unless node.const_type?
130
+
131
+ allowed_class_names = Array(cop_config.fetch('NotImplementedExceptions', []))
132
+ allowed_class_names.include?(node.const_name)
133
+ end
118
134
  end
119
135
  end
120
136
  end
@@ -159,12 +159,12 @@ module RuboCop
159
159
 
160
160
  # @!method dynamic_method_definition?(node)
161
161
  def_node_matcher :dynamic_method_definition?, <<~PATTERN
162
- {(send nil? :define_method ...) ({block numblock} (send nil? :define_method ...) ...)}
162
+ {(send nil? :define_method ...) (any_block (send nil? :define_method ...) ...)}
163
163
  PATTERN
164
164
 
165
165
  # @!method class_or_instance_eval?(node)
166
166
  def_node_matcher :class_or_instance_eval?, <<~PATTERN
167
- ({block numblock} (send _ {:class_eval :instance_eval}) ...)
167
+ (any_block (send _ {:class_eval :instance_eval}) ...)
168
168
  PATTERN
169
169
 
170
170
  def check_node(node)
@@ -268,7 +268,7 @@ module RuboCop
268
268
  end
269
269
 
270
270
  def start_of_new_scope?(child)
271
- child.module_type? || child.class_type? || child.sclass_type? || eval_call?(child)
271
+ child.type?(:module, :class, :sclass) || eval_call?(child)
272
272
  end
273
273
 
274
274
  def eval_call?(child)
@@ -282,7 +282,7 @@ module RuboCop
282
282
  matcher_name = :"#{m}_block?"
283
283
  unless respond_to?(matcher_name)
284
284
  self.class.def_node_matcher matcher_name, <<~PATTERN
285
- ({block numblock} (send {nil? const} {:#{m}} ...) ...)
285
+ (any_block (send {nil? const} {:#{m}} ...) ...)
286
286
  PATTERN
287
287
  end
288
288
 
@@ -17,7 +17,7 @@ module RuboCop
17
17
  # rescue, ensure, etc.
18
18
  #
19
19
  # This cop's autocorrection avoids cases like `a ||= 1` because removing assignment from
20
- # operator assignment can cause NameError if this assignment has been used to declare
20
+ # operator assignment can cause `NameError` if this assignment has been used to declare
21
21
  # a local variable. For example, replacing `a ||= 1` with `a || 1` may cause
22
22
  # "undefined local variable or method `a' for main:Object (NameError)".
23
23
  #
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for calls to `defined?` with strings or symbols as the argument.
7
+ # Such calls will always return `'expression'`, you probably meant to
8
+ # check for the existence of a constant, method, or variable instead.
9
+ #
10
+ # `defined?` is part of the Ruby syntax and doesn't behave like normal methods.
11
+ # You can safely pass in what you are checking for directly, without encountering
12
+ # a `NameError`.
13
+ #
14
+ # When interpolation is used, oftentimes it is not possible to write the
15
+ # code with `defined?`. In these cases, switch to one of the more specific methods:
16
+ #
17
+ # * `class_variable_defined?`
18
+ # * `const_defined?`
19
+ # * `method_defined?`
20
+ # * `instance_variable_defined?`
21
+ # * `binding.local_variable_defined?`
22
+ #
23
+ # @example
24
+ #
25
+ # # bad
26
+ # defined?('FooBar')
27
+ # defined?(:FooBar)
28
+ # defined?(:foo_bar)
29
+ # defined?('foo_bar')
30
+ #
31
+ # # good
32
+ # defined?(FooBar)
33
+ # defined?(foo_bar)
34
+ #
35
+ # # bad - interpolation
36
+ # bar = 'Bar'
37
+ # defined?("Foo::#{bar}::Baz")
38
+ #
39
+ # # good
40
+ # bar = 'Bar'
41
+ # defined?(Foo) && Foo.const_defined?(bar) && Foo.const_get(bar).const_defined?(:Baz)
42
+ class UselessDefined < Base
43
+ MSG = 'Calling `defined?` with a %<type>s argument will always return a truthy value.'
44
+ TYPES = { str: 'string', dstr: 'string', sym: 'symbol', dsym: 'symbol' }.freeze
45
+
46
+ def on_defined?(node)
47
+ # NOTE: `defined?` always takes one argument. Anything else is a syntax error.
48
+ return unless (type = TYPES[node.first_argument.type])
49
+
50
+ add_offense(node, message: format(MSG, type: type))
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -25,8 +25,12 @@ module RuboCop
25
25
  # do_something_else
26
26
  # end
27
27
  class UselessElseWithoutRescue < Base
28
+ extend TargetRubyVersion
29
+
28
30
  MSG = '`else` without `rescue` is useless.'
29
31
 
32
+ maximum_target_ruby_version 2.5
33
+
30
34
  def on_new_investigation
31
35
  processed_source.diagnostics.each do |diagnostic|
32
36
  next unless diagnostic.reason == :useless_else
@@ -59,7 +59,7 @@ module RuboCop
59
59
  end
60
60
 
61
61
  def use_rest_or_optional_args?(node)
62
- node.arguments.any? { |arg| arg.restarg_type? || arg.optarg_type? || arg.kwoptarg_type? }
62
+ node.arguments.any? { |arg| arg.type?(:restarg, :optarg, :kwoptarg) }
63
63
  end
64
64
 
65
65
  def delegating?(node, def_node)
@@ -35,7 +35,7 @@ module RuboCop
35
35
  RESTRICT_ON_SEND = %i[+ - * / **].freeze
36
36
 
37
37
  # @!method useless_operation?(node)
38
- def_node_matcher :useless_operation?, '(send (send nil? $_) $_ (int $_))'
38
+ def_node_matcher :useless_operation?, '(call (call nil? $_) $_ (int $_))'
39
39
 
40
40
  # @!method useless_abbreviated_assignment?(node)
41
41
  def_node_matcher :useless_abbreviated_assignment?, '(op-asgn (lvasgn $_) $_ (int $_))'
@@ -50,6 +50,7 @@ module RuboCop
50
50
  corrector.replace(node, variable)
51
51
  end
52
52
  end
53
+ alias on_csend on_send
53
54
 
54
55
  def on_op_asgn(node)
55
56
  return unless useless_abbreviated_assignment?(node)
@@ -75,7 +75,7 @@ module RuboCop
75
75
  def use_exception_variable_in_ensure?(resbody_node)
76
76
  return false unless (exception_variable = resbody_node.exception_variable)
77
77
  return false unless (ensure_node = resbody_node.each_ancestor(:ensure).first)
78
- return false unless (ensure_body = ensure_node.body)
78
+ return false unless (ensure_body = ensure_node.branch)
79
79
 
80
80
  ensure_body.each_descendant(:lvar).map(&:source).include?(exception_variable.source)
81
81
  end
@@ -72,7 +72,7 @@ module RuboCop
72
72
  def_node_matcher :method_definition, <<~PATTERN
73
73
  {
74
74
  (def %1 ...)
75
- ({block numblock} (send _ :define_method (sym %1)) ...)
75
+ (any_block (send _ :define_method (sym %1)) ...)
76
76
  }
77
77
  PATTERN
78
78
 
@@ -108,7 +108,7 @@ module RuboCop
108
108
 
109
109
  def find_method_definition(node, method_name)
110
110
  node.each_ancestor.lazy.map do |ancestor|
111
- ancestor.each_child_node(:def, :block, :numblock).find do |child|
111
+ ancestor.each_child_node(:def, :any_block).find do |child|
112
112
  method_definition(child, method_name)
113
113
  end
114
114
  end.find(&:itself)
@@ -102,24 +102,18 @@ module RuboCop
102
102
  when :op_asgn
103
103
  process_binary_operator_assignment(node)
104
104
  when *ASSIGNMENT_TYPES
105
- _, rhs_node = *node
106
- process_assignment(node, rhs_node) if rhs_node
105
+ process_assignment(node, node.rhs) if node.rhs
107
106
  end
108
107
  end
109
108
 
110
109
  def process_multiple_assignment(masgn_node)
111
- mlhs_node, mrhs_node = *masgn_node
112
-
113
- mlhs_node.children.each_with_index do |lhs_node, index|
110
+ masgn_node.assignments.each_with_index do |lhs_node, index|
114
111
  next unless ASSIGNMENT_TYPES.include?(lhs_node.type)
115
112
 
116
- lhs_variable_name, = *lhs_node
117
- rhs_node = mrhs_node.children[index]
118
-
119
- if mrhs_node.array_type? && rhs_node
120
- process_assignment(lhs_variable_name, rhs_node)
113
+ if masgn_node.rhs.array_type? && (rhs_node = masgn_node.rhs.children[index])
114
+ process_assignment(lhs_node, rhs_node)
121
115
  else
122
- @local[lhs_variable_name] = true
116
+ @local[lhs_node.name] = true
123
117
  end
124
118
  end
125
119
 
@@ -127,33 +121,28 @@ module RuboCop
127
121
  end
128
122
 
129
123
  def process_logical_operator_assignment(asgn_node)
130
- lhs_node, rhs_node = *asgn_node
131
- return unless ASSIGNMENT_TYPES.include?(lhs_node.type)
124
+ return unless ASSIGNMENT_TYPES.include?(asgn_node.lhs.type)
132
125
 
133
- process_assignment(lhs_node, rhs_node)
126
+ process_assignment(asgn_node.lhs, asgn_node.rhs)
134
127
 
135
128
  throw :skip_children
136
129
  end
137
130
 
138
131
  def process_binary_operator_assignment(op_asgn_node)
139
- lhs_node, = *op_asgn_node
132
+ lhs_node = op_asgn_node.lhs
140
133
  return unless ASSIGNMENT_TYPES.include?(lhs_node.type)
141
134
 
142
- lhs_variable_name, = *lhs_node
143
- @local[lhs_variable_name] = true
135
+ @local[lhs_node.name] = true
144
136
 
145
137
  throw :skip_children
146
138
  end
147
139
 
148
140
  def process_assignment(asgn_node, rhs_node)
149
- lhs_variable_name, = *asgn_node
150
-
151
- @local[lhs_variable_name] = if rhs_node.variable?
152
- rhs_variable_name, = *rhs_node
153
- @local[rhs_variable_name]
154
- else
155
- constructor?(rhs_node)
156
- end
141
+ @local[asgn_node.name] = if rhs_node.variable?
142
+ @local[rhs_node.name]
143
+ else
144
+ constructor?(rhs_node)
145
+ end
157
146
  end
158
147
 
159
148
  def constructor?(node)
@@ -103,7 +103,7 @@ module RuboCop
103
103
  expressions.pop unless in_void_context?(node)
104
104
  expressions.each do |expr|
105
105
  check_void_op(expr) do
106
- block_node = node.each_ancestor(:block).first
106
+ block_node = node.each_ancestor(:any_block).first
107
107
 
108
108
  block_node&.method?(:each)
109
109
  end
@@ -113,7 +113,8 @@ module RuboCop
113
113
  end
114
114
 
115
115
  def check_expression(expr)
116
- expr = expr.body if expr.if_type? && expr.modifier_form?
116
+ expr = expr.body if expr.if_type?
117
+ return unless expr
117
118
 
118
119
  check_literal(expr)
119
120
  check_var(expr)
@@ -126,7 +127,7 @@ module RuboCop
126
127
 
127
128
  def check_void_op(node, &block)
128
129
  node = node.children.first while node.begin_type?
129
- return unless node.send_type? && OPERATORS.include?(node.method_name)
130
+ return unless node.call_type? && OPERATORS.include?(node.method_name)
130
131
  return if block && yield(node)
131
132
 
132
133
  add_offense(node.loc.selector,
@@ -178,7 +179,7 @@ module RuboCop
178
179
  end
179
180
 
180
181
  def check_nonmutating(node)
181
- return if !node.send_type? && !node.block_type? && !node.numblock_type?
182
+ return unless node.type?(:send, :any_block)
182
183
 
183
184
  method_name = node.method_name
184
185
  return unless NONMUTATING_METHODS.include?(method_name)
@@ -196,15 +197,10 @@ module RuboCop
196
197
  end
197
198
 
198
199
  def check_ensure(node)
199
- return unless (body = node.body)
200
+ return unless (body = node.branch)
200
201
  # NOTE: the `begin` node case is already handled via `on_begin`
201
202
  return if body.begin_type?
202
203
 
203
- check_void_op(body) do
204
- block_node = node.each_ancestor(:block).first
205
- block_node&.method?(:each)
206
- end
207
-
208
204
  check_expression(body)
209
205
  end
210
206
 
@@ -219,6 +215,7 @@ module RuboCop
219
215
  if node.arguments.empty?
220
216
  corrector.replace(node, node.receiver.source)
221
217
  else
218
+ corrector.remove(node.loc.dot) if node.loc.dot
222
219
  corrector.replace(
223
220
  range_with_surrounding_space(range: node.loc.selector, side: :both,
224
221
  newlines: false),
@@ -228,7 +225,7 @@ module RuboCop
228
225
  end
229
226
 
230
227
  def autocorrect_void_expression(corrector, node)
231
- return if node.parent.if_type? && node.parent.modifier_form?
228
+ return if node.parent.if_type?
232
229
 
233
230
  corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
234
231
  end
@@ -52,7 +52,7 @@ module RuboCop
52
52
  def consider_node?(node)
53
53
  return true if NESTING_BLOCKS.include?(node.type)
54
54
 
55
- count_blocks? && (node.block_type? || node.numblock_type?)
55
+ count_blocks? && node.any_block_type?
56
56
  end
57
57
 
58
58
  def message(max)
@@ -51,15 +51,7 @@ module RuboCop
51
51
  end
52
52
 
53
53
  def on_casgn(node)
54
- parent = node.parent
55
-
56
- if parent&.assignment?
57
- block_node = parent.children[1]
58
- elsif parent&.parent&.masgn_type?
59
- block_node = parent.parent.children[1]
60
- else
61
- _scope, _name, block_node = *node
62
- end
54
+ block_node = node.expression || find_expression_within_parent(node.parent)
63
55
 
64
56
  return unless block_node.respond_to?(:class_definition?) && block_node.class_definition?
65
57
 
@@ -71,6 +63,14 @@ module RuboCop
71
63
  def message(length, max_length)
72
64
  format('Class has too many lines. [%<length>d/%<max>d]', length: length, max: max_length)
73
65
  end
66
+
67
+ def find_expression_within_parent(parent)
68
+ if parent&.assignment?
69
+ parent.expression
70
+ elsif parent&.parent&.masgn_type?
71
+ parent.parent.expression
72
+ end
73
+ end
74
74
  end
75
75
  end
76
76
  end
@@ -52,12 +52,19 @@ module RuboCop
52
52
  'Prefer reading the data from an external source.'
53
53
  RESTRICT_ON_SEND = [:[]].freeze
54
54
 
55
+ # @!method set_const?(node)
56
+ def_node_matcher :set_const?, <<~PATTERN
57
+ (const {cbase nil?} :Set)
58
+ PATTERN
59
+
55
60
  def on_array(node)
56
61
  add_offense(node) if node.children.length >= collection_threshold
57
62
  end
58
63
  alias on_hash on_array
59
64
 
60
65
  def on_index(node)
66
+ return unless set_const?(node.receiver)
67
+
61
68
  add_offense(node) if node.arguments.length >= collection_threshold
62
69
  end
63
70
 
@@ -36,7 +36,7 @@ module RuboCop
36
36
  include MethodComplexity
37
37
  include Utils::IteratingBlock
38
38
 
39
- MSG = 'Cyclomatic complexity for %<method>s is too high. [%<complexity>d/%<max>d]'
39
+ MSG = 'Cyclomatic complexity for `%<method>s` is too high. [%<complexity>d/%<max>d]'
40
40
  COUNTED_NODES = %i[if while until for csend block block_pass
41
41
  rescue when in_pattern and or or_asgn and_asgn].freeze
42
42