rubocop 1.54.1 → 1.64.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (297) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +5 -4
  4. data/assets/output.css.erb +159 -0
  5. data/assets/output.html.erb +1 -160
  6. data/config/default.yml +155 -26
  7. data/config/obsoletion.yml +5 -0
  8. data/lib/rubocop/cached_data.rb +11 -3
  9. data/lib/rubocop/cli/command/auto_generate_config.rb +22 -8
  10. data/lib/rubocop/cli/command/lsp.rb +2 -2
  11. data/lib/rubocop/cli/command/show_docs_url.rb +2 -2
  12. data/lib/rubocop/cli.rb +11 -2
  13. data/lib/rubocop/config.rb +36 -12
  14. data/lib/rubocop/config_finder.rb +14 -4
  15. data/lib/rubocop/config_loader.rb +0 -1
  16. data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
  17. data/lib/rubocop/config_obsoletion.rb +11 -8
  18. data/lib/rubocop/config_validator.rb +14 -7
  19. data/lib/rubocop/cop/autocorrect_logic.rb +9 -2
  20. data/lib/rubocop/cop/base.rb +64 -17
  21. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -0
  22. data/lib/rubocop/cop/bundler/duplicated_group.rb +127 -0
  23. data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
  24. data/lib/rubocop/cop/bundler/gem_version.rb +3 -5
  25. data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
  26. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
  27. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +5 -13
  28. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
  29. data/lib/rubocop/cop/documentation.rb +16 -6
  30. data/lib/rubocop/cop/exclude_limit.rb +1 -1
  31. data/lib/rubocop/cop/force.rb +12 -0
  32. data/lib/rubocop/cop/gemspec/dependency_version.rb +3 -5
  33. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +2 -2
  34. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
  35. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +5 -1
  36. data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
  37. data/lib/rubocop/cop/internal_affairs/example_description.rb +46 -24
  38. data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
  39. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +19 -20
  40. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
  41. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +123 -29
  42. data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
  43. data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
  44. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
  45. data/lib/rubocop/cop/internal_affairs.rb +2 -0
  46. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  47. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  48. data/lib/rubocop/cop/layout/dot_position.rb +1 -5
  49. data/lib/rubocop/cop/layout/empty_comment.rb +3 -1
  50. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +42 -9
  51. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +14 -7
  52. data/lib/rubocop/cop/layout/end_alignment.rb +15 -3
  53. data/lib/rubocop/cop/layout/extra_spacing.rb +4 -10
  54. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +24 -7
  55. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  56. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  57. data/lib/rubocop/cop/layout/heredoc_indentation.rb +4 -1
  58. data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
  59. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  60. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +17 -9
  61. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  62. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
  63. data/lib/rubocop/cop/layout/redundant_line_break.rb +29 -6
  64. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -4
  65. data/lib/rubocop/cop/layout/single_line_block_chain.rb +5 -0
  66. data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
  67. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +2 -2
  68. data/lib/rubocop/cop/layout/space_around_operators.rb +50 -20
  69. data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
  70. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
  71. data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
  72. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +3 -4
  73. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +5 -0
  74. data/lib/rubocop/cop/lint/assignment_in_condition.rb +6 -6
  75. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
  76. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
  77. data/lib/rubocop/cop/lint/debugger.rb +38 -3
  78. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  79. data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
  80. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  81. data/lib/rubocop/cop/lint/empty_conditional_body.rb +2 -2
  82. data/lib/rubocop/cop/lint/erb_new_arguments.rb +24 -17
  83. data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
  84. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
  85. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
  86. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +85 -0
  87. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  88. data/lib/rubocop/cop/lint/mixed_case_range.rb +10 -5
  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 +9 -4
  93. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -0
  94. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +72 -8
  95. data/lib/rubocop/cop/lint/redundant_with_index.rb +6 -2
  96. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  97. data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
  98. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +14 -8
  99. data/lib/rubocop/cop/lint/script_permission.rb +3 -3
  100. data/lib/rubocop/cop/lint/self_assignment.rb +38 -0
  101. data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
  102. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +7 -1
  103. data/lib/rubocop/cop/lint/struct_new_override.rb +12 -12
  104. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  105. data/lib/rubocop/cop/lint/symbol_conversion.rb +7 -2
  106. data/lib/rubocop/cop/lint/syntax.rb +6 -3
  107. data/lib/rubocop/cop/lint/to_enum_arguments.rb +12 -5
  108. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
  109. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
  110. data/lib/rubocop/cop/lint/unreachable_code.rb +4 -2
  111. data/lib/rubocop/cop/lint/unreachable_loop.rb +8 -2
  112. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  113. data/lib/rubocop/cop/lint/useless_assignment.rb +38 -12
  114. data/lib/rubocop/cop/lint/useless_times.rb +2 -2
  115. data/lib/rubocop/cop/lint/void.rb +48 -12
  116. data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
  117. data/lib/rubocop/cop/metrics/block_length.rb +1 -1
  118. data/lib/rubocop/cop/metrics/class_length.rb +8 -3
  119. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  120. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +7 -7
  121. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  122. data/lib/rubocop/cop/mixin/code_length.rb +12 -1
  123. data/lib/rubocop/cop/mixin/comments_help.rb +16 -12
  124. data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -0
  125. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  126. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +23 -13
  127. data/lib/rubocop/cop/mixin/method_complexity.rb +15 -6
  128. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +4 -3
  129. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -8
  130. data/lib/rubocop/cop/mixin/safe_assignment.rb +1 -1
  131. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  132. data/lib/rubocop/cop/mixin/string_help.rb +4 -2
  133. data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
  134. data/lib/rubocop/cop/naming/block_forwarding.rb +34 -7
  135. data/lib/rubocop/cop/naming/constant_name.rb +1 -2
  136. data/lib/rubocop/cop/naming/file_name.rb +3 -3
  137. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +3 -1
  138. data/lib/rubocop/cop/naming/inclusive_language.rb +1 -2
  139. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  140. data/lib/rubocop/cop/naming/predicate_name.rb +2 -2
  141. data/lib/rubocop/cop/registry.rb +1 -1
  142. data/lib/rubocop/cop/security/compound_hash.rb +2 -2
  143. data/lib/rubocop/cop/security/open.rb +2 -2
  144. data/lib/rubocop/cop/style/access_modifier_declarations.rb +52 -2
  145. data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
  146. data/lib/rubocop/cop/style/alias.rb +10 -8
  147. data/lib/rubocop/cop/style/arguments_forwarding.rb +414 -63
  148. data/lib/rubocop/cop/style/array_first_last.rb +64 -0
  149. data/lib/rubocop/cop/style/array_intersect.rb +13 -5
  150. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
  151. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
  152. data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
  153. data/lib/rubocop/cop/style/case_like_if.rb +5 -5
  154. data/lib/rubocop/cop/style/class_check.rb +1 -0
  155. data/lib/rubocop/cop/style/class_equality_comparison.rb +7 -0
  156. data/lib/rubocop/cop/style/class_vars.rb +3 -3
  157. data/lib/rubocop/cop/style/collection_compact.rb +21 -11
  158. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  159. data/lib/rubocop/cop/style/combinable_loops.rb +17 -9
  160. data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
  161. data/lib/rubocop/cop/style/concat_array_literals.rb +2 -1
  162. data/lib/rubocop/cop/style/conditional_assignment.rb +7 -8
  163. data/lib/rubocop/cop/style/copyright.rb +31 -21
  164. data/lib/rubocop/cop/style/date_time.rb +5 -4
  165. data/lib/rubocop/cop/style/documentation.rb +24 -24
  166. data/lib/rubocop/cop/style/documentation_method.rb +20 -0
  167. data/lib/rubocop/cop/style/each_for_simple_loop.rb +7 -7
  168. data/lib/rubocop/cop/style/each_with_object.rb +2 -2
  169. data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
  170. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  171. data/lib/rubocop/cop/style/eval_with_location.rb +6 -15
  172. data/lib/rubocop/cop/style/exact_regexp_match.rb +4 -2
  173. data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
  174. data/lib/rubocop/cop/style/for.rb +3 -1
  175. data/lib/rubocop/cop/style/format_string.rb +33 -12
  176. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -1
  177. data/lib/rubocop/cop/style/guard_clause.rb +26 -0
  178. data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
  179. data/lib/rubocop/cop/style/hash_each_methods.rb +105 -11
  180. data/lib/rubocop/cop/style/hash_except.rb +2 -1
  181. data/lib/rubocop/cop/style/hash_syntax.rb +24 -2
  182. data/lib/rubocop/cop/style/identical_conditional_branches.rb +28 -3
  183. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -3
  184. data/lib/rubocop/cop/style/inverse_methods.rb +14 -13
  185. data/lib/rubocop/cop/style/invertible_unless_condition.rb +44 -2
  186. data/lib/rubocop/cop/style/lambda_call.rb +5 -0
  187. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +8 -10
  188. data/lib/rubocop/cop/style/map_into_array.rb +175 -0
  189. data/lib/rubocop/cop/style/map_to_hash.rb +18 -8
  190. data/lib/rubocop/cop/style/map_to_set.rb +1 -1
  191. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +22 -6
  192. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -4
  193. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +20 -0
  194. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  195. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
  196. data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
  197. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  198. data/lib/rubocop/cop/style/multiline_method_signature.rb +10 -1
  199. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +6 -4
  200. data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
  201. data/lib/rubocop/cop/style/next.rb +1 -1
  202. data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
  203. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +1 -1
  204. data/lib/rubocop/cop/style/numeric_predicate.rb +10 -2
  205. data/lib/rubocop/cop/style/object_then.rb +5 -3
  206. data/lib/rubocop/cop/style/one_line_conditional.rb +1 -1
  207. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  208. data/lib/rubocop/cop/style/operator_method_call.rb +8 -2
  209. data/lib/rubocop/cop/style/parallel_assignment.rb +3 -5
  210. data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -0
  211. data/lib/rubocop/cop/style/raise_args.rb +4 -1
  212. data/lib/rubocop/cop/style/redundant_argument.rb +33 -4
  213. data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
  214. data/lib/rubocop/cop/style/redundant_begin.rb +9 -1
  215. data/lib/rubocop/cop/style/redundant_conditional.rb +1 -9
  216. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +5 -4
  217. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +93 -5
  218. data/lib/rubocop/cop/style/redundant_each.rb +7 -4
  219. data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
  220. data/lib/rubocop/cop/style/redundant_fetch_block.rb +3 -3
  221. data/lib/rubocop/cop/style/redundant_filter_chain.rb +23 -6
  222. data/lib/rubocop/cop/style/redundant_line_continuation.rb +19 -2
  223. data/lib/rubocop/cop/style/redundant_parentheses.rb +71 -22
  224. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  225. data/lib/rubocop/cop/style/redundant_return.rb +14 -3
  226. data/lib/rubocop/cop/style/redundant_self.rb +17 -2
  227. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +5 -0
  228. data/lib/rubocop/cop/style/redundant_sort.rb +9 -8
  229. data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
  230. data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -1
  231. data/lib/rubocop/cop/style/require_order.rb +1 -1
  232. data/lib/rubocop/cop/style/return_nil.rb +6 -2
  233. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +23 -9
  234. data/lib/rubocop/cop/style/sample.rb +3 -4
  235. data/lib/rubocop/cop/style/select_by_regexp.rb +7 -6
  236. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  237. data/lib/rubocop/cop/style/semicolon.rb +8 -3
  238. data/lib/rubocop/cop/style/send.rb +4 -4
  239. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +90 -0
  240. data/lib/rubocop/cop/style/single_argument_dig.rb +7 -3
  241. data/lib/rubocop/cop/style/single_line_do_end_block.rb +67 -0
  242. data/lib/rubocop/cop/style/slicing_with_range.rb +76 -10
  243. data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
  244. data/lib/rubocop/cop/style/special_global_vars.rb +1 -2
  245. data/lib/rubocop/cop/style/string_chars.rb +1 -0
  246. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
  247. data/lib/rubocop/cop/style/strip.rb +7 -4
  248. data/lib/rubocop/cop/style/super_arguments.rb +156 -0
  249. data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
  250. data/lib/rubocop/cop/style/symbol_array.rb +35 -15
  251. data/lib/rubocop/cop/style/symbol_proc.rb +68 -5
  252. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  253. data/lib/rubocop/cop/style/unpack_first.rb +11 -14
  254. data/lib/rubocop/cop/style/yoda_expression.rb +8 -7
  255. data/lib/rubocop/cop/team.rb +5 -0
  256. data/lib/rubocop/cop/utils/regexp_ranges.rb +27 -14
  257. data/lib/rubocop/cop/variable_force/assignment.rb +1 -3
  258. data/lib/rubocop/cops_documentation_generator.rb +15 -3
  259. data/lib/rubocop/directive_comment.rb +10 -8
  260. data/lib/rubocop/ext/regexp_node.rb +9 -4
  261. data/lib/rubocop/file_finder.rb +4 -7
  262. data/lib/rubocop/formatter/clang_style_formatter.rb +3 -7
  263. data/lib/rubocop/formatter/disabled_config_formatter.rb +23 -8
  264. data/lib/rubocop/formatter/formatter_set.rb +7 -1
  265. data/lib/rubocop/formatter/html_formatter.rb +35 -14
  266. data/lib/rubocop/formatter/json_formatter.rb +0 -1
  267. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  268. data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
  269. data/lib/rubocop/formatter/tap_formatter.rb +3 -7
  270. data/lib/rubocop/formatter.rb +1 -1
  271. data/lib/rubocop/lockfile.rb +56 -7
  272. data/lib/rubocop/lsp/logger.rb +1 -1
  273. data/lib/rubocop/lsp/routes.rb +43 -31
  274. data/lib/rubocop/lsp/runtime.rb +21 -4
  275. data/lib/rubocop/lsp/server.rb +13 -6
  276. data/lib/rubocop/lsp/severity.rb +1 -1
  277. data/lib/rubocop/lsp.rb +36 -0
  278. data/lib/rubocop/magic_comment.rb +13 -11
  279. data/lib/rubocop/options.rb +14 -11
  280. data/lib/rubocop/path_util.rb +6 -2
  281. data/lib/rubocop/rake_task.rb +1 -1
  282. data/lib/rubocop/result_cache.rb +4 -1
  283. data/lib/rubocop/rspec/cop_helper.rb +8 -2
  284. data/lib/rubocop/rspec/expect_offense.rb +16 -8
  285. data/lib/rubocop/rspec/shared_contexts.rb +55 -19
  286. data/lib/rubocop/rspec/support.rb +2 -0
  287. data/lib/rubocop/runner.rb +19 -6
  288. data/lib/rubocop/server/cache.rb +1 -1
  289. data/lib/rubocop/server/client_command/exec.rb +1 -2
  290. data/lib/rubocop/server/server_command/exec.rb +0 -1
  291. data/lib/rubocop/string_interpreter.rb +3 -3
  292. data/lib/rubocop/target_finder.rb +91 -81
  293. data/lib/rubocop/target_ruby.rb +82 -76
  294. data/lib/rubocop/version.rb +19 -4
  295. data/lib/rubocop.rb +9 -0
  296. metadata +29 -16
  297. /data/lib/rubocop/formatter/{git_hub_actions_formatter.rb → github_actions_formatter.rb} +0 -0
@@ -9,7 +9,7 @@ module RuboCop
9
9
  #
10
10
  # Conversion with `Integer`, `Float`, etc. will raise an `ArgumentError`
11
11
  # if given input that is not numeric (eg. an empty string), whereas
12
- # `to_i`, etc. will try to convert regardless of input (`''.to_i => 0`).
12
+ # `to_i`, etc. will try to convert regardless of input (``''.to_i => 0``).
13
13
  # As such, this cop is disabled by default because it's not necessarily
14
14
  # always correct to raise if a value is not numeric.
15
15
  #
@@ -91,19 +91,24 @@ module RuboCop
91
91
 
92
92
  # @!method to_method(node)
93
93
  def_node_matcher :to_method, <<~PATTERN
94
- (send $_ ${#{METHODS}})
94
+ (call $_ ${#{METHODS}})
95
95
  PATTERN
96
96
 
97
97
  # @!method to_method_symbol(node)
98
98
  def_node_matcher :to_method_symbol, <<~PATTERN
99
- {(send _ $_ ${(sym ${#{METHODS}})} ...)
100
- (send _ $_ ${(block_pass (sym ${#{METHODS}}))} ...)}
99
+ (call _ $_ ${
100
+ {
101
+ (sym ${#{METHODS}})
102
+ (block_pass (sym ${#{METHODS}}))
103
+ }
104
+ } ...)
101
105
  PATTERN
102
106
 
103
107
  def on_send(node)
104
108
  handle_conversion_method(node)
105
109
  handle_as_symbol(node)
106
110
  end
111
+ alias on_csend on_send
107
112
 
108
113
  private
109
114
 
@@ -24,6 +24,10 @@ module RuboCop
24
24
  #
25
25
  # This cop target those features.
26
26
  #
27
+ # @safety
28
+ # This cop's autocorrection is unsafe because if `require 'pp'` is removed from one file,
29
+ # `NameError` can be encountered when another file uses `PP.pp`.
30
+ #
27
31
  # @example
28
32
  # # bad
29
33
  # require 'unloaded_feature'
@@ -4,8 +4,13 @@ module RuboCop
4
4
  module Cop
5
5
  module Lint
6
6
  # Checks for redundant safe navigation calls.
7
- # `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`, and `equal?` methods
8
- # are checked by default. These are customizable with `AllowedMethods` option.
7
+ # Use cases where a constant, named in camel case for classes and modules is `nil` are rare,
8
+ # and an offense is not detected when the receiver is a constant. The detection also applies
9
+ # to literal receivers, except for `nil`.
10
+ #
11
+ # For all receivers, the `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`,
12
+ # and `equal?` methods are checked by default.
13
+ # These are customizable with `AllowedMethods` option.
9
14
  #
10
15
  # The `AllowedMethods` option specifies nil-safe methods,
11
16
  # in other words, it is a method that is allowed to skip safe navigation.
@@ -22,6 +27,9 @@ module RuboCop
22
27
  #
23
28
  # @example
24
29
  # # bad
30
+ # CamelCaseConst&.do_something
31
+ #
32
+ # # bad
25
33
  # do_something if attrs&.respond_to?(:[])
26
34
  #
27
35
  # # good
@@ -33,6 +41,9 @@ module RuboCop
33
41
  # end
34
42
  #
35
43
  # # good
44
+ # CamelCaseConst.do_something
45
+ #
46
+ # # good
36
47
  # while node.is_a?(BeginNode)
37
48
  # node = node.parent
38
49
  # end
@@ -40,6 +51,22 @@ module RuboCop
40
51
  # # good - without `&.` this will always return `true`
41
52
  # foo&.respond_to?(:to_a)
42
53
  #
54
+ # # bad - for `nil`s conversion methods return default values for the type
55
+ # foo&.to_h || {}
56
+ # foo&.to_h { |k, v| [k, v] } || {}
57
+ # foo&.to_a || []
58
+ # foo&.to_i || 0
59
+ # foo&.to_f || 0.0
60
+ # foo&.to_s || ''
61
+ #
62
+ # # good
63
+ # foo.to_h
64
+ # foo.to_h { |k, v| [k, v] }
65
+ # foo.to_a
66
+ # foo.to_i
67
+ # foo.to_f
68
+ # foo.to_s
69
+ #
43
70
  # @example AllowedMethods: [nil_safe_method]
44
71
  # # bad
45
72
  # do_something if attrs&.nil_safe_method(:[])
@@ -50,28 +77,65 @@ module RuboCop
50
77
  #
51
78
  class RedundantSafeNavigation < Base
52
79
  include AllowedMethods
53
- include RangeHelp
54
80
  extend AutoCorrector
55
81
 
56
- MSG = 'Redundant safe navigation detected.'
82
+ MSG = 'Redundant safe navigation detected, use `.` instead.'
83
+ MSG_LITERAL = 'Redundant safe navigation with default literal detected.'
57
84
 
58
85
  NIL_SPECIFIC_METHODS = (nil.methods - Object.new.methods).to_set.freeze
59
86
 
87
+ SNAKE_CASE = /\A[[:digit:][:upper:]_]+\z/.freeze
88
+
60
89
  # @!method respond_to_nil_specific_method?(node)
61
90
  def_node_matcher :respond_to_nil_specific_method?, <<~PATTERN
62
91
  (csend _ :respond_to? (sym %NIL_SPECIFIC_METHODS))
63
92
  PATTERN
64
93
 
94
+ # @!method conversion_with_default?(node)
95
+ def_node_matcher :conversion_with_default?, <<~PATTERN
96
+ {
97
+ (or $(csend _ :to_h) (hash))
98
+ (or (block $(csend _ :to_h) ...) (hash))
99
+ (or $(csend _ :to_a) (array))
100
+ (or $(csend _ :to_i) (int 0))
101
+ (or $(csend _ :to_f) (float 0.0))
102
+ (or $(csend _ :to_s) (str empty?))
103
+ }
104
+ PATTERN
105
+
106
+ # rubocop:disable Metrics/AbcSize
65
107
  def on_csend(node)
66
- return unless check?(node) && allowed_method?(node.method_name)
67
- return if respond_to_nil_specific_method?(node)
108
+ unless assume_receiver_instance_exists?(node.receiver)
109
+ return unless check?(node) && allowed_method?(node.method_name)
110
+ return if respond_to_nil_specific_method?(node)
111
+ end
68
112
 
69
- range = range_between(node.loc.dot.begin_pos, node.source_range.end_pos)
70
- add_offense(range) { |corrector| corrector.replace(node.loc.dot, '.') }
113
+ range = node.loc.dot
114
+ add_offense(range) { |corrector| corrector.replace(range, '.') }
71
115
  end
72
116
 
117
+ def on_or(node)
118
+ conversion_with_default?(node) do |send_node|
119
+ range = send_node.loc.dot.begin.join(node.source_range.end)
120
+
121
+ add_offense(range, message: MSG_LITERAL) do |corrector|
122
+ corrector.replace(send_node.loc.dot, '.')
123
+
124
+ range_with_default = node.lhs.source_range.end.begin.join(node.source_range.end)
125
+ corrector.remove(range_with_default)
126
+ end
127
+ end
128
+ end
129
+ # rubocop:enable Metrics/AbcSize
130
+
73
131
  private
74
132
 
133
+ def assume_receiver_instance_exists?(receiver)
134
+ return true if receiver.const_type? && !receiver.source.match?(SNAKE_CASE)
135
+
136
+ receiver.literal? && !receiver.nil_type?
137
+ end
138
+
75
139
  def check?(node)
76
140
  parent = node.parent
77
141
  return false unless parent
@@ -33,7 +33,10 @@ module RuboCop
33
33
  MSG_EACH_WITH_INDEX = 'Use `each` instead of `each_with_index`.'
34
34
  MSG_WITH_INDEX = 'Remove redundant `with_index`.'
35
35
 
36
+ # rubocop:disable Metrics/AbcSize
36
37
  def on_block(node)
38
+ return unless node.receiver
39
+ return if node.method?(:with_index) && !node.receiver.receiver
37
40
  return unless (send = redundant_with_index?(node))
38
41
 
39
42
  range = with_index_range(send)
@@ -47,6 +50,7 @@ module RuboCop
47
50
  end
48
51
  end
49
52
  end
53
+ # rubocop:enable Metrics/AbcSize
50
54
 
51
55
  alias on_numblock on_block
52
56
 
@@ -56,10 +60,10 @@ module RuboCop
56
60
  def_node_matcher :redundant_with_index?, <<~PATTERN
57
61
  {
58
62
  (block
59
- $(send _ {:each_with_index :with_index} ...)
63
+ $(call _ {:each_with_index :with_index} ...)
60
64
  (args (arg _)) ...)
61
65
  (numblock
62
- $(send _ {:each_with_index :with_index} ...) 1 ...)
66
+ $(call _ {:each_with_index :with_index} ...) 1 ...)
63
67
  }
64
68
  PATTERN
65
69
 
@@ -56,9 +56,9 @@ module RuboCop
56
56
  def_node_matcher :redundant_with_object?, <<~PATTERN
57
57
  {
58
58
  (block
59
- $(send _ {:each_with_object :with_object} _) (args (arg _)) ...)
59
+ $(call _ {:each_with_object :with_object} _) (args (arg _)) ...)
60
60
  (numblock
61
- $(send _ {:each_with_object :with_object} _) 1 ...)
61
+ $(call _ {:each_with_object :with_object} _) 1 ...)
62
62
  }
63
63
  PATTERN
64
64
 
@@ -59,9 +59,7 @@ module RuboCop
59
59
 
60
60
  def autocorrect(corrector, node)
61
61
  rescued, _, _body = *node
62
- range = Parser::Source::Range.new(node.source_range.source_buffer,
63
- node.loc.keyword.end_pos,
64
- rescued.source_range.end_pos)
62
+ range = node.loc.keyword.end.join(rescued.source_range.end)
65
63
 
66
64
  corrector.replace(range, correction(*rescued))
67
65
  end
@@ -45,10 +45,9 @@ module RuboCop
45
45
  bad_method?(node) do |safe_nav, method|
46
46
  return if nil_methods.include?(method) || PLUS_MINUS_METHODS.include?(node.method_name)
47
47
 
48
- location =
49
- Parser::Source::Range.new(node.source_range.source_buffer,
50
- safe_nav.source_range.end_pos,
51
- node.source_range.end_pos)
48
+ begin_range = node.loc.dot || safe_nav.source_range.end
49
+ location = begin_range.join(node.source_range.end)
50
+
52
51
  add_offense(location) do |corrector|
53
52
  autocorrect(corrector, offense_range: location, send_node: node)
54
53
  end
@@ -82,16 +81,23 @@ module RuboCop
82
81
  def autocorrect(corrector, offense_range:, send_node:)
83
82
  corrector.replace(
84
83
  offense_range,
85
- add_safe_navigation_operator(
86
- offense_range: offense_range,
87
- send_node: send_node
88
- )
84
+ add_safe_navigation_operator(offense_range: offense_range, send_node: send_node)
89
85
  )
86
+
87
+ corrector.wrap(send_node, '(', ')') if require_parentheses?(send_node)
90
88
  end
91
89
 
92
90
  def brackets?(send_node)
93
91
  send_node.method?(:[]) || send_node.method?(:[]=)
94
92
  end
93
+
94
+ def require_parentheses?(send_node)
95
+ return false unless send_node.comparison_method?
96
+ return false unless (node = send_node.parent)
97
+
98
+ (node.respond_to?(:logical_operator?) && node.logical_operator?) ||
99
+ (node.respond_to?(:comparison_method?) && node.comparison_method?)
100
+ end
95
101
  end
96
102
  end
97
103
  end
@@ -46,14 +46,14 @@ module RuboCop
46
46
  message = format_message_from(processed_source)
47
47
 
48
48
  add_offense(comment, message: message) do
49
- autocorrect(comment) if autocorrect_requested?
49
+ autocorrect if autocorrect_requested?
50
50
  end
51
51
  end
52
52
 
53
53
  private
54
54
 
55
- def autocorrect(comment)
56
- FileUtils.chmod('+x', comment.source_range.source_buffer.name)
55
+ def autocorrect
56
+ FileUtils.chmod('+x', processed_source.file_path)
57
57
  end
58
58
 
59
59
  def executable?(processed_source)
@@ -10,11 +10,18 @@ module RuboCop
10
10
  # foo = foo
11
11
  # foo, bar = foo, bar
12
12
  # Foo = Foo
13
+ # hash['foo'] = hash['foo']
14
+ # obj.attr = obj.attr
13
15
  #
14
16
  # # good
15
17
  # foo = bar
16
18
  # foo, bar = bar, foo
17
19
  # Foo = Bar
20
+ # hash['foo'] = hash['bar']
21
+ # obj.attr = obj.attr2
22
+ #
23
+ # # good (method calls possibly can return different results)
24
+ # hash[foo] = hash[foo]
18
25
  #
19
26
  class SelfAssignment < Base
20
27
  MSG = 'Self-assignment detected.'
@@ -26,6 +33,15 @@ module RuboCop
26
33
  gvasgn: :gvar
27
34
  }.freeze
28
35
 
36
+ def on_send(node)
37
+ if node.method?(:[]=)
38
+ handle_key_assignment(node) if node.arguments.size == 2
39
+ elsif node.assignment_method?
40
+ handle_attribute_assignment(node) if node.arguments.size == 1
41
+ end
42
+ end
43
+ alias on_csend on_send
44
+
29
45
  def on_lvasgn(node)
30
46
  lhs, rhs = *node
31
47
  return unless rhs
@@ -72,6 +88,28 @@ module RuboCop
72
88
  rhs.type == ASSIGNMENT_TYPE_TO_RHS_TYPE[lhs.type] &&
73
89
  rhs.children.first == lhs.children.first
74
90
  end
91
+
92
+ def handle_key_assignment(node)
93
+ value_node = node.arguments[1]
94
+
95
+ if value_node.send_type? && value_node.method?(:[]) &&
96
+ node.receiver == value_node.receiver &&
97
+ !node.first_argument.call_type? &&
98
+ node.first_argument == value_node.first_argument
99
+ add_offense(node)
100
+ end
101
+ end
102
+
103
+ def handle_attribute_assignment(node)
104
+ first_argument = node.first_argument
105
+ return unless first_argument.respond_to?(:arguments) && first_argument.arguments.empty?
106
+
107
+ if first_argument.call_type? &&
108
+ node.receiver == first_argument.receiver &&
109
+ first_argument.method_name.to_s == node.method_name.to_s.delete_suffix('=')
110
+ add_offense(node)
111
+ end
112
+ end
75
113
  end
76
114
  end
77
115
  end
@@ -123,6 +123,7 @@ module RuboCop
123
123
 
124
124
  # Shorthand assignments always use their arguments
125
125
  next false if assignment_node.shorthand_asgn?
126
+ next false unless assignment_node.parent
126
127
 
127
128
  node_within_block_or_conditional =
128
129
  node_within_block_or_conditional?(assignment_node.parent, argument.scope.node)
@@ -68,7 +68,7 @@ module RuboCop
68
68
 
69
69
  def same_conditions_node_different_branch?(variable, outer_local_variable)
70
70
  variable_node = variable_node(variable)
71
- return false unless variable_node.conditional?
71
+ return false unless node_or_its_ascendant_conditional?(variable_node)
72
72
 
73
73
  outer_local_variable_node =
74
74
  find_conditional_node_from_ascendant(outer_local_variable.declaration_node)
@@ -96,6 +96,12 @@ module RuboCop
96
96
 
97
97
  find_conditional_node_from_ascendant(parent)
98
98
  end
99
+
100
+ def node_or_its_ascendant_conditional?(node)
101
+ return true if node.conditional?
102
+
103
+ !!find_conditional_node_from_ascendant(node)
104
+ end
99
105
  end
100
106
  end
101
107
  end
@@ -32,25 +32,25 @@ module RuboCop
32
32
  # @!method struct_new(node)
33
33
  def_node_matcher :struct_new, <<~PATTERN
34
34
  (send
35
- (const ${nil? cbase} :Struct) :new ...)
35
+ (const {nil? cbase} :Struct) :new ...)
36
36
  PATTERN
37
37
 
38
38
  def on_send(node)
39
- return unless struct_new(node) do
40
- node.arguments.each_with_index do |arg, index|
41
- # Ignore if the first argument is a class name
42
- next if index.zero? && arg.str_type?
39
+ return unless struct_new(node)
43
40
 
44
- # Ignore if the argument is not a member name
45
- next unless STRUCT_MEMBER_NAME_TYPES.include?(arg.type)
41
+ node.arguments.each_with_index do |arg, index|
42
+ # Ignore if the first argument is a class name
43
+ next if index.zero? && arg.str_type?
46
44
 
47
- member_name = arg.value
45
+ # Ignore if the argument is not a member name
46
+ next unless STRUCT_MEMBER_NAME_TYPES.include?(arg.type)
48
47
 
49
- next unless STRUCT_METHOD_NAMES.include?(member_name.to_sym)
48
+ member_name = arg.value
50
49
 
51
- message = format(MSG, member_name: member_name.inspect, method_name: member_name.to_s)
52
- add_offense(arg, message: message)
53
- end
50
+ next unless STRUCT_METHOD_NAMES.include?(member_name.to_sym)
51
+
52
+ message = format(MSG, member_name: member_name.inspect, method_name: member_name.to_s)
53
+ add_offense(arg, message: message)
54
54
  end
55
55
  end
56
56
  end
@@ -119,7 +119,7 @@ module RuboCop
119
119
  ancestor = node.each_ancestor(:kwbegin, :def, :defs, :block, :numblock).first
120
120
  return false unless ancestor
121
121
 
122
- end_line = ancestor.loc.end.line
122
+ end_line = ancestor.loc.end&.line || ancestor.loc.last_line
123
123
  processed_source[node.first_line...end_line].any? { |line| comment_line?(line) }
124
124
  end
125
125
 
@@ -19,6 +19,7 @@ module RuboCop
19
19
  # 'underscored_string'.to_sym
20
20
  # :'underscored_symbol'
21
21
  # 'hyphenated-string'.to_sym
22
+ # "string_#{interpolation}".to_sym
22
23
  #
23
24
  # # good
24
25
  # :string
@@ -26,6 +27,7 @@ module RuboCop
26
27
  # :underscored_string
27
28
  # :underscored_symbol
28
29
  # :'hyphenated-string'
30
+ # :"string_#{interpolation}"
29
31
  #
30
32
  # @example EnforcedStyle: strict (default)
31
33
  #
@@ -75,9 +77,12 @@ module RuboCop
75
77
 
76
78
  def on_send(node)
77
79
  return unless node.receiver
78
- return unless node.receiver.str_type? || node.receiver.sym_type?
79
80
 
80
- register_offense(node, correction: node.receiver.value.to_sym.inspect)
81
+ if node.receiver.str_type? || node.receiver.sym_type?
82
+ register_offense(node, correction: node.receiver.value.to_sym.inspect)
83
+ elsif node.receiver.dstr_type?
84
+ register_offense(node, correction: ":\"#{node.receiver.value.to_sym}\"")
85
+ end
81
86
  end
82
87
 
83
88
  def on_sym(node)
@@ -17,9 +17,12 @@ module RuboCop
17
17
  private
18
18
 
19
19
  def add_offense_from_diagnostic(diagnostic, ruby_version)
20
- message =
21
- "#{diagnostic.message}\n(Using Ruby #{ruby_version} parser; " \
22
- 'configure using `TargetRubyVersion` parameter, under `AllCops`)'
20
+ message = if LSP.enabled?
21
+ diagnostic.message
22
+ else
23
+ "#{diagnostic.message}\n(Using Ruby #{ruby_version} parser; " \
24
+ 'configure using `TargetRubyVersion` parameter, under `AllCops`)'
25
+ end
23
26
  add_offense(diagnostic.location, message: message, severity: diagnostic.level)
24
27
  end
25
28
 
@@ -51,8 +51,13 @@ module RuboCop
51
51
  enum_conversion_call?(node) do |method_node, arguments|
52
52
  next if method_node.call_type? &&
53
53
  !method_node.method?(:__method__) && !method_node.method?(:__callee__)
54
- next if method_name?(method_node, def_node.method_name) &&
55
- arguments_match?(arguments, def_node)
54
+
55
+ valid = if method_name?(method_node, def_node.method_name)
56
+ arguments_match?(arguments, def_node)
57
+ else
58
+ def_node.arguments.empty?
59
+ end
60
+ return if valid
56
61
 
57
62
  add_offense(node)
58
63
  end
@@ -74,7 +79,7 @@ module RuboCop
74
79
  end
75
80
  end
76
81
 
77
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
82
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
78
83
  def argument_match?(send_arg, def_arg)
79
84
  def_arg_name = def_arg.children[0]
80
85
 
@@ -87,12 +92,14 @@ module RuboCop
87
92
  send_arg.hash_type? &&
88
93
  send_arg.pairs.any? { |pair| passing_keyword_arg?(pair, def_arg_name) }
89
94
  when :kwrestarg
90
- send_arg.each_child_node(:kwsplat).any? { |child| child.source == def_arg.source }
95
+ send_arg.each_child_node(:kwsplat, :forwarded_kwrestarg).any? do |child|
96
+ child.source == def_arg.source
97
+ end
91
98
  when :forward_arg
92
99
  send_arg.forwarded_args_type?
93
100
  end
94
101
  end
95
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
102
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
96
103
  end
97
104
  end
98
105
  end
@@ -34,7 +34,7 @@ module RuboCop
34
34
  MSG = 'Avoid leaving a trailing comma in attribute declarations.'
35
35
 
36
36
  def on_send(node)
37
- return unless node.attribute_accessor? && node.arguments.last.def_type?
37
+ return unless node.attribute_accessor? && node.last_argument.def_type?
38
38
 
39
39
  trailing_comma = trailing_comma_range(node)
40
40
 
@@ -69,8 +69,8 @@ module RuboCop
69
69
  # @!method reduce_with_block?(node)
70
70
  def_node_matcher :reduce_with_block?, <<~PATTERN
71
71
  {
72
- (block (send _recv {:reduce :inject} ...) args ...)
73
- (numblock (send _recv {:reduce :inject} ...) ...)
72
+ (block (call _recv {:reduce :inject} ...) args ...)
73
+ (numblock (call _recv {:reduce :inject} ...) ...)
74
74
  }
75
75
  PATTERN
76
76
 
@@ -71,7 +71,7 @@ module RuboCop
71
71
  expressions.any? { |expr| flow_expression?(expr) }
72
72
  when :if
73
73
  check_if(node)
74
- when :case
74
+ when :case, :case_match
75
75
  check_case(node)
76
76
  else
77
77
  false
@@ -89,7 +89,9 @@ module RuboCop
89
89
  return false unless else_branch
90
90
  return false unless flow_expression?(else_branch)
91
91
 
92
- node.when_branches.all? { |branch| branch.body && flow_expression?(branch.body) }
92
+ branches = node.case_type? ? node.when_branches : node.in_pattern_branches
93
+
94
+ branches.all? { |branch| branch.body && flow_expression?(branch.body) }
93
95
  end
94
96
  end
95
97
  end
@@ -160,7 +160,7 @@ module RuboCop
160
160
  break_statement && !preceded_by_continue_statement?(break_statement)
161
161
  when :if
162
162
  check_if(node)
163
- when :case
163
+ when :case, :case_match
164
164
  check_case(node)
165
165
  else
166
166
  false
@@ -178,7 +178,13 @@ module RuboCop
178
178
  return false unless else_branch
179
179
  return false unless break_statement?(else_branch)
180
180
 
181
- node.when_branches.all? { |branch| branch.body && break_statement?(branch.body) }
181
+ branches = if node.case_type?
182
+ node.when_branches
183
+ else
184
+ node.in_pattern_branches
185
+ end
186
+
187
+ branches.all? { |branch| branch.body && break_statement?(branch.body) }
182
188
  end
183
189
 
184
190
  def preceded_by_continue_statement?(break_statement)
@@ -256,7 +256,7 @@ module RuboCop
256
256
 
257
257
  def any_method_definition?(child)
258
258
  cop_config.fetch('MethodCreatingMethods', []).any? do |m|
259
- matcher_name = "#{m}_method?".to_sym
259
+ matcher_name = :"#{m}_method?"
260
260
  unless respond_to?(matcher_name)
261
261
  self.class.def_node_matcher matcher_name, <<~PATTERN
262
262
  {def (send nil? :#{m} ...)}
@@ -279,7 +279,7 @@ module RuboCop
279
279
 
280
280
  def any_context_creating_methods?(child)
281
281
  cop_config.fetch('ContextCreatingMethods', []).any? do |m|
282
- matcher_name = "#{m}_block?".to_sym
282
+ matcher_name = :"#{m}_block?"
283
283
  unless respond_to?(matcher_name)
284
284
  self.class.def_node_matcher matcher_name, <<~PATTERN
285
285
  ({block numblock} (send {nil? const} {:#{m}} ...) ...)