rubocop 1.69.0 → 1.79.2

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 (448) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +23 -19
  4. data/config/default.yml +290 -65
  5. data/config/internal_affairs.yml +20 -0
  6. data/config/obsoletion.yml +8 -3
  7. data/lib/rubocop/cli/command/execute_runner.rb +3 -3
  8. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  9. data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
  10. data/lib/rubocop/cli.rb +13 -2
  11. data/lib/rubocop/comment_config.rb +2 -2
  12. data/lib/rubocop/config.rb +52 -10
  13. data/lib/rubocop/config_loader.rb +53 -47
  14. data/lib/rubocop/config_loader_resolver.rb +36 -10
  15. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -3
  16. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  17. data/lib/rubocop/config_obsoletion.rb +46 -2
  18. data/lib/rubocop/config_validator.rb +25 -14
  19. data/lib/rubocop/cop/autocorrect_logic.rb +44 -39
  20. data/lib/rubocop/cop/base.rb +6 -0
  21. data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
  22. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  23. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
  24. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +5 -2
  25. data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
  26. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +37 -15
  27. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  28. data/lib/rubocop/cop/gemspec/require_mfa.rb +15 -1
  29. data/lib/rubocop/cop/generator.rb +6 -0
  30. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  31. data/lib/rubocop/cop/internal_affairs/example_description.rb +9 -5
  32. data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
  33. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  34. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
  35. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  36. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +5 -5
  37. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  38. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  39. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +231 -0
  40. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +92 -0
  41. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  42. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  43. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  44. data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +4 -2
  45. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  46. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  47. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  48. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  49. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +13 -2
  50. data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
  51. data/lib/rubocop/cop/internal_affairs.rb +6 -16
  52. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  53. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -8
  54. data/lib/rubocop/cop/layout/block_alignment.rb +3 -1
  55. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  56. data/lib/rubocop/cop/layout/class_structure.rb +44 -9
  57. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
  58. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  59. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  60. data/lib/rubocop/cop/layout/else_alignment.rb +2 -2
  61. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +2 -2
  62. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  63. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +101 -0
  64. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +35 -4
  65. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +8 -29
  66. data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
  67. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
  68. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +1 -1
  69. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
  70. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
  71. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  72. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  73. data/lib/rubocop/cop/layout/first_argument_indentation.rb +4 -9
  74. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  75. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  76. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  77. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  78. data/lib/rubocop/cop/layout/hash_alignment.rb +8 -6
  79. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
  80. data/lib/rubocop/cop/layout/indentation_width.rb +1 -0
  81. data/lib/rubocop/cop/layout/leading_comment_space.rb +13 -1
  82. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +11 -2
  83. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  84. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  85. data/lib/rubocop/cop/layout/line_length.rb +35 -9
  86. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
  87. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  88. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  89. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
  90. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
  91. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  92. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +1 -1
  93. data/lib/rubocop/cop/layout/redundant_line_break.rb +16 -11
  94. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -5
  95. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  96. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  97. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  98. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  99. data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
  100. data/lib/rubocop/cop/layout/space_around_keyword.rb +7 -1
  101. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  102. data/lib/rubocop/cop/layout/space_around_operators.rb +15 -4
  103. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
  104. data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -38
  105. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  106. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  107. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +12 -3
  108. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -0
  109. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
  110. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  111. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  112. data/lib/rubocop/cop/lint/ambiguous_range.rb +5 -0
  113. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +118 -0
  114. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  115. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -3
  116. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  117. data/lib/rubocop/cop/lint/circular_argument_reference.rb +4 -3
  118. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  119. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  120. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
  121. data/lib/rubocop/cop/lint/debugger.rb +3 -3
  122. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  123. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +2 -1
  124. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  125. data/lib/rubocop/cop/lint/duplicate_methods.rb +111 -23
  126. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  127. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  128. data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
  129. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  130. data/lib/rubocop/cop/lint/empty_interpolation.rb +3 -1
  131. data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
  132. data/lib/rubocop/cop/lint/float_comparison.rb +37 -12
  133. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  134. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  135. data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
  136. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  137. data/lib/rubocop/cop/lint/literal_as_condition.rb +125 -10
  138. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
  139. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
  140. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  141. data/lib/rubocop/cop/lint/mixed_case_range.rb +3 -3
  142. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  143. data/lib/rubocop/cop/lint/nested_method_definition.rb +9 -5
  144. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  145. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -2
  146. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -3
  147. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
  148. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +19 -31
  149. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  150. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
  151. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  152. data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
  153. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +2 -2
  154. data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
  155. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +101 -2
  156. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  157. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +261 -0
  158. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  159. data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
  160. data/lib/rubocop/cop/lint/refinement_import_methods.rb +1 -1
  161. data/lib/rubocop/cop/lint/require_range_parentheses.rb +1 -1
  162. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  163. data/lib/rubocop/cop/lint/rescue_type.rb +1 -1
  164. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  165. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -1
  166. data/lib/rubocop/cop/lint/self_assignment.rb +25 -0
  167. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +13 -1
  168. data/lib/rubocop/cop/lint/shared_mutable_default.rb +76 -0
  169. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  170. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
  171. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  172. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  173. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
  174. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  175. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -1
  176. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +3 -1
  177. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  178. data/lib/rubocop/cop/lint/unreachable_code.rb +52 -2
  179. data/lib/rubocop/cop/lint/unreachable_loop.rb +6 -6
  180. data/lib/rubocop/cop/lint/useless_access_modifier.rb +34 -8
  181. data/lib/rubocop/cop/lint/useless_assignment.rb +3 -1
  182. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +71 -0
  183. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +90 -0
  184. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +4 -0
  185. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  186. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +3 -1
  187. data/lib/rubocop/cop/lint/useless_or.rb +98 -0
  188. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
  189. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +5 -5
  190. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +121 -0
  191. data/lib/rubocop/cop/lint/void.rb +14 -11
  192. data/lib/rubocop/cop/message_annotator.rb +7 -3
  193. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  194. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  195. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  196. data/lib/rubocop/cop/metrics/class_length.rb +9 -9
  197. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  198. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  199. data/lib/rubocop/cop/metrics/method_length.rb +9 -1
  200. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  201. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  202. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
  203. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  204. data/lib/rubocop/cop/mixin/alignment.rb +3 -3
  205. data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
  206. data/lib/rubocop/cop/mixin/check_line_breakable.rb +13 -13
  207. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -2
  208. data/lib/rubocop/cop/mixin/comments_help.rb +8 -3
  209. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  210. data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
  211. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  212. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  213. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
  214. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -2
  215. data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
  216. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
  217. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
  218. data/lib/rubocop/cop/mixin/hash_subset.rb +203 -0
  219. data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
  220. data/lib/rubocop/cop/mixin/line_length_help.rb +27 -10
  221. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  222. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -0
  223. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  224. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  225. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +68 -30
  226. data/lib/rubocop/cop/mixin/range_help.rb +15 -3
  227. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  228. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
  229. data/lib/rubocop/cop/mixin/string_help.rb +2 -2
  230. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  231. data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
  232. data/lib/rubocop/cop/mixin/trailing_comma.rb +21 -5
  233. data/lib/rubocop/cop/naming/accessor_method_name.rb +6 -6
  234. data/lib/rubocop/cop/naming/block_forwarding.rb +19 -15
  235. data/lib/rubocop/cop/naming/file_name.rb +2 -2
  236. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  237. data/lib/rubocop/cop/naming/method_name.rb +185 -15
  238. data/lib/rubocop/cop/naming/predicate_method.rb +306 -0
  239. data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +48 -4
  240. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +4 -4
  241. data/lib/rubocop/cop/naming/variable_name.rb +51 -6
  242. data/lib/rubocop/cop/registry.rb +9 -6
  243. data/lib/rubocop/cop/security/compound_hash.rb +2 -0
  244. data/lib/rubocop/cop/security/eval.rb +2 -1
  245. data/lib/rubocop/cop/security/open.rb +1 -0
  246. data/lib/rubocop/cop/security/yaml_load.rb +3 -2
  247. data/lib/rubocop/cop/style/access_modifier_declarations.rb +66 -15
  248. data/lib/rubocop/cop/style/accessor_grouping.rb +32 -6
  249. data/lib/rubocop/cop/style/and_or.rb +1 -1
  250. data/lib/rubocop/cop/style/arguments_forwarding.rb +57 -44
  251. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  252. data/lib/rubocop/cop/style/array_intersect.rb +81 -40
  253. data/lib/rubocop/cop/style/block_delimiters.rb +27 -24
  254. data/lib/rubocop/cop/style/case_like_if.rb +1 -1
  255. data/lib/rubocop/cop/style/class_and_module_children.rb +52 -11
  256. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  257. data/lib/rubocop/cop/style/collection_methods.rb +2 -1
  258. data/lib/rubocop/cop/style/collection_querying.rb +167 -0
  259. data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
  260. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  261. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  262. data/lib/rubocop/cop/style/commented_keyword.rb +12 -5
  263. data/lib/rubocop/cop/style/comparable_between.rb +78 -0
  264. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  265. data/lib/rubocop/cop/style/conditional_assignment.rb +23 -7
  266. data/lib/rubocop/cop/style/data_inheritance.rb +7 -0
  267. data/lib/rubocop/cop/style/def_with_parentheses.rb +18 -5
  268. data/lib/rubocop/cop/style/dig_chain.rb +6 -7
  269. data/lib/rubocop/cop/style/documentation.rb +1 -1
  270. data/lib/rubocop/cop/style/double_negation.rb +4 -4
  271. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  272. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  273. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  274. data/lib/rubocop/cop/style/empty_literal.rb +5 -1
  275. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  276. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +100 -0
  277. data/lib/rubocop/cop/style/endless_method.rb +163 -18
  278. data/lib/rubocop/cop/style/eval_with_location.rb +4 -4
  279. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -3
  280. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  281. data/lib/rubocop/cop/style/explicit_block_argument.rb +16 -3
  282. data/lib/rubocop/cop/style/exponential_notation.rb +6 -5
  283. data/lib/rubocop/cop/style/fetch_env_var.rb +34 -7
  284. data/lib/rubocop/cop/style/file_null.rb +20 -4
  285. data/lib/rubocop/cop/style/float_division.rb +8 -4
  286. data/lib/rubocop/cop/style/for.rb +1 -0
  287. data/lib/rubocop/cop/style/format_string_token.rb +38 -11
  288. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  289. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  290. data/lib/rubocop/cop/style/guard_clause.rb +2 -1
  291. data/lib/rubocop/cop/style/hash_conversion.rb +16 -8
  292. data/lib/rubocop/cop/style/hash_each_methods.rb +6 -8
  293. data/lib/rubocop/cop/style/hash_except.rb +35 -147
  294. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  295. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  296. data/lib/rubocop/cop/style/hash_syntax.rb +9 -3
  297. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  298. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  299. data/lib/rubocop/cop/style/identical_conditional_branches.rb +25 -6
  300. data/lib/rubocop/cop/style/if_inside_else.rb +10 -13
  301. data/lib/rubocop/cop/style/if_unless_modifier.rb +36 -9
  302. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -7
  303. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +2 -2
  304. data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -5
  305. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  306. data/lib/rubocop/cop/style/inverse_methods.rb +16 -12
  307. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  308. data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
  309. data/lib/rubocop/cop/style/it_assignment.rb +93 -0
  310. data/lib/rubocop/cop/style/it_block_parameter.rb +121 -0
  311. data/lib/rubocop/cop/style/keyword_parameters_order.rb +14 -8
  312. data/lib/rubocop/cop/style/lambda.rb +1 -0
  313. data/lib/rubocop/cop/style/lambda_call.rb +10 -3
  314. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  315. data/lib/rubocop/cop/style/map_into_array.rb +5 -2
  316. data/lib/rubocop/cop/style/map_to_hash.rb +13 -4
  317. data/lib/rubocop/cop/style/map_to_set.rb +4 -5
  318. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +27 -19
  319. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +18 -0
  320. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +3 -2
  321. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
  322. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  323. data/lib/rubocop/cop/style/min_max_comparison.rb +13 -5
  324. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  325. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -2
  326. data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
  327. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
  328. data/lib/rubocop/cop/style/multiple_comparison.rb +34 -22
  329. data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
  330. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
  331. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  332. data/lib/rubocop/cop/style/next.rb +44 -0
  333. data/lib/rubocop/cop/style/object_then.rb +15 -15
  334. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  335. data/lib/rubocop/cop/style/parallel_assignment.rb +33 -25
  336. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  337. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  338. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  339. data/lib/rubocop/cop/style/proc.rb +2 -2
  340. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  341. data/lib/rubocop/cop/style/raise_args.rb +14 -12
  342. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  343. data/lib/rubocop/cop/style/redundant_argument.rb +3 -1
  344. data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
  345. data/lib/rubocop/cop/style/redundant_begin.rb +2 -1
  346. data/lib/rubocop/cop/style/redundant_condition.rb +59 -2
  347. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +16 -5
  348. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  349. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  350. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  351. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -9
  352. data/lib/rubocop/cop/style/redundant_format.rb +262 -0
  353. data/lib/rubocop/cop/style/redundant_freeze.rb +4 -4
  354. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  355. data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
  356. data/lib/rubocop/cop/style/redundant_line_continuation.rb +39 -22
  357. data/lib/rubocop/cop/style/redundant_parentheses.rb +85 -17
  358. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
  359. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  360. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  361. data/lib/rubocop/cop/style/redundant_self.rb +10 -6
  362. data/lib/rubocop/cop/style/redundant_self_assignment.rb +14 -28
  363. data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
  364. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  365. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  366. data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
  367. data/lib/rubocop/cop/style/rescue_modifier.rb +3 -0
  368. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  369. data/lib/rubocop/cop/style/safe_navigation.rb +46 -16
  370. data/lib/rubocop/cop/style/select_by_regexp.rb +4 -1
  371. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  372. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  373. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  374. data/lib/rubocop/cop/style/single_line_do_end_block.rb +4 -3
  375. data/lib/rubocop/cop/style/single_line_methods.rb +13 -11
  376. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  377. data/lib/rubocop/cop/style/sole_nested_conditional.rb +68 -101
  378. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -1
  379. data/lib/rubocop/cop/style/string_concatenation.rb +15 -14
  380. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  381. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  382. data/lib/rubocop/cop/style/struct_inheritance.rb +8 -1
  383. data/lib/rubocop/cop/style/super_arguments.rb +66 -19
  384. data/lib/rubocop/cop/style/symbol_proc.rb +3 -1
  385. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  386. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -1
  387. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +11 -2
  388. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  389. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  390. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  391. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  392. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  393. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  394. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  395. data/lib/rubocop/cop/team.rb +1 -1
  396. data/lib/rubocop/cop/util.rb +12 -5
  397. data/lib/rubocop/cop/utils/format_string.rb +10 -5
  398. data/lib/rubocop/cop/variable_force/assignment.rb +7 -3
  399. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  400. data/lib/rubocop/cop/variable_force/variable.rb +10 -3
  401. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  402. data/lib/rubocop/cop/variable_force.rb +23 -8
  403. data/lib/rubocop/cops_documentation_generator.rb +32 -16
  404. data/lib/rubocop/directive_comment.rb +45 -11
  405. data/lib/rubocop/ext/regexp_node.rb +0 -1
  406. data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -1
  407. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  408. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  409. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  410. data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
  411. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  412. data/lib/rubocop/formatter/pacman_formatter.rb +2 -1
  413. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  414. data/lib/rubocop/lsp/logger.rb +2 -2
  415. data/lib/rubocop/lsp/routes.rb +10 -26
  416. data/lib/rubocop/lsp/runtime.rb +18 -50
  417. data/lib/rubocop/lsp/server.rb +0 -2
  418. data/lib/rubocop/lsp/stdin_runner.rb +85 -0
  419. data/lib/rubocop/magic_comment.rb +11 -3
  420. data/lib/rubocop/options.rb +28 -12
  421. data/lib/rubocop/path_util.rb +15 -8
  422. data/lib/rubocop/pending_cops_reporter.rb +56 -0
  423. data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
  424. data/lib/rubocop/plugin/load_error.rb +26 -0
  425. data/lib/rubocop/plugin/loader.rb +100 -0
  426. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  427. data/lib/rubocop/plugin.rb +46 -0
  428. data/lib/rubocop/rake_task.rb +4 -1
  429. data/lib/rubocop/result_cache.rb +26 -24
  430. data/lib/rubocop/rspec/cop_helper.rb +13 -1
  431. data/lib/rubocop/rspec/expect_offense.rb +15 -5
  432. data/lib/rubocop/rspec/shared_contexts.rb +38 -1
  433. data/lib/rubocop/rspec/support.rb +4 -2
  434. data/lib/rubocop/runner.rb +10 -7
  435. data/lib/rubocop/server/cache.rb +51 -13
  436. data/lib/rubocop/server/cli.rb +2 -2
  437. data/lib/rubocop/server/client_command/base.rb +10 -0
  438. data/lib/rubocop/server/client_command/exec.rb +2 -1
  439. data/lib/rubocop/server/client_command/start.rb +11 -1
  440. data/lib/rubocop/target_finder.rb +7 -2
  441. data/lib/rubocop/target_ruby.rb +16 -1
  442. data/lib/rubocop/version.rb +30 -8
  443. data/lib/rubocop.rb +27 -2
  444. data/lib/ruby_lsp/rubocop/addon.rb +75 -0
  445. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +65 -0
  446. metadata +72 -19
  447. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  448. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -68,12 +68,12 @@ module RuboCop
68
68
 
69
69
  # @!method constant_assigned_in_block?(node)
70
70
  def_node_matcher :constant_assigned_in_block?, <<~PATTERN
71
- ({^block_type? [^begin_type? ^^block_type?]} nil? ...)
71
+ ({^any_block [^begin ^^any_block]} nil? ...)
72
72
  PATTERN
73
73
 
74
74
  # @!method module_defined_in_block?(node)
75
75
  def_node_matcher :module_defined_in_block?, <<~PATTERN
76
- ({^block_type? [^begin_type? ^^block_type?]} ...)
76
+ ({^any_block [^begin ^^any_block]} ...)
77
77
  PATTERN
78
78
 
79
79
  def on_casgn(node)
@@ -92,7 +92,7 @@ module RuboCop
92
92
  private
93
93
 
94
94
  def method_name(node)
95
- node.ancestors.find(&:block_type?).method_name
95
+ node.ancestors.find(&:any_block_type?).method_name
96
96
  end
97
97
  end
98
98
  end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for constant reassignments.
7
+ #
8
+ # Emulates Ruby's runtime warning "already initialized constant X"
9
+ # when a constant is reassigned in the same file and namespace using the
10
+ # `NAME = value` syntax.
11
+ #
12
+ # The cop cannot catch all offenses, like, for example, when a constant
13
+ # is reassigned in another file, or when using metaprogramming (`Module#const_set`).
14
+ #
15
+ # The cop only takes into account constants assigned in a "simple" way: directly
16
+ # inside class/module definition, or within another constant. Other type of assignments
17
+ # (e.g., inside a conditional) are disregarded.
18
+ #
19
+ # The cop also tracks constant removal using `Module#remove_const` with symbol
20
+ # or string argument.
21
+ #
22
+ # @example
23
+ # # bad
24
+ # X = :foo
25
+ # X = :bar
26
+ #
27
+ # # bad
28
+ # class A
29
+ # X = :foo
30
+ # X = :bar
31
+ # end
32
+ #
33
+ # # bad
34
+ # module A
35
+ # X = :foo
36
+ # X = :bar
37
+ # end
38
+ #
39
+ # # good - keep only one assignment
40
+ # X = :bar
41
+ #
42
+ # class A
43
+ # X = :bar
44
+ # end
45
+ #
46
+ # module A
47
+ # X = :bar
48
+ # end
49
+ #
50
+ # # good - use OR assignment
51
+ # X = :foo
52
+ # X ||= :bar
53
+ #
54
+ # # good - use conditional assignment
55
+ # X = :foo
56
+ # X = :bar unless defined?(X)
57
+ #
58
+ # # good - remove the assigned constant first
59
+ # class A
60
+ # X = :foo
61
+ # remove_const :X
62
+ # X = :bar
63
+ # end
64
+ #
65
+ class ConstantReassignment < Base
66
+ MSG = 'Constant `%<constant>s` is already assigned in this namespace.'
67
+
68
+ RESTRICT_ON_SEND = %i[remove_const].freeze
69
+
70
+ # @!method remove_constant(node)
71
+ def_node_matcher :remove_constant, <<~PATTERN
72
+ (send _ :remove_const
73
+ ({sym str} $_))
74
+ PATTERN
75
+
76
+ def on_casgn(node)
77
+ return unless fixed_constant_path?(node)
78
+ return unless simple_assignment?(node)
79
+ return if constant_names.add?(fully_qualified_constant_name(node))
80
+
81
+ add_offense(node, message: format(MSG, constant: node.name))
82
+ end
83
+
84
+ def on_send(node)
85
+ constant = remove_constant(node)
86
+
87
+ return unless constant
88
+
89
+ namespaces = ancestor_namespaces(node)
90
+
91
+ return if namespaces.none?
92
+
93
+ constant_names.delete(fully_qualified_name_for(namespaces, constant))
94
+ end
95
+
96
+ private
97
+
98
+ def fixed_constant_path?(node)
99
+ node.each_path.all? { |path| path.type?(:cbase, :const, :self) }
100
+ end
101
+
102
+ def simple_assignment?(node)
103
+ node.ancestors.all? do |ancestor|
104
+ return true if ancestor.type?(:module, :class)
105
+
106
+ ancestor.begin_type? || ancestor.literal? || ancestor.casgn_type? ||
107
+ freeze_method?(ancestor)
108
+ end
109
+ end
110
+
111
+ def freeze_method?(node)
112
+ node.send_type? && node.method?(:freeze)
113
+ end
114
+
115
+ def fully_qualified_constant_name(node)
116
+ if node.absolute?
117
+ namespace = node.namespace.const_type? ? node.namespace.source : nil
118
+
119
+ "#{namespace}::#{node.name}"
120
+ else
121
+ constant_namespaces = ancestor_namespaces(node) + constant_namespaces(node)
122
+
123
+ fully_qualified_name_for(constant_namespaces, node.name)
124
+ end
125
+ end
126
+
127
+ def fully_qualified_name_for(namespaces, constant)
128
+ ['', *namespaces, constant].join('::')
129
+ end
130
+
131
+ def constant_namespaces(node)
132
+ node.each_path.select(&:const_type?).map(&:short_name)
133
+ end
134
+
135
+ def ancestor_namespaces(node)
136
+ node
137
+ .each_ancestor(:class, :module)
138
+ .map { |ancestor| ancestor.identifier.short_name }
139
+ .reverse
140
+ end
141
+
142
+ def constant_names
143
+ @constant_names ||= Set.new
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Lint/RedundantCopDisableDirective
4
+ # rubocop:disable Style/DoubleCopDisableDirective
5
+ module RuboCop
6
+ module Cop
7
+ module Lint
8
+ # Checks that `# rubocop:enable ...` and `# rubocop:disable ...` statements
9
+ # are strictly formatted.
10
+ #
11
+ # A comment can be added to the directive by prefixing it with `--`.
12
+ #
13
+ # @example
14
+ # # bad
15
+ # # rubocop:disable Layout/LineLength Style/Encoding
16
+ # # ^ missing comma
17
+ #
18
+ # # bad
19
+ # # rubocop:disable
20
+ #
21
+ # # bad
22
+ # # rubocop:disable Layout/LineLength # rubocop:disable Style/Encoding
23
+ #
24
+ # # bad
25
+ # # rubocop:wrongmode Layout/LineLength
26
+ #
27
+ # # good
28
+ # # rubocop:disable Layout/LineLength
29
+ #
30
+ # # good
31
+ # # rubocop:disable Layout/LineLength, Style/Encoding
32
+ #
33
+ # # good
34
+ # # rubocop:disable all
35
+ #
36
+ # # good
37
+ # # rubocop:disable Layout/LineLength -- This is a good comment.
38
+ #
39
+ class CopDirectiveSyntax < Base
40
+ COMMON_MSG = 'Malformed directive comment detected.'
41
+
42
+ MISSING_MODE_NAME_MSG = 'The mode name is missing.'
43
+ INVALID_MODE_NAME_MSG = 'The mode name must be one of `enable`, `disable`, or `todo`.'
44
+ MISSING_COP_NAME_MSG = 'The cop name is missing.'
45
+ MALFORMED_COP_NAMES_MSG = 'Cop names must be separated by commas. ' \
46
+ 'Comment in the directive must start with `--`.'
47
+
48
+ def on_new_investigation
49
+ processed_source.comments.each do |comment|
50
+ directive_comment = DirectiveComment.new(comment)
51
+ next unless directive_comment.start_with_marker?
52
+ next unless directive_comment.malformed?
53
+
54
+ message = offense_message(directive_comment)
55
+ add_offense(comment, message: message)
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ # rubocop:disable Metrics/MethodLength
62
+ def offense_message(directive_comment)
63
+ comment = directive_comment.comment
64
+ after_marker = comment.text.sub(DirectiveComment::DIRECTIVE_MARKER_REGEXP, '')
65
+ mode = after_marker.split(' ', 2).first
66
+ additional_msg = if mode.nil?
67
+ MISSING_MODE_NAME_MSG
68
+ elsif !DirectiveComment::AVAILABLE_MODES.include?(mode)
69
+ INVALID_MODE_NAME_MSG
70
+ elsif directive_comment.missing_cop_name?
71
+ MISSING_COP_NAME_MSG
72
+ else
73
+ MALFORMED_COP_NAMES_MSG
74
+ end
75
+
76
+ "#{COMMON_MSG} #{additional_msg}"
77
+ end
78
+ # rubocop:enable Metrics/MethodLength
79
+ end
80
+ end
81
+ end
82
+ end
83
+ # rubocop:enable Lint/RedundantCopDisableDirective
84
+ # rubocop:enable Style/DoubleCopDisableDirective
@@ -73,7 +73,7 @@ module RuboCop
73
73
  # require 'my_debugger/start'
74
74
  class Debugger < Base
75
75
  MSG = 'Remove debugger entry point `%<source>s`.'
76
- BLOCK_TYPES = %i[block numblock kwbegin].freeze
76
+ BLOCK_TYPES = %i[block numblock itblock kwbegin].freeze
77
77
 
78
78
  def on_send(node)
79
79
  return if assumed_usage_context?(node)
@@ -116,11 +116,11 @@ module RuboCop
116
116
 
117
117
  def assumed_usage_context?(node)
118
118
  # Basically, debugger methods are not used as a method argument without arguments.
119
- return false unless node.arguments.empty? && node.each_ancestor(:send, :csend).any?
119
+ return false unless node.arguments.empty? && node.each_ancestor(:call).any?
120
120
  return true if assumed_argument?(node)
121
121
 
122
122
  node.each_ancestor.none? do |ancestor|
123
- BLOCK_TYPES.include?(ancestor.type) || ancestor.lambda_or_proc?
123
+ ancestor.type?(:any_block, :kwbegin) || ancestor.lambda_or_proc?
124
124
  end
125
125
  end
126
126
 
@@ -43,7 +43,7 @@ module RuboCop
43
43
  dup: 'to_h',
44
44
  exists?: 'exist?',
45
45
  gethostbyaddr: 'Addrinfo#getnameinfo',
46
- gethostbyname: 'Addrinfo#getaddrinfo',
46
+ gethostbyname: 'Addrinfo.getaddrinfo',
47
47
  iterator?: 'block_given?'
48
48
  }.freeze
49
49
 
@@ -33,6 +33,7 @@ module RuboCop
33
33
 
34
34
  MSG = 'Use `%<constant>s.%<method>s(%<replacement_args>s)` instead of `%<original>s`.'
35
35
 
36
+ RESTRICT_ON_SEND = %i[new digest].freeze
36
37
  NO_ARG_ALGORITHM = %w[BF DES IDEA RC4].freeze
37
38
 
38
39
  # @!method algorithm_const(node)
@@ -133,7 +134,7 @@ module RuboCop
133
134
  if NO_ARG_ALGORITHM.include?(algorithm_parts.first.upcase) && no_arguments
134
135
  "'#{algorithm_parts.first}'"
135
136
  else
136
- mode = 'cbc' unless size_and_mode == ['cbc']
137
+ mode = 'cbc' if size_and_mode.empty?
137
138
 
138
139
  "'#{(algorithm_parts + size_and_mode + [mode]).compact.take(3).join('-')}'"
139
140
  end
@@ -106,7 +106,7 @@ module RuboCop
106
106
  private
107
107
 
108
108
  def pattern_identity(pattern)
109
- pattern_source = if pattern.hash_pattern_type? || pattern.match_alt_type?
109
+ pattern_source = if pattern.type?(:hash_pattern, :match_alt)
110
110
  pattern.children.map(&:source).sort.to_s
111
111
  else
112
112
  pattern.source
@@ -6,6 +6,10 @@ module RuboCop
6
6
  # Checks for duplicated instance (or singleton) method
7
7
  # definitions.
8
8
  #
9
+ # NOTE: Aliasing a method to itself is allowed, as it indicates that
10
+ # the developer intends to suppress Ruby's method redefinition warnings.
11
+ # See https://bugs.ruby-lang.org/issues/13574.
12
+ #
9
13
  # @example
10
14
  #
11
15
  # # bad
@@ -39,10 +43,64 @@ module RuboCop
39
43
  # end
40
44
  #
41
45
  # alias bar foo
46
+ #
47
+ # # good
48
+ # alias foo foo
49
+ # def foo
50
+ # 1
51
+ # end
52
+ #
53
+ # # good
54
+ # alias_method :foo, :foo
55
+ # def foo
56
+ # 1
57
+ # end
58
+ #
59
+ # @example AllCops:ActiveSupportExtensionsEnabled: false (default)
60
+ #
61
+ # # good
62
+ # def foo
63
+ # 1
64
+ # end
65
+ #
66
+ # delegate :foo, to: :bar
67
+ #
68
+ # @example AllCops:ActiveSupportExtensionsEnabled: true
69
+ #
70
+ # # bad
71
+ # def foo
72
+ # 1
73
+ # end
74
+ #
75
+ # delegate :foo, to: :bar
76
+ #
77
+ # # good
78
+ # def foo
79
+ # 1
80
+ # end
81
+ #
82
+ # delegate :baz, to: :bar
83
+ #
84
+ # # good - delegate with splat arguments is ignored
85
+ # def foo
86
+ # 1
87
+ # end
88
+ #
89
+ # delegate :foo, **options
90
+ #
91
+ # # good - delegate inside a condition is ignored
92
+ # def foo
93
+ # 1
94
+ # end
95
+ #
96
+ # if cond
97
+ # delegate :foo, to: :bar
98
+ # end
99
+ #
42
100
  class DuplicateMethods < Base
43
101
  MSG = 'Method `%<method>s` is defined at both %<defined>s and %<current>s.'
44
- RESTRICT_ON_SEND = %i[alias_method attr_reader attr_writer attr_accessor attr].freeze
45
- DEF_TYPES = %i[def defs].freeze
102
+ RESTRICT_ON_SEND = %i[alias_method attr_reader attr_writer attr_accessor attr
103
+ delegate].freeze
46
104
 
47
105
  def initialize(config = nil, options = nil)
48
106
  super
@@ -54,14 +112,12 @@ module RuboCop
54
112
  # if a method definition is inside an if, it is very likely
55
113
  # that a different definition is used depending on platform, etc.
56
114
  return if node.each_ancestor.any?(&:if_type?)
57
- return if possible_dsl?(node)
58
115
 
59
116
  found_instance_method(node, node.method_name)
60
117
  end
61
118
 
62
119
  def on_defs(node)
63
120
  return if node.each_ancestor.any?(&:if_type?)
64
- return if possible_dsl?(node)
65
121
 
66
122
  if node.receiver.const_type?
67
123
  _, const_name = *node.receiver
@@ -73,32 +129,48 @@ module RuboCop
73
129
 
74
130
  # @!method method_alias?(node)
75
131
  def_node_matcher :method_alias?, <<~PATTERN
76
- (alias (sym $_name) sym)
132
+ (alias (sym $_name) (sym $_original_name))
77
133
  PATTERN
78
134
 
79
135
  def on_alias(node)
80
- return unless (name = method_alias?(node))
136
+ name, original_name = method_alias?(node)
137
+ return unless name && original_name
138
+ return if name == original_name
81
139
  return if node.ancestors.any?(&:if_type?)
82
- return if possible_dsl?(node)
83
140
 
84
141
  found_instance_method(node, name)
85
142
  end
86
143
 
87
144
  # @!method alias_method?(node)
88
145
  def_node_matcher :alias_method?, <<~PATTERN
89
- (send nil? :alias_method (sym $_name) _)
146
+ (send nil? :alias_method (sym $_name) (sym $_original_name))
147
+ PATTERN
148
+
149
+ # @!method delegate_method?(node)
150
+ def_node_matcher :delegate_method?, <<~PATTERN
151
+ (send nil? :delegate
152
+ ({sym str} $_)+
153
+ (hash <(pair (sym :to) {sym str}) ...>)
154
+ )
90
155
  PATTERN
91
156
 
92
157
  # @!method sym_name(node)
93
158
  def_node_matcher :sym_name, '(sym $_name)'
94
- def on_send(node)
95
- if (name = alias_method?(node))
159
+
160
+ def on_send(node) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
161
+ name, original_name = alias_method?(node)
162
+
163
+ if name && original_name
164
+ return if name == original_name
96
165
  return if node.ancestors.any?(&:if_type?)
97
- return if possible_dsl?(node)
98
166
 
99
167
  found_instance_method(node, name)
100
168
  elsif (attr = node.attribute_accessor?)
101
169
  on_attr(node, *attr)
170
+ elsif active_support_extensions_enabled? && (names = delegate_method?(node))
171
+ return if node.ancestors.any?(&:if_type?)
172
+
173
+ on_delegate(node, names)
102
174
  end
103
175
  end
104
176
 
@@ -123,6 +195,32 @@ module RuboCop
123
195
  current: source_location(node))
124
196
  end
125
197
 
198
+ def on_delegate(node, method_names)
199
+ name_prefix = delegate_prefix(node)
200
+
201
+ method_names.each do |name|
202
+ name = "#{name_prefix}_#{name}" if name_prefix
203
+
204
+ found_instance_method(node, name)
205
+ end
206
+ end
207
+
208
+ def delegate_prefix(node)
209
+ kwargs_node = node.last_argument
210
+
211
+ return unless (prefix = hash_value(kwargs_node, :prefix))
212
+
213
+ if prefix.true_type?
214
+ hash_value(kwargs_node, :to).value
215
+ elsif prefix.type?(:sym, :str)
216
+ prefix.value
217
+ end
218
+ end
219
+
220
+ def hash_value(node, key)
221
+ node.pairs.find { |pair| pair.key.value == key }&.value
222
+ end
223
+
126
224
  def found_instance_method(node, name)
127
225
  return found_sclass_method(node, name) unless (scope = node.parent_module_name)
128
226
 
@@ -166,7 +264,7 @@ module RuboCop
166
264
  end
167
265
 
168
266
  def method_key(node, method_name)
169
- if (ancestor_def = node.each_ancestor(*DEF_TYPES).first)
267
+ if (ancestor_def = node.each_ancestor(:any_def).first)
170
268
  "#{ancestor_def.method_name}.#{method_name}"
171
269
  else
172
270
  method_name
@@ -174,7 +272,7 @@ module RuboCop
174
272
  end
175
273
 
176
274
  def location(node)
177
- if DEF_TYPES.include?(node.type)
275
+ if node.any_def_type?
178
276
  node.loc.keyword.join(node.loc.name)
179
277
  else
180
278
  node.source_range
@@ -237,16 +335,6 @@ module RuboCop
237
335
  end
238
336
  end
239
337
 
240
- def possible_dsl?(node)
241
- # DSL methods may evaluate a block in the context of a newly created
242
- # class or module
243
- # Assume that if a method definition is inside any block call which
244
- # we can't identify, it could be a DSL
245
- node.each_ancestor(:block).any? do |ancestor|
246
- !ancestor.method?(:class_eval) && !ancestor.class_constructor?
247
- end
248
- end
249
-
250
338
  def source_location(node)
251
339
  range = node.source_range
252
340
  path = smart_path(range.source_buffer.name)
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for duplicate elements in Regexp character classes.
6
+ # Checks for duplicate elements in `Regexp` character classes.
7
7
  #
8
8
  # @example
9
9
  #
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for duplicate literal, constant, or variable elements in Set.
6
+ # Checks for duplicate literal, constant, or variable elements in `Set` and `SortedSet`.
7
7
  #
8
8
  # @example
9
9
  #
@@ -25,17 +25,28 @@ module RuboCop
25
25
  # # good
26
26
  # [:foo, :bar].to_set
27
27
  #
28
+ # # bad
29
+ # SortedSet[:foo, :bar, :foo]
30
+ #
31
+ # # good
32
+ # SortedSet[:foo, :bar]
33
+ #
34
+ # # bad
35
+ # SortedSet.new([:foo, :bar, :foo])
36
+ #
37
+ # # good
38
+ # SortedSet.new([:foo, :bar])
28
39
  class DuplicateSetElement < Base
29
40
  extend AutoCorrector
30
41
 
31
- MSG = 'Remove the duplicate element in Set.'
42
+ MSG = 'Remove the duplicate element in %<class_name>s.'
32
43
  RESTRICT_ON_SEND = %i[\[\] new to_set].freeze
33
44
 
34
45
  # @!method set_init_elements(node)
35
46
  def_node_matcher :set_init_elements, <<~PATTERN
36
47
  {
37
- (send (const {nil? cbase} :Set) :[] $...)
38
- (send (const {nil? cbase} :Set) :new (array $...))
48
+ (send (const {nil? cbase} {:Set :SortedSet}) :[] $...)
49
+ (send (const {nil? cbase} {:Set :SortedSet}) :new (array $...))
39
50
  (call (array $...) :to_set)
40
51
  }
41
52
  PATTERN
@@ -51,7 +62,7 @@ module RuboCop
51
62
  next if !set_element.literal? && !set_element.const_type? && !set_element.variable?
52
63
 
53
64
  if seen_elements.include?(set_element)
54
- register_offense(set_element, set_elements[index - 1])
65
+ register_offense(set_element, set_elements[index - 1], node)
55
66
  else
56
67
  seen_elements << set_element
57
68
  end
@@ -61,8 +72,10 @@ module RuboCop
61
72
 
62
73
  private
63
74
 
64
- def register_offense(current_element, prev_element)
65
- add_offense(current_element) do |corrector|
75
+ def register_offense(current_element, prev_element, node)
76
+ class_name = node.receiver.const_type? ? node.receiver.const_name : 'Set'
77
+
78
+ add_offense(current_element, message: format(MSG, class_name: class_name)) do |corrector|
66
79
  range = prev_element.source_range.end.join(current_element.source_range.end)
67
80
 
68
81
  corrector.remove(range)