rubocop 1.65.1 → 1.75.6

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 (507) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +72 -72
  4. data/config/default.yml +299 -55
  5. data/config/internal_affairs.yml +31 -0
  6. data/config/obsoletion.yml +3 -1
  7. data/exe/rubocop +4 -3
  8. data/lib/rubocop/cached_data.rb +12 -4
  9. data/lib/rubocop/cli/command/auto_generate_config.rb +6 -7
  10. data/lib/rubocop/cli/command/execute_runner.rb +4 -4
  11. data/lib/rubocop/cli/command/lsp.rb +2 -2
  12. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  13. data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
  14. data/lib/rubocop/cli/command/version.rb +2 -2
  15. data/lib/rubocop/cli.rb +1 -1
  16. data/lib/rubocop/comment_config.rb +3 -3
  17. data/lib/rubocop/config.rb +57 -11
  18. data/lib/rubocop/config_loader.rb +66 -17
  19. data/lib/rubocop/config_loader_resolver.rb +39 -14
  20. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -3
  21. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  22. data/lib/rubocop/config_obsoletion.rb +46 -2
  23. data/lib/rubocop/config_validator.rb +27 -15
  24. data/lib/rubocop/cop/autocorrect_logic.rb +36 -19
  25. data/lib/rubocop/cop/base.rb +17 -3
  26. data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
  27. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  28. data/lib/rubocop/cop/bundler/gem_filename.rb +0 -1
  29. data/lib/rubocop/cop/bundler/gem_version.rb +1 -0
  30. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +0 -1
  31. data/lib/rubocop/cop/cop.rb +8 -0
  32. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -12
  33. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +1 -1
  34. data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -0
  35. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
  36. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
  37. data/lib/rubocop/cop/documentation.rb +18 -1
  38. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
  39. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
  40. data/lib/rubocop/cop/generator.rb +6 -0
  41. data/lib/rubocop/cop/internal_affairs/cop_description.rb +0 -4
  42. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  43. data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +2 -1
  44. data/lib/rubocop/cop/internal_affairs/example_description.rb +8 -4
  45. data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
  46. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  47. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -4
  48. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  49. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -2
  50. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  51. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  52. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +230 -0
  53. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +91 -0
  54. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  55. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  56. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
  57. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  58. data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +48 -0
  59. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  60. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  61. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +6 -21
  62. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +11 -2
  63. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  64. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
  65. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +23 -2
  66. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +0 -5
  67. data/lib/rubocop/cop/internal_affairs.rb +7 -0
  68. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +6 -2
  69. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -9
  70. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  71. data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
  72. data/lib/rubocop/cop/layout/block_alignment.rb +32 -13
  73. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  74. data/lib/rubocop/cop/layout/class_structure.rb +9 -9
  75. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +4 -4
  76. data/lib/rubocop/cop/layout/def_end_alignment.rb +2 -2
  77. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  78. data/lib/rubocop/cop/layout/else_alignment.rb +2 -2
  79. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +4 -4
  80. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +9 -12
  81. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +30 -4
  82. data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
  83. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
  84. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +12 -8
  85. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +23 -1
  86. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  87. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  88. data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
  89. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -10
  90. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  91. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  92. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +8 -0
  93. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  94. data/lib/rubocop/cop/layout/hash_alignment.rb +8 -6
  95. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
  96. data/lib/rubocop/cop/layout/indentation_width.rb +12 -12
  97. data/lib/rubocop/cop/layout/leading_comment_space.rb +83 -1
  98. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +11 -2
  99. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  100. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  101. data/lib/rubocop/cop/layout/line_length.rb +135 -16
  102. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
  103. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  104. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  105. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +2 -1
  106. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
  107. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
  108. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  109. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +3 -4
  110. data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
  111. data/lib/rubocop/cop/layout/redundant_line_break.rb +19 -46
  112. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +6 -7
  113. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  114. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  115. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  116. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  117. data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
  118. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -1
  119. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  120. data/lib/rubocop/cop/layout/space_around_operators.rb +23 -21
  121. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
  122. data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -5
  123. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  124. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  125. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +11 -1
  126. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +5 -0
  127. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +7 -0
  128. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
  129. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  130. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  131. data/lib/rubocop/cop/lint/ambiguous_range.rb +4 -1
  132. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +118 -0
  133. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  134. data/lib/rubocop/cop/lint/big_decimal_new.rb +4 -7
  135. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +10 -12
  136. data/lib/rubocop/cop/lint/boolean_symbol.rb +2 -2
  137. data/lib/rubocop/cop/lint/circular_argument_reference.rb +4 -1
  138. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  139. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  140. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
  141. data/lib/rubocop/cop/lint/debugger.rb +3 -3
  142. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  143. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +3 -2
  144. data/lib/rubocop/cop/lint/duplicate_branch.rb +39 -4
  145. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  146. data/lib/rubocop/cop/lint/duplicate_methods.rb +46 -19
  147. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  148. data/lib/rubocop/cop/lint/duplicate_set_element.rb +87 -0
  149. data/lib/rubocop/cop/lint/empty_conditional_body.rb +29 -58
  150. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
  151. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  152. data/lib/rubocop/cop/lint/empty_file.rb +0 -2
  153. data/lib/rubocop/cop/lint/ensure_return.rb +1 -4
  154. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -7
  155. data/lib/rubocop/cop/lint/float_comparison.rb +21 -17
  156. data/lib/rubocop/cop/lint/float_out_of_range.rb +2 -4
  157. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  158. data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
  159. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +13 -5
  160. data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
  161. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +8 -14
  162. data/lib/rubocop/cop/lint/literal_as_condition.rb +118 -9
  163. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  164. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +49 -8
  165. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
  166. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  167. data/lib/rubocop/cop/lint/mixed_case_range.rb +5 -8
  168. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  169. data/lib/rubocop/cop/lint/nested_method_definition.rb +10 -6
  170. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  171. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
  172. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +12 -3
  173. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -3
  174. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
  175. data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
  176. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
  177. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +93 -0
  178. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -3
  179. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +3 -2
  180. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +6 -11
  181. data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
  182. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  183. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  184. data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
  185. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +13 -8
  186. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
  187. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  188. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +261 -0
  189. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  190. data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
  191. data/lib/rubocop/cop/lint/refinement_import_methods.rb +1 -1
  192. data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
  193. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  194. data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
  195. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  196. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -1
  197. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +109 -41
  198. data/lib/rubocop/cop/lint/self_assignment.rb +8 -10
  199. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  200. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +8 -1
  201. data/lib/rubocop/cop/lint/shared_mutable_default.rb +76 -0
  202. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  203. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
  204. data/lib/rubocop/cop/lint/symbol_conversion.rb +2 -2
  205. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  206. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
  207. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  208. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +88 -0
  209. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +3 -1
  210. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  211. data/lib/rubocop/cop/lint/unreachable_code.rb +52 -2
  212. data/lib/rubocop/cop/lint/unreachable_loop.rb +6 -6
  213. data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
  214. data/lib/rubocop/cop/lint/uri_regexp.rb +25 -7
  215. data/lib/rubocop/cop/lint/useless_access_modifier.rb +5 -4
  216. data/lib/rubocop/cop/lint/useless_assignment.rb +20 -11
  217. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +71 -0
  218. data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
  219. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +4 -0
  220. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  221. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +78 -0
  222. data/lib/rubocop/cop/lint/useless_rescue.rb +2 -2
  223. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  224. data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
  225. data/lib/rubocop/cop/lint/void.rb +40 -14
  226. data/lib/rubocop/cop/message_annotator.rb +7 -3
  227. data/lib/rubocop/cop/metrics/block_length.rb +7 -5
  228. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  229. data/lib/rubocop/cop/metrics/class_length.rb +15 -14
  230. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  231. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +5 -2
  232. data/lib/rubocop/cop/metrics/method_length.rb +15 -6
  233. data/lib/rubocop/cop/metrics/module_length.rb +7 -6
  234. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  235. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  236. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +3 -4
  237. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  238. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  239. data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
  240. data/lib/rubocop/cop/mixin/annotation_comment.rb +0 -2
  241. data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
  242. data/lib/rubocop/cop/mixin/check_line_breakable.rb +22 -12
  243. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
  244. data/lib/rubocop/cop/mixin/comments_help.rb +8 -3
  245. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  246. data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
  247. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  248. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
  249. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  250. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
  251. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +22 -11
  252. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
  253. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
  254. data/lib/rubocop/cop/mixin/hash_subset.rb +203 -0
  255. data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
  256. data/lib/rubocop/cop/mixin/line_length_help.rb +12 -6
  257. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  258. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +7 -9
  259. data/lib/rubocop/cop/mixin/percent_array.rb +1 -1
  260. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  261. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +68 -30
  262. data/lib/rubocop/cop/mixin/range_help.rb +15 -4
  263. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  264. data/lib/rubocop/cop/mixin/statement_modifier.rb +11 -5
  265. data/lib/rubocop/cop/mixin/string_help.rb +2 -2
  266. data/lib/rubocop/cop/mixin/string_literals_help.rb +12 -0
  267. data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
  268. data/lib/rubocop/cop/mixin/trailing_comma.rb +21 -5
  269. data/lib/rubocop/cop/naming/accessor_method_name.rb +11 -6
  270. data/lib/rubocop/cop/naming/block_forwarding.rb +20 -16
  271. data/lib/rubocop/cop/naming/constant_name.rb +6 -7
  272. data/lib/rubocop/cop/naming/file_name.rb +0 -2
  273. data/lib/rubocop/cop/naming/inclusive_language.rb +12 -3
  274. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +12 -13
  275. data/lib/rubocop/cop/naming/method_name.rb +64 -8
  276. data/lib/rubocop/cop/naming/predicate_name.rb +46 -2
  277. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +6 -14
  278. data/lib/rubocop/cop/naming/variable_name.rb +50 -6
  279. data/lib/rubocop/cop/naming/variable_number.rb +2 -3
  280. data/lib/rubocop/cop/offense.rb +4 -5
  281. data/lib/rubocop/cop/registry.rb +9 -6
  282. data/lib/rubocop/cop/security/compound_hash.rb +2 -0
  283. data/lib/rubocop/cop/security/yaml_load.rb +3 -2
  284. data/lib/rubocop/cop/style/access_modifier_declarations.rb +96 -28
  285. data/lib/rubocop/cop/style/accessor_grouping.rb +29 -7
  286. data/lib/rubocop/cop/style/alias.rb +1 -1
  287. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +79 -0
  288. data/lib/rubocop/cop/style/and_or.rb +1 -1
  289. data/lib/rubocop/cop/style/arguments_forwarding.rb +94 -30
  290. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  291. data/lib/rubocop/cop/style/array_intersect.rb +42 -30
  292. data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
  293. data/lib/rubocop/cop/style/block_delimiters.rb +51 -20
  294. data/lib/rubocop/cop/style/case_like_if.rb +8 -11
  295. data/lib/rubocop/cop/style/class_and_module_children.rb +52 -11
  296. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  297. data/lib/rubocop/cop/style/collection_compact.rb +10 -10
  298. data/lib/rubocop/cop/style/collection_methods.rb +2 -1
  299. data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
  300. data/lib/rubocop/cop/style/combinable_loops.rb +10 -2
  301. data/lib/rubocop/cop/style/commented_keyword.rb +25 -2
  302. data/lib/rubocop/cop/style/comparable_between.rb +78 -0
  303. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  304. data/lib/rubocop/cop/style/conditional_assignment.rb +40 -28
  305. data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
  306. data/lib/rubocop/cop/style/data_inheritance.rb +8 -1
  307. data/lib/rubocop/cop/style/dig_chain.rb +89 -0
  308. data/lib/rubocop/cop/style/documentation.rb +1 -1
  309. data/lib/rubocop/cop/style/double_negation.rb +4 -4
  310. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  311. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  312. data/lib/rubocop/cop/style/empty_else.rb +10 -7
  313. data/lib/rubocop/cop/style/empty_heredoc.rb +1 -14
  314. data/lib/rubocop/cop/style/empty_literal.rb +35 -22
  315. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  316. data/lib/rubocop/cop/style/endless_method.rb +150 -18
  317. data/lib/rubocop/cop/style/eval_with_location.rb +5 -5
  318. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -3
  319. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  320. data/lib/rubocop/cop/style/explicit_block_argument.rb +16 -3
  321. data/lib/rubocop/cop/style/exponential_notation.rb +3 -3
  322. data/lib/rubocop/cop/style/fetch_env_var.rb +2 -1
  323. data/lib/rubocop/cop/style/file_null.rb +89 -0
  324. data/lib/rubocop/cop/style/file_touch.rb +75 -0
  325. data/lib/rubocop/cop/style/float_division.rb +8 -4
  326. data/lib/rubocop/cop/style/for.rb +1 -1
  327. data/lib/rubocop/cop/style/format_string_token.rb +38 -11
  328. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  329. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  330. data/lib/rubocop/cop/style/global_vars.rb +1 -3
  331. data/lib/rubocop/cop/style/guard_clause.rb +20 -4
  332. data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
  333. data/lib/rubocop/cop/style/hash_each_methods.rb +12 -8
  334. data/lib/rubocop/cop/style/hash_except.rb +35 -147
  335. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  336. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  337. data/lib/rubocop/cop/style/hash_syntax.rb +11 -5
  338. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  339. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  340. data/lib/rubocop/cop/style/identical_conditional_branches.rb +26 -7
  341. data/lib/rubocop/cop/style/if_inside_else.rb +11 -15
  342. data/lib/rubocop/cop/style/if_unless_modifier.rb +25 -5
  343. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +3 -4
  344. data/lib/rubocop/cop/style/if_with_semicolon.rb +60 -6
  345. data/lib/rubocop/cop/style/in_pattern_then.rb +6 -2
  346. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  347. data/lib/rubocop/cop/style/inverse_methods.rb +15 -12
  348. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  349. data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
  350. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  351. data/lib/rubocop/cop/style/it_block_parameter.rb +100 -0
  352. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
  353. data/lib/rubocop/cop/style/keyword_parameters_order.rb +14 -8
  354. data/lib/rubocop/cop/style/lambda.rb +2 -1
  355. data/lib/rubocop/cop/style/lambda_call.rb +10 -4
  356. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  357. data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
  358. data/lib/rubocop/cop/style/map_into_array.rb +75 -14
  359. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  360. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  361. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +38 -23
  362. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  363. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +10 -13
  364. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
  365. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  366. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  367. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
  368. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -2
  369. data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
  370. data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
  371. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
  372. data/lib/rubocop/cop/style/multiple_comparison.rb +53 -60
  373. data/lib/rubocop/cop/style/mutable_constant.rb +7 -8
  374. data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -5
  375. data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
  376. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -2
  377. data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
  378. data/lib/rubocop/cop/style/next.rb +44 -0
  379. data/lib/rubocop/cop/style/not.rb +1 -1
  380. data/lib/rubocop/cop/style/numeric_predicate.rb +2 -2
  381. data/lib/rubocop/cop/style/object_then.rb +15 -15
  382. data/lib/rubocop/cop/style/one_line_conditional.rb +30 -5
  383. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  384. data/lib/rubocop/cop/style/operator_method_call.rb +25 -7
  385. data/lib/rubocop/cop/style/or_assignment.rb +3 -6
  386. data/lib/rubocop/cop/style/parallel_assignment.rb +14 -22
  387. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  388. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  389. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  390. data/lib/rubocop/cop/style/proc.rb +2 -2
  391. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -3
  392. data/lib/rubocop/cop/style/raise_args.rb +15 -13
  393. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  394. data/lib/rubocop/cop/style/redundant_argument.rb +3 -1
  395. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
  396. data/lib/rubocop/cop/style/redundant_begin.rb +6 -1
  397. data/lib/rubocop/cop/style/redundant_condition.rb +97 -24
  398. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +16 -5
  399. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  400. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  401. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  402. data/lib/rubocop/cop/style/redundant_format.rb +257 -0
  403. data/lib/rubocop/cop/style/redundant_freeze.rb +3 -3
  404. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  405. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +46 -0
  406. data/lib/rubocop/cop/style/redundant_line_continuation.rb +56 -20
  407. data/lib/rubocop/cop/style/redundant_parentheses.rb +57 -27
  408. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +8 -1
  409. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  410. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  411. data/lib/rubocop/cop/style/redundant_return.rb +2 -2
  412. data/lib/rubocop/cop/style/redundant_self.rb +9 -15
  413. data/lib/rubocop/cop/style/redundant_self_assignment.rb +20 -32
  414. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
  415. data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
  416. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  417. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  418. data/lib/rubocop/cop/style/require_order.rb +1 -1
  419. data/lib/rubocop/cop/style/rescue_modifier.rb +18 -4
  420. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  421. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +54 -12
  422. data/lib/rubocop/cop/style/safe_navigation.rb +123 -54
  423. data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
  424. data/lib/rubocop/cop/style/select_by_regexp.rb +14 -8
  425. data/lib/rubocop/cop/style/self_assignment.rb +11 -17
  426. data/lib/rubocop/cop/style/semicolon.rb +2 -2
  427. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  428. data/lib/rubocop/cop/style/signal_exception.rb +2 -3
  429. data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
  430. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  431. data/lib/rubocop/cop/style/single_line_do_end_block.rb +15 -4
  432. data/lib/rubocop/cop/style/single_line_methods.rb +6 -7
  433. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  434. data/lib/rubocop/cop/style/sole_nested_conditional.rb +42 -106
  435. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  436. data/lib/rubocop/cop/style/string_concatenation.rb +15 -15
  437. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  438. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  439. data/lib/rubocop/cop/style/struct_inheritance.rb +9 -2
  440. data/lib/rubocop/cop/style/super_arguments.rb +66 -19
  441. data/lib/rubocop/cop/style/swap_values.rb +4 -15
  442. data/lib/rubocop/cop/style/symbol_proc.rb +2 -0
  443. data/lib/rubocop/cop/style/ternary_parentheses.rb +26 -5
  444. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -1
  445. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +11 -2
  446. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  447. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  448. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
  449. data/lib/rubocop/cop/style/trivial_accessors.rb +2 -2
  450. data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
  451. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  452. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  453. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  454. data/lib/rubocop/cop/team.rb +14 -3
  455. data/lib/rubocop/cop/util.rb +12 -5
  456. data/lib/rubocop/cop/utils/format_string.rb +10 -5
  457. data/lib/rubocop/cop/variable_force/assignment.rb +18 -3
  458. data/lib/rubocop/cop/variable_force/branch.rb +1 -1
  459. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  460. data/lib/rubocop/cop/variable_force/variable.rb +14 -3
  461. data/lib/rubocop/cop/variable_force/variable_table.rb +5 -5
  462. data/lib/rubocop/cop/variable_force.rb +5 -11
  463. data/lib/rubocop/cops_documentation_generator.rb +117 -53
  464. data/lib/rubocop/directive_comment.rb +45 -11
  465. data/lib/rubocop/ext/regexp_node.rb +0 -1
  466. data/lib/rubocop/file_finder.rb +9 -4
  467. data/lib/rubocop/formatter/disabled_config_formatter.rb +3 -2
  468. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  469. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  470. data/lib/rubocop/formatter/junit_formatter.rb +70 -23
  471. data/lib/rubocop/formatter/pacman_formatter.rb +1 -1
  472. data/lib/rubocop/lockfile.rb +6 -4
  473. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  474. data/lib/rubocop/lsp/logger.rb +2 -2
  475. data/lib/rubocop/lsp/routes.rb +7 -23
  476. data/lib/rubocop/lsp/runtime.rb +19 -49
  477. data/lib/rubocop/lsp/server.rb +0 -3
  478. data/lib/rubocop/lsp/stdin_runner.rb +85 -0
  479. data/lib/rubocop/magic_comment.rb +11 -3
  480. data/lib/rubocop/options.rb +28 -12
  481. data/lib/rubocop/path_util.rb +15 -8
  482. data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
  483. data/lib/rubocop/plugin/load_error.rb +26 -0
  484. data/lib/rubocop/plugin/loader.rb +100 -0
  485. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  486. data/lib/rubocop/plugin.rb +46 -0
  487. data/lib/rubocop/rake_task.rb +4 -1
  488. data/lib/rubocop/remote_config.rb +5 -1
  489. data/lib/rubocop/result_cache.rb +15 -21
  490. data/lib/rubocop/rspec/cop_helper.rb +13 -1
  491. data/lib/rubocop/rspec/expect_offense.rb +7 -2
  492. data/lib/rubocop/rspec/shared_contexts.rb +40 -3
  493. data/lib/rubocop/rspec/support.rb +4 -2
  494. data/lib/rubocop/runner.rb +27 -13
  495. data/lib/rubocop/server/cache.rb +52 -11
  496. data/lib/rubocop/server/cli.rb +2 -2
  497. data/lib/rubocop/server/core.rb +1 -0
  498. data/lib/rubocop/target_finder.rb +7 -2
  499. data/lib/rubocop/target_ruby.rb +36 -17
  500. data/lib/rubocop/version.rb +54 -11
  501. data/lib/rubocop/yaml_duplication_checker.rb +20 -26
  502. data/lib/rubocop.rb +36 -2
  503. data/lib/ruby_lsp/rubocop/addon.rb +75 -0
  504. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +65 -0
  505. metadata +83 -40
  506. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  507. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -0,0 +1,257 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for calls to `Kernel#format` or `Kernel#sprintf` that are redundant.
7
+ #
8
+ # Calling `format` with only a single string or constant argument is redundant,
9
+ # as it can be replaced by the string or constant itself.
10
+ #
11
+ # Also looks for `format` calls where the arguments are literals that can be
12
+ # inlined into a string easily. This applies to the `%s`, `%d`, `%i`, `%u`, and
13
+ # `%f` format specifiers.
14
+ #
15
+ # @safety
16
+ # This cop's autocorrection is unsafe because string object returned by
17
+ # `format` and `sprintf` are never frozen. If `format('string')` is autocorrected to
18
+ # `'string'`, `FrozenError` may occur when calling a destructive method like `String#<<`.
19
+ # Consider using `'string'.dup` instead of `format('string')`.
20
+ # Additionally, since the necessity of `dup` cannot be determined automatically,
21
+ # this autocorrection is inherently unsafe.
22
+ #
23
+ # [source,ruby]
24
+ # ----
25
+ # # frozen_string_literal: true
26
+ #
27
+ # format('template').frozen? # => false
28
+ # 'template'.frozen? # => true
29
+ # ----
30
+ #
31
+ # @example
32
+ #
33
+ # # bad
34
+ # format('the quick brown fox jumps over the lazy dog.')
35
+ # sprintf('the quick brown fox jumps over the lazy dog.')
36
+ #
37
+ # # good
38
+ # 'the quick brown fox jumps over the lazy dog.'
39
+ #
40
+ # # bad
41
+ # format(MESSAGE)
42
+ # sprintf(MESSAGE)
43
+ #
44
+ # # good
45
+ # MESSAGE
46
+ #
47
+ # # bad
48
+ # format('%s %s', 'foo', 'bar')
49
+ # sprintf('%s %s', 'foo', 'bar')
50
+ #
51
+ # # good
52
+ # 'foo bar'
53
+ #
54
+ class RedundantFormat < Base
55
+ extend AutoCorrector
56
+
57
+ MSG = 'Use `%<prefer>s` directly instead of `%<method_name>s`.'
58
+
59
+ RESTRICT_ON_SEND = %i[format sprintf].to_set.freeze
60
+ ACCEPTABLE_LITERAL_TYPES = %i[str dstr sym dsym numeric boolean nil].freeze
61
+
62
+ # @!method format_without_additional_args?(node)
63
+ def_node_matcher :format_without_additional_args?, <<~PATTERN
64
+ (send {(const {nil? cbase} :Kernel) nil?} %RESTRICT_ON_SEND ${str dstr const})
65
+ PATTERN
66
+
67
+ # @!method rational_number?(node)
68
+ def_node_matcher :rational_number?, <<~PATTERN
69
+ {rational (send int :/ rational) (begin rational) (begin (send int :/ rational))}
70
+ PATTERN
71
+
72
+ # @!method complex_number?(node)
73
+ def_node_matcher :complex_number?, <<~PATTERN
74
+ {complex (send int :+ complex) (begin complex) (begin (send int :+ complex))}
75
+ PATTERN
76
+
77
+ # @!method find_hash_value_node(node, name)
78
+ def_node_search :find_hash_value_node, <<~PATTERN
79
+ (pair (sym %1) $_)
80
+ PATTERN
81
+
82
+ # @!method splatted_arguments?(node)
83
+ def_node_matcher :splatted_arguments?, <<~PATTERN
84
+ (send _ %RESTRICT_ON_SEND <{
85
+ splat
86
+ (hash <kwsplat ...>)
87
+ } ...>)
88
+ PATTERN
89
+
90
+ def on_send(node)
91
+ format_without_additional_args?(node) do |value|
92
+ replacement = value.source
93
+
94
+ add_offense(node, message: message(node, replacement)) do |corrector|
95
+ corrector.replace(node, replacement)
96
+ end
97
+ return
98
+ end
99
+
100
+ detect_unnecessary_fields(node)
101
+ end
102
+
103
+ private
104
+
105
+ def message(node, prefer)
106
+ format(MSG, prefer: prefer, method_name: node.method_name)
107
+ end
108
+
109
+ def detect_unnecessary_fields(node)
110
+ return unless node.first_argument&.str_type?
111
+
112
+ string = node.first_argument.value
113
+ arguments = node.arguments[1..]
114
+
115
+ return unless string && arguments.any?
116
+ return if splatted_arguments?(node)
117
+
118
+ register_all_fields_literal(node, string, arguments)
119
+ end
120
+
121
+ def register_all_fields_literal(node, string, arguments)
122
+ return unless all_fields_literal?(string, arguments.dup)
123
+
124
+ formatted_string = format(string, *argument_values(arguments))
125
+ replacement = quote(formatted_string, node)
126
+
127
+ add_offense(node, message: message(node, replacement)) do |corrector|
128
+ corrector.replace(node, replacement)
129
+ end
130
+ end
131
+
132
+ def all_fields_literal?(string, arguments)
133
+ count = 0
134
+ sequences = RuboCop::Cop::Utils::FormatString.new(string).format_sequences
135
+ return false unless sequences.any?
136
+
137
+ sequences.each do |sequence|
138
+ next if sequence.percent?
139
+
140
+ hash = arguments.detect(&:hash_type?)
141
+ next unless (argument = find_argument(sequence, arguments, hash))
142
+ next unless matching_argument?(sequence, argument)
143
+
144
+ count += 1
145
+ end
146
+
147
+ sequences.size == count
148
+ end
149
+
150
+ def find_argument(sequence, arguments, hash)
151
+ if hash && (sequence.annotated? || sequence.template?)
152
+ find_hash_value_node(hash, sequence.name.to_sym).first
153
+ elsif sequence.arg_number
154
+ arguments[sequence.arg_number.to_i - 1]
155
+ else
156
+ # If the specifier contains `*`, the following arguments will be used
157
+ # to specify the width and can be ignored.
158
+ (sequence.arity - 1).times { arguments.shift }
159
+ arguments.shift
160
+ end
161
+ end
162
+
163
+ def matching_argument?(sequence, argument)
164
+ # Template specifiers don't give a type, any acceptable literal type is ok.
165
+ return argument.type?(*ACCEPTABLE_LITERAL_TYPES) if sequence.template?
166
+
167
+ # An argument matches a specifier if it can be easily converted
168
+ # to that type.
169
+ case sequence.type
170
+ when 's'
171
+ argument.type?(*ACCEPTABLE_LITERAL_TYPES)
172
+ when 'd', 'i', 'u'
173
+ integer?(argument)
174
+ when 'f'
175
+ float?(argument)
176
+ else
177
+ false
178
+ end
179
+ end
180
+
181
+ def numeric?(argument)
182
+ argument.type?(:numeric, :str) ||
183
+ rational_number?(argument) ||
184
+ complex_number?(argument)
185
+ end
186
+
187
+ def integer?(argument)
188
+ numeric?(argument) && Integer(argument_value(argument), exception: false)
189
+ end
190
+
191
+ def float?(argument)
192
+ numeric?(argument) && Float(argument_value(argument), exception: false)
193
+ end
194
+
195
+ # Add correct quotes to the formatted string, preferring retaining the existing
196
+ # quotes if possible.
197
+ def quote(string, node)
198
+ str_node = node.first_argument
199
+ start_delimiter = str_node.loc.begin.source
200
+ end_delimiter = str_node.loc.end.source
201
+
202
+ # If there is any interpolation, the delimiters need to be changed potentially
203
+ if node.each_descendant(:dstr, :dsym).any?
204
+ case start_delimiter
205
+ when "'"
206
+ start_delimiter = end_delimiter = '"'
207
+ when /\A%q(.)/
208
+ start_delimiter = "%Q#{Regexp.last_match[1]}"
209
+ end
210
+ end
211
+
212
+ "#{start_delimiter}#{string}#{end_delimiter}"
213
+ end
214
+
215
+ def argument_values(arguments)
216
+ arguments.map { |argument| argument_value(argument) }
217
+ end
218
+
219
+ def argument_value(argument)
220
+ argument = argument.children.first if argument.begin_type?
221
+
222
+ if argument.dsym_type?
223
+ dsym_value(argument)
224
+ elsif argument.hash_type?
225
+ hash_value(argument)
226
+ elsif rational_number?(argument)
227
+ rational_value(argument)
228
+ elsif complex_number?(argument)
229
+ complex_value(argument)
230
+ elsif argument.respond_to?(:value)
231
+ argument.value
232
+ else
233
+ argument.source
234
+ end
235
+ end
236
+
237
+ def dsym_value(dsym_node)
238
+ dsym_node.children.first.source
239
+ end
240
+
241
+ def hash_value(hash_node)
242
+ hash_node.each_pair.with_object({}) do |pair, hash|
243
+ hash[pair.key.value] = argument_value(pair.value)
244
+ end
245
+ end
246
+
247
+ def rational_value(rational_node)
248
+ rational_node.source.to_r
249
+ end
250
+
251
+ def complex_value(complex_node)
252
+ Complex(complex_node.source)
253
+ end
254
+ end
255
+ end
256
+ end
257
+ end
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Style
6
6
  # Check for uses of `Object#freeze` on immutable objects.
7
7
  #
8
- # NOTE: Regexp and Range literals are frozen objects since Ruby 3.0.
8
+ # NOTE: `Regexp` and `Range` literals are frozen objects since Ruby 3.0.
9
9
  #
10
10
  # NOTE: From Ruby 3.0, this cop allows explicit freezing of interpolated
11
11
  # string literals when `# frozen-string-literal: true` is used.
@@ -42,7 +42,7 @@ module RuboCop
42
42
  return true if node.immutable_literal?
43
43
  return true if frozen_string_literal?(node)
44
44
 
45
- target_ruby_version >= 3.0 && (node.regexp_type? || node.range_type?)
45
+ target_ruby_version >= 3.0 && node.type?(:regexp, :range)
46
46
  end
47
47
 
48
48
  def strip_parenthesis(node)
@@ -60,7 +60,7 @@ module RuboCop
60
60
  (begin (send !{(str _) array} {:+ :- :* :** :/ :%} {float int}))
61
61
  (begin (send _ {:== :=== :!= :<= :>= :< :>} _))
62
62
  (send _ {:count :length :size} ...)
63
- (block (send _ {:count :length :size} ...) ...)
63
+ (any_block (send _ {:count :length :size} ...) ...)
64
64
  }
65
65
  PATTERN
66
66
  end
@@ -11,6 +11,9 @@ module RuboCop
11
11
  # will not register an offense, because it allows the initializer to take a different
12
12
  # number of arguments as its superclass potentially does.
13
13
  #
14
+ # NOTE: If an initializer takes any arguments and has an empty body, RuboCop
15
+ # assumes it to *not* be redundant. This is to prevent potential `ArgumentError`.
16
+ #
14
17
  # NOTE: If an initializer argument has a default value, RuboCop assumes it
15
18
  # to *not* be redundant.
16
19
  #
@@ -19,8 +22,10 @@ module RuboCop
19
22
  # initializer.
20
23
  #
21
24
  # @safety
22
- # This cop is unsafe because if subclass overrides `initialize` method with
23
- # a different arity than superclass.
25
+ # This cop is unsafe because removing an empty initializer may alter
26
+ # the behavior of the code, particularly if the superclass initializer
27
+ # raises an exception. In such cases, the empty initializer may act as
28
+ # a safeguard to prevent unintended errors from propagating.
24
29
  #
25
30
  # @example
26
31
  # # bad
@@ -69,6 +74,10 @@ module RuboCop
69
74
  # end
70
75
  #
71
76
  # # good (changes the parameter requirements)
77
+ # def initialize(_)
78
+ # end
79
+ #
80
+ # # good (changes the parameter requirements)
72
81
  # def initialize(*)
73
82
  # end
74
83
  #
@@ -111,7 +120,7 @@ module RuboCop
111
120
  return if acceptable?(node)
112
121
 
113
122
  if node.body.nil?
114
- register_offense(node, MSG_EMPTY)
123
+ register_offense(node, MSG_EMPTY) if node.arguments.empty?
115
124
  else
116
125
  return if node.body.begin_type?
117
126
 
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Before Ruby 3.0, interpolated strings followed the frozen string literal
7
+ # magic comment which sometimes made it necessary to explicitly unfreeze them.
8
+ # Ruby 3.0 changed interpolated strings to always be unfrozen which makes
9
+ # unfreezing them redundant.
10
+ #
11
+ # @example
12
+ # # bad
13
+ # +"#{foo} bar"
14
+ #
15
+ # # bad
16
+ # "#{foo} bar".dup
17
+ #
18
+ # # good
19
+ # "#{foo} bar"
20
+ #
21
+ class RedundantInterpolationUnfreeze < Base
22
+ include FrozenStringLiteral
23
+ extend AutoCorrector
24
+ extend TargetRubyVersion
25
+
26
+ MSG = "Don't unfreeze interpolated strings as they are already unfrozen."
27
+
28
+ RESTRICT_ON_SEND = %i[+@ dup].freeze
29
+
30
+ minimum_target_ruby_version 3.0
31
+
32
+ def on_send(node)
33
+ return if node.arguments?
34
+ return unless (receiver = node.receiver)
35
+ return unless receiver.dstr_type?
36
+ return if uninterpolated_string?(receiver) || uninterpolated_heredoc?(receiver)
37
+
38
+ add_offense(node.loc.selector) do |corrector|
39
+ corrector.remove(node.loc.selector)
40
+ corrector.remove(node.loc.dot) unless node.unary_operation?
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -69,17 +69,24 @@ module RuboCop
69
69
  extend AutoCorrector
70
70
 
71
71
  MSG = 'Redundant line continuation.'
72
+ LINE_CONTINUATION = '\\'
73
+ LINE_CONTINUATION_PATTERN = /(\\\n)/.freeze
72
74
  ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
73
75
  ARGUMENT_TYPES = %i[
74
- kFALSE kNIL kSELF kTRUE tCONSTANT tCVAR tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR
75
- tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
76
+ kDEF kDEFINED kFALSE kNIL kSELF kTRUE tAMPER tBANG tCARET tCHARACTER tCOLON3 tCONSTANT
77
+ tCVAR tDOT2 tDOT3 tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR tLAMBDA tLBRACK tLCURLY
78
+ tLPAREN_ARG tPIPE tQSYMBOLS_BEG tQWORDS_BEG tREGEXP_BEG tSTAR tSTRING tSTRING_BEG tSYMBEG
79
+ tSYMBOL tSYMBOLS_BEG tTILDE tUMINUS tUNARY_NUM tUPLUS tWORDS_BEG tXSTRING_BEG
76
80
  ].freeze
77
- ARGUMENT_TAKING_FLOW_TOKEN_TYPES = %i[tIDENTIFIER kRETURN kBREAK kNEXT kYIELD].freeze
81
+ ARGUMENT_TAKING_FLOW_TOKEN_TYPES = %i[
82
+ tIDENTIFIER kBREAK kNEXT kRETURN kSUPER kYIELD
83
+ ].freeze
84
+ ARITHMETIC_OPERATOR_TOKENS = %i[tDIVIDE tDSTAR tMINUS tPERCENT tPLUS tSTAR2].freeze
78
85
 
79
86
  def on_new_investigation
80
87
  return unless processed_source.ast
81
88
 
82
- each_match_range(processed_source.ast.source_range, /(\\\n)/) do |range|
89
+ each_match_range(processed_source.ast.source_range, LINE_CONTINUATION_PATTERN) do |range|
83
90
  next if require_line_continuation?(range)
84
91
  next unless redundant_line_continuation?(range)
85
92
 
@@ -87,20 +94,27 @@ module RuboCop
87
94
  corrector.remove_leading(range, 1)
88
95
  end
89
96
  end
97
+
98
+ inspect_end_of_ruby_code_line_continuation
90
99
  end
91
100
 
92
101
  private
93
102
 
94
103
  def require_line_continuation?(range)
95
- !ends_with_backslash_without_comment?(range.source_line) ||
104
+ !ends_with_uncommented_backslash?(range) ||
96
105
  string_concatenation?(range.source_line) ||
97
- start_with_arithmetic_operator?(processed_source[range.line]) ||
106
+ start_with_arithmetic_operator?(range) ||
98
107
  inside_string_literal_or_method_with_argument?(range) ||
99
108
  leading_dot_method_chain_with_blank_line?(range)
100
109
  end
101
110
 
102
- def ends_with_backslash_without_comment?(source_line)
103
- source_line.gsub(/#.+/, '').end_with?('\\')
111
+ def ends_with_uncommented_backslash?(range)
112
+ # A line continuation always needs to be the last character on the line, which
113
+ # means that it is impossible to have a comment following a continuation.
114
+ # Therefore, if the line contains a comment, it cannot end with a continuation.
115
+ return false if processed_source.line_with_comment?(range.line)
116
+
117
+ range.source_line.end_with?(LINE_CONTINUATION)
104
118
  end
105
119
 
106
120
  def string_concatenation?(source_line)
@@ -108,10 +122,13 @@ module RuboCop
108
122
  end
109
123
 
110
124
  def inside_string_literal_or_method_with_argument?(range)
125
+ line_range = range_by_whole_lines(range)
126
+
111
127
  processed_source.tokens.each_cons(2).any? do |token, next_token|
112
128
  next if token.line == next_token.line
113
129
 
114
- inside_string_literal?(range, token) || method_with_argument?(token, next_token)
130
+ inside_string_literal?(range, token) ||
131
+ method_with_argument?(line_range, token, next_token)
115
132
  end
116
133
  end
117
134
 
@@ -122,11 +139,31 @@ module RuboCop
122
139
  end
123
140
 
124
141
  def redundant_line_continuation?(range)
125
- return true unless (node = find_node_for_line(range.line))
142
+ return true unless (node = find_node_for_line(range.last_line))
126
143
  return false if argument_newline?(node)
127
144
 
128
- source = node.parent ? node.parent.source : node.source
129
- parse(source.gsub("\\\n", "\n")).valid_syntax?
145
+ # Check if source is still valid without the continuation
146
+ source = processed_source.raw_source.dup
147
+ source[range.begin_pos, range.length] = "\n"
148
+ parse(source).valid_syntax?
149
+ end
150
+
151
+ def inspect_end_of_ruby_code_line_continuation
152
+ last_line = processed_source.lines[processed_source.ast.last_line - 1]
153
+ return unless code_ends_with_continuation?(last_line)
154
+
155
+ last_column = last_line.length
156
+ line_continuation_range = range_between(last_column - 1, last_column)
157
+
158
+ add_offense(line_continuation_range) do |corrector|
159
+ corrector.remove_trailing(line_continuation_range, 1)
160
+ end
161
+ end
162
+
163
+ def code_ends_with_continuation?(last_line)
164
+ return false if processed_source.line_with_comment?(processed_source.ast.last_line)
165
+
166
+ last_line.end_with?(LINE_CONTINUATION)
130
167
  end
131
168
 
132
169
  def inside_string_literal?(range, token)
@@ -137,15 +174,14 @@ module RuboCop
137
174
  #
138
175
  # do_something \
139
176
  # argument
140
- def method_with_argument?(current_token, next_token)
177
+ def method_with_argument?(line_range, current_token, next_token)
141
178
  return false unless ARGUMENT_TAKING_FLOW_TOKEN_TYPES.include?(current_token.type)
179
+ return false unless current_token.pos.overlaps?(line_range)
142
180
 
143
181
  ARGUMENT_TYPES.include?(next_token.type)
144
182
  end
145
183
 
146
- # rubocop:disable Metrics/AbcSize
147
184
  def argument_newline?(node)
148
- node = node.to_a.last if node.assignment?
149
185
  return false if node.parenthesized_call?
150
186
 
151
187
  node = node.children.first if node.root? && node.begin_type?
@@ -158,11 +194,10 @@ module RuboCop
158
194
  node.loc.selector.line != node.first_argument.loc.line
159
195
  end
160
196
  end
161
- # rubocop:enable Metrics/AbcSize
162
197
 
163
- def find_node_for_line(line)
198
+ def find_node_for_line(last_line)
164
199
  processed_source.ast.each_node do |node|
165
- return node if same_line?(node, line)
200
+ return node if same_line?(node, last_line)
166
201
  end
167
202
  end
168
203
 
@@ -191,8 +226,9 @@ module RuboCop
191
226
  node.call_type? && !node.arguments.empty?
192
227
  end
193
228
 
194
- def start_with_arithmetic_operator?(source_line)
195
- %r{\A\s*[+\-*/%]}.match?(source_line)
229
+ def start_with_arithmetic_operator?(range)
230
+ line_range = processed_source.buffer.line_range(range.line + 1)
231
+ ARITHMETIC_OPERATOR_TOKENS.include?(processed_source.first_token_of(line_range).type)
196
232
  end
197
233
  end
198
234
  end