rubocop 1.67.0 → 1.76.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 (488) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +22 -16
  4. data/config/default.yml +315 -53
  5. data/config/internal_affairs.yml +20 -0
  6. data/config/obsoletion.yml +8 -3
  7. data/lib/rubocop/cached_data.rb +12 -4
  8. data/lib/rubocop/cli/command/execute_runner.rb +4 -4
  9. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  10. data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
  11. data/lib/rubocop/cli/command/version.rb +2 -2
  12. data/lib/rubocop/cli.rb +1 -1
  13. data/lib/rubocop/comment_config.rb +2 -2
  14. data/lib/rubocop/config.rb +52 -10
  15. data/lib/rubocop/config_loader.rb +52 -9
  16. data/lib/rubocop/config_loader_resolver.rb +36 -10
  17. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -3
  18. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  19. data/lib/rubocop/config_obsoletion.rb +46 -2
  20. data/lib/rubocop/config_validator.rb +25 -14
  21. data/lib/rubocop/cop/autocorrect_logic.rb +51 -26
  22. data/lib/rubocop/cop/base.rb +7 -1
  23. data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
  24. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  25. data/lib/rubocop/cop/bundler/gem_filename.rb +0 -1
  26. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +0 -1
  27. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
  28. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -12
  29. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +1 -1
  30. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
  31. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
  32. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +50 -6
  33. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  34. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
  35. data/lib/rubocop/cop/generator.rb +6 -0
  36. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  37. data/lib/rubocop/cop/internal_affairs/example_description.rb +8 -4
  38. data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
  39. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  40. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -4
  41. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  42. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  43. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  44. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  45. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +231 -0
  46. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +91 -0
  47. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  48. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  49. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
  50. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  51. data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +48 -0
  52. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  53. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  54. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  55. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  56. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
  57. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +13 -2
  58. data/lib/rubocop/cop/internal_affairs.rb +7 -16
  59. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  60. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -9
  61. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  62. data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
  63. data/lib/rubocop/cop/layout/block_alignment.rb +3 -2
  64. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  65. data/lib/rubocop/cop/layout/class_structure.rb +44 -9
  66. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +4 -4
  67. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  68. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  69. data/lib/rubocop/cop/layout/else_alignment.rb +2 -2
  70. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -3
  71. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  72. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +36 -6
  73. data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
  74. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
  75. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +4 -5
  76. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +23 -1
  77. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  78. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  79. data/lib/rubocop/cop/layout/first_argument_indentation.rb +4 -9
  80. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  81. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  82. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  83. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  84. data/lib/rubocop/cop/layout/hash_alignment.rb +8 -6
  85. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
  86. data/lib/rubocop/cop/layout/indentation_width.rb +8 -7
  87. data/lib/rubocop/cop/layout/leading_comment_space.rb +57 -2
  88. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +11 -2
  89. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  90. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  91. data/lib/rubocop/cop/layout/line_length.rb +123 -4
  92. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
  93. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  94. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  95. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +2 -1
  96. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
  97. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
  98. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  99. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +3 -4
  100. data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
  101. data/lib/rubocop/cop/layout/redundant_line_break.rb +19 -46
  102. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +6 -7
  103. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  104. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  105. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  106. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  107. data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
  108. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -1
  109. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  110. data/lib/rubocop/cop/layout/space_around_operators.rb +23 -21
  111. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
  112. data/lib/rubocop/cop/layout/space_before_brackets.rb +8 -34
  113. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  114. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  115. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +11 -1
  116. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +5 -0
  117. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +7 -0
  118. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
  119. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  120. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  121. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +118 -0
  122. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  123. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +10 -12
  124. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  125. data/lib/rubocop/cop/lint/circular_argument_reference.rb +4 -1
  126. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  127. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  128. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
  129. data/lib/rubocop/cop/lint/debugger.rb +3 -3
  130. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  131. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +3 -2
  132. data/lib/rubocop/cop/lint/duplicate_branch.rb +39 -4
  133. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  134. data/lib/rubocop/cop/lint/duplicate_methods.rb +86 -19
  135. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  136. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  137. data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
  138. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
  139. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  140. data/lib/rubocop/cop/lint/empty_file.rb +0 -2
  141. data/lib/rubocop/cop/lint/empty_interpolation.rb +3 -1
  142. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  143. data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
  144. data/lib/rubocop/cop/lint/float_comparison.rb +47 -14
  145. data/lib/rubocop/cop/lint/float_out_of_range.rb +2 -4
  146. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  147. data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
  148. data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
  149. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  150. data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
  151. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +3 -0
  152. data/lib/rubocop/cop/lint/literal_as_condition.rb +110 -9
  153. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  154. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
  155. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
  156. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  157. data/lib/rubocop/cop/lint/mixed_case_range.rb +5 -8
  158. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  159. data/lib/rubocop/cop/lint/nested_method_definition.rb +10 -6
  160. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  161. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
  162. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +12 -3
  163. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -3
  164. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
  165. data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
  166. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
  167. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +93 -0
  168. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -3
  169. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +3 -2
  170. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  171. data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
  172. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  173. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  174. data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
  175. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +12 -7
  176. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
  177. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  178. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +261 -0
  179. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  180. data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
  181. data/lib/rubocop/cop/lint/refinement_import_methods.rb +1 -1
  182. data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
  183. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  184. data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
  185. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  186. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -1
  187. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +5 -1
  188. data/lib/rubocop/cop/lint/self_assignment.rb +8 -10
  189. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  190. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +13 -1
  191. data/lib/rubocop/cop/lint/shared_mutable_default.rb +76 -0
  192. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  193. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
  194. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  195. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  196. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
  197. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  198. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +88 -0
  199. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +3 -1
  200. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  201. data/lib/rubocop/cop/lint/unreachable_code.rb +52 -2
  202. data/lib/rubocop/cop/lint/unreachable_loop.rb +6 -6
  203. data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
  204. data/lib/rubocop/cop/lint/useless_access_modifier.rb +5 -4
  205. data/lib/rubocop/cop/lint/useless_assignment.rb +3 -1
  206. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +71 -0
  207. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +87 -0
  208. data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
  209. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +4 -0
  210. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  211. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  212. data/lib/rubocop/cop/lint/useless_or.rb +98 -0
  213. data/lib/rubocop/cop/lint/useless_rescue.rb +2 -2
  214. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  215. data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
  216. data/lib/rubocop/cop/lint/void.rb +16 -12
  217. data/lib/rubocop/cop/message_annotator.rb +7 -3
  218. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  219. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  220. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  221. data/lib/rubocop/cop/metrics/class_length.rb +9 -9
  222. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  223. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +5 -2
  224. data/lib/rubocop/cop/metrics/method_length.rb +9 -1
  225. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  226. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  227. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  228. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +3 -4
  229. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  230. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  231. data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
  232. data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
  233. data/lib/rubocop/cop/mixin/check_line_breakable.rb +22 -12
  234. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
  235. data/lib/rubocop/cop/mixin/comments_help.rb +8 -3
  236. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  237. data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
  238. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  239. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
  240. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  241. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
  242. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +3 -2
  243. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
  244. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
  245. data/lib/rubocop/cop/mixin/hash_subset.rb +203 -0
  246. data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
  247. data/lib/rubocop/cop/mixin/line_length_help.rb +5 -4
  248. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  249. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +7 -9
  250. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  251. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  252. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +68 -30
  253. data/lib/rubocop/cop/mixin/range_help.rb +15 -4
  254. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  255. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
  256. data/lib/rubocop/cop/mixin/string_help.rb +2 -2
  257. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  258. data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
  259. data/lib/rubocop/cop/mixin/trailing_comma.rb +21 -5
  260. data/lib/rubocop/cop/naming/accessor_method_name.rb +6 -6
  261. data/lib/rubocop/cop/naming/block_forwarding.rb +20 -16
  262. data/lib/rubocop/cop/naming/constant_name.rb +6 -7
  263. data/lib/rubocop/cop/naming/file_name.rb +0 -2
  264. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +12 -13
  265. data/lib/rubocop/cop/naming/method_name.rb +64 -8
  266. data/lib/rubocop/cop/naming/predicate_method.rb +216 -0
  267. data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +46 -2
  268. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +6 -14
  269. data/lib/rubocop/cop/naming/variable_name.rb +50 -6
  270. data/lib/rubocop/cop/naming/variable_number.rb +2 -3
  271. data/lib/rubocop/cop/offense.rb +2 -3
  272. data/lib/rubocop/cop/registry.rb +9 -6
  273. data/lib/rubocop/cop/security/compound_hash.rb +2 -0
  274. data/lib/rubocop/cop/security/yaml_load.rb +3 -2
  275. data/lib/rubocop/cop/style/access_modifier_declarations.rb +114 -34
  276. data/lib/rubocop/cop/style/accessor_grouping.rb +19 -5
  277. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +79 -0
  278. data/lib/rubocop/cop/style/and_or.rb +1 -1
  279. data/lib/rubocop/cop/style/arguments_forwarding.rb +47 -28
  280. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  281. data/lib/rubocop/cop/style/array_intersect.rb +42 -30
  282. data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
  283. data/lib/rubocop/cop/style/block_delimiters.rb +43 -25
  284. data/lib/rubocop/cop/style/case_like_if.rb +8 -11
  285. data/lib/rubocop/cop/style/class_and_module_children.rb +52 -11
  286. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  287. data/lib/rubocop/cop/style/collection_methods.rb +2 -1
  288. data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
  289. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  290. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  291. data/lib/rubocop/cop/style/commented_keyword.rb +20 -3
  292. data/lib/rubocop/cop/style/comparable_between.rb +78 -0
  293. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  294. data/lib/rubocop/cop/style/conditional_assignment.rb +39 -27
  295. data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
  296. data/lib/rubocop/cop/style/data_inheritance.rb +7 -0
  297. data/lib/rubocop/cop/style/def_with_parentheses.rb +18 -5
  298. data/lib/rubocop/cop/style/dig_chain.rb +89 -0
  299. data/lib/rubocop/cop/style/documentation.rb +1 -1
  300. data/lib/rubocop/cop/style/double_negation.rb +4 -4
  301. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  302. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  303. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  304. data/lib/rubocop/cop/style/empty_literal.rb +5 -1
  305. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  306. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +100 -0
  307. data/lib/rubocop/cop/style/endless_method.rb +150 -18
  308. data/lib/rubocop/cop/style/eval_with_location.rb +4 -4
  309. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -3
  310. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  311. data/lib/rubocop/cop/style/explicit_block_argument.rb +16 -3
  312. data/lib/rubocop/cop/style/exponential_notation.rb +3 -3
  313. data/lib/rubocop/cop/style/fetch_env_var.rb +2 -1
  314. data/lib/rubocop/cop/style/file_null.rb +89 -0
  315. data/lib/rubocop/cop/style/file_touch.rb +75 -0
  316. data/lib/rubocop/cop/style/float_division.rb +8 -4
  317. data/lib/rubocop/cop/style/for.rb +1 -1
  318. data/lib/rubocop/cop/style/format_string_token.rb +38 -11
  319. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  320. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  321. data/lib/rubocop/cop/style/global_vars.rb +1 -3
  322. data/lib/rubocop/cop/style/guard_clause.rb +17 -3
  323. data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
  324. data/lib/rubocop/cop/style/hash_each_methods.rb +6 -8
  325. data/lib/rubocop/cop/style/hash_except.rb +35 -147
  326. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  327. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  328. data/lib/rubocop/cop/style/hash_syntax.rb +9 -3
  329. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  330. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  331. data/lib/rubocop/cop/style/identical_conditional_branches.rb +25 -6
  332. data/lib/rubocop/cop/style/if_inside_else.rb +10 -14
  333. data/lib/rubocop/cop/style/if_unless_modifier.rb +25 -7
  334. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -7
  335. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +3 -4
  336. data/lib/rubocop/cop/style/if_with_semicolon.rb +20 -9
  337. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  338. data/lib/rubocop/cop/style/inverse_methods.rb +15 -12
  339. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  340. data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
  341. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  342. data/lib/rubocop/cop/style/it_block_parameter.rb +119 -0
  343. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
  344. data/lib/rubocop/cop/style/keyword_parameters_order.rb +14 -8
  345. data/lib/rubocop/cop/style/lambda.rb +1 -0
  346. data/lib/rubocop/cop/style/lambda_call.rb +10 -4
  347. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  348. data/lib/rubocop/cop/style/map_into_array.rb +11 -3
  349. data/lib/rubocop/cop/style/map_to_hash.rb +12 -1
  350. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  351. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +27 -17
  352. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  353. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +8 -11
  354. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
  355. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  356. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  357. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
  358. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -2
  359. data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
  360. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  361. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
  362. data/lib/rubocop/cop/style/multiple_comparison.rb +52 -51
  363. data/lib/rubocop/cop/style/mutable_constant.rb +7 -8
  364. data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -5
  365. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  366. data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
  367. data/lib/rubocop/cop/style/next.rb +44 -0
  368. data/lib/rubocop/cop/style/not.rb +1 -1
  369. data/lib/rubocop/cop/style/object_then.rb +15 -15
  370. data/lib/rubocop/cop/style/one_line_conditional.rb +25 -4
  371. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  372. data/lib/rubocop/cop/style/operator_method_call.rb +5 -6
  373. data/lib/rubocop/cop/style/or_assignment.rb +3 -6
  374. data/lib/rubocop/cop/style/parallel_assignment.rb +9 -18
  375. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  376. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  377. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  378. data/lib/rubocop/cop/style/proc.rb +2 -2
  379. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  380. data/lib/rubocop/cop/style/raise_args.rb +15 -13
  381. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  382. data/lib/rubocop/cop/style/redundant_argument.rb +3 -1
  383. data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
  384. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
  385. data/lib/rubocop/cop/style/redundant_begin.rb +2 -1
  386. data/lib/rubocop/cop/style/redundant_condition.rb +95 -23
  387. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +16 -5
  388. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  389. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  390. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  391. data/lib/rubocop/cop/style/redundant_format.rb +262 -0
  392. data/lib/rubocop/cop/style/redundant_freeze.rb +3 -3
  393. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  394. data/lib/rubocop/cop/style/redundant_line_continuation.rb +54 -18
  395. data/lib/rubocop/cop/style/redundant_parentheses.rb +68 -26
  396. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -0
  397. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  398. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  399. data/lib/rubocop/cop/style/redundant_return.rb +2 -2
  400. data/lib/rubocop/cop/style/redundant_self.rb +9 -15
  401. data/lib/rubocop/cop/style/redundant_self_assignment.rb +20 -32
  402. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
  403. data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
  404. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  405. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  406. data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
  407. data/lib/rubocop/cop/style/rescue_modifier.rb +5 -3
  408. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  409. data/lib/rubocop/cop/style/safe_navigation.rb +56 -16
  410. data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
  411. data/lib/rubocop/cop/style/select_by_regexp.rb +5 -2
  412. data/lib/rubocop/cop/style/self_assignment.rb +11 -17
  413. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  414. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  415. data/lib/rubocop/cop/style/signal_exception.rb +2 -3
  416. data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
  417. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  418. data/lib/rubocop/cop/style/single_line_do_end_block.rb +15 -4
  419. data/lib/rubocop/cop/style/single_line_methods.rb +6 -7
  420. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  421. data/lib/rubocop/cop/style/sole_nested_conditional.rb +42 -106
  422. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  423. data/lib/rubocop/cop/style/string_concatenation.rb +15 -15
  424. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  425. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  426. data/lib/rubocop/cop/style/struct_inheritance.rb +8 -1
  427. data/lib/rubocop/cop/style/super_arguments.rb +66 -19
  428. data/lib/rubocop/cop/style/swap_values.rb +4 -15
  429. data/lib/rubocop/cop/style/symbol_proc.rb +2 -0
  430. data/lib/rubocop/cop/style/ternary_parentheses.rb +25 -4
  431. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -1
  432. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +11 -2
  433. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  434. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  435. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
  436. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  437. data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
  438. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  439. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  440. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  441. data/lib/rubocop/cop/team.rb +1 -1
  442. data/lib/rubocop/cop/util.rb +12 -5
  443. data/lib/rubocop/cop/utils/format_string.rb +10 -5
  444. data/lib/rubocop/cop/variable_force/assignment.rb +24 -5
  445. data/lib/rubocop/cop/variable_force/branch.rb +1 -1
  446. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  447. data/lib/rubocop/cop/variable_force/variable.rb +14 -3
  448. data/lib/rubocop/cop/variable_force/variable_table.rb +5 -5
  449. data/lib/rubocop/cop/variable_force.rb +5 -11
  450. data/lib/rubocop/cops_documentation_generator.rb +50 -25
  451. data/lib/rubocop/directive_comment.rb +45 -11
  452. data/lib/rubocop/ext/regexp_node.rb +0 -1
  453. data/lib/rubocop/formatter/disabled_config_formatter.rb +3 -2
  454. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  455. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  456. data/lib/rubocop/formatter/pacman_formatter.rb +1 -1
  457. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  458. data/lib/rubocop/lsp/logger.rb +2 -2
  459. data/lib/rubocop/lsp/routes.rb +7 -23
  460. data/lib/rubocop/lsp/runtime.rb +18 -50
  461. data/lib/rubocop/lsp/server.rb +0 -2
  462. data/lib/rubocop/lsp/stdin_runner.rb +85 -0
  463. data/lib/rubocop/magic_comment.rb +11 -3
  464. data/lib/rubocop/options.rb +28 -12
  465. data/lib/rubocop/path_util.rb +15 -8
  466. data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
  467. data/lib/rubocop/plugin/load_error.rb +26 -0
  468. data/lib/rubocop/plugin/loader.rb +100 -0
  469. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  470. data/lib/rubocop/plugin.rb +46 -0
  471. data/lib/rubocop/rake_task.rb +4 -1
  472. data/lib/rubocop/result_cache.rb +13 -13
  473. data/lib/rubocop/rspec/cop_helper.rb +13 -1
  474. data/lib/rubocop/rspec/expect_offense.rb +15 -5
  475. data/lib/rubocop/rspec/shared_contexts.rb +38 -1
  476. data/lib/rubocop/rspec/support.rb +4 -2
  477. data/lib/rubocop/runner.rb +26 -15
  478. data/lib/rubocop/server/cache.rb +47 -11
  479. data/lib/rubocop/server/cli.rb +2 -2
  480. data/lib/rubocop/target_finder.rb +7 -2
  481. data/lib/rubocop/target_ruby.rb +17 -2
  482. data/lib/rubocop/version.rb +53 -12
  483. data/lib/rubocop.rb +38 -2
  484. data/lib/ruby_lsp/rubocop/addon.rb +75 -0
  485. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +65 -0
  486. metadata +85 -21
  487. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  488. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Certain numeric operations have a constant result, usually 0 or 1.
7
+ # Multiplying a number by 0 will always return 0.
8
+ # Dividing a number by itself or raising it to the power of 0 will always return 1.
9
+ # As such, they can be replaced with that result.
10
+ # These are probably leftover from debugging, or are mistakes.
11
+ # Other numeric operations that are similarly leftover from debugging or mistakes
12
+ # are handled by `Lint/UselessNumericOperation`.
13
+ #
14
+ # NOTE: This cop doesn't detect offenses for the `-` and `%` operator because it
15
+ # can't determine the type of `x`. If `x` is an `Array` or `String`, it doesn't perform
16
+ # a numeric operation.
17
+ #
18
+ # @example
19
+ #
20
+ # # bad
21
+ # x * 0
22
+ #
23
+ # # good
24
+ # 0
25
+ #
26
+ # # bad
27
+ # x *= 0
28
+ #
29
+ # # good
30
+ # x = 0
31
+ #
32
+ # # bad
33
+ # x / x
34
+ # x ** 0
35
+ #
36
+ # # good
37
+ # 1
38
+ #
39
+ # # bad
40
+ # x /= x
41
+ # x **= 0
42
+ #
43
+ # # good
44
+ # x = 1
45
+ #
46
+ class NumericOperationWithConstantResult < Base
47
+ extend AutoCorrector
48
+ MSG = 'Numeric operation with a constant result detected.'
49
+ RESTRICT_ON_SEND = %i[* / **].freeze
50
+
51
+ # @!method operation_with_constant_result?(node)
52
+ def_node_matcher :operation_with_constant_result?,
53
+ '(call (call nil? $_lhs) $_operation ({int | call nil?} $_rhs))'
54
+
55
+ # @!method abbreviated_assignment_with_constant_result?(node)
56
+ def_node_matcher :abbreviated_assignment_with_constant_result?,
57
+ '(op-asgn (lvasgn $_lhs) $_operation ({int lvar} $_rhs))'
58
+
59
+ def on_send(node)
60
+ return unless (lhs, operation, rhs = operation_with_constant_result?(node))
61
+ return unless (result = constant_result?(lhs, operation, rhs))
62
+
63
+ add_offense(node) do |corrector|
64
+ corrector.replace(node, result.to_s)
65
+ end
66
+ end
67
+ alias on_csend on_send
68
+
69
+ def on_op_asgn(node)
70
+ return unless (lhs, operation, rhs = abbreviated_assignment_with_constant_result?(node))
71
+ return unless (result = constant_result?(lhs, operation, rhs))
72
+
73
+ add_offense(node) do |corrector|
74
+ corrector.replace(node, "#{lhs} = #{result}")
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def constant_result?(lhs, operation, rhs)
81
+ if rhs.to_s == '0'
82
+ return 0 if operation == :*
83
+ return 1 if operation == :**
84
+ elsif rhs == lhs
85
+ return 1 if operation == :/
86
+ end
87
+ # If we weren't able to find any matches, return false so we can bail out.
88
+ false
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -27,11 +27,10 @@ module RuboCop
27
27
  MSG = 'Avoid using or-assignment with constants.'
28
28
 
29
29
  def on_or_asgn(node)
30
- lhs, _rhs = *node
31
- return unless lhs&.casgn_type?
30
+ return unless node.lhs&.casgn_type?
32
31
 
33
32
  add_offense(node.loc.operator) do |corrector|
34
- next if node.each_ancestor(:def, :defs).any?
33
+ next if node.each_ancestor(:any_def).any?
35
34
 
36
35
  corrector.replace(node.loc.operator, '=')
37
36
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Looks for references of Regexp captures that are out of range
6
+ # Looks for references of `Regexp` captures that are out of range
7
7
  # and thus always returns nil.
8
8
  #
9
9
  # @safety
@@ -61,6 +61,7 @@ module RuboCop
61
61
  check_regexp(node.receiver)
62
62
  end
63
63
  end
64
+ alias after_csend after_send
64
65
 
65
66
  def on_when(node)
66
67
  regexp_conditions = node.conditions.select(&:regexp_type?)
@@ -75,7 +76,7 @@ module RuboCop
75
76
  end
76
77
 
77
78
  def on_nth_ref(node)
78
- backref, = *node
79
+ backref = node.children.first
79
80
  return if @valid_ref.nil? || backref <= @valid_ref
80
81
 
81
82
  message = format(
@@ -38,16 +38,12 @@ module RuboCop
38
38
 
39
39
  def valid_context?(node)
40
40
  return true unless node.arguments.one? && node.first_argument.parenthesized_call?
41
- return true if first_argument_block_type?(node.first_argument)
41
+ return true if node.first_argument.any_block_type?
42
42
 
43
43
  node.operator_method? || node.setter_method? || chained_calls?(node) ||
44
44
  valid_first_argument?(node.first_argument)
45
45
  end
46
46
 
47
- def first_argument_block_type?(first_arg)
48
- first_arg.block_type? || first_arg.numblock_type?
49
- end
50
-
51
47
  def valid_first_argument?(first_arg)
52
48
  first_arg.operator_keyword? || first_arg.hash_type? || ternary_expression?(first_arg) ||
53
49
  compound_range?(first_arg)
@@ -3,15 +3,18 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for `raise` or `fail` statements which are
7
- # raising `Exception` class.
6
+ # Checks for `raise` or `fail` statements which raise `Exception` or
7
+ # `Exception.new`. Use `StandardError` or a specific exception class instead.
8
8
  #
9
- # You can specify a module name that will be an implicit namespace
10
- # using `AllowedImplicitNamespaces` option. The cop cause a false positive
11
- # for namespaced `Exception` when a namespace is omitted. This option can
12
- # prevent the false positive by specifying a namespace to be omitted for
13
- # `Exception`. Alternatively, make `Exception` a fully qualified class
14
- # name with an explicit namespace.
9
+ # If you have defined your own namespaced `Exception` class, it is possible
10
+ # to configure the cop to allow it by setting `AllowedImplicitNamespaces` to
11
+ # an array with the names of the namespaces to allow. By default, this is set to
12
+ # `['Gem']`, which allows `Gem::Exception` to be raised without an explicit namespace.
13
+ # If not allowed, a false positive may be registered if `raise Exception` is called
14
+ # within the namespace.
15
+ #
16
+ # Alternatively, use a fully qualified name with `raise`/`fail`
17
+ # (eg. `raise Namespace::Exception`).
15
18
  #
16
19
  # @safety
17
20
  # This cop is unsafe because it will change the exception class being
@@ -20,15 +23,31 @@ module RuboCop
20
23
  # @example
21
24
  # # bad
22
25
  # raise Exception, 'Error message here'
26
+ # raise Exception.new('Error message here')
23
27
  #
24
28
  # # good
25
29
  # raise StandardError, 'Error message here'
30
+ # raise MyError.new, 'Error message here'
31
+ #
32
+ # @example AllowedImplicitNamespaces: ['Gem'] (default)
33
+ # # bad - `Foo` is not an allowed implicit namespace
34
+ # module Foo
35
+ # def self.foo
36
+ # raise Exception # This is qualified to `Foo::Exception`.
37
+ # end
38
+ # end
26
39
  #
27
- # @example AllowedImplicitNamespaces: ['Gem']
28
40
  # # good
29
41
  # module Gem
30
42
  # def self.foo
31
- # raise Exception # This exception means `Gem::Exception`.
43
+ # raise Exception # This is qualified to `Gem::Exception`.
44
+ # end
45
+ # end
46
+ #
47
+ # # good
48
+ # module Foo
49
+ # def self.foo
50
+ # raise Foo::Exception
32
51
  # end
33
52
  # end
34
53
  class RaiseException < Base
@@ -111,7 +111,7 @@ module RuboCop
111
111
  range_between(start + begin_pos - 1, start + end_pos)
112
112
  end
113
113
 
114
- # If the list of cops is comma-separated, but without a empty space after the comma,
114
+ # If the list of cops is comma-separated, but without an empty space after the comma,
115
115
  # we should **not** remove the prepending empty space, thus begin_pos += 1
116
116
  def range_with_comma_after(comment, start, begin_pos, end_pos)
117
117
  begin_pos += 1 if comment.source[end_pos + 1] != ' '
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for redundant quantifiers inside Regexp literals.
6
+ # Checks for redundant quantifiers inside `Regexp` literals.
7
7
  #
8
8
  # It is always allowed when interpolation is used in a regexp literal,
9
9
  # because it's unknown what kind of string will be expanded as a result:
@@ -17,17 +17,12 @@ module RuboCop
17
17
  # * 2.0+ ... `enumerator`
18
18
  # * 2.1+ ... `thread`
19
19
  # * 2.2+ ... Add `rational` and `complex` above
20
- # * 2.5+ ... Add `pp` above
21
20
  # * 2.7+ ... Add `ruby2_keywords` above
22
21
  # * 3.1+ ... Add `fiber` above
23
22
  # * 3.2+ ... `set`
24
23
  #
25
24
  # This cop target those features.
26
25
  #
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
- #
31
26
  # @example
32
27
  # # bad
33
28
  # require 'unloaded_feature'
@@ -42,10 +37,6 @@ module RuboCop
42
37
  MSG = 'Remove unnecessary `require` statement.'
43
38
  RESTRICT_ON_SEND = %i[require].freeze
44
39
  RUBY_22_LOADED_FEATURES = %w[rational complex].freeze
45
- PRETTY_PRINT_METHODS = %i[
46
- pretty_inspect pretty_print pretty_print_cycle
47
- pretty_print_inspect pretty_print_instance_variables
48
- ].freeze
49
40
 
50
41
  # @!method redundant_require_statement?(node)
51
42
  def_node_matcher :redundant_require_statement?, <<~PATTERN
@@ -53,11 +44,6 @@ module RuboCop
53
44
  (str #redundant_feature?))
54
45
  PATTERN
55
46
 
56
- # @!method pp_const?(node)
57
- def_node_matcher :pp_const?, <<~PATTERN
58
- (const {nil? cbase} :PP)
59
- PATTERN
60
-
61
47
  def on_send(node)
62
48
  return unless redundant_require_statement?(node)
63
49
 
@@ -81,18 +67,11 @@ module RuboCop
81
67
  feature_name == 'enumerator' ||
82
68
  (target_ruby_version >= 2.1 && feature_name == 'thread') ||
83
69
  (target_ruby_version >= 2.2 && RUBY_22_LOADED_FEATURES.include?(feature_name)) ||
84
- (target_ruby_version >= 2.5 && feature_name == 'pp' && !need_to_require_pp?) ||
85
70
  (target_ruby_version >= 2.7 && feature_name == 'ruby2_keywords') ||
86
71
  (target_ruby_version >= 3.1 && feature_name == 'fiber') ||
87
72
  (target_ruby_version >= 3.2 && feature_name == 'set')
88
73
  end
89
74
  # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
90
-
91
- def need_to_require_pp?
92
- processed_source.ast.each_descendant(:send).any? do |node|
93
- pp_const?(node.receiver) || PRETTY_PRINT_METHODS.include?(node.method_name)
94
- end
95
- end
96
75
  end
97
76
  end
98
77
  end
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # Checks for redundant safe navigation calls.
7
7
  # Use cases where a constant, named in camel case for classes and modules is `nil` are rare,
8
8
  # and an offense is not detected when the receiver is a constant. The detection also applies
9
- # to literal receivers, except for `nil`.
9
+ # to `self`, and to literal receivers, except for `nil`.
10
10
  #
11
11
  # For all receivers, the `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`,
12
12
  # and `equal?` methods are checked by default.
@@ -29,6 +29,9 @@ module RuboCop
29
29
  # # bad
30
30
  # CamelCaseConst&.do_something
31
31
  #
32
+ # # good
33
+ # CamelCaseConst.do_something
34
+ #
32
35
  # # bad
33
36
  # do_something if attrs&.respond_to?(:[])
34
37
  #
@@ -41,9 +44,6 @@ module RuboCop
41
44
  # end
42
45
  #
43
46
  # # good
44
- # CamelCaseConst.do_something
45
- #
46
- # # good
47
47
  # while node.is_a?(BeginNode)
48
48
  # node = node.parent
49
49
  # end
@@ -67,6 +67,12 @@ module RuboCop
67
67
  # foo.to_f
68
68
  # foo.to_s
69
69
  #
70
+ # # bad
71
+ # self&.foo
72
+ #
73
+ # # good
74
+ # self.foo
75
+ #
70
76
  # @example AllowedMethods: [nil_safe_method]
71
77
  # # bad
72
78
  # do_something if attrs&.nil_safe_method(:[])
@@ -133,7 +139,7 @@ module RuboCop
133
139
  def assume_receiver_instance_exists?(receiver)
134
140
  return true if receiver.const_type? && !receiver.short_name.match?(SNAKE_CASE)
135
141
 
136
- receiver.literal? && !receiver.nil_type?
142
+ receiver.self_type? || (receiver.literal? && !receiver.nil_type?)
137
143
  end
138
144
 
139
145
  def check?(node)
@@ -141,8 +147,7 @@ module RuboCop
141
147
  return false unless parent
142
148
 
143
149
  condition?(parent, node) ||
144
- parent.and_type? ||
145
- parent.or_type? ||
150
+ parent.operator_keyword? ||
146
151
  (parent.send_type? && parent.negation_method?)
147
152
  end
148
153
 
@@ -135,10 +135,10 @@ module RuboCop
135
135
  grandparent.array_type? && grandparent.children.size > 1
136
136
  end
137
137
 
138
+ # rubocop:disable Metrics/AbcSize
138
139
  def replacement_range_and_content(node)
139
- variable, = *node
140
- loc = node.loc
141
- expression = loc.expression
140
+ variable = node.children.first
141
+ expression = node.source_range
142
142
 
143
143
  if array_new?(variable)
144
144
  expression = node.parent.source_range if node.parent.array_type?
@@ -148,16 +148,17 @@ module RuboCop
148
148
  elsif redundant_brackets?(node)
149
149
  [expression, remove_brackets(variable)]
150
150
  else
151
- [loc.operator, '']
151
+ [node.loc.operator, '']
152
152
  end
153
153
  end
154
+ # rubocop:enable Metrics/AbcSize
154
155
 
155
156
  def array_splat?(node)
156
157
  node.children.first.array_type?
157
158
  end
158
159
 
159
160
  def method_argument?(node)
160
- node.parent.send_type?
161
+ node.parent.call_type?
161
162
  end
162
163
 
163
164
  def part_of_an_array?(node)
@@ -171,7 +172,7 @@ module RuboCop
171
172
  parent = node.parent
172
173
  grandparent = node.parent.parent
173
174
 
174
- parent.when_type? || parent.send_type? || part_of_an_array?(node) ||
175
+ parent.when_type? || method_argument?(node) || part_of_an_array?(node) ||
175
176
  grandparent&.resbody_type?
176
177
  end
177
178
 
@@ -196,7 +197,7 @@ module RuboCop
196
197
  def use_percent_literal_array_argument?(node)
197
198
  argument = node.children.first
198
199
 
199
- node.parent.send_type? &&
200
+ method_argument?(node) &&
200
201
  (argument.percent_literal?(:string) || argument.percent_literal?(:symbol))
201
202
  end
202
203
 
@@ -29,7 +29,7 @@ module RuboCop
29
29
  RESTRICT_ON_SEND = %i[print puts warn].freeze
30
30
 
31
31
  # @!method to_s_without_args?(node)
32
- def_node_matcher :to_s_without_args?, '(send _ :to_s)'
32
+ def_node_matcher :to_s_without_args?, '(call _ :to_s)'
33
33
 
34
34
  def on_interpolation(begin_node)
35
35
  final_node = begin_node.children.last
@@ -42,7 +42,7 @@ module RuboCop
42
42
  def on_send(node)
43
43
  return if node.receiver
44
44
 
45
- node.each_child_node(:send) do |child|
45
+ node.each_child_node(:call) do |child|
46
46
  next if !child.method?(:to_s) || child.arguments.any?
47
47
 
48
48
  register_offense(child, "`#{node.method_name}`")
@@ -0,0 +1,261 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for redundant uses of `to_s`, `to_sym`, `to_i`, `to_f`, `to_d`, `to_r`, `to_c`,
7
+ # `to_a`, `to_h`, and `to_set`.
8
+ #
9
+ # When one of these methods is called on an object of the same type, that object
10
+ # is returned, making the call unnecessary. The cop detects conversion methods called
11
+ # on object literals, class constructors, class `[]` methods, and the `Kernel` methods
12
+ # `String()`, `Integer()`, `Float()`, BigDecimal(), `Rational()`, `Complex()`, and `Array()`.
13
+ #
14
+ # Specifically, these cases are detected for each conversion method:
15
+ #
16
+ # * `to_s` when called on a string literal, interpolated string, heredoc,
17
+ # or with `String.new` or `String()`.
18
+ # * `to_sym` when called on a symbol literal or interpolated symbol.
19
+ # * `to_i` when called on an integer literal or with `Integer()`.
20
+ # * `to_f` when called on a float literal of with `Float()`.
21
+ # * `to_r` when called on a rational literal or with `Rational()`.
22
+ # * `to_c` when called on a complex literal of with `Complex()`.
23
+ # * `to_a` when called on an array literal, or with `Array.new`, `Array()` or `Array[]`.
24
+ # * `to_h` when called on a hash literal, or with `Hash.new`, `Hash()` or `Hash[]`.
25
+ # * `to_set` when called on `Set.new` or `Set[]`.
26
+ #
27
+ # In all cases, chaining one same `to_*` conversion methods listed above is redundant.
28
+ #
29
+ # The cop can also register an offense for chaining conversion methods on methods that are
30
+ # expected to return a specific type regardless of receiver (eg. `foo.inspect.to_s` and
31
+ # `foo.to_json.to_s`).
32
+ #
33
+ # @example
34
+ # # bad
35
+ # "text".to_s
36
+ # :sym.to_sym
37
+ # 42.to_i
38
+ # 8.5.to_f
39
+ # 12r.to_r
40
+ # 1i.to_c
41
+ # [].to_a
42
+ # {}.to_h
43
+ # Set.new.to_set
44
+ #
45
+ # # good
46
+ # "text"
47
+ # :sym
48
+ # 42
49
+ # 8.5
50
+ # 12r
51
+ # 1i
52
+ # []
53
+ # {}
54
+ # Set.new
55
+ #
56
+ # # bad
57
+ # Integer(var).to_i
58
+ #
59
+ # # good
60
+ # Integer(var)
61
+ #
62
+ # # good - chaining to a type constructor with exceptions suppressed
63
+ # # in this case, `Integer()` could return `nil`
64
+ # Integer(var, exception: false).to_i
65
+ #
66
+ # # bad - chaining the same conversion
67
+ # foo.to_s.to_s
68
+ #
69
+ # # good
70
+ # foo.to_s
71
+ #
72
+ # # bad - chaining a conversion to a method that is expected to return the same type
73
+ # foo.inspect.to_s
74
+ # foo.to_json.to_s
75
+ #
76
+ # # good
77
+ # foo.inspect
78
+ # foo.to_json
79
+ #
80
+ class RedundantTypeConversion < Base
81
+ extend AutoCorrector
82
+
83
+ MSG = 'Redundant `%<method>s` detected.'
84
+
85
+ # Maps conversion methods to the node types for the literals of that type
86
+ LITERAL_NODE_TYPES = {
87
+ to_s: %i[str dstr],
88
+ to_sym: %i[sym dsym],
89
+ to_i: %i[int],
90
+ to_f: %i[float],
91
+ to_r: %i[rational],
92
+ to_c: %i[complex],
93
+ to_a: %i[array],
94
+ to_h: %i[hash],
95
+ to_set: [] # sets don't have a literal or node type
96
+ }.freeze
97
+
98
+ # Maps each conversion method to the pattern matcher for that type's constructors
99
+ # Not every type has a constructor, for instance Symbol.
100
+ CONSTRUCTOR_MAPPING = {
101
+ to_s: 'string_constructor?',
102
+ to_i: 'integer_constructor?',
103
+ to_f: 'float_constructor?',
104
+ to_d: 'bigdecimal_constructor?',
105
+ to_r: 'rational_constructor?',
106
+ to_c: 'complex_constructor?',
107
+ to_a: 'array_constructor?',
108
+ to_h: 'hash_constructor?',
109
+ to_set: 'set_constructor?'
110
+ }.freeze
111
+
112
+ # Methods that already are expected to return a given type, which makes a further
113
+ # conversion redundant.
114
+ TYPED_METHODS = { to_s: %i[inspect to_json] }.freeze
115
+
116
+ CONVERSION_METHODS = Set[*LITERAL_NODE_TYPES.keys].freeze
117
+ RESTRICT_ON_SEND = CONVERSION_METHODS + [:to_d]
118
+
119
+ private_constant :LITERAL_NODE_TYPES, :CONSTRUCTOR_MAPPING
120
+
121
+ # @!method type_constructor?(node, type_symbol)
122
+ def_node_matcher :type_constructor?, <<~PATTERN
123
+ (send {nil? (const {cbase nil?} :Kernel)} %1 ...)
124
+ PATTERN
125
+
126
+ # @!method string_constructor?(node)
127
+ def_node_matcher :string_constructor?, <<~PATTERN
128
+ {
129
+ (send (const {cbase nil?} :String) :new ...)
130
+ #type_constructor?(:String)
131
+ }
132
+ PATTERN
133
+
134
+ # @!method integer_constructor?(node)
135
+ def_node_matcher :integer_constructor?, <<~PATTERN
136
+ #type_constructor?(:Integer)
137
+ PATTERN
138
+
139
+ # @!method float_constructor?(node)
140
+ def_node_matcher :float_constructor?, <<~PATTERN
141
+ #type_constructor?(:Float)
142
+ PATTERN
143
+
144
+ # @!method bigdecimal_constructor?(node)
145
+ def_node_matcher :bigdecimal_constructor?, <<~PATTERN
146
+ #type_constructor?(:BigDecimal)
147
+ PATTERN
148
+
149
+ # @!method rational_constructor?(node)
150
+ def_node_matcher :rational_constructor?, <<~PATTERN
151
+ #type_constructor?(:Rational)
152
+ PATTERN
153
+
154
+ # @!method complex_constructor?(node)
155
+ def_node_matcher :complex_constructor?, <<~PATTERN
156
+ #type_constructor?(:Complex)
157
+ PATTERN
158
+
159
+ # @!method array_constructor?(node)
160
+ def_node_matcher :array_constructor?, <<~PATTERN
161
+ {
162
+ (send (const {cbase nil?} :Array) {:new :[]} ...)
163
+ #type_constructor?(:Array)
164
+ }
165
+ PATTERN
166
+
167
+ # @!method hash_constructor?(node)
168
+ def_node_matcher :hash_constructor?, <<~PATTERN
169
+ {
170
+ (block (send (const {cbase nil?} :Hash) :new) ...)
171
+ (send (const {cbase nil?} :Hash) {:new :[]} ...)
172
+ (send {nil? (const {cbase nil?} :Kernel)} :Hash ...)
173
+ }
174
+ PATTERN
175
+
176
+ # @!method set_constructor?(node)
177
+ def_node_matcher :set_constructor?, <<~PATTERN
178
+ {
179
+ (send (const {cbase nil?} :Set) {:new :[]} ...)
180
+ }
181
+ PATTERN
182
+
183
+ # @!method exception_false_keyword_argument?(node)
184
+ def_node_matcher :exception_false_keyword_argument?, <<~PATTERN
185
+ (hash (pair (sym :exception) false))
186
+ PATTERN
187
+
188
+ # rubocop:disable Metrics/AbcSize
189
+ def on_send(node)
190
+ return if hash_or_set_with_block?(node)
191
+
192
+ receiver = find_receiver(node)
193
+ return unless literal_receiver?(node, receiver) ||
194
+ constructor?(node, receiver) ||
195
+ chained_conversion?(node, receiver) ||
196
+ chained_to_typed_method?(node, receiver)
197
+
198
+ message = format(MSG, method: node.method_name)
199
+
200
+ add_offense(node.loc.selector, message: message) do |corrector|
201
+ corrector.remove(node.loc.dot.join(node.loc.selector))
202
+ end
203
+ end
204
+ # rubocop:enable Metrics/AbcSize
205
+ alias on_csend on_send
206
+
207
+ private
208
+
209
+ def hash_or_set_with_block?(node)
210
+ return false if !node.method?(:to_h) && !node.method?(:to_set)
211
+
212
+ node.parent&.any_block_type? || node.last_argument&.block_pass_type?
213
+ end
214
+
215
+ def find_receiver(node)
216
+ receiver = node.receiver
217
+ return unless receiver
218
+
219
+ while receiver.begin_type?
220
+ break unless receiver.children.one?
221
+
222
+ receiver = receiver.children.first
223
+ end
224
+
225
+ receiver
226
+ end
227
+
228
+ def literal_receiver?(node, receiver)
229
+ return false unless receiver
230
+
231
+ receiver.type?(*LITERAL_NODE_TYPES[node.method_name])
232
+ end
233
+
234
+ def constructor?(node, receiver)
235
+ matcher = CONSTRUCTOR_MAPPING[node.method_name]
236
+ return false unless matcher
237
+
238
+ public_send(matcher, receiver) && !constructor_suppresses_exceptions?(receiver)
239
+ end
240
+
241
+ def constructor_suppresses_exceptions?(receiver)
242
+ # If the constructor suppresses exceptions with `exception: false`, it is possible
243
+ # it could return `nil`, and therefore a chained conversion is not redundant.
244
+ receiver.arguments.any? { |arg| exception_false_keyword_argument?(arg) }
245
+ end
246
+
247
+ def chained_conversion?(node, receiver)
248
+ return false unless receiver&.call_type?
249
+
250
+ receiver.method?(node.method_name)
251
+ end
252
+
253
+ def chained_to_typed_method?(node, receiver)
254
+ return false unless receiver&.call_type?
255
+
256
+ TYPED_METHODS.fetch(node.method_name, []).include?(receiver.method_name)
257
+ end
258
+ end
259
+ end
260
+ end
261
+ end