rubocop 1.67.0 → 1.79.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 (512) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +23 -19
  4. data/config/default.yml +371 -71
  5. data/config/internal_affairs.yml +20 -0
  6. data/config/obsoletion.yml +8 -3
  7. data/lib/rubocop/cached_data.rb +12 -4
  8. data/lib/rubocop/cli/command/execute_runner.rb +4 -4
  9. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  10. data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
  11. data/lib/rubocop/cli/command/version.rb +2 -2
  12. data/lib/rubocop/cli.rb +13 -2
  13. data/lib/rubocop/comment_config.rb +2 -2
  14. data/lib/rubocop/config.rb +52 -10
  15. data/lib/rubocop/config_loader.rb +53 -47
  16. data/lib/rubocop/config_loader_resolver.rb +36 -10
  17. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -3
  18. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  19. data/lib/rubocop/config_obsoletion.rb +46 -2
  20. data/lib/rubocop/config_validator.rb +25 -14
  21. data/lib/rubocop/cop/autocorrect_logic.rb +51 -26
  22. data/lib/rubocop/cop/base.rb +7 -1
  23. data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
  24. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  25. data/lib/rubocop/cop/bundler/gem_filename.rb +0 -1
  26. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +0 -1
  27. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
  28. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -12
  29. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +1 -1
  30. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +5 -2
  31. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
  32. data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
  33. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
  34. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +37 -15
  35. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  36. data/lib/rubocop/cop/gemspec/require_mfa.rb +15 -1
  37. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
  38. data/lib/rubocop/cop/generator.rb +6 -0
  39. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  40. data/lib/rubocop/cop/internal_affairs/example_description.rb +9 -5
  41. data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
  42. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  43. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -4
  44. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  45. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +5 -5
  46. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  47. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  48. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +231 -0
  49. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +92 -0
  50. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  51. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  52. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
  53. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  54. data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +48 -0
  55. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  56. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  57. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  58. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  59. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
  60. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +13 -2
  61. data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
  62. data/lib/rubocop/cop/internal_affairs.rb +7 -16
  63. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  64. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -9
  65. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  66. data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
  67. data/lib/rubocop/cop/layout/block_alignment.rb +3 -2
  68. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  69. data/lib/rubocop/cop/layout/class_structure.rb +44 -9
  70. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
  71. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  72. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  73. data/lib/rubocop/cop/layout/else_alignment.rb +2 -2
  74. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -3
  75. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  76. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +99 -0
  77. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +37 -7
  78. data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
  79. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
  80. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +4 -5
  81. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +23 -1
  82. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  83. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  84. data/lib/rubocop/cop/layout/first_argument_indentation.rb +4 -9
  85. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  86. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  87. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  88. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  89. data/lib/rubocop/cop/layout/hash_alignment.rb +8 -6
  90. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
  91. data/lib/rubocop/cop/layout/indentation_width.rb +8 -7
  92. data/lib/rubocop/cop/layout/leading_comment_space.rb +57 -2
  93. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +11 -2
  94. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  95. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  96. data/lib/rubocop/cop/layout/line_length.rb +149 -9
  97. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
  98. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  99. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  100. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +2 -1
  101. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
  102. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
  103. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  104. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +3 -4
  105. data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
  106. data/lib/rubocop/cop/layout/redundant_line_break.rb +19 -46
  107. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +6 -7
  108. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  109. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  110. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  111. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  112. data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
  113. data/lib/rubocop/cop/layout/space_around_keyword.rb +8 -2
  114. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  115. data/lib/rubocop/cop/layout/space_around_operators.rb +31 -21
  116. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
  117. data/lib/rubocop/cop/layout/space_before_brackets.rb +7 -40
  118. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  119. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  120. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +18 -3
  121. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +5 -0
  122. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +7 -0
  123. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
  124. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  125. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  126. data/lib/rubocop/cop/lint/ambiguous_range.rb +5 -0
  127. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +118 -0
  128. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  129. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +10 -12
  130. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  131. data/lib/rubocop/cop/lint/circular_argument_reference.rb +4 -1
  132. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  133. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  134. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
  135. data/lib/rubocop/cop/lint/debugger.rb +3 -3
  136. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  137. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +3 -2
  138. data/lib/rubocop/cop/lint/duplicate_branch.rb +39 -4
  139. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  140. data/lib/rubocop/cop/lint/duplicate_methods.rb +111 -23
  141. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  142. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  143. data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
  144. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
  145. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  146. data/lib/rubocop/cop/lint/empty_file.rb +0 -2
  147. data/lib/rubocop/cop/lint/empty_interpolation.rb +3 -1
  148. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  149. data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
  150. data/lib/rubocop/cop/lint/float_comparison.rb +51 -18
  151. data/lib/rubocop/cop/lint/float_out_of_range.rb +2 -4
  152. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  153. data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
  154. data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
  155. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  156. data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
  157. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +3 -0
  158. data/lib/rubocop/cop/lint/literal_as_condition.rb +125 -10
  159. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  160. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
  161. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
  162. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  163. data/lib/rubocop/cop/lint/mixed_case_range.rb +5 -8
  164. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  165. data/lib/rubocop/cop/lint/nested_method_definition.rb +10 -6
  166. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  167. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
  168. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +12 -3
  169. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -3
  170. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
  171. data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
  172. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
  173. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +94 -0
  174. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -3
  175. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +3 -2
  176. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  177. data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
  178. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  179. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +2 -2
  180. data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
  181. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +113 -9
  182. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
  183. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  184. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +261 -0
  185. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  186. data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
  187. data/lib/rubocop/cop/lint/refinement_import_methods.rb +1 -1
  188. data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
  189. data/lib/rubocop/cop/lint/require_range_parentheses.rb +1 -1
  190. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  191. data/lib/rubocop/cop/lint/rescue_type.rb +4 -8
  192. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  193. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -1
  194. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +5 -1
  195. data/lib/rubocop/cop/lint/self_assignment.rb +33 -10
  196. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  197. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +13 -1
  198. data/lib/rubocop/cop/lint/shared_mutable_default.rb +76 -0
  199. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  200. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
  201. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  202. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  203. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
  204. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  205. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +88 -0
  206. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +3 -1
  207. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  208. data/lib/rubocop/cop/lint/unreachable_code.rb +52 -2
  209. data/lib/rubocop/cop/lint/unreachable_loop.rb +6 -6
  210. data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
  211. data/lib/rubocop/cop/lint/useless_access_modifier.rb +34 -8
  212. data/lib/rubocop/cop/lint/useless_assignment.rb +3 -1
  213. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +71 -0
  214. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +90 -0
  215. data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
  216. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +4 -0
  217. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  218. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +3 -1
  219. data/lib/rubocop/cop/lint/useless_or.rb +98 -0
  220. data/lib/rubocop/cop/lint/useless_rescue.rb +2 -2
  221. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +5 -5
  222. data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
  223. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +121 -0
  224. data/lib/rubocop/cop/lint/void.rb +16 -12
  225. data/lib/rubocop/cop/message_annotator.rb +7 -3
  226. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  227. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  228. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  229. data/lib/rubocop/cop/metrics/class_length.rb +9 -9
  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 +9 -1
  233. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  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 +3 -3
  239. data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
  240. data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
  241. data/lib/rubocop/cop/mixin/check_line_breakable.rb +22 -12
  242. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
  243. data/lib/rubocop/cop/mixin/comments_help.rb +8 -3
  244. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  245. data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
  246. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  247. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
  248. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  249. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
  250. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -3
  251. data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
  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 +27 -10
  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/ordered_gem_node.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 +8 -3
  265. data/lib/rubocop/cop/mixin/string_help.rb +2 -2
  266. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  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 +6 -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 +2 -4
  273. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +12 -13
  274. data/lib/rubocop/cop/naming/method_name.rb +185 -15
  275. data/lib/rubocop/cop/naming/predicate_method.rb +306 -0
  276. data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +48 -4
  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 +2 -3
  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/eval.rb +2 -1
  284. data/lib/rubocop/cop/security/open.rb +1 -0
  285. data/lib/rubocop/cop/security/yaml_load.rb +3 -2
  286. data/lib/rubocop/cop/style/access_modifier_declarations.rb +114 -34
  287. data/lib/rubocop/cop/style/accessor_grouping.rb +32 -6
  288. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +79 -0
  289. data/lib/rubocop/cop/style/and_or.rb +1 -1
  290. data/lib/rubocop/cop/style/arguments_forwarding.rb +57 -44
  291. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  292. data/lib/rubocop/cop/style/array_intersect.rb +84 -42
  293. data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
  294. data/lib/rubocop/cop/style/block_delimiters.rb +44 -26
  295. data/lib/rubocop/cop/style/case_like_if.rb +9 -12
  296. data/lib/rubocop/cop/style/class_and_module_children.rb +52 -11
  297. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  298. data/lib/rubocop/cop/style/collection_methods.rb +2 -1
  299. data/lib/rubocop/cop/style/collection_querying.rb +167 -0
  300. data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
  301. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  302. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  303. data/lib/rubocop/cop/style/commented_keyword.rb +20 -3
  304. data/lib/rubocop/cop/style/comparable_between.rb +78 -0
  305. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  306. data/lib/rubocop/cop/style/conditional_assignment.rb +42 -28
  307. data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
  308. data/lib/rubocop/cop/style/data_inheritance.rb +7 -0
  309. data/lib/rubocop/cop/style/def_with_parentheses.rb +18 -5
  310. data/lib/rubocop/cop/style/dig_chain.rb +89 -0
  311. data/lib/rubocop/cop/style/documentation.rb +1 -1
  312. data/lib/rubocop/cop/style/double_negation.rb +4 -4
  313. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  314. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  315. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  316. data/lib/rubocop/cop/style/empty_literal.rb +5 -1
  317. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  318. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +100 -0
  319. data/lib/rubocop/cop/style/endless_method.rb +150 -18
  320. data/lib/rubocop/cop/style/eval_with_location.rb +4 -4
  321. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -3
  322. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  323. data/lib/rubocop/cop/style/explicit_block_argument.rb +16 -3
  324. data/lib/rubocop/cop/style/exponential_notation.rb +6 -5
  325. data/lib/rubocop/cop/style/fetch_env_var.rb +34 -7
  326. data/lib/rubocop/cop/style/file_null.rb +89 -0
  327. data/lib/rubocop/cop/style/file_touch.rb +75 -0
  328. data/lib/rubocop/cop/style/float_division.rb +8 -4
  329. data/lib/rubocop/cop/style/for.rb +1 -1
  330. data/lib/rubocop/cop/style/format_string_token.rb +38 -11
  331. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  332. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  333. data/lib/rubocop/cop/style/global_vars.rb +1 -3
  334. data/lib/rubocop/cop/style/guard_clause.rb +17 -3
  335. data/lib/rubocop/cop/style/hash_conversion.rb +16 -9
  336. data/lib/rubocop/cop/style/hash_each_methods.rb +6 -8
  337. data/lib/rubocop/cop/style/hash_except.rb +35 -147
  338. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  339. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  340. data/lib/rubocop/cop/style/hash_syntax.rb +9 -3
  341. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  342. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  343. data/lib/rubocop/cop/style/identical_conditional_branches.rb +25 -6
  344. data/lib/rubocop/cop/style/if_inside_else.rb +10 -14
  345. data/lib/rubocop/cop/style/if_unless_modifier.rb +36 -9
  346. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -7
  347. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +3 -4
  348. data/lib/rubocop/cop/style/if_with_semicolon.rb +20 -9
  349. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  350. data/lib/rubocop/cop/style/inverse_methods.rb +16 -13
  351. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  352. data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
  353. data/lib/rubocop/cop/style/it_assignment.rb +93 -0
  354. data/lib/rubocop/cop/style/it_block_parameter.rb +121 -0
  355. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
  356. data/lib/rubocop/cop/style/keyword_parameters_order.rb +14 -8
  357. data/lib/rubocop/cop/style/lambda.rb +1 -0
  358. data/lib/rubocop/cop/style/lambda_call.rb +10 -4
  359. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  360. data/lib/rubocop/cop/style/map_into_array.rb +11 -3
  361. data/lib/rubocop/cop/style/map_to_hash.rb +12 -1
  362. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  363. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +28 -20
  364. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +18 -0
  365. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +8 -11
  366. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
  367. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  368. data/lib/rubocop/cop/style/min_max_comparison.rb +13 -5
  369. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  370. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
  371. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -2
  372. data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
  373. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  374. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
  375. data/lib/rubocop/cop/style/multiple_comparison.rb +52 -51
  376. data/lib/rubocop/cop/style/mutable_constant.rb +7 -8
  377. data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -5
  378. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  379. data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
  380. data/lib/rubocop/cop/style/next.rb +44 -0
  381. data/lib/rubocop/cop/style/not.rb +1 -1
  382. data/lib/rubocop/cop/style/object_then.rb +15 -15
  383. data/lib/rubocop/cop/style/one_line_conditional.rb +25 -4
  384. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  385. data/lib/rubocop/cop/style/operator_method_call.rb +5 -6
  386. data/lib/rubocop/cop/style/or_assignment.rb +3 -6
  387. data/lib/rubocop/cop/style/parallel_assignment.rb +41 -38
  388. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  389. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  390. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  391. data/lib/rubocop/cop/style/proc.rb +2 -2
  392. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  393. data/lib/rubocop/cop/style/raise_args.rb +15 -13
  394. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  395. data/lib/rubocop/cop/style/redundant_argument.rb +3 -1
  396. data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
  397. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
  398. data/lib/rubocop/cop/style/redundant_begin.rb +2 -1
  399. data/lib/rubocop/cop/style/redundant_condition.rb +95 -23
  400. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +16 -5
  401. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  402. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  403. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  404. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -9
  405. data/lib/rubocop/cop/style/redundant_format.rb +262 -0
  406. data/lib/rubocop/cop/style/redundant_freeze.rb +4 -4
  407. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  408. data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
  409. data/lib/rubocop/cop/style/redundant_line_continuation.rb +55 -19
  410. data/lib/rubocop/cop/style/redundant_parentheses.rb +86 -26
  411. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -0
  412. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  413. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  414. data/lib/rubocop/cop/style/redundant_return.rb +2 -2
  415. data/lib/rubocop/cop/style/redundant_self.rb +15 -18
  416. data/lib/rubocop/cop/style/redundant_self_assignment.rb +20 -32
  417. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
  418. data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
  419. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  420. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  421. data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
  422. data/lib/rubocop/cop/style/rescue_modifier.rb +5 -3
  423. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  424. data/lib/rubocop/cop/style/safe_navigation.rb +56 -16
  425. data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
  426. data/lib/rubocop/cop/style/select_by_regexp.rb +5 -2
  427. data/lib/rubocop/cop/style/self_assignment.rb +11 -17
  428. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  429. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  430. data/lib/rubocop/cop/style/signal_exception.rb +2 -3
  431. data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
  432. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  433. data/lib/rubocop/cop/style/single_line_do_end_block.rb +15 -4
  434. data/lib/rubocop/cop/style/single_line_methods.rb +13 -11
  435. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  436. data/lib/rubocop/cop/style/sole_nested_conditional.rb +68 -102
  437. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  438. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -1
  439. data/lib/rubocop/cop/style/string_concatenation.rb +15 -15
  440. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  441. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  442. data/lib/rubocop/cop/style/struct_inheritance.rb +8 -1
  443. data/lib/rubocop/cop/style/super_arguments.rb +66 -19
  444. data/lib/rubocop/cop/style/swap_values.rb +4 -15
  445. data/lib/rubocop/cop/style/symbol_proc.rb +3 -1
  446. data/lib/rubocop/cop/style/ternary_parentheses.rb +25 -4
  447. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -1
  448. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +11 -2
  449. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  450. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  451. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  452. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
  453. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  454. data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
  455. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  456. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  457. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  458. data/lib/rubocop/cop/team.rb +1 -1
  459. data/lib/rubocop/cop/util.rb +12 -5
  460. data/lib/rubocop/cop/utils/format_string.rb +10 -5
  461. data/lib/rubocop/cop/variable_force/assignment.rb +24 -5
  462. data/lib/rubocop/cop/variable_force/branch.rb +1 -1
  463. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  464. data/lib/rubocop/cop/variable_force/variable.rb +14 -3
  465. data/lib/rubocop/cop/variable_force/variable_table.rb +5 -5
  466. data/lib/rubocop/cop/variable_force.rb +23 -18
  467. data/lib/rubocop/cops_documentation_generator.rb +51 -25
  468. data/lib/rubocop/directive_comment.rb +45 -11
  469. data/lib/rubocop/ext/regexp_node.rb +0 -1
  470. data/lib/rubocop/formatter/disabled_config_formatter.rb +3 -2
  471. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  472. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  473. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  474. data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
  475. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  476. data/lib/rubocop/formatter/pacman_formatter.rb +2 -1
  477. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  478. data/lib/rubocop/lsp/logger.rb +2 -2
  479. data/lib/rubocop/lsp/routes.rb +10 -26
  480. data/lib/rubocop/lsp/runtime.rb +18 -50
  481. data/lib/rubocop/lsp/server.rb +0 -2
  482. data/lib/rubocop/lsp/stdin_runner.rb +85 -0
  483. data/lib/rubocop/magic_comment.rb +11 -3
  484. data/lib/rubocop/options.rb +28 -12
  485. data/lib/rubocop/path_util.rb +15 -8
  486. data/lib/rubocop/pending_cops_reporter.rb +56 -0
  487. data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
  488. data/lib/rubocop/plugin/load_error.rb +26 -0
  489. data/lib/rubocop/plugin/loader.rb +100 -0
  490. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  491. data/lib/rubocop/plugin.rb +46 -0
  492. data/lib/rubocop/rake_task.rb +4 -1
  493. data/lib/rubocop/result_cache.rb +13 -13
  494. data/lib/rubocop/rspec/cop_helper.rb +13 -1
  495. data/lib/rubocop/rspec/expect_offense.rb +15 -5
  496. data/lib/rubocop/rspec/shared_contexts.rb +38 -1
  497. data/lib/rubocop/rspec/support.rb +4 -2
  498. data/lib/rubocop/runner.rb +26 -15
  499. data/lib/rubocop/server/cache.rb +51 -13
  500. data/lib/rubocop/server/cli.rb +2 -2
  501. data/lib/rubocop/server/client_command/base.rb +10 -0
  502. data/lib/rubocop/server/client_command/exec.rb +2 -1
  503. data/lib/rubocop/server/client_command/start.rb +11 -1
  504. data/lib/rubocop/target_finder.rb +7 -2
  505. data/lib/rubocop/target_ruby.rb +17 -2
  506. data/lib/rubocop/version.rb +53 -12
  507. data/lib/rubocop.rb +43 -2
  508. data/lib/ruby_lsp/rubocop/addon.rb +75 -0
  509. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +65 -0
  510. metadata +89 -17
  511. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  512. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This module encapsulates the ability to forbid certain identifiers in a cop.
6
+ module ForbiddenIdentifiers
7
+ SIGILS = '@$' # if a variable starts with a sigil it will be removed
8
+
9
+ def forbidden_identifier?(name)
10
+ name = name.to_s.delete(SIGILS)
11
+
12
+ forbidden_identifiers.any? && forbidden_identifiers.include?(name)
13
+ end
14
+
15
+ def forbidden_identifiers
16
+ cop_config.fetch('ForbiddenIdentifiers', [])
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This module encapsulates the ability to forbid certain patterns in a cop.
6
+ module ForbiddenPattern
7
+ def forbidden_pattern?(name)
8
+ forbidden_patterns.any? { |pattern| Regexp.new(pattern).match?(name) }
9
+ end
10
+
11
+ def forbidden_patterns
12
+ cop_config.fetch('ForbiddenPatterns', [])
13
+ end
14
+ end
15
+ end
16
+ end
@@ -6,7 +6,6 @@ module RuboCop
6
6
  module FrozenStringLiteral
7
7
  module_function
8
8
 
9
- FROZEN_STRING_LITERAL = '# frozen_string_literal:'
10
9
  FROZEN_STRING_LITERAL_ENABLED = '# frozen_string_literal: true'
11
10
  FROZEN_STRING_LITERAL_TYPES_RUBY27 = %i[str dstr].freeze
12
11
 
@@ -29,7 +28,9 @@ module RuboCop
29
28
  end
30
29
 
31
30
  def uninterpolated_string?(node)
32
- node.str_type? || (node.dstr_type? && node.each_descendant(:begin).none?)
31
+ node.str_type? || (
32
+ node.dstr_type? && node.each_descendant(:begin, :ivar, :cvar, :gvar).none?
33
+ )
33
34
  end
34
35
 
35
36
  def uninterpolated_heredoc?(node)
@@ -88,7 +89,7 @@ module RuboCop
88
89
 
89
90
  if first_non_comment_token
90
91
  # `line` is 1-indexed so we need to subtract 1 to get the array index
91
- processed_source.lines[0...first_non_comment_token.line - 1]
92
+ processed_source.lines[0...(first_non_comment_token.line - 1)]
92
93
  else
93
94
  processed_source.lines
94
95
  end
@@ -25,6 +25,28 @@ module RuboCop
25
25
  (args
26
26
  (arg $_)) ...)
27
27
  PATTERN
28
+
29
+ # @!method assignment_method_declarations(node)
30
+ def_node_search :assignment_method_declarations, <<~PATTERN
31
+ (send
32
+ (lvar {#match_block_variable_name? :_1 :it}) _ ...)
33
+ PATTERN
34
+
35
+ # @!method indexed_assignment_method_declarations(node)
36
+ def_node_search :indexed_assignment_method_declarations, <<~PATTERN
37
+ (send
38
+ (send (lvar {#match_block_variable_name? :_1 :it}) _)
39
+ :[]=
40
+ literal?
41
+ _
42
+ )
43
+ PATTERN
44
+
45
+ def match_block_variable_name?(receiver_name)
46
+ gem_specification(processed_source.ast) do |block_variable_name|
47
+ return block_variable_name == receiver_name
48
+ end
49
+ end
28
50
  end
29
51
  end
30
52
  end
@@ -10,7 +10,7 @@ module RuboCop
10
10
  true
11
11
  end
12
12
 
13
- def deltas_for_first_pair(first_pair, _node)
13
+ def deltas_for_first_pair(first_pair)
14
14
  {
15
15
  separator: separator_delta(first_pair),
16
16
  value: value_delta(first_pair)
@@ -81,13 +81,7 @@ module RuboCop
81
81
  class TableAlignment
82
82
  include ValueAlignment
83
83
 
84
- def initialize
85
- self.max_key_width = 0
86
- end
87
-
88
- def deltas_for_first_pair(first_pair, node)
89
- self.max_key_width = node.keys.map { |key| key.source.length }.max
90
-
84
+ def deltas_for_first_pair(first_pair)
91
85
  separator_delta = separator_delta(first_pair, first_pair, 0)
92
86
  {
93
87
  separator: separator_delta,
@@ -97,30 +91,37 @@ module RuboCop
97
91
 
98
92
  private
99
93
 
100
- attr_accessor :max_key_width
101
-
102
94
  def key_delta(first_pair, current_pair)
103
95
  first_pair.key_delta(current_pair)
104
96
  end
105
97
 
106
98
  def hash_rocket_delta(first_pair, current_pair)
107
- first_pair.loc.column + max_key_width + 1 - current_pair.loc.operator.column
99
+ first_pair.loc.column + max_key_width(first_pair.parent) + 1 -
100
+ current_pair.loc.operator.column
108
101
  end
109
102
 
110
103
  def value_delta(first_pair, current_pair)
111
104
  correct_value_column = first_pair.key.loc.column +
112
- current_pair.delimiter(true).length +
113
- max_key_width
105
+ max_key_width(first_pair.parent) +
106
+ max_delimiter_width(first_pair.parent)
114
107
 
115
108
  current_pair.value_omission? ? 0 : correct_value_column - current_pair.value.loc.column
116
109
  end
110
+
111
+ def max_key_width(hash_node)
112
+ hash_node.keys.map { |key| key.source.length }.max
113
+ end
114
+
115
+ def max_delimiter_width(hash_node)
116
+ hash_node.pairs.map { |pair| pair.delimiter(true).length }.max
117
+ end
117
118
  end
118
119
 
119
120
  # Handles calculation of deltas when the enforced style is 'separator'.
120
121
  class SeparatorAlignment
121
122
  include ValueAlignment
122
123
 
123
- def deltas_for_first_pair(*_nodes)
124
+ def deltas_for_first_pair(_first_pair)
124
125
  {}
125
126
  end
126
127
 
@@ -11,6 +11,24 @@ module RuboCop
11
11
  DO_NOT_MIX_OMIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{OMIT_HASH_VALUE_MSG}"
12
12
  DO_NOT_MIX_EXPLICIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{EXPLICIT_HASH_VALUE_MSG}"
13
13
 
14
+ DefNode = Struct.new(:node) do
15
+ def selector
16
+ if node.loc.respond_to?(:selector)
17
+ node.loc.selector
18
+ else
19
+ node.loc.keyword
20
+ end
21
+ end
22
+
23
+ def first_argument
24
+ node.first_argument
25
+ end
26
+
27
+ def last_argument
28
+ node.last_argument
29
+ end
30
+ end
31
+
14
32
  def on_hash_for_mixed_shorthand(hash_node)
15
33
  return if ignore_mixed_hash_shorthand_syntax?(hash_node)
16
34
 
@@ -86,7 +104,7 @@ module RuboCop
86
104
  return true if !node.key.sym_type? || require_hash_value_for_around_hash_literal?(node)
87
105
 
88
106
  hash_value = node.value
89
- return true unless hash_value.send_type? || hash_value.lvar_type?
107
+ return true unless hash_value.type?(:send, :lvar)
90
108
 
91
109
  hash_key_source != hash_value.source || hash_key_source.end_with?('!', '?')
92
110
  end
@@ -109,7 +127,7 @@ module RuboCop
109
127
  return if dispatch_node.parent && parentheses?(dispatch_node.parent)
110
128
  return if last_expression?(dispatch_node) && !method_dispatch_as_argument?(dispatch_node)
111
129
 
112
- def_node = node.each_ancestor(:send, :csend, :super, :yield).first
130
+ def_node = node.each_ancestor(:call, :super, :yield).first
113
131
 
114
132
  DefNode.new(def_node) unless def_node && def_node.arguments.empty?
115
133
  end
@@ -117,7 +135,7 @@ module RuboCop
117
135
 
118
136
  def find_ancestor_method_dispatch_node(node)
119
137
  return unless (ancestor = node.parent.parent)
120
- return unless ancestor.call_type? || ancestor.super_type? || ancestor.yield_type?
138
+ return unless ancestor.type?(:call, :super, :yield)
121
139
  return if brackets?(ancestor)
122
140
 
123
141
  ancestor
@@ -150,7 +168,7 @@ module RuboCop
150
168
  parent = method_dispatch_node.parent
151
169
  return false unless parent
152
170
 
153
- parent.call_type? || parent.super_type? || parent.yield_type?
171
+ parent.type?(:call, :super, :yield)
154
172
  end
155
173
 
156
174
  def breakdown_value_types_of_hash(hash_node)
@@ -212,24 +230,6 @@ module RuboCop
212
230
  register_offense(pair_node, OMIT_HASH_VALUE_MSG, replacement)
213
231
  end
214
232
  end
215
-
216
- DefNode = Struct.new(:node) do
217
- def selector
218
- if node.loc.respond_to?(:selector)
219
- node.loc.selector
220
- else
221
- node.loc.keyword
222
- end
223
- end
224
-
225
- def first_argument
226
- node.first_argument
227
- end
228
-
229
- def last_argument
230
- node.last_argument
231
- end
232
- end
233
233
  end
234
234
  end
235
235
  # rubocop:enable Metrics/ModuleLength
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Common functionality for Style/HashExcept and Style/HashSlice cops.
6
+ # It registers an offense on methods with blocks that are equivalent
7
+ # to Hash#except or Hash#slice.
8
+ # rubocop:disable Metrics/ModuleLength
9
+ module HashSubset
10
+ include RangeHelp
11
+ extend NodePattern::Macros
12
+
13
+ RESTRICT_ON_SEND = %i[reject select filter].freeze
14
+
15
+ SUBSET_METHODS = %i[== != eql? include?].freeze
16
+ ACTIVE_SUPPORT_SUBSET_METHODS = (SUBSET_METHODS + %i[in? exclude?]).freeze
17
+
18
+ MSG = 'Use `%<prefer>s` instead.'
19
+
20
+ # @!method block_with_first_arg_check?(node)
21
+ def_node_matcher :block_with_first_arg_check?, <<~PATTERN
22
+ (block
23
+ (call _ _)
24
+ (args
25
+ $(arg _key)
26
+ $(arg _))
27
+ {
28
+ $(send
29
+ {(lvar _key) $_ _ | _ $_ (lvar _key)})
30
+ (send
31
+ $(send
32
+ {(lvar _key) $_ _ | _ $_ (lvar _key)}) :!)
33
+ })
34
+ PATTERN
35
+
36
+ def on_send(node)
37
+ offense_range, key_source = extract_offense(node)
38
+
39
+ return unless offense_range
40
+ return unless semantically_subset_method?(node)
41
+
42
+ preferred_method = "#{preferred_method_name}(#{key_source})"
43
+ add_offense(offense_range, message: format(MSG, prefer: preferred_method)) do |corrector|
44
+ corrector.replace(offense_range, preferred_method)
45
+ end
46
+ end
47
+ alias on_csend on_send
48
+
49
+ private
50
+
51
+ def semantically_subset_method?(node)
52
+ raise NotImplementedError
53
+ end
54
+
55
+ def preferred_method_name
56
+ raise NotImplementedError
57
+ end
58
+
59
+ def extract_offense(node)
60
+ block = node.parent
61
+ return unless extracts_hash_subset?(block)
62
+
63
+ except_key = except_key(block)
64
+ return if except_key.nil? || !safe_to_register_offense?(block, except_key)
65
+
66
+ [offense_range(node), except_key_source(except_key)]
67
+ end
68
+
69
+ def extracts_hash_subset?(block)
70
+ block_with_first_arg_check?(block) do |key_arg, value_arg, send_node, method|
71
+ # Only consider methods that have one argument
72
+ return false unless send_node.arguments.one?
73
+
74
+ return false unless supported_subset_method?(method)
75
+ return false if range_include?(send_node)
76
+
77
+ case method
78
+ when :include?, :exclude?
79
+ slices_key?(send_node, :first_argument, key_arg, value_arg)
80
+ when :in?
81
+ slices_key?(send_node, :receiver, key_arg, value_arg)
82
+ else
83
+ true
84
+ end
85
+ end
86
+ end
87
+
88
+ def slices_key?(send_node, method, key_arg, value_arg)
89
+ return false if using_value_variable?(send_node, value_arg)
90
+
91
+ node = method == :receiver ? send_node.receiver : send_node.first_argument
92
+ node.source == key_arg.source
93
+ end
94
+
95
+ def range_include?(send_node)
96
+ # When checking `include?`, `exclude?` and `in?` for offenses, if the receiver
97
+ # or first argument is a range, an offense should not be registered.
98
+ # ie. `(1..5).include?(k)` or `k.in?('a'..'z')`
99
+
100
+ return true if send_node.first_argument.range_type?
101
+
102
+ receiver = send_node.receiver
103
+ receiver = receiver.child_nodes.first while receiver.begin_type?
104
+ receiver.range_type?
105
+ end
106
+
107
+ def using_value_variable?(send_node, value_arg)
108
+ # If the receiver of `include?` or `exclude?`, or the first argument of `in?` is the
109
+ # hash value block argument, an offense should not be registered.
110
+ # ie. `v.include?(k)` or `k.in?(v)`
111
+ (send_node.receiver.lvar_type? && send_node.receiver.name == value_arg.name) ||
112
+ (send_node.first_argument.lvar_type? && send_node.first_argument.name == value_arg.name)
113
+ end
114
+
115
+ def supported_subset_method?(method)
116
+ if active_support_extensions_enabled?
117
+ ACTIVE_SUPPORT_SUBSET_METHODS.include?(method)
118
+ else
119
+ SUBSET_METHODS.include?(method)
120
+ end
121
+ end
122
+
123
+ def semantically_except_method?(node)
124
+ block = node.parent
125
+ body, negated = extract_body_if_negated(block.body)
126
+
127
+ if node.method?('reject')
128
+ body.method?('==') || body.method?('eql?') || included?(body, negated)
129
+ else
130
+ body.method?('!=') || not_included?(body, negated)
131
+ end
132
+ end
133
+
134
+ def semantically_slice_method?(node)
135
+ !semantically_except_method?(node)
136
+ end
137
+
138
+ def included?(body, negated)
139
+ if negated
140
+ body.method?('exclude?')
141
+ else
142
+ body.method?('include?') || body.method?('in?')
143
+ end
144
+ end
145
+
146
+ def not_included?(body, negated)
147
+ included?(body, !negated)
148
+ end
149
+
150
+ def safe_to_register_offense?(block, except_key)
151
+ body = block.body
152
+
153
+ if body.method?('==') || body.method?('!=')
154
+ except_key.type?(:sym, :str)
155
+ else
156
+ true
157
+ end
158
+ end
159
+
160
+ def extract_body_if_negated(body)
161
+ if body.method?('!')
162
+ [body.receiver, true]
163
+ else
164
+ [body, false]
165
+ end
166
+ end
167
+
168
+ def except_key_source(key)
169
+ if key.array_type?
170
+ key = if key.percent_literal?
171
+ key.each_value.map { |v| decorate_source(v) }
172
+ else
173
+ key.each_value.map(&:source)
174
+ end
175
+ return key.join(', ')
176
+ end
177
+
178
+ key.literal? ? key.source : "*#{key.source}"
179
+ end
180
+
181
+ def decorate_source(value)
182
+ return ":\"#{value.source}\"" if value.dsym_type?
183
+ return "\"#{value.source}\"" if value.dstr_type?
184
+ return ":#{value.source}" if value.sym_type?
185
+
186
+ "'#{value.source}'"
187
+ end
188
+
189
+ def except_key(node)
190
+ key_arg = node.argument_list.first.source
191
+ body, = extract_body_if_negated(node.body)
192
+ lhs, _method_name, rhs = *body
193
+
194
+ lhs.source == key_arg ? rhs : lhs
195
+ end
196
+
197
+ def offense_range(node)
198
+ range_between(node.loc.selector.begin_pos, node.parent.loc.end.end_pos)
199
+ end
200
+ end
201
+ # rubocop:enable Metrics/ModuleLength
202
+ end
203
+ end
@@ -9,6 +9,80 @@ module RuboCop
9
9
 
10
10
  RESTRICT_ON_SEND = %i[[] to_h].freeze
11
11
 
12
+ # Internal helper class to hold match data
13
+ Captures = Struct.new(:transformed_argname, :transforming_body_expr, :unchanged_body_expr) do
14
+ def noop_transformation?
15
+ transforming_body_expr.lvar_type? &&
16
+ transforming_body_expr.children == [transformed_argname]
17
+ end
18
+
19
+ def transformation_uses_both_args?
20
+ transforming_body_expr.descendants.include?(unchanged_body_expr)
21
+ end
22
+
23
+ def use_transformed_argname?
24
+ transforming_body_expr.each_descendant(:lvar).any? do |node|
25
+ node.source == transformed_argname.to_s
26
+ end
27
+ end
28
+ end
29
+
30
+ # Internal helper class to hold autocorrect data
31
+ Autocorrection = Struct.new(:match, :block_node, :leading, :trailing) do
32
+ def self.from_each_with_object(node, match)
33
+ new(match, node, 0, 0)
34
+ end
35
+
36
+ def self.from_hash_brackets_map(node, match)
37
+ new(match, node.children.last, 'Hash['.length, ']'.length)
38
+ end
39
+
40
+ def self.from_map_to_h(node, match)
41
+ if node.parent&.block_type? && node.parent.send_node == node
42
+ strip_trailing_chars = 0
43
+ else
44
+ map_range = node.children.first.source_range
45
+ node_range = node.source_range
46
+ strip_trailing_chars = node_range.end_pos - map_range.end_pos
47
+ end
48
+
49
+ new(match, node.children.first, 0, strip_trailing_chars)
50
+ end
51
+
52
+ def self.from_to_h(node, match)
53
+ new(match, node, 0, 0)
54
+ end
55
+
56
+ def strip_prefix_and_suffix(node, corrector)
57
+ expression = node.source_range
58
+ corrector.remove_leading(expression, leading)
59
+ corrector.remove_trailing(expression, trailing)
60
+ end
61
+
62
+ def set_new_method_name(new_method_name, corrector)
63
+ range = block_node.send_node.loc.selector
64
+ if (send_end = block_node.send_node.loc.end)
65
+ # If there are arguments (only true in the `each_with_object`
66
+ # case)
67
+ range = range.begin.join(send_end)
68
+ end
69
+ corrector.replace(range, new_method_name)
70
+ end
71
+
72
+ def set_new_arg_name(transformed_argname, corrector)
73
+ corrector.replace(block_node.arguments, "|#{transformed_argname}|")
74
+ end
75
+
76
+ def set_new_body_expression(transforming_body_expr, corrector)
77
+ body_source = transforming_body_expr.source
78
+ if transforming_body_expr.hash_type? && !transforming_body_expr.braces?
79
+ body_source = "{ #{body_source} }"
80
+ end
81
+
82
+ corrector.replace(block_node.body, body_source)
83
+ end
84
+ end
85
+
12
86
  # @!method array_receiver?(node)
13
87
  def_node_matcher :array_receiver?, <<~PATTERN
14
88
  {(array ...) (send _ :each_with_index) (send _ :with_index _ ?) (send _ :zip ...)}
@@ -113,80 +187,6 @@ module RuboCop
113
187
  correction.set_new_arg_name(captures.transformed_argname, corrector)
114
188
  correction.set_new_body_expression(captures.transforming_body_expr, corrector)
115
189
  end
116
-
117
- # Internal helper class to hold match data
118
- Captures = Struct.new(:transformed_argname, :transforming_body_expr, :unchanged_body_expr) do
119
- def noop_transformation?
120
- transforming_body_expr.lvar_type? &&
121
- transforming_body_expr.children == [transformed_argname]
122
- end
123
-
124
- def transformation_uses_both_args?
125
- transforming_body_expr.descendants.include?(unchanged_body_expr)
126
- end
127
-
128
- def use_transformed_argname?
129
- transforming_body_expr.each_descendant(:lvar).any? do |node|
130
- node.source == transformed_argname.to_s
131
- end
132
- end
133
- end
134
-
135
- # Internal helper class to hold autocorrect data
136
- Autocorrection = Struct.new(:match, :block_node, :leading, :trailing) do
137
- def self.from_each_with_object(node, match)
138
- new(match, node, 0, 0)
139
- end
140
-
141
- def self.from_hash_brackets_map(node, match)
142
- new(match, node.children.last, 'Hash['.length, ']'.length)
143
- end
144
-
145
- def self.from_map_to_h(node, match)
146
- if node.parent&.block_type? && node.parent.send_node == node
147
- strip_trailing_chars = 0
148
- else
149
- map_range = node.children.first.source_range
150
- node_range = node.source_range
151
- strip_trailing_chars = node_range.end_pos - map_range.end_pos
152
- end
153
-
154
- new(match, node.children.first, 0, strip_trailing_chars)
155
- end
156
-
157
- def self.from_to_h(node, match)
158
- new(match, node, 0, 0)
159
- end
160
-
161
- def strip_prefix_and_suffix(node, corrector)
162
- expression = node.source_range
163
- corrector.remove_leading(expression, leading)
164
- corrector.remove_trailing(expression, trailing)
165
- end
166
-
167
- def set_new_method_name(new_method_name, corrector)
168
- range = block_node.send_node.loc.selector
169
- if (send_end = block_node.send_node.loc.end)
170
- # If there are arguments (only true in the `each_with_object`
171
- # case)
172
- range = range.begin.join(send_end)
173
- end
174
- corrector.replace(range, new_method_name)
175
- end
176
-
177
- def set_new_arg_name(transformed_argname, corrector)
178
- corrector.replace(block_node.arguments, "|#{transformed_argname}|")
179
- end
180
-
181
- def set_new_body_expression(transforming_body_expr, corrector)
182
- body_source = transforming_body_expr.source
183
- if transforming_body_expr.hash_type? && !transforming_body_expr.braces?
184
- body_source = "{ #{body_source} }"
185
- end
186
-
187
- corrector.replace(block_node.body, body_source)
188
- end
189
- end
190
190
  end
191
191
  end
192
192
  end
@@ -25,23 +25,28 @@ module RuboCop
25
25
  config.for_cop('Layout/LineLength')['AllowURI']
26
26
  end
27
27
 
28
- def allowed_uri_position?(line, uri_range)
29
- uri_range.begin < max_line_length && uri_range.end == line_length(line)
28
+ def allow_qualified_name?
29
+ config.for_cop('Layout/LineLength')['AllowQualifiedName']
30
+ end
31
+
32
+ def allowed_position?(line, range)
33
+ range.begin < max_line_length && range.end == line_length(line)
30
34
  end
31
35
 
32
36
  def line_length(line)
33
37
  line.length + indentation_difference(line)
34
38
  end
35
39
 
36
- def find_excessive_uri_range(line)
37
- last_uri_match = match_uris(line).last
38
- return nil unless last_uri_match
40
+ def find_excessive_range(line, type)
41
+ last_match = (type == :uri ? match_uris(line) : match_qualified_names(line)).last
42
+ return nil unless last_match
39
43
 
40
- begin_position, end_position = last_uri_match.offset(0).map do |pos|
41
- pos + indentation_difference(line)
42
- end
44
+ begin_position, end_position = last_match.offset(0)
45
+ end_position = extend_end_position(line, end_position)
43
46
 
44
- end_position = extend_uri_end_position(line, end_position)
47
+ line_indentation_difference = indentation_difference(line)
48
+ begin_position += line_indentation_difference
49
+ end_position += line_indentation_difference
45
50
 
46
51
  return nil if begin_position < max_line_length && end_position < max_line_length
47
52
 
@@ -56,6 +61,14 @@ module RuboCop
56
61
  matches
57
62
  end
58
63
 
64
+ def match_qualified_names(string)
65
+ matches = []
66
+ string.scan(qualified_name_regexp) do
67
+ matches << $LAST_MATCH_INFO
68
+ end
69
+ matches
70
+ end
71
+
59
72
  def indentation_difference(line)
60
73
  return 0 unless tab_indentation_width
61
74
 
@@ -69,7 +82,7 @@ module RuboCop
69
82
  index * (tab_indentation_width - 1)
70
83
  end
71
84
 
72
- def extend_uri_end_position(line, end_position)
85
+ def extend_end_position(line, end_position)
73
86
  # Extend the end position YARD comments with linked URLs of the form {<uri> <title>}
74
87
  if line&.match(/{(\s|\S)*}$/)
75
88
  match = line[end_position..line_length(line)]&.match(/(\s|\S)*}/)
@@ -100,6 +113,10 @@ module RuboCop
100
113
  end
101
114
  end
102
115
 
116
+ def qualified_name_regexp
117
+ /\b(?:[A-Z][A-Za-z0-9_]*::)+[A-Za-z_][A-Za-z0-9_]*\b/
118
+ end
119
+
103
120
  def valid_uri?(uri_ish_string)
104
121
  URI.parse(uri_ish_string)
105
122
  true
@@ -30,12 +30,13 @@ module RuboCop
30
30
  end
31
31
 
32
32
  alias on_numblock on_block
33
+ alias on_itblock on_block
33
34
 
34
35
  private
35
36
 
36
37
  # @!method define_method?(node)
37
38
  def_node_matcher :define_method?, <<~PATTERN
38
- ({block numblock}
39
+ (any_block
39
40
  (send nil? :define_method ({sym str} $_)) _ _)
40
41
  PATTERN
41
42