rubocop 1.69.2 → 1.75.4

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 (372) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +4 -4
  4. data/config/default.yml +183 -41
  5. data/config/internal_affairs.yml +20 -0
  6. data/config/obsoletion.yml +3 -1
  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 +1 -1
  11. data/lib/rubocop/comment_config.rb +2 -2
  12. data/lib/rubocop/config.rb +52 -10
  13. data/lib/rubocop/config_loader.rb +52 -9
  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 +1 -1
  20. data/lib/rubocop/cop/base.rb +6 -0
  21. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  22. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  23. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  24. data/lib/rubocop/cop/internal_affairs/example_description.rb +8 -4
  25. data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
  26. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  27. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  28. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  29. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  30. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  31. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +230 -0
  32. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +91 -0
  33. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  34. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  35. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  36. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  37. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  38. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  39. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  40. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +13 -2
  41. data/lib/rubocop/cop/internal_affairs.rb +6 -16
  42. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  43. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -8
  44. data/lib/rubocop/cop/layout/block_alignment.rb +3 -1
  45. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  46. data/lib/rubocop/cop/layout/class_structure.rb +9 -9
  47. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +4 -4
  48. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  49. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  50. data/lib/rubocop/cop/layout/else_alignment.rb +2 -2
  51. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +2 -2
  52. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  53. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +28 -1
  54. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
  55. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
  56. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
  57. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  58. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  59. data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
  60. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  61. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  62. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  63. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  64. data/lib/rubocop/cop/layout/hash_alignment.rb +7 -5
  65. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
  66. data/lib/rubocop/cop/layout/indentation_width.rb +1 -0
  67. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  68. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  69. data/lib/rubocop/cop/layout/line_length.rb +9 -4
  70. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
  71. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  72. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  73. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
  74. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
  75. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  76. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +1 -1
  77. data/lib/rubocop/cop/layout/redundant_line_break.rb +16 -11
  78. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -5
  79. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  80. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  81. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  82. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  83. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  84. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -0
  85. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  86. data/lib/rubocop/cop/layout/space_around_operators.rb +7 -4
  87. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
  88. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  89. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  90. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -0
  91. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  92. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  93. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
  94. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  95. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +1 -1
  96. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  97. data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -5
  98. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  99. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  100. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
  101. data/lib/rubocop/cop/lint/debugger.rb +3 -3
  102. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  103. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  104. data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -17
  105. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  106. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  107. data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
  108. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  109. data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
  110. data/lib/rubocop/cop/lint/float_comparison.rb +6 -8
  111. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  112. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  113. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  114. data/lib/rubocop/cop/lint/literal_as_condition.rb +117 -9
  115. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
  116. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
  117. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  118. data/lib/rubocop/cop/lint/mixed_case_range.rb +3 -3
  119. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  120. data/lib/rubocop/cop/lint/nested_method_definition.rb +9 -5
  121. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  122. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -3
  123. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
  124. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +18 -31
  125. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  126. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
  127. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  128. data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
  129. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  130. data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
  131. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  132. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +261 -0
  133. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  134. data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
  135. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  136. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  137. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -1
  138. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +8 -1
  139. data/lib/rubocop/cop/lint/shared_mutable_default.rb +76 -0
  140. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  141. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
  142. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  143. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  144. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
  145. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  146. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -4
  147. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +3 -1
  148. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  149. data/lib/rubocop/cop/lint/unreachable_code.rb +2 -1
  150. data/lib/rubocop/cop/lint/unreachable_loop.rb +6 -6
  151. data/lib/rubocop/cop/lint/useless_access_modifier.rb +5 -4
  152. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  153. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +71 -0
  154. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  155. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  156. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
  157. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  158. data/lib/rubocop/cop/lint/void.rb +12 -9
  159. data/lib/rubocop/cop/message_annotator.rb +7 -3
  160. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  161. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  162. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  163. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  164. data/lib/rubocop/cop/metrics/method_length.rb +9 -1
  165. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  166. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  167. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  168. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  169. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  170. data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
  171. data/lib/rubocop/cop/mixin/check_line_breakable.rb +13 -13
  172. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -2
  173. data/lib/rubocop/cop/mixin/comments_help.rb +4 -2
  174. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  175. data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
  176. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  177. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  178. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
  179. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +0 -1
  180. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
  181. data/lib/rubocop/cop/mixin/hash_subset.rb +203 -0
  182. data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
  183. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  184. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -0
  185. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  186. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +48 -24
  187. data/lib/rubocop/cop/mixin/range_help.rb +15 -3
  188. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  189. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
  190. data/lib/rubocop/cop/mixin/string_help.rb +2 -2
  191. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  192. data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
  193. data/lib/rubocop/cop/mixin/trailing_comma.rb +16 -4
  194. data/lib/rubocop/cop/naming/block_forwarding.rb +19 -15
  195. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  196. data/lib/rubocop/cop/naming/method_name.rb +64 -8
  197. data/lib/rubocop/cop/naming/predicate_name.rb +44 -0
  198. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -3
  199. data/lib/rubocop/cop/naming/variable_name.rb +51 -6
  200. data/lib/rubocop/cop/registry.rb +9 -6
  201. data/lib/rubocop/cop/security/compound_hash.rb +1 -0
  202. data/lib/rubocop/cop/style/access_modifier_declarations.rb +34 -5
  203. data/lib/rubocop/cop/style/accessor_grouping.rb +19 -5
  204. data/lib/rubocop/cop/style/and_or.rb +1 -1
  205. data/lib/rubocop/cop/style/arguments_forwarding.rb +44 -28
  206. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  207. data/lib/rubocop/cop/style/array_intersect.rb +39 -28
  208. data/lib/rubocop/cop/style/block_delimiters.rb +9 -21
  209. data/lib/rubocop/cop/style/class_and_module_children.rb +52 -11
  210. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  211. data/lib/rubocop/cop/style/collection_methods.rb +2 -1
  212. data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
  213. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  214. data/lib/rubocop/cop/style/commented_keyword.rb +12 -5
  215. data/lib/rubocop/cop/style/comparable_between.rb +75 -0
  216. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  217. data/lib/rubocop/cop/style/conditional_assignment.rb +20 -6
  218. data/lib/rubocop/cop/style/documentation.rb +1 -1
  219. data/lib/rubocop/cop/style/double_negation.rb +4 -4
  220. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  221. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  222. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  223. data/lib/rubocop/cop/style/empty_literal.rb +5 -1
  224. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  225. data/lib/rubocop/cop/style/endless_method.rb +163 -18
  226. data/lib/rubocop/cop/style/eval_with_location.rb +4 -4
  227. data/lib/rubocop/cop/style/exact_regexp_match.rb +3 -10
  228. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  229. data/lib/rubocop/cop/style/explicit_block_argument.rb +16 -3
  230. data/lib/rubocop/cop/style/exponential_notation.rb +3 -3
  231. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  232. data/lib/rubocop/cop/style/float_division.rb +8 -4
  233. data/lib/rubocop/cop/style/for.rb +1 -0
  234. data/lib/rubocop/cop/style/format_string_token.rb +38 -11
  235. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  236. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  237. data/lib/rubocop/cop/style/guard_clause.rb +2 -1
  238. data/lib/rubocop/cop/style/hash_each_methods.rb +6 -8
  239. data/lib/rubocop/cop/style/hash_except.rb +24 -148
  240. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  241. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  242. data/lib/rubocop/cop/style/hash_syntax.rb +9 -3
  243. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  244. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  245. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  246. data/lib/rubocop/cop/style/if_inside_else.rb +10 -13
  247. data/lib/rubocop/cop/style/if_unless_modifier.rb +5 -5
  248. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +2 -2
  249. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  250. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  251. data/lib/rubocop/cop/style/inverse_methods.rb +15 -11
  252. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  253. data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
  254. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  255. data/lib/rubocop/cop/style/it_block_parameter.rb +100 -0
  256. data/lib/rubocop/cop/style/keyword_parameters_order.rb +14 -8
  257. data/lib/rubocop/cop/style/lambda.rb +1 -0
  258. data/lib/rubocop/cop/style/lambda_call.rb +7 -2
  259. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  260. data/lib/rubocop/cop/style/map_into_array.rb +5 -2
  261. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  262. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  263. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +23 -16
  264. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  265. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
  266. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
  267. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  268. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  269. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -2
  270. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
  271. data/lib/rubocop/cop/style/multiple_comparison.rb +26 -20
  272. data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
  273. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
  274. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  275. data/lib/rubocop/cop/style/next.rb +44 -0
  276. data/lib/rubocop/cop/style/object_then.rb +14 -15
  277. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  278. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -5
  279. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  280. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  281. data/lib/rubocop/cop/style/proc.rb +2 -2
  282. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  283. data/lib/rubocop/cop/style/raise_args.rb +14 -12
  284. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  285. data/lib/rubocop/cop/style/redundant_begin.rb +2 -1
  286. data/lib/rubocop/cop/style/redundant_condition.rb +59 -2
  287. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +16 -5
  288. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  289. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  290. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  291. data/lib/rubocop/cop/style/redundant_format.rb +257 -0
  292. data/lib/rubocop/cop/style/redundant_freeze.rb +3 -3
  293. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  294. data/lib/rubocop/cop/style/redundant_line_continuation.rb +34 -16
  295. data/lib/rubocop/cop/style/redundant_parentheses.rb +48 -16
  296. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
  297. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  298. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  299. data/lib/rubocop/cop/style/redundant_self.rb +1 -0
  300. data/lib/rubocop/cop/style/redundant_self_assignment.rb +14 -28
  301. data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
  302. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  303. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  304. data/lib/rubocop/cop/style/rescue_modifier.rb +3 -0
  305. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  306. data/lib/rubocop/cop/style/safe_navigation.rb +20 -5
  307. data/lib/rubocop/cop/style/select_by_regexp.rb +4 -1
  308. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  309. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  310. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  311. data/lib/rubocop/cop/style/single_line_do_end_block.rb +4 -3
  312. data/lib/rubocop/cop/style/single_line_methods.rb +6 -7
  313. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  314. data/lib/rubocop/cop/style/sole_nested_conditional.rb +41 -106
  315. data/lib/rubocop/cop/style/string_concatenation.rb +2 -2
  316. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  317. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  318. data/lib/rubocop/cop/style/super_arguments.rb +66 -19
  319. data/lib/rubocop/cop/style/symbol_proc.rb +2 -0
  320. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  321. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -1
  322. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +11 -2
  323. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  324. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  325. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  326. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  327. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  328. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  329. data/lib/rubocop/cop/util.rb +12 -5
  330. data/lib/rubocop/cop/utils/format_string.rb +10 -5
  331. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  332. data/lib/rubocop/cop/variable_force/variable.rb +10 -3
  333. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  334. data/lib/rubocop/cop/variable_force.rb +1 -1
  335. data/lib/rubocop/cops_documentation_generator.rb +31 -16
  336. data/lib/rubocop/directive_comment.rb +45 -11
  337. data/lib/rubocop/ext/regexp_node.rb +0 -1
  338. data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
  339. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  340. data/lib/rubocop/formatter/pacman_formatter.rb +1 -1
  341. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  342. data/lib/rubocop/lsp/logger.rb +2 -2
  343. data/lib/rubocop/lsp/routes.rb +7 -23
  344. data/lib/rubocop/lsp/runtime.rb +18 -50
  345. data/lib/rubocop/lsp/server.rb +0 -2
  346. data/lib/rubocop/lsp/stdin_runner.rb +85 -0
  347. data/lib/rubocop/magic_comment.rb +8 -0
  348. data/lib/rubocop/options.rb +28 -12
  349. data/lib/rubocop/path_util.rb +15 -8
  350. data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
  351. data/lib/rubocop/plugin/load_error.rb +26 -0
  352. data/lib/rubocop/plugin/loader.rb +100 -0
  353. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  354. data/lib/rubocop/plugin.rb +46 -0
  355. data/lib/rubocop/rake_task.rb +4 -1
  356. data/lib/rubocop/result_cache.rb +13 -13
  357. data/lib/rubocop/rspec/cop_helper.rb +13 -1
  358. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  359. data/lib/rubocop/rspec/shared_contexts.rb +38 -1
  360. data/lib/rubocop/rspec/support.rb +4 -2
  361. data/lib/rubocop/runner.rb +10 -7
  362. data/lib/rubocop/server/cache.rb +47 -11
  363. data/lib/rubocop/server/cli.rb +2 -2
  364. data/lib/rubocop/target_finder.rb +7 -2
  365. data/lib/rubocop/target_ruby.rb +16 -1
  366. data/lib/rubocop/version.rb +30 -8
  367. data/lib/rubocop.rb +16 -1
  368. data/lib/ruby_lsp/rubocop/addon.rb +75 -0
  369. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +65 -0
  370. metadata +59 -16
  371. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  372. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -101,7 +101,7 @@ module RuboCop
101
101
  ranges << loc.expression
102
102
  elsif literal.heredoc?
103
103
  ranges << loc.heredoc_body
104
- elsif loc.respond_to?(:begin) && loc.begin
104
+ elsif (loc.respond_to?(:begin) && loc.begin) || ignored_parent?(literal)
105
105
  ranges << loc.expression
106
106
  end
107
107
  end
@@ -127,6 +127,12 @@ module RuboCop
127
127
  comment_ranges(processed_source.comments)
128
128
  end
129
129
 
130
+ def ignored_parent?(node)
131
+ return false unless node.parent
132
+
133
+ node.parent.type?(:regexp, :xstr)
134
+ end
135
+
130
136
  def no_space_style?
131
137
  cop_config['EnforcedStyle'] == 'no_space'
132
138
  end
@@ -102,7 +102,7 @@ module RuboCop
102
102
 
103
103
  def strings_concatenated_with_backslash?(dstr_node)
104
104
  dstr_node.multiline? &&
105
- dstr_node.children.all? { |c| c.str_type? || c.dstr_type? } &&
105
+ dstr_node.children.all? { |c| c.type?(:str, :dstr) } &&
106
106
  dstr_node.children.none?(&:multiline?)
107
107
  end
108
108
 
@@ -127,7 +127,7 @@ module RuboCop
127
127
 
128
128
  def base_column(child)
129
129
  grandparent = child.parent.parent
130
- if grandparent&.type == :pair
130
+ if grandparent&.pair_type?
131
131
  grandparent.loc.column
132
132
  else
133
133
  child.source_range.source_line =~ /\S/
@@ -75,6 +75,7 @@ module RuboCop
75
75
  check_for_breakable_block(node)
76
76
  end
77
77
  alias on_numblock on_block
78
+ alias on_itblock on_block
78
79
 
79
80
  def on_str(node)
80
81
  check_for_breakable_str(node)
@@ -90,7 +91,9 @@ module RuboCop
90
91
  alias on_array on_potential_breakable_node
91
92
  alias on_hash on_potential_breakable_node
92
93
  alias on_send on_potential_breakable_node
94
+ alias on_csend on_potential_breakable_node
93
95
  alias on_def on_potential_breakable_node
96
+ alias on_defs on_potential_breakable_node
94
97
 
95
98
  def on_new_investigation
96
99
  return unless processed_source.raw_source.include?(';')
@@ -208,7 +211,7 @@ module RuboCop
208
211
  # are not bisected.
209
212
  # If the string contains spaces, use them to determine a place for a clean break;
210
213
  # otherwise, the string will be broken at the line length limit.
211
- def breakable_string_range(node) # rubocop:disable Metrics/AbcSize
214
+ def breakable_string_range(node)
212
215
  source_range = node.source_range
213
216
  relevant_substr = largest_possible_string(node)
214
217
 
@@ -220,13 +223,13 @@ module RuboCop
220
223
  adjustment = max - source_range.last_column - 3
221
224
  return if adjustment.abs > source_range.size
222
225
 
223
- source_range.adjust(end_pos: max - source_range.last_column - 3)
226
+ source_range.adjust(end_pos: adjustment)
224
227
  end
225
228
  end
226
229
 
227
230
  def breakable_dstr_begin_position(node)
228
231
  source_range = node.source_range
229
- source_range.begin_pos if source_range.begin_pos < max && source_range.end_pos >= max
232
+ source_range.begin_pos if source_range.column < max && source_range.last_column >= max
230
233
  end
231
234
 
232
235
  def breakable_range_by_line_index
@@ -369,7 +372,9 @@ module RuboCop
369
372
 
370
373
  def string_delimiter(node)
371
374
  delimiter = node.loc.begin
372
- delimiter ||= node.parent.loc.begin if node.parent&.dstr_type?
375
+ if node.parent&.dstr_type? && node.parent.loc.respond_to?(:begin)
376
+ delimiter ||= node.parent.loc.begin
377
+ end
373
378
  delimiter = delimiter&.source
374
379
 
375
380
  delimiter if %w[' "].include?(delimiter)
@@ -69,6 +69,7 @@ module RuboCop
69
69
  end
70
70
 
71
71
  alias on_numblock on_block
72
+ alias on_itblock on_block
72
73
 
73
74
  private
74
75
 
@@ -52,7 +52,7 @@ module RuboCop
52
52
  def on_hash(node)
53
53
  # This cop only deals with hashes wrapped by a set of curly
54
54
  # braces like {foo: 1}. That is, not a kwargs hashes.
55
- # Style/MultilineMethodArgumentLineBreaks handles those.
55
+ # Layout/MultilineMethodArgumentLineBreaks handles those.
56
56
  return unless starts_with_curly_brace?(node)
57
57
  return unless node.loc.begin
58
58
 
@@ -33,6 +33,18 @@ module RuboCop
33
33
  #
34
34
  # @example AllowMultilineFinalElement: false (default)
35
35
  #
36
+ # # bad
37
+ # foo(a, b,
38
+ # c
39
+ # )
40
+ #
41
+ # # bad
42
+ # foo(
43
+ # a, b, {
44
+ # foo: "bar",
45
+ # }
46
+ # )
47
+ #
36
48
  # # good
37
49
  # foo(
38
50
  # a,
@@ -44,6 +56,18 @@ module RuboCop
44
56
  #
45
57
  # @example AllowMultilineFinalElement: true
46
58
  #
59
+ # # bad
60
+ # foo(a, b,
61
+ # c
62
+ # )
63
+ #
64
+ # # good
65
+ # foo(
66
+ # a, b, {
67
+ # foo: "bar",
68
+ # }
69
+ # )
70
+ #
47
71
  # # good
48
72
  # foo(
49
73
  # a,
@@ -75,6 +99,7 @@ module RuboCop
75
99
 
76
100
  check_line_breaks(node, args, ignore_last: ignore_last_element?)
77
101
  end
102
+ alias on_csend on_send
78
103
 
79
104
  private
80
105
 
@@ -109,6 +109,7 @@ module RuboCop
109
109
  def on_send(node)
110
110
  check_brace_layout(node)
111
111
  end
112
+ alias on_csend on_send
112
113
 
113
114
  private
114
115
 
@@ -100,7 +100,7 @@ module RuboCop
100
100
 
101
101
  def extra_indentation(given_style, parent)
102
102
  if given_style == :indented_relative_to_receiver
103
- if parent && (parent.splat_type? || parent.kwsplat_type?)
103
+ if parent&.type?(:splat, :kwsplat)
104
104
  configured_indentation_width - parent.loc.operator.length
105
105
  else
106
106
  configured_indentation_width
@@ -216,7 +216,7 @@ module RuboCop
216
216
 
217
217
  def get_dot_right_above(node)
218
218
  node.each_ancestor.find do |a|
219
- dot = a.loc.respond_to?(:dot) && a.loc.dot
219
+ dot = a.loc.dot if a.loc?(:dot)
220
220
  next unless dot
221
221
 
222
222
  dot.line == node.loc.dot.line - 1 && dot.column == node.loc.dot.column
@@ -224,7 +224,7 @@ module RuboCop
224
224
  end
225
225
 
226
226
  def find_multiline_block_chain_node(node)
227
- return unless (block_node = node.each_descendant(:block, :numblock).first)
227
+ return unless (block_node = node.each_descendant(:any_block).first)
228
228
  return unless block_node.multiline? && block_node.parent.call_type?
229
229
 
230
230
  if node.receiver.call_type?
@@ -239,7 +239,7 @@ module RuboCop
239
239
  node = node.receiver while node.receiver
240
240
  # ascend to first call which has a dot
241
241
  node = node.parent
242
- node = node.parent until node.loc.respond_to?(:dot) && node.loc.dot
242
+ node = node.parent until node.loc?(:dot)
243
243
 
244
244
  node
245
245
  end
@@ -65,6 +65,7 @@ module RuboCop
65
65
 
66
66
  check_line_breaks(node, node.arguments, ignore_last: ignore_last_element?)
67
67
  end
68
+ alias on_defs on_def
68
69
 
69
70
  private
70
71
 
@@ -118,7 +118,7 @@ module RuboCop
118
118
  end
119
119
 
120
120
  def right_hand_side(send_node)
121
- send_node.first_argument.source_range
121
+ send_node.first_argument&.source_range
122
122
  end
123
123
  end
124
124
  end
@@ -6,25 +6,29 @@ module RuboCop
6
6
  # Checks whether certain expressions, e.g. method calls, that could fit
7
7
  # completely on a single line, are broken up into multiple lines unnecessarily.
8
8
  #
9
- # @example any configuration
9
+ # @example
10
10
  # # bad
11
11
  # foo(
12
12
  # a,
13
13
  # b
14
14
  # )
15
15
  #
16
+ # # good
17
+ # foo(a, b)
18
+ #
19
+ # # bad
16
20
  # puts 'string that fits on ' \
17
21
  # 'a single line'
18
22
  #
23
+ # # good
24
+ # puts 'string that fits on a single line'
25
+ #
26
+ # # bad
19
27
  # things
20
28
  # .select { |thing| thing.cond? }
21
29
  # .join('-')
22
30
  #
23
31
  # # good
24
- # foo(a, b)
25
- #
26
- # puts 'string that fits on a single line'
27
- #
28
32
  # things.select { |thing| thing.cond? }.join('-')
29
33
  #
30
34
  # @example InspectBlocks: false (default)
@@ -103,24 +107,25 @@ module RuboCop
103
107
 
104
108
  def configured_to_not_be_inspected?(node)
105
109
  return true if other_cop_takes_precedence?(node)
110
+ return false if cop_config['InspectBlocks']
106
111
 
107
- !cop_config['InspectBlocks'] && (node.block_type? ||
108
- any_descendant?(node, :block, &:multiline?))
112
+ node.any_block_type? || any_descendant?(node, :any_block, &:multiline?)
109
113
  end
110
114
 
111
115
  def other_cop_takes_precedence?(node)
112
- single_line_block_chain_enabled? && any_descendant?(node, :block) do |block_node|
116
+ single_line_block_chain_enabled? && any_descendant?(node, :any_block) do |block_node|
113
117
  block_node.parent.send_type? && block_node.parent.loc.dot && !block_node.multiline?
114
118
  end
115
119
  end
116
120
 
117
121
  def single_line_block_chain_enabled?
118
- @config.for_cop('Layout/SingleLineBlockChain')['Enabled']
122
+ @config.cop_enabled?('Layout/SingleLineBlockChain')
119
123
  end
120
124
 
121
125
  def convertible_block?(node)
122
- parent = node.parent
123
- parent&.block_type? && node == parent.send_node &&
126
+ return false unless (parent = node.parent)
127
+
128
+ parent.any_block_type? && node == parent.send_node &&
124
129
  (node.parenthesized? || !node.arguments?)
125
130
  end
126
131
  end
@@ -29,8 +29,7 @@ module RuboCop
29
29
  MSG = '`%<kw_loc>s` at %<kw_loc_line>d, %<kw_loc_column>d is not ' \
30
30
  'aligned with `%<beginning>s` at ' \
31
31
  '%<begin_loc_line>d, %<begin_loc_column>d.'
32
- ANCESTOR_TYPES = %i[kwbegin def defs class module block numblock].freeze
33
- ANCESTOR_TYPES_WITH_ACCESS_MODIFIERS = %i[def defs].freeze
32
+ ANCESTOR_TYPES = %i[kwbegin any_def class module any_block].freeze
34
33
  ALTERNATIVE_ACCESS_MODIFIERS = %i[public_class_method private_class_method].freeze
35
34
 
36
35
  def on_resbody(node)
@@ -96,7 +95,7 @@ module RuboCop
96
95
  def alignment_source(node, starting_loc)
97
96
  ending_loc =
98
97
  case node.type
99
- when :block, :numblock, :kwbegin
98
+ when :block, :numblock, :itblock, :kwbegin
100
99
  node.loc.begin
101
100
  when :def, :defs, :class, :module,
102
101
  :lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn
@@ -162,8 +161,7 @@ module RuboCop
162
161
  end
163
162
 
164
163
  def access_modifier_node(node)
165
- return nil unless
166
- ANCESTOR_TYPES_WITH_ACCESS_MODIFIERS.include?(node.type)
164
+ return nil unless node.any_def_type?
167
165
 
168
166
  access_modifier_node = node.ancestors.first
169
167
  return nil unless access_modifier?(access_modifier_node)
@@ -39,7 +39,7 @@ module RuboCop
39
39
 
40
40
  def offending_range(node)
41
41
  receiver = node.receiver
42
- return unless receiver&.block_type?
42
+ return unless receiver&.any_block_type?
43
43
 
44
44
  receiver_location = receiver.loc
45
45
  closing_block_delimiter_line_num = receiver_location.end.line
@@ -3,9 +3,9 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Checks for colon (:) not followed by some kind of space.
6
+ # Checks for colon (`:`) not followed by some kind of space.
7
7
  # N.B. this cop does not handle spaces after a ternary operator, which are
8
- # instead handled by Layout/SpaceAroundOperators.
8
+ # instead handled by `Layout/SpaceAroundOperators`.
9
9
  #
10
10
  # @example
11
11
  # # bad
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Checks for comma (,) not followed by some kind of space.
6
+ # Checks for comma (`,`) not followed by some kind of space.
7
7
  #
8
8
  # @example
9
9
  #
@@ -22,7 +22,7 @@ module RuboCop
22
22
 
23
23
  def on_def(node)
24
24
  args = node.arguments
25
- return unless args.loc.begin&.is?('(')
25
+ return unless args.parenthesized_call?
26
26
 
27
27
  expr = args.source_range
28
28
  pos_before_left_paren = range_between(expr.begin_pos - 1, expr.begin_pos)
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Checks for semicolon (;) not followed by some kind of space.
6
+ # Checks for semicolon (`;`) not followed by some kind of space.
7
7
  #
8
8
  # @example
9
9
  # # bad
@@ -36,6 +36,7 @@ module RuboCop
36
36
  ACCEPT_LEFT_PAREN = %w[break defined? next not rescue return super yield].freeze
37
37
  ACCEPT_LEFT_SQUARE_BRACKET = %w[super yield].freeze
38
38
  ACCEPT_NAMESPACE_OPERATOR = 'super'
39
+ RESTRICT_ON_SEND = %i[!].freeze
39
40
 
40
41
  def on_and(node)
41
42
  check(node, [:operator].freeze) if node.keyword?
@@ -51,7 +51,7 @@ module RuboCop
51
51
  alias on_csend on_send
52
52
 
53
53
  def on_const(node)
54
- return unless node.loc.respond_to?(:double_colon) && node.loc.double_colon
54
+ return unless node.loc?(:double_colon)
55
55
 
56
56
  check_space_after_double_colon(node)
57
57
  end
@@ -242,12 +242,12 @@ module RuboCop
242
242
  return !aligned_with_operator?(operator) unless type == :assignment
243
243
 
244
244
  token = Token.new(operator, nil, operator.source)
245
- align_preceding = aligned_with_preceding_assignment(token)
245
+ align_preceding = aligned_with_preceding_equals_operator(token)
246
246
 
247
247
  return false if align_preceding == :yes ||
248
- aligned_with_subsequent_assignment(token) == :none
248
+ aligned_with_subsequent_equals_operator(token) == :none
249
249
 
250
- aligned_with_subsequent_assignment(token) != :yes
250
+ aligned_with_subsequent_equals_operator(token) != :yes
251
251
  end
252
252
 
253
253
  def excess_trailing_space?(right_operand, with_space)
@@ -260,7 +260,10 @@ module RuboCop
260
260
  end
261
261
 
262
262
  def hash_table_style?
263
- align_hash_cop_config && align_hash_cop_config['EnforcedHashRocketStyle'] == 'table'
263
+ return false unless align_hash_cop_config
264
+
265
+ enforced_styles = Array(align_hash_cop_config['EnforcedHashRocketStyle'])
266
+ enforced_styles.include?('table')
264
267
  end
265
268
 
266
269
  def space_around_exponent_operator?
@@ -77,6 +77,7 @@ module RuboCop
77
77
  end
78
78
 
79
79
  alias on_numblock on_block
80
+ alias on_itblock on_block
80
81
 
81
82
  private
82
83
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Checks for comma (,) preceded by space.
6
+ # Checks for comma (`,`) preceded by space.
7
7
  #
8
8
  # @example
9
9
  # # bad
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Checks for semicolon (;) preceded by space.
6
+ # Checks for semicolon (`;`) preceded by space.
7
7
  #
8
8
  # @example
9
9
  # # bad
@@ -103,6 +103,7 @@ module RuboCop
103
103
  end
104
104
 
105
105
  alias on_numblock on_block
106
+ alias on_itblock on_block
106
107
 
107
108
  private
108
109
 
@@ -48,7 +48,7 @@ module RuboCop
48
48
 
49
49
  def on_new_investigation
50
50
  processed_source.lines.each_with_index do |line, index|
51
- next unless line.end_with?(' ', "\t")
51
+ next unless line.match?(/[[:blank:]]\z/)
52
52
 
53
53
  process_line(line, index + 1)
54
54
  end
@@ -84,7 +84,7 @@ module RuboCop
84
84
  end
85
85
 
86
86
  def whitespace_is_indentation?(range, level)
87
- range.source[/[ \t]+/].length <= level
87
+ range.source[/[[:blank:]]+/].length <= level
88
88
  end
89
89
 
90
90
  def whitespace_only?(range)
@@ -123,7 +123,9 @@ module RuboCop
123
123
  end
124
124
 
125
125
  def offense_range(lineno, line)
126
- source_range(processed_source.buffer, lineno, (line.rstrip.length)...(line.length))
126
+ source_range(
127
+ processed_source.buffer, lineno, (line.sub(/[[:blank:]]+\z/, '').length)...(line.length)
128
+ )
127
129
  end
128
130
  end
129
131
  end
@@ -77,7 +77,7 @@ module RuboCop
77
77
  private
78
78
 
79
79
  def ambiguous_block_association?(send_node)
80
- send_node.last_argument.block_type? && !send_node.last_argument.send_node.arguments?
80
+ send_node.last_argument.any_block_type? && !send_node.last_argument.send_node.arguments?
81
81
  end
82
82
 
83
83
  def allowed_method_pattern?(node)
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for an array literal interpolated inside a regexp.
7
+ #
8
+ # When interpolating an array literal, it is converted to a string. This means
9
+ # that when inside a regexp, it acts as a character class but with additional
10
+ # quotes, spaces and commas that are likely not intended. For example,
11
+ # `/#{%w[a b c]}/` parses as `/["a", "b", "c"]/` (or `/["a, bc]/` without
12
+ # repeated characters).
13
+ #
14
+ # The cop can autocorrect to a character class (if all items in the array are a
15
+ # single character) or alternation (if the array contains longer items).
16
+ #
17
+ # NOTE: This only considers interpolated arrays that contain only strings, symbols,
18
+ # integers, and floats. Any other type is not easily convertible to a character class
19
+ # or regexp alternation.
20
+ #
21
+ # @safety
22
+ # Autocorrection is unsafe because it will change the regexp pattern, by
23
+ # removing the additional quotes, spaces and commas from the character class.
24
+ #
25
+ # @example
26
+ # # bad
27
+ # /#{%w[a b c]}/
28
+ #
29
+ # # good
30
+ # /[abc]/
31
+ #
32
+ # # bad
33
+ # /#{%w[foo bar baz]}/
34
+ #
35
+ # # good
36
+ # /(?:foo|bar|baz)/
37
+ #
38
+ # # bad - construct a regexp rather than interpolate an array of identifiers
39
+ # /#{[foo, bar]}/
40
+ #
41
+ class ArrayLiteralInRegexp < Base
42
+ include Interpolation
43
+ extend AutoCorrector
44
+
45
+ LITERAL_TYPES = %i[str sym int float true false nil].freeze
46
+ private_constant :LITERAL_TYPES
47
+
48
+ MSG_CHARACTER_CLASS = 'Use a character class instead of interpolating an array in a regexp.'
49
+ MSG_ALTERNATION = 'Use alternation instead of interpolating an array in a regexp.'
50
+ MSG_UNKNOWN = 'Use alternation or a character class instead of interpolating an array ' \
51
+ 'in a regexp.'
52
+
53
+ def on_interpolation(begin_node)
54
+ final_node = begin_node.children.last
55
+
56
+ return unless begin_node.parent.regexp_type?
57
+ return unless final_node.array_type?
58
+
59
+ if array_of_literal_values?(final_node)
60
+ register_array_of_literal_values(begin_node, final_node)
61
+ else
62
+ register_array_of_nonliteral_values(begin_node)
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def array_of_literal_values?(node)
69
+ node.each_value.all? { |value| value.type?(*LITERAL_TYPES) }
70
+ end
71
+
72
+ def register_array_of_literal_values(begin_node, node)
73
+ array_values = array_values(node)
74
+
75
+ if character_class?(array_values)
76
+ message = MSG_CHARACTER_CLASS
77
+ replacement = character_class_for(array_values)
78
+ else
79
+ message = MSG_ALTERNATION
80
+ replacement = alternation_for(array_values)
81
+ end
82
+
83
+ add_offense(begin_node, message: message) do |corrector|
84
+ corrector.replace(begin_node, replacement)
85
+ end
86
+ end
87
+
88
+ def register_array_of_nonliteral_values(node)
89
+ # Add offense but do not correct if the array contains any nonliteral values.
90
+ add_offense(node, message: MSG_UNKNOWN)
91
+ end
92
+
93
+ def array_values(node)
94
+ node.each_value.map do |value|
95
+ value.respond_to?(:value) ? value.value : value.source
96
+ end
97
+ end
98
+
99
+ def character_class?(values)
100
+ values.all? { |v| v.to_s.length == 1 }
101
+ end
102
+
103
+ def character_class_for(values)
104
+ "[#{escape_values(values).join}]"
105
+ end
106
+
107
+ def alternation_for(values)
108
+ "(?:#{escape_values(values).join('|')})"
109
+ end
110
+
111
+ def escape_values(values)
112
+ # This may add extraneous escape characters, but they can be cleaned up
113
+ # by `Style/RedundantRegexpEscape`.
114
+ values.map { |value| Regexp.escape(value.to_s) }
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -53,8 +53,6 @@ module RuboCop
53
53
  ASGN_TYPES = [:begin, *AST::Node::EQUALS_ASSIGNMENTS, :send, :csend].freeze
54
54
 
55
55
  def on_if(node)
56
- return if node.condition.block_type?
57
-
58
56
  traverse_node(node.condition) do |asgn_node|
59
57
  next :skip_children if skip_children?(asgn_node)
60
58
  next if allowed_construct?(asgn_node)
@@ -95,7 +93,7 @@ module RuboCop
95
93
 
96
94
  def traverse_node(node, &block)
97
95
  # if the node is a block, any assignments are irrelevant
98
- return if node.block_type?
96
+ return if node.any_block_type?
99
97
 
100
98
  result = yield node if ASGN_TYPES.include?(node.type)
101
99
 
@@ -14,7 +14,7 @@ module RuboCop
14
14
  # Although these can be rewritten in a different way, it should not be necessary to
15
15
  # do so. Operations such as `-` or `/` where the result will always be the same
16
16
  # (`x - x` will always be 0; `x / x` will always be 1) are offenses, but these
17
- # are covered by Lint/NumericOperationWithConstantResult instead.
17
+ # are covered by `Lint/NumericOperationWithConstantResult` instead.
18
18
  #
19
19
  # @safety
20
20
  # This cop is unsafe as it does not consider side effects when calling methods
@@ -48,7 +48,7 @@ module RuboCop
48
48
  def autocorrect(corrector, node)
49
49
  boolean_literal = node.source.delete(':')
50
50
  parent = node.parent
51
- if parent&.pair_type? && node.equal?(parent.children[0])
51
+ if parent&.pair_type? && parent.colon? && node.equal?(parent.children[0])
52
52
  corrector.remove(parent.loc.operator)
53
53
  boolean_literal = "#{node.source} =>"
54
54
  end