rubocop 1.48.1 → 1.62.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (386) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +7 -5
  4. data/assets/output.css.erb +159 -0
  5. data/assets/output.html.erb +1 -160
  6. data/config/default.yml +217 -35
  7. data/config/obsoletion.yml +5 -0
  8. data/lib/rubocop/cli/command/auto_generate_config.rb +22 -8
  9. data/lib/rubocop/cli/command/execute_runner.rb +7 -2
  10. data/lib/rubocop/cli/command/lsp.rb +19 -0
  11. data/lib/rubocop/cli.rb +16 -8
  12. data/lib/rubocop/config.rb +9 -3
  13. data/lib/rubocop/config_finder.rb +14 -4
  14. data/lib/rubocop/config_loader.rb +8 -9
  15. data/lib/rubocop/config_loader_resolver.rb +4 -3
  16. data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
  17. data/lib/rubocop/config_obsoletion.rb +13 -10
  18. data/lib/rubocop/config_validator.rb +14 -7
  19. data/lib/rubocop/cop/autocorrect_logic.rb +36 -13
  20. data/lib/rubocop/cop/base.rb +23 -4
  21. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -0
  22. data/lib/rubocop/cop/bundler/duplicated_group.rb +127 -0
  23. data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
  24. data/lib/rubocop/cop/bundler/gem_version.rb +2 -2
  25. data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
  26. data/lib/rubocop/cop/cop.rb +2 -2
  27. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
  28. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
  29. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +5 -13
  30. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
  31. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
  32. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  33. data/lib/rubocop/cop/exclude_limit.rb +1 -1
  34. data/lib/rubocop/cop/gemspec/dependency_version.rb +2 -2
  35. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +3 -3
  36. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  37. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
  38. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +5 -1
  39. data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
  40. data/lib/rubocop/cop/internal_affairs/cop_description.rb +33 -9
  41. data/lib/rubocop/cop/internal_affairs/example_description.rb +45 -24
  42. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +2 -2
  43. data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +1 -1
  44. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -1
  45. data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
  46. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +19 -20
  47. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
  48. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +127 -33
  49. data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
  50. data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
  51. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +29 -2
  52. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
  53. data/lib/rubocop/cop/internal_affairs.rb +2 -0
  54. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  55. data/lib/rubocop/cop/layout/class_structure.rb +8 -0
  56. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -2
  57. data/lib/rubocop/cop/layout/dot_position.rb +1 -5
  58. data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
  59. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +42 -9
  60. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +14 -7
  61. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +27 -4
  62. data/lib/rubocop/cop/layout/empty_lines.rb +1 -1
  63. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +2 -0
  64. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
  65. data/lib/rubocop/cop/layout/end_alignment.rb +20 -4
  66. data/lib/rubocop/cop/layout/extra_spacing.rb +3 -4
  67. data/lib/rubocop/cop/layout/first_argument_indentation.rb +6 -1
  68. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +22 -7
  69. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +25 -34
  70. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +7 -19
  71. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +42 -52
  72. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +38 -55
  73. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  74. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +6 -6
  75. data/lib/rubocop/cop/layout/heredoc_indentation.rb +4 -1
  76. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  77. data/lib/rubocop/cop/layout/indentation_width.rb +3 -3
  78. data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
  79. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  80. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +17 -9
  81. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  82. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -0
  83. data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +8 -27
  84. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +7 -26
  85. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +4 -21
  86. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
  87. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +6 -30
  88. data/lib/rubocop/cop/layout/redundant_line_break.rb +33 -11
  89. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -4
  90. data/lib/rubocop/cop/layout/single_line_block_chain.rb +5 -0
  91. data/lib/rubocop/cop/layout/space_after_comma.rb +9 -1
  92. data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
  93. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +2 -2
  94. data/lib/rubocop/cop/layout/space_around_operators.rb +53 -21
  95. data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
  96. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
  97. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -0
  98. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
  99. data/lib/rubocop/cop/layout/space_inside_parens.rb +3 -3
  100. data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
  101. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +5 -0
  102. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +13 -1
  103. data/lib/rubocop/cop/lint/assignment_in_condition.rb +4 -4
  104. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
  105. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
  106. data/lib/rubocop/cop/lint/debugger.rb +19 -5
  107. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +3 -3
  108. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +2 -1
  109. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +122 -0
  110. data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
  111. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +46 -19
  112. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  113. data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
  114. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  115. data/lib/rubocop/cop/lint/erb_new_arguments.rb +6 -7
  116. data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
  117. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
  118. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +1 -1
  119. data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
  120. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -3
  121. data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
  122. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
  123. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  124. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +85 -0
  125. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  126. data/lib/rubocop/cop/lint/missing_super.rb +34 -5
  127. data/lib/rubocop/cop/lint/mixed_case_range.rb +111 -0
  128. data/lib/rubocop/cop/lint/nested_method_definition.rb +2 -2
  129. data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
  130. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -7
  131. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -5
  132. data/lib/rubocop/cop/lint/number_conversion.rb +14 -4
  133. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
  134. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
  135. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -2
  136. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +1 -1
  137. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +130 -0
  138. data/lib/rubocop/cop/lint/redundant_require_statement.rb +12 -3
  139. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +72 -8
  140. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +35 -15
  141. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -2
  142. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  143. data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
  144. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +14 -8
  145. data/lib/rubocop/cop/lint/script_permission.rb +3 -3
  146. data/lib/rubocop/cop/lint/self_assignment.rb +38 -0
  147. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -2
  148. data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
  149. data/lib/rubocop/cop/lint/shadowed_exception.rb +5 -11
  150. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +7 -1
  151. data/lib/rubocop/cop/lint/struct_new_override.rb +12 -12
  152. data/lib/rubocop/cop/lint/suppressed_exception.rb +2 -2
  153. data/lib/rubocop/cop/lint/symbol_conversion.rb +8 -3
  154. data/lib/rubocop/cop/lint/syntax.rb +6 -3
  155. data/lib/rubocop/cop/lint/to_enum_arguments.rb +19 -6
  156. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
  157. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
  158. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
  159. data/lib/rubocop/cop/lint/unreachable_loop.rb +3 -3
  160. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  161. data/lib/rubocop/cop/lint/useless_assignment.rb +94 -10
  162. data/lib/rubocop/cop/lint/useless_method_definition.rb +10 -2
  163. data/lib/rubocop/cop/lint/useless_times.rb +2 -2
  164. data/lib/rubocop/cop/lint/void.rb +104 -14
  165. data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
  166. data/lib/rubocop/cop/metrics/block_length.rb +1 -1
  167. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  168. data/lib/rubocop/cop/metrics/class_length.rb +8 -2
  169. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  170. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -2
  171. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +31 -3
  172. data/lib/rubocop/cop/migration/department_name.rb +2 -2
  173. data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
  174. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  175. data/lib/rubocop/cop/mixin/comments_help.rb +19 -11
  176. data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -0
  177. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  178. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
  179. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +14 -11
  180. data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
  181. data/lib/rubocop/cop/mixin/heredoc.rb +6 -2
  182. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +4 -3
  183. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  184. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -8
  185. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  186. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  187. data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
  188. data/lib/rubocop/cop/mixin/string_help.rb +4 -2
  189. data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
  190. data/lib/rubocop/cop/naming/ascii_identifiers.rb +1 -1
  191. data/lib/rubocop/cop/naming/block_forwarding.rb +13 -5
  192. data/lib/rubocop/cop/naming/constant_name.rb +2 -3
  193. data/lib/rubocop/cop/naming/file_name.rb +1 -1
  194. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +3 -1
  195. data/lib/rubocop/cop/naming/inclusive_language.rb +23 -4
  196. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +26 -11
  197. data/lib/rubocop/cop/naming/predicate_name.rb +2 -2
  198. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -3
  199. data/lib/rubocop/cop/naming/variable_name.rb +6 -1
  200. data/lib/rubocop/cop/registry.rb +1 -1
  201. data/lib/rubocop/cop/security/open.rb +2 -2
  202. data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -2
  203. data/lib/rubocop/cop/style/accessor_grouping.rb +6 -2
  204. data/lib/rubocop/cop/style/alias.rb +9 -8
  205. data/lib/rubocop/cop/style/arguments_forwarding.rb +411 -63
  206. data/lib/rubocop/cop/style/array_first_last.rb +64 -0
  207. data/lib/rubocop/cop/style/array_intersect.rb +13 -5
  208. data/lib/rubocop/cop/style/attr.rb +11 -1
  209. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
  210. data/lib/rubocop/cop/style/begin_block.rb +1 -2
  211. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
  212. data/lib/rubocop/cop/style/block_comments.rb +1 -1
  213. data/lib/rubocop/cop/style/block_delimiters.rb +5 -4
  214. data/lib/rubocop/cop/style/case_like_if.rb +5 -5
  215. data/lib/rubocop/cop/style/class_and_module_children.rb +2 -2
  216. data/lib/rubocop/cop/style/class_check.rb +1 -0
  217. data/lib/rubocop/cop/style/class_equality_comparison.rb +58 -40
  218. data/lib/rubocop/cop/style/class_vars.rb +3 -3
  219. data/lib/rubocop/cop/style/collection_compact.rb +35 -12
  220. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  221. data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
  222. data/lib/rubocop/cop/style/combinable_loops.rb +36 -8
  223. data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
  224. data/lib/rubocop/cop/style/concat_array_literals.rb +2 -1
  225. data/lib/rubocop/cop/style/conditional_assignment.rb +11 -10
  226. data/lib/rubocop/cop/style/copyright.rb +6 -3
  227. data/lib/rubocop/cop/style/data_inheritance.rb +75 -0
  228. data/lib/rubocop/cop/style/date_time.rb +5 -4
  229. data/lib/rubocop/cop/style/dir.rb +1 -1
  230. data/lib/rubocop/cop/style/dir_empty.rb +8 -14
  231. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +2 -2
  232. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +2 -2
  233. data/lib/rubocop/cop/style/documentation.rb +1 -1
  234. data/lib/rubocop/cop/style/double_negation.rb +2 -2
  235. data/lib/rubocop/cop/style/each_for_simple_loop.rb +7 -7
  236. data/lib/rubocop/cop/style/each_with_object.rb +2 -2
  237. data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
  238. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  239. data/lib/rubocop/cop/style/eval_with_location.rb +8 -19
  240. data/lib/rubocop/cop/style/exact_regexp_match.rb +69 -0
  241. data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
  242. data/lib/rubocop/cop/style/file_empty.rb +3 -3
  243. data/lib/rubocop/cop/style/file_read.rb +2 -2
  244. data/lib/rubocop/cop/style/for.rb +3 -1
  245. data/lib/rubocop/cop/style/format_string.rb +24 -3
  246. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +4 -2
  247. data/lib/rubocop/cop/style/guard_clause.rb +28 -0
  248. data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
  249. data/lib/rubocop/cop/style/hash_each_methods.rb +106 -33
  250. data/lib/rubocop/cop/style/hash_except.rb +25 -13
  251. data/lib/rubocop/cop/style/hash_syntax.rb +9 -2
  252. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  253. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  254. data/lib/rubocop/cop/style/identical_conditional_branches.rb +34 -5
  255. data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
  256. data/lib/rubocop/cop/style/if_unless_modifier.rb +41 -12
  257. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  258. data/lib/rubocop/cop/style/inverse_methods.rb +14 -13
  259. data/lib/rubocop/cop/style/invertible_unless_condition.rb +54 -8
  260. data/lib/rubocop/cop/style/lambda.rb +3 -3
  261. data/lib/rubocop/cop/style/lambda_call.rb +5 -0
  262. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +8 -10
  263. data/lib/rubocop/cop/style/map_to_hash.rb +19 -6
  264. data/lib/rubocop/cop/style/map_to_set.rb +4 -1
  265. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +27 -16
  266. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +45 -40
  267. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +20 -0
  268. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  269. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
  270. data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
  271. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  272. data/lib/rubocop/cop/style/multiline_method_signature.rb +16 -4
  273. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +6 -4
  274. data/lib/rubocop/cop/style/multiple_comparison.rb +14 -0
  275. data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
  276. data/lib/rubocop/cop/style/next.rb +1 -1
  277. data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
  278. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +1 -1
  279. data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
  280. data/lib/rubocop/cop/style/object_then.rb +5 -3
  281. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  282. data/lib/rubocop/cop/style/operator_method_call.rb +8 -2
  283. data/lib/rubocop/cop/style/parallel_assignment.rb +29 -23
  284. data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -0
  285. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -3
  286. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  287. data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
  288. data/lib/rubocop/cop/style/raise_args.rb +4 -1
  289. data/lib/rubocop/cop/style/redundant_argument.rb +10 -4
  290. data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
  291. data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
  292. data/lib/rubocop/cop/style/redundant_begin.rb +10 -2
  293. data/lib/rubocop/cop/style/redundant_conditional.rb +2 -10
  294. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +39 -0
  295. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +93 -5
  296. data/lib/rubocop/cop/style/redundant_each.rb +7 -4
  297. data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
  298. data/lib/rubocop/cop/style/redundant_fetch_block.rb +9 -7
  299. data/lib/rubocop/cop/style/redundant_filter_chain.rb +118 -0
  300. data/lib/rubocop/cop/style/redundant_line_continuation.rb +203 -0
  301. data/lib/rubocop/cop/style/redundant_parentheses.rb +72 -23
  302. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  303. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +100 -0
  304. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +2 -2
  305. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
  306. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +3 -2
  307. data/lib/rubocop/cop/style/redundant_return.rb +14 -3
  308. data/lib/rubocop/cop/style/redundant_self.rb +17 -2
  309. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +8 -1
  310. data/lib/rubocop/cop/style/redundant_sort.rb +10 -9
  311. data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
  312. data/lib/rubocop/cop/style/redundant_string_escape.rb +5 -4
  313. data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
  314. data/lib/rubocop/cop/style/require_order.rb +11 -5
  315. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
  316. data/lib/rubocop/cop/style/return_nil.rb +6 -2
  317. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +95 -0
  318. data/lib/rubocop/cop/style/sample.rb +3 -4
  319. data/lib/rubocop/cop/style/select_by_regexp.rb +22 -11
  320. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  321. data/lib/rubocop/cop/style/semicolon.rb +20 -4
  322. data/lib/rubocop/cop/style/signal_exception.rb +1 -1
  323. data/lib/rubocop/cop/style/single_argument_dig.rb +7 -3
  324. data/lib/rubocop/cop/style/single_line_do_end_block.rb +67 -0
  325. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  326. data/lib/rubocop/cop/style/slicing_with_range.rb +76 -10
  327. data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -4
  328. data/lib/rubocop/cop/style/special_global_vars.rb +3 -4
  329. data/lib/rubocop/cop/style/string_chars.rb +1 -0
  330. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
  331. data/lib/rubocop/cop/style/strip.rb +7 -4
  332. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  333. data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
  334. data/lib/rubocop/cop/style/symbol_array.rb +35 -15
  335. data/lib/rubocop/cop/style/symbol_proc.rb +36 -0
  336. data/lib/rubocop/cop/style/trailing_body_on_class.rb +1 -0
  337. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  338. data/lib/rubocop/cop/style/unless_logical_operators.rb +1 -0
  339. data/lib/rubocop/cop/style/unpack_first.rb +11 -14
  340. data/lib/rubocop/cop/style/yaml_file_read.rb +66 -0
  341. data/lib/rubocop/cop/style/yoda_condition.rb +4 -2
  342. data/lib/rubocop/cop/style/yoda_expression.rb +8 -7
  343. data/lib/rubocop/cop/team.rb +1 -1
  344. data/lib/rubocop/cop/util.rb +1 -1
  345. data/lib/rubocop/cop/utils/regexp_ranges.rb +113 -0
  346. data/lib/rubocop/cop/variable_force/assignment.rb +45 -4
  347. data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
  348. data/lib/rubocop/cop/variable_force.rb +1 -0
  349. data/lib/rubocop/cops_documentation_generator.rb +26 -7
  350. data/lib/rubocop/directive_comment.rb +10 -8
  351. data/lib/rubocop/ext/regexp_node.rb +10 -5
  352. data/lib/rubocop/ext/regexp_parser.rb +5 -2
  353. data/lib/rubocop/file_finder.rb +4 -7
  354. data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
  355. data/lib/rubocop/formatter/html_formatter.rb +35 -14
  356. data/lib/rubocop/formatter/json_formatter.rb +0 -1
  357. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  358. data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
  359. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
  360. data/lib/rubocop/formatter.rb +1 -1
  361. data/lib/rubocop/lsp/logger.rb +22 -0
  362. data/lib/rubocop/lsp/routes.rb +246 -0
  363. data/lib/rubocop/lsp/runtime.rb +99 -0
  364. data/lib/rubocop/lsp/server.rb +71 -0
  365. data/lib/rubocop/lsp/severity.rb +27 -0
  366. data/lib/rubocop/lsp.rb +29 -0
  367. data/lib/rubocop/magic_comment.rb +13 -11
  368. data/lib/rubocop/options.rb +26 -10
  369. data/lib/rubocop/path_util.rb +6 -2
  370. data/lib/rubocop/result_cache.rb +6 -3
  371. data/lib/rubocop/rspec/cop_helper.rb +8 -2
  372. data/lib/rubocop/rspec/expect_offense.rb +8 -8
  373. data/lib/rubocop/rspec/shared_contexts.rb +42 -18
  374. data/lib/rubocop/rspec/support.rb +2 -0
  375. data/lib/rubocop/runner.rb +15 -6
  376. data/lib/rubocop/server/cache.rb +1 -1
  377. data/lib/rubocop/server/client_command/exec.rb +3 -3
  378. data/lib/rubocop/server/helper.rb +1 -1
  379. data/lib/rubocop/server/server_command/exec.rb +1 -2
  380. data/lib/rubocop/string_interpreter.rb +3 -3
  381. data/lib/rubocop/target_finder.rb +91 -81
  382. data/lib/rubocop/target_ruby.rb +85 -78
  383. data/lib/rubocop/version.rb +27 -8
  384. data/lib/rubocop.rb +22 -0
  385. metadata +59 -14
  386. /data/lib/rubocop/formatter/{git_hub_actions_formatter.rb → github_actions_formatter.rb} +0 -0
@@ -4,6 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Lint
6
6
  # Checks for duplicated keys in hash literals.
7
+ # This cop considers both primitive types and constants for the hash keys.
7
8
  #
8
9
  # This cop mirrors a warning in Ruby 2.2.
9
10
  #
@@ -24,7 +25,7 @@ module RuboCop
24
25
  MSG = 'Duplicated key in hash literal.'
25
26
 
26
27
  def on_hash(node)
27
- keys = node.keys.select(&:recursive_basic_literal?)
28
+ keys = node.keys.select { |key| key.recursive_basic_literal? || key.const_type? }
28
29
 
29
30
  return unless duplicates?(keys)
30
31
 
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks that there are no repeated patterns used in `in` keywords.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # case x
12
+ # in 'first'
13
+ # do_something
14
+ # in 'first'
15
+ # do_something_else
16
+ # end
17
+ #
18
+ # # good
19
+ # case x
20
+ # in 'first'
21
+ # do_something
22
+ # in 'second'
23
+ # do_something_else
24
+ # end
25
+ #
26
+ # # bad - repeated alternate patterns with the same conditions don't depend on the order
27
+ # case x
28
+ # in foo | bar
29
+ # first_method
30
+ # in bar | foo
31
+ # second_method
32
+ # end
33
+ #
34
+ # # good
35
+ # case x
36
+ # in foo | bar
37
+ # first_method
38
+ # in bar | baz
39
+ # second_method
40
+ # end
41
+ #
42
+ # # bad - repeated hash patterns with the same conditions don't depend on the order
43
+ # case x
44
+ # in foo: a, bar: b
45
+ # first_method
46
+ # in bar: b, foo: a
47
+ # second_method
48
+ # end
49
+ #
50
+ # # good
51
+ # case x
52
+ # in foo: a, bar: b
53
+ # first_method
54
+ # in bar: b, baz: c
55
+ # second_method
56
+ # end
57
+ #
58
+ # # bad - repeated array patterns with elements in the same order
59
+ # case x
60
+ # in [foo, bar]
61
+ # first_method
62
+ # in [foo, bar]
63
+ # second_method
64
+ # end
65
+ #
66
+ # # good
67
+ # case x
68
+ # in [foo, bar]
69
+ # first_method
70
+ # in [bar, foo]
71
+ # second_method
72
+ # end
73
+ #
74
+ # # bad - repeated the same patterns and guard conditions
75
+ # case x
76
+ # in foo if bar
77
+ # first_method
78
+ # in foo if bar
79
+ # second_method
80
+ # end
81
+ #
82
+ # # good
83
+ # case x
84
+ # in foo if bar
85
+ # first_method
86
+ # in foo if baz
87
+ # second_method
88
+ # end
89
+ #
90
+ class DuplicateMatchPattern < Base
91
+ extend TargetRubyVersion
92
+
93
+ MSG = 'Duplicate `in` pattern detected.'
94
+
95
+ minimum_target_ruby_version 2.7
96
+
97
+ def on_case_match(case_node)
98
+ case_node.in_pattern_branches.each_with_object(Set.new) do |in_pattern_node, previous|
99
+ pattern = in_pattern_node.pattern
100
+ next if previous.add?(pattern_identity(pattern))
101
+
102
+ add_offense(pattern)
103
+ end
104
+ end
105
+
106
+ private
107
+
108
+ def pattern_identity(pattern)
109
+ pattern_source = if pattern.hash_pattern_type? || pattern.match_alt_type?
110
+ pattern.children.map(&:source).sort.to_s
111
+ else
112
+ pattern.source
113
+ end
114
+
115
+ return pattern_source unless (guard = pattern.parent.children[1])
116
+
117
+ pattern_source + guard.source
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -253,7 +253,7 @@ module RuboCop
253
253
  # Assume that if a method definition is inside any block call which
254
254
  # we can't identify, it could be a DSL
255
255
  node.each_ancestor(:block).any? do |ancestor|
256
- ancestor.method_name != :class_eval && !ancestor.class_constructor?
256
+ !ancestor.method?(:class_eval) && !ancestor.class_constructor?
257
257
  end
258
258
  end
259
259
 
@@ -24,6 +24,8 @@ module RuboCop
24
24
 
25
25
  MSG_REPEATED_ELEMENT = 'Duplicate element inside regexp character class'
26
26
 
27
+ OCTAL_DIGITS_AFTER_ESCAPE = 2
28
+
27
29
  def on_regexp(node)
28
30
  each_repeated_character_class_element_loc(node) do |loc|
29
31
  add_offense(loc, message: MSG_REPEATED_ELEMENT) do |corrector|
@@ -32,35 +34,57 @@ module RuboCop
32
34
  end
33
35
  end
34
36
 
35
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
36
37
  def each_repeated_character_class_element_loc(node)
37
38
  node.parsed_tree&.each_expression do |expr|
38
39
  next if skip_expression?(expr)
39
40
 
40
41
  seen = Set.new
41
- enum = expr.expressions.to_enum
42
- expression_count = expr.expressions.count
42
+ group_expressions(node, expr.expressions) do |group|
43
+ group_source = group.map(&:to_s).join
43
44
 
44
- expression_count.times do |current_number|
45
- current_child = enum.next
46
- next if within_interpolation?(node, current_child)
45
+ yield source_range(group) if seen.include?(group_source)
47
46
 
48
- current_child_source = current_child.to_s
49
- next_child = enum.peek if current_number + 1 < expression_count
47
+ seen << group_source
48
+ end
49
+ end
50
+ end
50
51
 
51
- if seen.include?(current_child_source)
52
- next if start_with_escaped_zero_number?(current_child_source, next_child.to_s)
52
+ private
53
53
 
54
- yield current_child.expression
55
- end
54
+ def group_expressions(node, expressions)
55
+ # Create a mutable list to simplify state tracking while we iterate.
56
+ expressions = expressions.to_a
56
57
 
57
- seen << current_child_source
58
- end
58
+ until expressions.empty?
59
+ # With we may need to compose a group of multiple expressions.
60
+ group = [expressions.shift]
61
+ next if within_interpolation?(node, group.first)
62
+
63
+ # With regexp_parser < 2.7 escaped octal sequences may be up to 3
64
+ # separate expressions ("\\0", "0", "1").
65
+ pop_octal_digits(group, expressions) if escaped_octal?(group.first.to_s)
66
+
67
+ yield(group)
59
68
  end
60
69
  end
61
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
62
70
 
63
- private
71
+ def pop_octal_digits(current_child, expressions)
72
+ OCTAL_DIGITS_AFTER_ESCAPE.times do
73
+ next_child = expressions.first
74
+ break unless octal?(next_child.to_s)
75
+
76
+ current_child << expressions.shift
77
+ end
78
+ end
79
+
80
+ def source_range(children)
81
+ return children.first.expression if children.size == 1
82
+
83
+ range_between(
84
+ children.first.expression.begin_pos,
85
+ children.last.expression.begin_pos + children.last.to_s.length
86
+ )
87
+ end
64
88
 
65
89
  def skip_expression?(expr)
66
90
  expr.type != :set || expr.token == :intersection
@@ -75,9 +99,12 @@ module RuboCop
75
99
  interpolation_locs(node).any? { |il| il.overlaps?(parse_tree_child_loc) }
76
100
  end
77
101
 
78
- def start_with_escaped_zero_number?(current_child, next_child)
79
- # Represents escaped code from `"\00"` (`"\u0000"`) to `"\07"` (`"\a"`).
80
- current_child == '\\0' && next_child.match?(/[0-7]/)
102
+ def escaped_octal?(string)
103
+ string.length == 2 && string[0] == '\\' && octal?(string[1])
104
+ end
105
+
106
+ def octal?(char)
107
+ ('0'..'7').cover?(char)
81
108
  end
82
109
 
83
110
  def interpolation_locs(node)
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Lint
6
6
  # Checks for blocks without a body.
7
7
  # Such empty blocks are typically an oversight or we should provide a comment
8
- # be clearer what we're aiming for.
8
+ # to clarify what we're aiming for.
9
9
  #
10
10
  # Empty lambdas and procs are ignored by default.
11
11
  #
@@ -104,7 +104,7 @@ module RuboCop
104
104
  def correct_other_branches(corrector, node)
105
105
  return unless require_other_branches_correction?(node)
106
106
 
107
- if node.else_branch&.if_type?
107
+ if node.else_branch&.if_type? && !node.else_branch.modifier_form?
108
108
  # Replace an orphaned `elsif` with `if`
109
109
  corrector.replace(node.else_branch.loc.keyword, 'if')
110
110
  else
@@ -25,7 +25,7 @@ module RuboCop
25
25
  def on_interpolation(begin_node)
26
26
  return unless begin_node.children.empty?
27
27
 
28
- add_offense(begin_node) { |corrector| corrector.remove(begin_node.source_range) }
28
+ add_offense(begin_node) { |corrector| corrector.remove(begin_node) }
29
29
  end
30
30
  end
31
31
  end
@@ -3,14 +3,13 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- #
7
- # This cop emulates the following Ruby warnings in Ruby 2.6.
6
+ # Emulates the following Ruby warnings in Ruby 2.6.
8
7
  #
9
8
  # [source,console]
10
9
  # ----
11
- # % cat example.rb
10
+ # $ cat example.rb
12
11
  # ERB.new('hi', nil, '-', '@output_buffer')
13
- # % ruby -rerb example.rb
12
+ # $ ruby -rerb example.rb
14
13
  # example.rb:1: warning: Passing safe_level with the 2nd argument of ERB.new is
15
14
  # deprecated. Do not use it, and specify other arguments as keyword arguments.
16
15
  # example.rb:1: warning: Passing trim_mode with the 3rd argument of ERB.new is
@@ -107,7 +106,7 @@ module RuboCop
107
106
  private
108
107
 
109
108
  def autocorrect(corrector, node)
110
- str_arg = node.arguments[0].source
109
+ str_arg = node.first_argument.source
111
110
 
112
111
  kwargs = build_kwargs(node)
113
112
  overridden_kwargs = override_by_legacy_args(kwargs, node)
@@ -122,11 +121,11 @@ module RuboCop
122
121
  end
123
122
 
124
123
  def build_kwargs(node)
125
- return [nil, nil] unless node.arguments.last.hash_type?
124
+ return [nil, nil] unless node.last_argument.hash_type?
126
125
 
127
126
  trim_mode_arg, eoutvar_arg = nil
128
127
 
129
- node.arguments.last.pairs.each do |pair|
128
+ node.last_argument.pairs.each do |pair|
130
129
  case pair.key.source
131
130
  when 'trim_mode'
132
131
  trim_mode_arg = "trim_mode: #{pair.value.source}"
@@ -18,6 +18,10 @@ module RuboCop
18
18
  # # good - using BigDecimal
19
19
  # x.to_d == 0.1.to_d
20
20
  #
21
+ # # good - comparing against zero
22
+ # x == 0.0
23
+ # x != 0.0
24
+ #
21
25
  # # good
22
26
  # (x - 0.1).abs < Float::EPSILON
23
27
  #
@@ -39,6 +43,8 @@ module RuboCop
39
43
 
40
44
  def on_send(node)
41
45
  lhs, _method, rhs = *node
46
+ return if literal_zero?(lhs) || literal_zero?(rhs)
47
+
42
48
  add_offense(node) if float?(lhs) || float?(rhs)
43
49
  end
44
50
 
@@ -59,6 +65,10 @@ module RuboCop
59
65
  end
60
66
  end
61
67
 
68
+ def literal_zero?(node)
69
+ node&.numeric_type? && node.value.zero?
70
+ end
71
+
62
72
  # rubocop:disable Metrics/PerceivedComplexity
63
73
  def check_send(node)
64
74
  if node.arithmetic_operation?
@@ -35,12 +35,13 @@ module RuboCop
35
35
 
36
36
  # @!method id_as_hash_key?(node)
37
37
  def_node_matcher :id_as_hash_key?, <<~PATTERN
38
- (send _ {:key? :has_key? :fetch :[] :[]=} (send _ :object_id) ...)
38
+ (call _ {:key? :has_key? :fetch :[] :[]=} (send _ :object_id) ...)
39
39
  PATTERN
40
40
 
41
41
  def on_send(node)
42
42
  add_offense(node) if id_as_hash_key?(node)
43
43
  end
44
+ alias on_csend on_send
44
45
  end
45
46
  end
46
47
  end
@@ -65,7 +65,7 @@ module RuboCop
65
65
  end
66
66
 
67
67
  def send_node?(node)
68
- return nil unless node
68
+ return false unless node
69
69
 
70
70
  node.call_type?
71
71
  end
@@ -3,7 +3,6 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- #
7
6
  # Prefer `equal?` over `==` when comparing `object_id`.
8
7
  #
9
8
  # `Object#equal?` is provided to compare objects for identity, and in contrast
@@ -3,8 +3,10 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
+ # Checks for `IO.select` that is incompatible with Fiber Scheduler since Ruby 3.0.
6
7
  #
7
- # This cop checks for `IO.select` that is incompatible with Fiber Scheduler since Ruby 3.0.
8
+ # When an array of IO objects waiting for an exception (the third argument of `IO.select`)
9
+ # is used as an argument, there is no alternative API, so offenses are not registered.
8
10
  #
9
11
  # NOTE: When the method is successful the return value of `IO.select` is `[[IO]]`,
10
12
  # and the return value of `io.wait_readable` and `io.wait_writable` are `self`.
@@ -42,8 +44,8 @@ module RuboCop
42
44
  PATTERN
43
45
 
44
46
  def on_send(node)
45
- read, write, _excepts, timeout = *io_select(node)
46
- return unless read
47
+ read, write, excepts, timeout = *io_select(node)
48
+ return if excepts && !excepts.children.empty?
47
49
  return unless scheduler_compatible?(read, write) || scheduler_compatible?(write, read)
48
50
 
49
51
  preferred = preferred_method(read, write, timeout)
@@ -58,6 +58,7 @@ module RuboCop
58
58
 
59
59
  def on_class(node)
60
60
  return unless node.parent_class && exception_class?(node.parent_class)
61
+ return if inherit_exception_class_with_omitted_namespace?(node)
61
62
 
62
63
  message = message(node.parent_class)
63
64
 
@@ -87,6 +88,14 @@ module RuboCop
87
88
  class_node.const_name == 'Exception'
88
89
  end
89
90
 
91
+ def inherit_exception_class_with_omitted_namespace?(class_node)
92
+ return false if class_node.parent_class.namespace&.cbase_type?
93
+
94
+ class_node.left_siblings.any? do |sibling|
95
+ sibling.respond_to?(:identifier) && exception_class?(sibling.identifier)
96
+ end
97
+ end
98
+
90
99
  def preferred_base_class
91
100
  PREFERRED_BASE_CLASS[style]
92
101
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Emulates the following Ruby warning in Ruby 3.3.
7
+ #
8
+ # [source,ruby]
9
+ # ----
10
+ # $ ruby -e '0.times { it }'
11
+ # -e:1: warning: `it` calls without arguments will refer to the first block param in Ruby 3.4;
12
+ # use it() or self.it
13
+ # ----
14
+ #
15
+ # `it` calls without arguments will refer to the first block param in Ruby 3.4.
16
+ # So use `it()` or `self.it` to ensure compatibility.
17
+ #
18
+ # @example
19
+ #
20
+ # # bad
21
+ # do_something { it }
22
+ #
23
+ # # good
24
+ # do_something { it() }
25
+ # do_something { self.it }
26
+ #
27
+ class ItWithoutArgumentsInBlock < Base
28
+ include NodePattern::Macros
29
+
30
+ MSG = '`it` calls without arguments will refer to the first block param in Ruby 3.4; ' \
31
+ 'use `it()` or `self.it`.'
32
+
33
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
34
+ return unless (body = node.body)
35
+ return unless node.arguments.empty_and_without_delimiters?
36
+
37
+ if body.send_type? && deprecated_it_method?(body)
38
+ add_offense(body)
39
+ else
40
+ body.each_descendant(:send).each do |send_node|
41
+ next unless deprecated_it_method?(send_node)
42
+
43
+ add_offense(send_node)
44
+ end
45
+ end
46
+ end
47
+
48
+ def deprecated_it_method?(node)
49
+ return false unless node.method?(:it)
50
+
51
+ !node.receiver && node.arguments.empty? && !node.parenthesized? && !node.block_literal?
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # Checks uses of lambda without a literal block.
7
7
  # It emulates the following warning in Ruby 3.0:
8
8
  #
9
- # % ruby -vwe 'lambda(&proc {})'
9
+ # $ ruby -vwe 'lambda(&proc {})'
10
10
  # ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
11
11
  # -e:1: warning: lambda without a literal block is deprecated; use the proc without
12
12
  # lambda instead
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for literal assignments in the conditions of `if`, `while`, and `until`.
7
+ # It emulates the following Ruby warning:
8
+ #
9
+ # [source,console]
10
+ # ----
11
+ # $ ruby -we 'if x = true; end'
12
+ # -e:1: warning: found `= literal' in conditional, should be ==
13
+ # ----
14
+ #
15
+ # As a lint cop, it cannot be determined if `==` is appropriate as intended,
16
+ # therefore this cop does not provide autocorrection.
17
+ #
18
+ # @example
19
+ #
20
+ # # bad
21
+ # if x = 42
22
+ # do_something
23
+ # end
24
+ #
25
+ # # good
26
+ # if x == 42
27
+ # do_something
28
+ # end
29
+ #
30
+ # # good
31
+ # if x = y
32
+ # do_something
33
+ # end
34
+ #
35
+ class LiteralAssignmentInCondition < Base
36
+ MSG = "Don't use literal assignment `= %<literal>s` in conditional, " \
37
+ 'should be `==` or non-literal operand.'
38
+
39
+ def on_if(node)
40
+ traverse_node(node.condition) do |asgn_node|
41
+ next unless asgn_node.loc.operator
42
+
43
+ rhs = asgn_node.to_a.last
44
+ next if !all_literals?(rhs) || parallel_assignment_with_splat_operator?(rhs)
45
+
46
+ range = offense_range(asgn_node, rhs)
47
+
48
+ add_offense(range, message: format(MSG, literal: rhs.source))
49
+ end
50
+ end
51
+ alias on_while on_if
52
+ alias on_until on_if
53
+
54
+ private
55
+
56
+ def traverse_node(node, &block)
57
+ yield node if AST::Node::EQUALS_ASSIGNMENTS.include?(node.type)
58
+
59
+ node.each_child_node { |child| traverse_node(child, &block) }
60
+ end
61
+
62
+ def all_literals?(node)
63
+ case node.type
64
+ when :dstr, :xstr
65
+ false
66
+ when :array
67
+ node.values.all? { |value| all_literals?(value) }
68
+ when :hash
69
+ (node.values + node.keys).all? { |item| all_literals?(item) }
70
+ else
71
+ node.respond_to?(:literal?) && node.literal?
72
+ end
73
+ end
74
+
75
+ def parallel_assignment_with_splat_operator?(node)
76
+ node.array_type? && node.values.first&.splat_type?
77
+ end
78
+
79
+ def offense_range(asgn_node, rhs)
80
+ asgn_node.loc.operator.join(rhs.source_range.end)
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -34,7 +34,7 @@ module RuboCop
34
34
  # interpolation should not be removed if the expanded value
35
35
  # contains a space character.
36
36
  expanded_value = autocorrected_value(final_node)
37
- return if in_array_percent_literal?(begin_node) && /\s/.match?(expanded_value)
37
+ return if in_array_percent_literal?(begin_node) && /\s|\A\z/.match?(expanded_value)
38
38
 
39
39
  add_offense(final_node) do |corrector|
40
40
  return if final_node.dstr_type? # nested, fixed in next iteration
@@ -11,6 +11,16 @@ module RuboCop
11
11
  # missing method. In other cases, the theoretical ideal handling could be
12
12
  # challenging or verbose for no actual gain.
13
13
  #
14
+ # Autocorrection is not supported because the position of `super` cannot be
15
+ # determined automatically.
16
+ #
17
+ # `Object` and `BasicObject` are allowed by this cop because of their
18
+ # stateless nature. However, sometimes you might want to allow other parent
19
+ # classes from this cop, for example in the case of an abstract class that is
20
+ # not meant to be called with `super`. In those cases, you can use the
21
+ # `AllowedParentClasses` option to specify which classes should be allowed
22
+ # *in addition to* `Object` and `BasicObject`.
23
+ #
14
24
  # @example
15
25
  # # bad
16
26
  # class Employee < Person
@@ -57,6 +67,21 @@ module RuboCop
57
67
  # end
58
68
  # end
59
69
  #
70
+ # # good
71
+ # class ClassWithNoParent
72
+ # def initialize
73
+ # do_something
74
+ # end
75
+ # end
76
+ #
77
+ # @example AllowedParentClasses: [MyAbstractClass]
78
+ # # good
79
+ # class MyConcreteClass < MyAbstractClass
80
+ # def initialize
81
+ # do_something
82
+ # end
83
+ # end
84
+ #
60
85
  class MissingSuper < Base
61
86
  CONSTRUCTOR_MSG = 'Call `super` to initialize state of the parent class.'
62
87
  CALLBACK_MSG = 'Call `super` to invoke callback defined in the parent class.'
@@ -100,7 +125,7 @@ module RuboCop
100
125
  end
101
126
 
102
127
  def callback_method_def?(node)
103
- return unless CALLBACKS.include?(node.method_name)
128
+ return false unless CALLBACKS.include?(node.method_name)
104
129
 
105
130
  node.each_ancestor(:class, :sclass, :module).first
106
131
  end
@@ -113,16 +138,20 @@ module RuboCop
113
138
  if (block_node = node.each_ancestor(:block, :numblock).first)
114
139
  return false unless (super_class = class_new_block(block_node))
115
140
 
116
- !stateless_class?(super_class)
141
+ !allowed_class?(super_class)
117
142
  elsif (class_node = node.each_ancestor(:class).first)
118
- class_node.parent_class && !stateless_class?(class_node.parent_class)
143
+ class_node.parent_class && !allowed_class?(class_node.parent_class)
119
144
  else
120
145
  false
121
146
  end
122
147
  end
123
148
 
124
- def stateless_class?(node)
125
- STATELESS_CLASSES.include?(node.const_name)
149
+ def allowed_class?(node)
150
+ allowed_classes.include?(node.const_name)
151
+ end
152
+
153
+ def allowed_classes
154
+ @allowed_classes ||= STATELESS_CLASSES + cop_config.fetch('AllowedParentClasses', [])
126
155
  end
127
156
  end
128
157
  end