rubocop 1.67.0 → 1.77.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +23 -17
  4. data/config/default.yml +337 -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/parentheses_corrector.rb +5 -2
  31. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
  32. data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
  33. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
  34. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +37 -15
  35. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  36. data/lib/rubocop/cop/gemspec/require_mfa.rb +15 -1
  37. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
  38. data/lib/rubocop/cop/generator.rb +6 -0
  39. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  40. data/lib/rubocop/cop/internal_affairs/example_description.rb +8 -4
  41. data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
  42. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  43. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -4
  44. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  45. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +5 -5
  46. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  47. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  48. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +231 -0
  49. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +91 -0
  50. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  51. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  52. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
  53. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  54. data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +48 -0
  55. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  56. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  57. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  58. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  59. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
  60. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +13 -2
  61. data/lib/rubocop/cop/internal_affairs.rb +7 -16
  62. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  63. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -9
  64. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  65. data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
  66. data/lib/rubocop/cop/layout/block_alignment.rb +3 -2
  67. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  68. data/lib/rubocop/cop/layout/class_structure.rb +44 -9
  69. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
  70. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  71. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  72. data/lib/rubocop/cop/layout/else_alignment.rb +2 -2
  73. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -3
  74. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  75. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +37 -7
  76. data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
  77. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
  78. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +4 -5
  79. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +23 -1
  80. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  81. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  82. data/lib/rubocop/cop/layout/first_argument_indentation.rb +4 -9
  83. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  84. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  85. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  86. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  87. data/lib/rubocop/cop/layout/hash_alignment.rb +8 -6
  88. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
  89. data/lib/rubocop/cop/layout/indentation_width.rb +8 -7
  90. data/lib/rubocop/cop/layout/leading_comment_space.rb +57 -2
  91. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +11 -2
  92. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  93. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  94. data/lib/rubocop/cop/layout/line_length.rb +149 -9
  95. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
  96. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  97. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  98. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +2 -1
  99. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
  100. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
  101. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  102. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +3 -4
  103. data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
  104. data/lib/rubocop/cop/layout/redundant_line_break.rb +19 -46
  105. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +6 -7
  106. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  107. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  108. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  109. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  110. data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
  111. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -1
  112. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  113. data/lib/rubocop/cop/layout/space_around_operators.rb +23 -21
  114. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
  115. data/lib/rubocop/cop/layout/space_before_brackets.rb +7 -40
  116. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  117. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  118. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +18 -3
  119. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +5 -0
  120. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +7 -0
  121. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
  122. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  123. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  124. data/lib/rubocop/cop/lint/ambiguous_range.rb +5 -0
  125. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +118 -0
  126. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  127. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +10 -12
  128. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  129. data/lib/rubocop/cop/lint/circular_argument_reference.rb +4 -1
  130. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  131. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  132. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
  133. data/lib/rubocop/cop/lint/debugger.rb +3 -3
  134. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  135. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +3 -2
  136. data/lib/rubocop/cop/lint/duplicate_branch.rb +39 -4
  137. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  138. data/lib/rubocop/cop/lint/duplicate_methods.rb +86 -19
  139. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  140. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  141. data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
  142. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
  143. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  144. data/lib/rubocop/cop/lint/empty_file.rb +0 -2
  145. data/lib/rubocop/cop/lint/empty_interpolation.rb +3 -1
  146. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  147. data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
  148. data/lib/rubocop/cop/lint/float_comparison.rb +51 -18
  149. data/lib/rubocop/cop/lint/float_out_of_range.rb +2 -4
  150. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  151. data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
  152. data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
  153. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  154. data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
  155. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +3 -0
  156. data/lib/rubocop/cop/lint/literal_as_condition.rb +110 -9
  157. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  158. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
  159. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
  160. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  161. data/lib/rubocop/cop/lint/mixed_case_range.rb +5 -8
  162. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  163. data/lib/rubocop/cop/lint/nested_method_definition.rb +10 -6
  164. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  165. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
  166. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +12 -3
  167. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -3
  168. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
  169. data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
  170. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
  171. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +93 -0
  172. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -3
  173. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +3 -2
  174. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  175. data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
  176. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  177. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +2 -2
  178. data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
  179. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +12 -7
  180. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
  181. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  182. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +261 -0
  183. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  184. data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
  185. data/lib/rubocop/cop/lint/refinement_import_methods.rb +1 -1
  186. data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
  187. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  188. data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
  189. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  190. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -1
  191. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +5 -1
  192. data/lib/rubocop/cop/lint/self_assignment.rb +33 -10
  193. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  194. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +13 -1
  195. data/lib/rubocop/cop/lint/shared_mutable_default.rb +76 -0
  196. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  197. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
  198. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  199. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  200. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
  201. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  202. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +88 -0
  203. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +3 -1
  204. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  205. data/lib/rubocop/cop/lint/unreachable_code.rb +52 -2
  206. data/lib/rubocop/cop/lint/unreachable_loop.rb +6 -6
  207. data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
  208. data/lib/rubocop/cop/lint/useless_access_modifier.rb +34 -8
  209. data/lib/rubocop/cop/lint/useless_assignment.rb +3 -1
  210. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +71 -0
  211. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +90 -0
  212. data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
  213. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +4 -0
  214. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  215. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  216. data/lib/rubocop/cop/lint/useless_or.rb +98 -0
  217. data/lib/rubocop/cop/lint/useless_rescue.rb +2 -2
  218. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +5 -5
  219. data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
  220. data/lib/rubocop/cop/lint/void.rb +16 -12
  221. data/lib/rubocop/cop/message_annotator.rb +7 -3
  222. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  223. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  224. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  225. data/lib/rubocop/cop/metrics/class_length.rb +9 -9
  226. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  227. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +5 -2
  228. data/lib/rubocop/cop/metrics/method_length.rb +9 -1
  229. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  230. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  231. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  232. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +3 -4
  233. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  234. data/lib/rubocop/cop/mixin/alignment.rb +3 -3
  235. data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
  236. data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
  237. data/lib/rubocop/cop/mixin/check_line_breakable.rb +22 -12
  238. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
  239. data/lib/rubocop/cop/mixin/comments_help.rb +8 -3
  240. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  241. data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
  242. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  243. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
  244. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  245. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
  246. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -3
  247. data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
  248. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
  249. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
  250. data/lib/rubocop/cop/mixin/hash_subset.rb +203 -0
  251. data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
  252. data/lib/rubocop/cop/mixin/line_length_help.rb +27 -10
  253. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  254. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +7 -9
  255. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  256. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  257. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +68 -30
  258. data/lib/rubocop/cop/mixin/range_help.rb +15 -4
  259. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  260. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
  261. data/lib/rubocop/cop/mixin/string_help.rb +2 -2
  262. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  263. data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
  264. data/lib/rubocop/cop/mixin/trailing_comma.rb +21 -5
  265. data/lib/rubocop/cop/naming/accessor_method_name.rb +6 -6
  266. data/lib/rubocop/cop/naming/block_forwarding.rb +20 -16
  267. data/lib/rubocop/cop/naming/constant_name.rb +6 -7
  268. data/lib/rubocop/cop/naming/file_name.rb +2 -4
  269. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +12 -13
  270. data/lib/rubocop/cop/naming/method_name.rb +64 -8
  271. data/lib/rubocop/cop/naming/predicate_method.rb +281 -0
  272. data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +48 -4
  273. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +6 -14
  274. data/lib/rubocop/cop/naming/variable_name.rb +50 -6
  275. data/lib/rubocop/cop/naming/variable_number.rb +2 -3
  276. data/lib/rubocop/cop/offense.rb +2 -3
  277. data/lib/rubocop/cop/registry.rb +9 -6
  278. data/lib/rubocop/cop/security/compound_hash.rb +2 -0
  279. data/lib/rubocop/cop/security/yaml_load.rb +3 -2
  280. data/lib/rubocop/cop/style/access_modifier_declarations.rb +114 -34
  281. data/lib/rubocop/cop/style/accessor_grouping.rb +19 -5
  282. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +79 -0
  283. data/lib/rubocop/cop/style/and_or.rb +1 -1
  284. data/lib/rubocop/cop/style/arguments_forwarding.rb +47 -28
  285. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  286. data/lib/rubocop/cop/style/array_intersect.rb +42 -30
  287. data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
  288. data/lib/rubocop/cop/style/block_delimiters.rb +43 -25
  289. data/lib/rubocop/cop/style/case_like_if.rb +9 -12
  290. data/lib/rubocop/cop/style/class_and_module_children.rb +52 -11
  291. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  292. data/lib/rubocop/cop/style/collection_methods.rb +2 -1
  293. data/lib/rubocop/cop/style/collection_querying.rb +167 -0
  294. data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
  295. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  296. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  297. data/lib/rubocop/cop/style/commented_keyword.rb +20 -3
  298. data/lib/rubocop/cop/style/comparable_between.rb +78 -0
  299. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  300. data/lib/rubocop/cop/style/conditional_assignment.rb +41 -27
  301. data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
  302. data/lib/rubocop/cop/style/data_inheritance.rb +7 -0
  303. data/lib/rubocop/cop/style/def_with_parentheses.rb +18 -5
  304. data/lib/rubocop/cop/style/dig_chain.rb +89 -0
  305. data/lib/rubocop/cop/style/documentation.rb +1 -1
  306. data/lib/rubocop/cop/style/double_negation.rb +4 -4
  307. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  308. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  309. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  310. data/lib/rubocop/cop/style/empty_literal.rb +5 -1
  311. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  312. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +100 -0
  313. data/lib/rubocop/cop/style/endless_method.rb +150 -18
  314. data/lib/rubocop/cop/style/eval_with_location.rb +4 -4
  315. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -3
  316. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  317. data/lib/rubocop/cop/style/explicit_block_argument.rb +16 -3
  318. data/lib/rubocop/cop/style/exponential_notation.rb +5 -5
  319. data/lib/rubocop/cop/style/fetch_env_var.rb +34 -7
  320. data/lib/rubocop/cop/style/file_null.rb +89 -0
  321. data/lib/rubocop/cop/style/file_touch.rb +75 -0
  322. data/lib/rubocop/cop/style/float_division.rb +8 -4
  323. data/lib/rubocop/cop/style/for.rb +1 -1
  324. data/lib/rubocop/cop/style/format_string_token.rb +38 -11
  325. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  326. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  327. data/lib/rubocop/cop/style/global_vars.rb +1 -3
  328. data/lib/rubocop/cop/style/guard_clause.rb +17 -3
  329. data/lib/rubocop/cop/style/hash_conversion.rb +12 -4
  330. data/lib/rubocop/cop/style/hash_each_methods.rb +6 -8
  331. data/lib/rubocop/cop/style/hash_except.rb +35 -147
  332. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  333. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  334. data/lib/rubocop/cop/style/hash_syntax.rb +9 -3
  335. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  336. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  337. data/lib/rubocop/cop/style/identical_conditional_branches.rb +25 -6
  338. data/lib/rubocop/cop/style/if_inside_else.rb +10 -14
  339. data/lib/rubocop/cop/style/if_unless_modifier.rb +36 -9
  340. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -7
  341. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +3 -4
  342. data/lib/rubocop/cop/style/if_with_semicolon.rb +20 -9
  343. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  344. data/lib/rubocop/cop/style/inverse_methods.rb +15 -12
  345. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  346. data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
  347. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  348. data/lib/rubocop/cop/style/it_block_parameter.rb +119 -0
  349. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
  350. data/lib/rubocop/cop/style/keyword_parameters_order.rb +14 -8
  351. data/lib/rubocop/cop/style/lambda.rb +1 -0
  352. data/lib/rubocop/cop/style/lambda_call.rb +10 -4
  353. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  354. data/lib/rubocop/cop/style/map_into_array.rb +11 -3
  355. data/lib/rubocop/cop/style/map_to_hash.rb +12 -1
  356. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  357. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +28 -18
  358. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  359. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +8 -11
  360. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
  361. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  362. data/lib/rubocop/cop/style/min_max_comparison.rb +13 -5
  363. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  364. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
  365. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -2
  366. data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
  367. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  368. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
  369. data/lib/rubocop/cop/style/multiple_comparison.rb +52 -51
  370. data/lib/rubocop/cop/style/mutable_constant.rb +7 -8
  371. data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -5
  372. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  373. data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
  374. data/lib/rubocop/cop/style/next.rb +44 -0
  375. data/lib/rubocop/cop/style/not.rb +1 -1
  376. data/lib/rubocop/cop/style/object_then.rb +15 -15
  377. data/lib/rubocop/cop/style/one_line_conditional.rb +25 -4
  378. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  379. data/lib/rubocop/cop/style/operator_method_call.rb +5 -6
  380. data/lib/rubocop/cop/style/or_assignment.rb +3 -6
  381. data/lib/rubocop/cop/style/parallel_assignment.rb +9 -18
  382. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  383. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  384. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  385. data/lib/rubocop/cop/style/proc.rb +2 -2
  386. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  387. data/lib/rubocop/cop/style/raise_args.rb +15 -13
  388. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  389. data/lib/rubocop/cop/style/redundant_argument.rb +3 -1
  390. data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
  391. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
  392. data/lib/rubocop/cop/style/redundant_begin.rb +2 -1
  393. data/lib/rubocop/cop/style/redundant_condition.rb +95 -23
  394. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +16 -5
  395. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  396. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  397. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  398. data/lib/rubocop/cop/style/redundant_format.rb +262 -0
  399. data/lib/rubocop/cop/style/redundant_freeze.rb +3 -3
  400. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  401. data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
  402. data/lib/rubocop/cop/style/redundant_line_continuation.rb +54 -18
  403. data/lib/rubocop/cop/style/redundant_parentheses.rb +77 -26
  404. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -0
  405. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  406. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  407. data/lib/rubocop/cop/style/redundant_return.rb +2 -2
  408. data/lib/rubocop/cop/style/redundant_self.rb +15 -18
  409. data/lib/rubocop/cop/style/redundant_self_assignment.rb +20 -32
  410. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
  411. data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
  412. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  413. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  414. data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
  415. data/lib/rubocop/cop/style/rescue_modifier.rb +5 -3
  416. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  417. data/lib/rubocop/cop/style/safe_navigation.rb +56 -16
  418. data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
  419. data/lib/rubocop/cop/style/select_by_regexp.rb +5 -2
  420. data/lib/rubocop/cop/style/self_assignment.rb +11 -17
  421. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  422. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  423. data/lib/rubocop/cop/style/signal_exception.rb +2 -3
  424. data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
  425. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  426. data/lib/rubocop/cop/style/single_line_do_end_block.rb +15 -4
  427. data/lib/rubocop/cop/style/single_line_methods.rb +6 -7
  428. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  429. data/lib/rubocop/cop/style/sole_nested_conditional.rb +43 -106
  430. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  431. data/lib/rubocop/cop/style/string_concatenation.rb +15 -15
  432. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  433. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  434. data/lib/rubocop/cop/style/struct_inheritance.rb +8 -1
  435. data/lib/rubocop/cop/style/super_arguments.rb +66 -19
  436. data/lib/rubocop/cop/style/swap_values.rb +4 -15
  437. data/lib/rubocop/cop/style/symbol_proc.rb +3 -1
  438. data/lib/rubocop/cop/style/ternary_parentheses.rb +25 -4
  439. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -1
  440. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +11 -2
  441. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  442. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  443. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  444. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
  445. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  446. data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
  447. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  448. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  449. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  450. data/lib/rubocop/cop/team.rb +1 -1
  451. data/lib/rubocop/cop/util.rb +12 -5
  452. data/lib/rubocop/cop/utils/format_string.rb +10 -5
  453. data/lib/rubocop/cop/variable_force/assignment.rb +24 -5
  454. data/lib/rubocop/cop/variable_force/branch.rb +1 -1
  455. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  456. data/lib/rubocop/cop/variable_force/variable.rb +14 -3
  457. data/lib/rubocop/cop/variable_force/variable_table.rb +5 -5
  458. data/lib/rubocop/cop/variable_force.rb +5 -11
  459. data/lib/rubocop/cops_documentation_generator.rb +50 -25
  460. data/lib/rubocop/directive_comment.rb +45 -11
  461. data/lib/rubocop/ext/regexp_node.rb +0 -1
  462. data/lib/rubocop/formatter/disabled_config_formatter.rb +3 -2
  463. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  464. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  465. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  466. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  467. data/lib/rubocop/formatter/pacman_formatter.rb +1 -1
  468. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  469. data/lib/rubocop/lsp/logger.rb +2 -2
  470. data/lib/rubocop/lsp/routes.rb +7 -23
  471. data/lib/rubocop/lsp/runtime.rb +18 -50
  472. data/lib/rubocop/lsp/server.rb +0 -2
  473. data/lib/rubocop/lsp/stdin_runner.rb +85 -0
  474. data/lib/rubocop/magic_comment.rb +11 -3
  475. data/lib/rubocop/options.rb +28 -12
  476. data/lib/rubocop/path_util.rb +15 -8
  477. data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
  478. data/lib/rubocop/plugin/load_error.rb +26 -0
  479. data/lib/rubocop/plugin/loader.rb +100 -0
  480. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  481. data/lib/rubocop/plugin.rb +46 -0
  482. data/lib/rubocop/rake_task.rb +4 -1
  483. data/lib/rubocop/result_cache.rb +13 -13
  484. data/lib/rubocop/rspec/cop_helper.rb +13 -1
  485. data/lib/rubocop/rspec/expect_offense.rb +15 -5
  486. data/lib/rubocop/rspec/shared_contexts.rb +38 -1
  487. data/lib/rubocop/rspec/support.rb +4 -2
  488. data/lib/rubocop/runner.rb +26 -15
  489. data/lib/rubocop/server/cache.rb +47 -11
  490. data/lib/rubocop/server/cli.rb +2 -2
  491. data/lib/rubocop/target_finder.rb +7 -2
  492. data/lib/rubocop/target_ruby.rb +17 -2
  493. data/lib/rubocop/version.rb +53 -12
  494. data/lib/rubocop.rb +40 -2
  495. data/lib/ruby_lsp/rubocop/addon.rb +75 -0
  496. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +65 -0
  497. metadata +87 -21
  498. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  499. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -43,7 +43,7 @@ module RuboCop
43
43
  MSG = 'Do not return from an `ensure` block.'
44
44
 
45
45
  def on_ensure(node)
46
- node.body&.each_node(:return) { |return_node| add_offense(return_node) }
46
+ node.branch&.each_node(:return) { |return_node| add_offense(return_node) }
47
47
  end
48
48
  end
49
49
  end
@@ -156,12 +156,6 @@ module RuboCop
156
156
 
157
157
  overridden_kwargs
158
158
  end
159
-
160
- def arguments_range(node)
161
- arguments = node.arguments
162
-
163
- range_between(arguments.first.source_range.begin_pos, arguments.last.source_range.end_pos)
164
- end
165
159
  end
166
160
  end
167
161
  end
@@ -15,6 +15,14 @@ module RuboCop
15
15
  # x == 0.1
16
16
  # x != 0.1
17
17
  #
18
+ # # bad
19
+ # case value
20
+ # when 1.0
21
+ # foo
22
+ # when 2.0
23
+ # bar
24
+ # end
25
+ #
18
26
  # # good - using BigDecimal
19
27
  # x.to_d == 0.1.to_d
20
28
  #
@@ -29,11 +37,24 @@ module RuboCop
29
37
  # tolerance = 0.0001
30
38
  # (x - 0.1).abs < tolerance
31
39
  #
40
+ # # good - comparing against nil
41
+ # Float(x, exception: false) == nil
42
+ #
43
+ # # good - using epsilon comparison in case expression
44
+ # case
45
+ # when (value - 1.0).abs < Float::EPSILON
46
+ # foo
47
+ # when (value - 2.0).abs < Float::EPSILON
48
+ # bar
49
+ # end
50
+ #
32
51
  # # Or some other epsilon based type of comparison:
33
52
  # # https://www.embeddeduse.com/2019/08/26/qt-compare-two-floats/
34
53
  #
35
54
  class FloatComparison < Base
36
- MSG = 'Avoid (in)equality comparisons of floats as they are unreliable.'
55
+ MSG_EQUALITY = 'Avoid equality comparisons of floats as they are unreliable.'
56
+ MSG_INEQUALITY = 'Avoid inequality comparisons of floats as they are unreliable.'
57
+ MSG_CASE = 'Avoid float literal comparisons in case statements as they are unreliable.'
37
58
 
38
59
  EQUALITY_METHODS = %i[== != eql? equal?].freeze
39
60
  FLOAT_RETURNING_METHODS = %i[to_f Float fdiv].freeze
@@ -42,10 +63,26 @@ module RuboCop
42
63
  RESTRICT_ON_SEND = EQUALITY_METHODS
43
64
 
44
65
  def on_send(node)
45
- lhs, _method, rhs = *node
46
- return if literal_zero?(lhs) || literal_zero?(rhs)
66
+ return unless node.arguments.one?
67
+
68
+ lhs = node.receiver
69
+ rhs = node.first_argument
70
+
71
+ return if literal_safe?(lhs) || literal_safe?(rhs)
72
+
73
+ message = node.method?(:!=) ? MSG_INEQUALITY : MSG_EQUALITY
74
+ add_offense(node, message: message) if float?(lhs) || float?(rhs)
75
+ end
76
+ alias on_csend on_send
77
+
78
+ def on_case(node)
79
+ node.when_branches.each do |when_branch|
80
+ when_branch.each_condition do |condition|
81
+ next if !float?(condition) || literal_safe?(condition)
47
82
 
48
- add_offense(node) if float?(lhs) || float?(rhs)
83
+ add_offense(condition, message: MSG_CASE)
84
+ end
85
+ end
49
86
  end
50
87
 
51
88
  private
@@ -57,7 +94,7 @@ module RuboCop
57
94
  when :float
58
95
  true
59
96
  when :send
60
- check_send(node)
97
+ float_send?(node)
61
98
  when :begin
62
99
  float?(node.children.first)
63
100
  else
@@ -65,28 +102,24 @@ module RuboCop
65
102
  end
66
103
  end
67
104
 
68
- def literal_zero?(node)
69
- node&.numeric_type? && node.value.zero?
105
+ def literal_safe?(node)
106
+ return false unless node
107
+
108
+ (node.numeric_type? && node.value.zero?) || node.nil_type?
70
109
  end
71
110
 
72
- # rubocop:disable Metrics/PerceivedComplexity
73
- def check_send(node)
111
+ def float_send?(node)
74
112
  if node.arithmetic_operation?
75
- lhs, _operation, rhs = *node
76
- float?(lhs) || float?(rhs)
113
+ float?(node.receiver) || float?(node.first_argument)
77
114
  elsif FLOAT_RETURNING_METHODS.include?(node.method_name)
78
115
  true
79
116
  elsif node.receiver&.float_type?
80
- if FLOAT_INSTANCE_METHODS.include?(node.method_name)
81
- true
82
- else
83
- check_numeric_returning_method(node)
84
- end
117
+ FLOAT_INSTANCE_METHODS.include?(node.method_name) ||
118
+ numeric_returning_method?(node)
85
119
  end
86
120
  end
87
- # rubocop:enable Metrics/PerceivedComplexity
88
121
 
89
- def check_numeric_returning_method(node)
122
+ def numeric_returning_method?(node)
90
123
  return false unless node.receiver
91
124
 
92
125
  case node.method_name
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Identifies Float literals which are, like, really really really
6
+ # Identifies `Float` literals which are, like, really really really
7
7
  # really really really really really big. Too big. No-one needs Floats
8
8
  # that big. If you need a float that big, something is wrong with you.
9
9
  #
@@ -18,9 +18,7 @@ module RuboCop
18
18
  MSG = 'Float out of range.'
19
19
 
20
20
  def on_float(node)
21
- value, = *node
22
-
23
- return unless value.infinite? || (value.zero? && /[1-9]/.match?(node.source))
21
+ return unless node.value.infinite? || (node.value.zero? && /[1-9]/.match?(node.source))
24
22
 
25
23
  add_offense(node)
26
24
  end
@@ -7,7 +7,7 @@ module RuboCop
7
7
  # expected fields for format/sprintf/#% and what is actually
8
8
  # passed as arguments.
9
9
  #
10
- # In addition it checks whether different formats are used in the same
10
+ # In addition, it checks whether different formats are used in the same
11
11
  # format string. Do not mix numbered, unnumbered, and named formats in
12
12
  # the same format string.
13
13
  #
@@ -73,7 +73,7 @@ module RuboCop
73
73
 
74
74
  first_arg = node.first_argument
75
75
  return false if num_of_expected_fields.zero? &&
76
- (first_arg.dstr_type? || first_arg.array_type?)
76
+ first_arg.type?(:dstr, :array)
77
77
 
78
78
  matched_arguments_count?(num_of_expected_fields, num_of_format_args)
79
79
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for the deprecated use of keyword arguments as a default in `Hash.new`.
7
+ #
8
+ # This usage raises a warning in Ruby 3.3 and results in an error in Ruby 3.4.
9
+ # In Ruby 3.4, keyword arguments will instead be used to change the behavior of a hash.
10
+ # For example, the capacity option can be passed to create a hash with a certain size
11
+ # if you know it in advance, for better performance.
12
+ #
13
+ # NOTE: The following corner case may result in a false negative when upgrading from Ruby 3.3
14
+ # or earlier, but it is intentionally not detected to respect the expected usage in Ruby 3.4.
15
+ #
16
+ # [source,ruby]
17
+ # ----
18
+ # Hash.new(capacity: 42)
19
+ # ----
20
+ #
21
+ # @example
22
+ #
23
+ # # bad
24
+ # Hash.new(key: :value)
25
+ #
26
+ # # good
27
+ # Hash.new({key: :value})
28
+ #
29
+ class HashNewWithKeywordArgumentsAsDefault < Base
30
+ extend AutoCorrector
31
+
32
+ MSG = 'Use a hash literal instead of keyword arguments.'
33
+ RESTRICT_ON_SEND = %i[new].freeze
34
+
35
+ # @!method hash_new(node)
36
+ def_node_matcher :hash_new, <<~PATTERN
37
+ (send (const {nil? (cbase)} :Hash) :new $[hash !braces?])
38
+ PATTERN
39
+
40
+ def on_send(node)
41
+ return unless (first_argument = hash_new(node))
42
+
43
+ if first_argument.pairs.one?
44
+ key = first_argument.pairs.first.key
45
+ return if key.respond_to?(:value) && key.value == :capacity
46
+ end
47
+
48
+ add_offense(first_argument) do |corrector|
49
+ corrector.wrap(first_argument, '{', '}')
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -11,39 +11,43 @@ module RuboCop
11
11
  # @example
12
12
  # # bad
13
13
  # foo.object_id == bar.object_id
14
+ # foo.object_id != baz.object_id
14
15
  #
15
16
  # # good
16
17
  # foo.equal?(bar)
18
+ # !foo.equal?(baz)
17
19
  #
18
20
  class IdentityComparison < Base
19
21
  extend AutoCorrector
20
22
 
21
- MSG = 'Use `equal?` instead `==` when comparing `object_id`.'
22
- RESTRICT_ON_SEND = %i[==].freeze
23
+ MSG = 'Use `%<bang>sequal?` instead of `%<comparison_method>s` when comparing `object_id`.'
24
+ RESTRICT_ON_SEND = %i[== !=].freeze
25
+
26
+ # @!method object_id_comparison(node)
27
+ def_node_matcher :object_id_comparison, <<~PATTERN
28
+ (send
29
+ (send
30
+ _lhs_receiver :object_id) ${:== :!=}
31
+ (send
32
+ _rhs_receiver :object_id))
33
+ PATTERN
23
34
 
24
35
  def on_send(node)
25
- return unless compare_between_object_id_by_double_equal?(node)
36
+ return unless (comparison_method = object_id_comparison(node))
26
37
 
27
- add_offense(node) do |corrector|
38
+ bang = comparison_method == :== ? '' : '!'
39
+ add_offense(node,
40
+ message: format(MSG, comparison_method: comparison_method,
41
+ bang: bang)) do |corrector|
28
42
  receiver = node.receiver.receiver
29
43
  argument = node.first_argument.receiver
30
44
  return unless receiver && argument
31
45
 
32
- replacement = "#{receiver.source}.equal?(#{argument.source})"
46
+ replacement = "#{bang}#{receiver.source}.equal?(#{argument.source})"
33
47
 
34
48
  corrector.replace(node, replacement)
35
49
  end
36
50
  end
37
-
38
- private
39
-
40
- def compare_between_object_id_by_double_equal?(node)
41
- object_id_method?(node.receiver) && object_id_method?(node.first_argument)
42
- end
43
-
44
- def object_id_method?(node)
45
- node.send_type? && node.method?(:object_id)
46
- end
47
51
  end
48
52
  end
49
53
  end
@@ -82,7 +82,7 @@ module RuboCop
82
82
  end
83
83
 
84
84
  def string_literal?(node)
85
- node.str_type? || node.dstr_type?
85
+ node.type?(:str, :dstr)
86
86
  end
87
87
 
88
88
  def string_literals?(node1, node2)
@@ -24,14 +24,17 @@ module RuboCop
24
24
  MSG = 'Interpolation in single quoted string detected. ' \
25
25
  'Use double quoted strings if you need interpolation.'
26
26
 
27
+ # rubocop:disable Metrics/CyclomaticComplexity
27
28
  def on_str(node)
28
29
  return if node.parent&.regexp_type?
29
30
  return unless /(?<!\\)#\{.*\}/.match?(node.source)
30
31
  return if heredoc?(node)
31
32
  return unless node.loc.begin && node.loc.end
33
+ return unless valid_syntax?(node)
32
34
 
33
35
  add_offense(node) { |corrector| autocorrect(corrector, node) }
34
36
  end
37
+ # rubocop:enable Metrics/CyclomaticComplexity
35
38
 
36
39
  private
37
40
 
@@ -49,6 +52,12 @@ module RuboCop
49
52
  def heredoc?(node)
50
53
  node.loc.is_a?(Parser::Source::Map::Heredoc) || (node.parent && heredoc?(node.parent))
51
54
  end
55
+
56
+ def valid_syntax?(node)
57
+ double_quoted_string = node.source.gsub(/\A'|'\z/, '"')
58
+
59
+ parse(double_quoted_string).valid_syntax?
60
+ end
52
61
  end
53
62
  end
54
63
  end
@@ -26,6 +26,9 @@ module RuboCop
26
26
  #
27
27
  class ItWithoutArgumentsInBlock < Base
28
28
  include NodePattern::Macros
29
+ extend TargetRubyVersion
30
+
31
+ maximum_target_ruby_version 3.3
29
32
 
30
33
  MSG = '`it` calls without arguments will refer to the first block param in Ruby 3.4; ' \
31
34
  'use `it()` or `self.it`.'
@@ -18,12 +18,15 @@ module RuboCop
18
18
  # end
19
19
  #
20
20
  # # bad
21
- # if some_var && true
21
+ # # We're only interested in the left hand side being a truthy literal,
22
+ # # because it affects the evaluation of the &&, whereas the right hand
23
+ # # side will be conditionally executed/called and can be a literal.
24
+ # if true && some_var
22
25
  # do_something
23
26
  # end
24
27
  #
25
28
  # # good
26
- # if some_var && some_condition
29
+ # if some_var
27
30
  # do_something
28
31
  # end
29
32
  #
@@ -34,26 +37,90 @@ module RuboCop
34
37
  # end
35
38
  class LiteralAsCondition < Base
36
39
  include RangeHelp
40
+ extend AutoCorrector
37
41
 
38
42
  MSG = 'Literal `%<literal>s` appeared as a condition.'
43
+ RESTRICT_ON_SEND = [:!].freeze
44
+
45
+ def on_and(node)
46
+ return unless node.lhs.truthy_literal?
47
+
48
+ add_offense(node.lhs) do |corrector|
49
+ # Don't autocorrect `'foo' && return` because having `return` as
50
+ # the leftmost node can lead to a void value expression syntax error.
51
+ next if node.rhs.type?(:return, :break, :next)
52
+
53
+ corrector.replace(node, node.rhs.source)
54
+ end
55
+ end
39
56
 
40
57
  def on_if(node)
41
- check_for_literal(node)
58
+ cond = condition(node)
59
+
60
+ return unless cond.falsey_literal? || cond.truthy_literal?
61
+
62
+ correct_if_node(node, cond)
42
63
  end
43
64
 
44
65
  def on_while(node)
45
- return if condition(node).true_type?
66
+ return if node.condition.source == 'true'
46
67
 
47
- check_for_literal(node)
68
+ if node.condition.truthy_literal?
69
+ add_offense(node.condition) do |corrector|
70
+ corrector.replace(node.condition, 'true')
71
+ end
72
+ elsif node.condition.falsey_literal?
73
+ add_offense(node.condition) do |corrector|
74
+ corrector.remove(node)
75
+ end
76
+ end
77
+ end
78
+
79
+ # rubocop:disable Metrics/AbcSize
80
+ def on_while_post(node)
81
+ return if node.condition.source == 'true'
82
+
83
+ if node.condition.truthy_literal?
84
+ add_offense(node.condition) do |corrector|
85
+ corrector.replace(node, node.source.sub(node.condition.source, 'true'))
86
+ end
87
+ elsif node.condition.falsey_literal?
88
+ add_offense(node.condition) do |corrector|
89
+ corrector.replace(node, node.body.child_nodes.map(&:source).join("\n"))
90
+ end
91
+ end
48
92
  end
49
- alias on_while_post on_while
93
+ # rubocop:enable Metrics/AbcSize
50
94
 
51
95
  def on_until(node)
52
- return if condition(node).false_type?
96
+ return if node.condition.source == 'false'
53
97
 
54
- check_for_literal(node)
98
+ if node.condition.falsey_literal?
99
+ add_offense(node.condition) do |corrector|
100
+ corrector.replace(node.condition, 'false')
101
+ end
102
+ elsif node.condition.truthy_literal?
103
+ add_offense(node.condition) do |corrector|
104
+ corrector.remove(node)
105
+ end
106
+ end
107
+ end
108
+
109
+ # rubocop:disable Metrics/AbcSize
110
+ def on_until_post(node)
111
+ return if node.condition.source == 'false'
112
+
113
+ if node.condition.falsey_literal?
114
+ add_offense(node.condition) do |corrector|
115
+ corrector.replace(node, node.source.sub(node.condition.source, 'false'))
116
+ end
117
+ elsif node.condition.truthy_literal?
118
+ add_offense(node.condition) do |corrector|
119
+ corrector.replace(node, node.body.child_nodes.map(&:source).join("\n"))
120
+ end
121
+ end
55
122
  end
56
- alias on_until_post on_until
123
+ # rubocop:enable Metrics/AbcSize
57
124
 
58
125
  def on_case(case_node)
59
126
  if case_node.condition
@@ -129,6 +196,8 @@ module RuboCop
129
196
 
130
197
  def handle_node(node)
131
198
  if node.literal?
199
+ return if node.parent.and_type?
200
+
132
201
  add_offense(node)
133
202
  elsif %i[send and or begin].include?(node.type)
134
203
  check_node(node)
@@ -158,6 +227,38 @@ module RuboCop
158
227
  when_node.conditions.last.source_range.end_pos
159
228
  )
160
229
  end
230
+
231
+ def condition_evaluation?(node, cond)
232
+ if node.unless?
233
+ cond.falsey_literal?
234
+ else
235
+ cond.truthy_literal?
236
+ end
237
+ end
238
+
239
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
240
+ def correct_if_node(node, cond)
241
+ result = condition_evaluation?(node, cond)
242
+
243
+ new_node = if node.elsif? && result
244
+ "else\n #{range_with_comments(node.if_branch).source}"
245
+ elsif node.elsif? && !result
246
+ "else\n #{node.else_branch.source}"
247
+ elsif node.if_branch && result
248
+ node.if_branch.source
249
+ elsif node.elsif_conditional?
250
+ "#{node.else_branch.source.sub('elsif', 'if')}\nend"
251
+ elsif node.else? || node.ternary?
252
+ node.else_branch.source
253
+ else
254
+ '' # Equivalent to removing the node
255
+ end
256
+
257
+ add_offense(cond) do |corrector|
258
+ corrector.replace(node, new_node)
259
+ end
260
+ end
261
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
161
262
  end
162
263
  end
163
264
  end
@@ -40,7 +40,7 @@ module RuboCop
40
40
  traverse_node(node.condition) do |asgn_node|
41
41
  next unless asgn_node.loc.operator
42
42
 
43
- rhs = asgn_node.to_a.last
43
+ rhs = asgn_node.rhs
44
44
  next if !all_literals?(rhs) || parallel_assignment_with_splat_operator?(rhs)
45
45
 
46
46
  range = offense_range(asgn_node, rhs)
@@ -5,6 +5,9 @@ module RuboCop
5
5
  module Lint
6
6
  # Checks for interpolated literals.
7
7
  #
8
+ # NOTE: Array literals interpolated in regexps are not handled by this cop, but
9
+ # by `Lint/ArrayLiteralInRegexp` instead.
10
+ #
8
11
  # @example
9
12
  #
10
13
  # # bad
@@ -21,6 +24,7 @@ module RuboCop
21
24
  MSG = 'Literal interpolation detected.'
22
25
  COMPOSITE = %i[array hash pair irange erange].freeze
23
26
 
27
+ # rubocop:disable Metrics/AbcSize
24
28
  def on_interpolation(begin_node)
25
29
  final_node = begin_node.children.last
26
30
  return unless offending?(final_node)
@@ -35,11 +39,18 @@ module RuboCop
35
39
  return if in_array_percent_literal?(begin_node) && /\s|\A\z/.match?(expanded_value)
36
40
 
37
41
  add_offense(final_node) do |corrector|
38
- return if final_node.dstr_type? # nested, fixed in next iteration
42
+ next if final_node.dstr_type? # nested, fixed in next iteration
43
+
44
+ replacement = if final_node.str_type? && !final_node.value.valid_encoding?
45
+ final_node.source.delete_prefix('"').delete_suffix('"')
46
+ else
47
+ expanded_value
48
+ end
39
49
 
40
- corrector.replace(final_node.parent, expanded_value)
50
+ corrector.replace(final_node.parent, replacement)
41
51
  end
42
52
  end
53
+ # rubocop:enable Metrics/AbcSize
43
54
 
44
55
  private
45
56
 
@@ -47,8 +58,10 @@ module RuboCop
47
58
  node &&
48
59
  !special_keyword?(node) &&
49
60
  prints_as_self?(node) &&
50
- # Special case for Layout/TrailingWhitespace
51
- !(space_literal?(node) && ends_heredoc_line?(node))
61
+ # Special case for `Layout/TrailingWhitespace`
62
+ !(space_literal?(node) && ends_heredoc_line?(node)) &&
63
+ # Handled by `Lint/ArrayLiteralInRegexp`
64
+ !array_in_regexp?(node)
52
65
  end
53
66
 
54
67
  def special_keyword?(node)
@@ -56,6 +69,11 @@ module RuboCop
56
69
  (node.str_type? && !node.loc.respond_to?(:begin)) || node.source_range.is?('__LINE__')
57
70
  end
58
71
 
72
+ def array_in_regexp?(node)
73
+ grandparent = node.parent.parent
74
+ node.array_type? && grandparent.regexp_type?
75
+ end
76
+
59
77
  # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
60
78
  def autocorrected_value(node)
61
79
  case node.type
@@ -168,7 +186,7 @@ module RuboCop
168
186
  end
169
187
 
170
188
  def space_literal?(node)
171
- node.str_type? && node.value.blank?
189
+ node.str_type? && node.value.valid_encoding? && node.value.blank?
172
190
  end
173
191
 
174
192
  def ends_heredoc_line?(node)
@@ -181,7 +199,7 @@ module RuboCop
181
199
 
182
200
  def in_array_percent_literal?(node)
183
201
  parent = node.parent
184
- return false unless parent.dstr_type? || parent.dsym_type?
202
+ return false unless parent.type?(:dstr, :dsym)
185
203
 
186
204
  grandparent = parent.parent
187
205
  grandparent&.array_type? && grandparent.percent_literal?
@@ -52,7 +52,7 @@ module RuboCop
52
52
  each_missing_enable do |cop, line_range|
53
53
  next if acceptable_range?(cop, line_range)
54
54
 
55
- range = source_range(processed_source.buffer, line_range.min, (0..0))
55
+ range = source_range(processed_source.buffer, line_range.min, 0..0)
56
56
  comment = processed_source.comment_at_line(line_range.begin)
57
57
 
58
58
  add_offense(range, message: message(cop, comment))
@@ -97,7 +97,7 @@ module RuboCop
97
97
 
98
98
  # @!method class_new_block(node)
99
99
  def_node_matcher :class_new_block, <<~RUBY
100
- ({block numblock}
100
+ (any_block
101
101
  (send
102
102
  (const {nil? cbase} :Class) :new $_) ...)
103
103
  RUBY
@@ -135,7 +135,7 @@ module RuboCop
135
135
  end
136
136
 
137
137
  def inside_class_with_stateful_parent?(node)
138
- if (block_node = node.each_ancestor(:block, :numblock).first)
138
+ if (block_node = node.each_ancestor(:any_block).first)
139
139
  return false unless (super_class = class_new_block(block_node))
140
140
 
141
141
  !allowed_class?(super_class)
@@ -8,7 +8,7 @@ module RuboCop
8
8
  # Offenses are registered for regexp character classes like `/[A-z]/`
9
9
  # as well as range objects like `('A'..'z')`.
10
10
  #
11
- # NOTE: Range objects cannot be autocorrected.
11
+ # NOTE: `Range` objects cannot be autocorrected.
12
12
  #
13
13
  # @safety
14
14
  # The cop autocorrects regexp character classes
@@ -36,12 +36,9 @@ module RuboCop
36
36
 
37
37
  def on_irange(node)
38
38
  return unless node.children.compact.all?(&:str_type?)
39
+ return if node.begin.nil? || node.end.nil?
39
40
 
40
- range_start, range_end = node.children
41
-
42
- return if range_start.nil? || range_end.nil?
43
-
44
- add_offense(node) if unsafe_range?(range_start.value, range_end.value)
41
+ add_offense(node) if unsafe_range?(node.begin.value, node.end.value)
45
42
  end
46
43
  alias on_erange on_irange
47
44
 
@@ -82,7 +79,7 @@ module RuboCop
82
79
  end
83
80
 
84
81
  def range_pairs(expr)
85
- RuboCop::Cop::Utils::RegexpRanges.new(expr).pairs
82
+ expr.expressions.filter_map { |e| [e.expressions[0], e.expressions[1]] if e.type == :set }
86
83
  end
87
84
 
88
85
  def unsafe_range?(range_start, range_end)
@@ -97,7 +94,7 @@ module RuboCop
97
94
 
98
95
  def skip_range?(range_start, range_end)
99
96
  [range_start, range_end].any? do |bound|
100
- bound.type != :literal
97
+ bound&.type != :literal
101
98
  end
102
99
  end
103
100
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Do not mix named captures and numbered captures in a Regexp literal
6
+ # Do not mix named captures and numbered captures in a `Regexp` literal
7
7
  # because numbered capture is ignored if they're mixed.
8
8
  # Replace numbered captures with non-capturing groupings or
9
9
  # named captures.