rubocop 1.65.1 → 1.75.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (507) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +72 -72
  4. data/config/default.yml +299 -55
  5. data/config/internal_affairs.yml +31 -0
  6. data/config/obsoletion.yml +3 -1
  7. data/exe/rubocop +4 -3
  8. data/lib/rubocop/cached_data.rb +12 -4
  9. data/lib/rubocop/cli/command/auto_generate_config.rb +6 -7
  10. data/lib/rubocop/cli/command/execute_runner.rb +4 -4
  11. data/lib/rubocop/cli/command/lsp.rb +2 -2
  12. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  13. data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
  14. data/lib/rubocop/cli/command/version.rb +2 -2
  15. data/lib/rubocop/cli.rb +1 -1
  16. data/lib/rubocop/comment_config.rb +3 -3
  17. data/lib/rubocop/config.rb +57 -11
  18. data/lib/rubocop/config_loader.rb +66 -17
  19. data/lib/rubocop/config_loader_resolver.rb +39 -14
  20. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -3
  21. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  22. data/lib/rubocop/config_obsoletion.rb +46 -2
  23. data/lib/rubocop/config_validator.rb +27 -15
  24. data/lib/rubocop/cop/autocorrect_logic.rb +36 -19
  25. data/lib/rubocop/cop/base.rb +17 -3
  26. data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
  27. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  28. data/lib/rubocop/cop/bundler/gem_filename.rb +0 -1
  29. data/lib/rubocop/cop/bundler/gem_version.rb +1 -0
  30. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +0 -1
  31. data/lib/rubocop/cop/cop.rb +8 -0
  32. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -12
  33. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +1 -1
  34. data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -0
  35. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
  36. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
  37. data/lib/rubocop/cop/documentation.rb +18 -1
  38. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
  39. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
  40. data/lib/rubocop/cop/generator.rb +6 -0
  41. data/lib/rubocop/cop/internal_affairs/cop_description.rb +0 -4
  42. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  43. data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +2 -1
  44. data/lib/rubocop/cop/internal_affairs/example_description.rb +8 -4
  45. data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
  46. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  47. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -4
  48. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  49. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -2
  50. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  51. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  52. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +230 -0
  53. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +91 -0
  54. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  55. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  56. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
  57. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  58. data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +48 -0
  59. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  60. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  61. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +6 -21
  62. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +11 -2
  63. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  64. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
  65. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +23 -2
  66. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +0 -5
  67. data/lib/rubocop/cop/internal_affairs.rb +7 -0
  68. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +6 -2
  69. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -9
  70. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  71. data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
  72. data/lib/rubocop/cop/layout/block_alignment.rb +32 -13
  73. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  74. data/lib/rubocop/cop/layout/class_structure.rb +9 -9
  75. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +4 -4
  76. data/lib/rubocop/cop/layout/def_end_alignment.rb +2 -2
  77. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  78. data/lib/rubocop/cop/layout/else_alignment.rb +2 -2
  79. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +4 -4
  80. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +9 -12
  81. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +30 -4
  82. data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
  83. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
  84. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +12 -8
  85. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +23 -1
  86. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  87. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  88. data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
  89. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -10
  90. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  91. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  92. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +8 -0
  93. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  94. data/lib/rubocop/cop/layout/hash_alignment.rb +8 -6
  95. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
  96. data/lib/rubocop/cop/layout/indentation_width.rb +12 -12
  97. data/lib/rubocop/cop/layout/leading_comment_space.rb +83 -1
  98. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +11 -2
  99. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  100. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  101. data/lib/rubocop/cop/layout/line_length.rb +135 -16
  102. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
  103. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  104. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  105. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +2 -1
  106. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
  107. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
  108. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  109. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +3 -4
  110. data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
  111. data/lib/rubocop/cop/layout/redundant_line_break.rb +19 -46
  112. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +6 -7
  113. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  114. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  115. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  116. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  117. data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
  118. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -1
  119. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  120. data/lib/rubocop/cop/layout/space_around_operators.rb +23 -21
  121. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
  122. data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -5
  123. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  124. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  125. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +11 -1
  126. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +5 -0
  127. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +7 -0
  128. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
  129. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  130. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  131. data/lib/rubocop/cop/lint/ambiguous_range.rb +4 -1
  132. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +118 -0
  133. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  134. data/lib/rubocop/cop/lint/big_decimal_new.rb +4 -7
  135. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +10 -12
  136. data/lib/rubocop/cop/lint/boolean_symbol.rb +2 -2
  137. data/lib/rubocop/cop/lint/circular_argument_reference.rb +4 -1
  138. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  139. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  140. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
  141. data/lib/rubocop/cop/lint/debugger.rb +3 -3
  142. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  143. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +3 -2
  144. data/lib/rubocop/cop/lint/duplicate_branch.rb +39 -4
  145. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  146. data/lib/rubocop/cop/lint/duplicate_methods.rb +46 -19
  147. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  148. data/lib/rubocop/cop/lint/duplicate_set_element.rb +87 -0
  149. data/lib/rubocop/cop/lint/empty_conditional_body.rb +29 -58
  150. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
  151. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  152. data/lib/rubocop/cop/lint/empty_file.rb +0 -2
  153. data/lib/rubocop/cop/lint/ensure_return.rb +1 -4
  154. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -7
  155. data/lib/rubocop/cop/lint/float_comparison.rb +21 -17
  156. data/lib/rubocop/cop/lint/float_out_of_range.rb +2 -4
  157. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  158. data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
  159. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +13 -5
  160. data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
  161. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +8 -14
  162. data/lib/rubocop/cop/lint/literal_as_condition.rb +118 -9
  163. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  164. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +49 -8
  165. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
  166. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  167. data/lib/rubocop/cop/lint/mixed_case_range.rb +5 -8
  168. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  169. data/lib/rubocop/cop/lint/nested_method_definition.rb +10 -6
  170. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  171. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
  172. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +12 -3
  173. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -3
  174. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
  175. data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
  176. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
  177. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +93 -0
  178. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -3
  179. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +3 -2
  180. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +6 -11
  181. data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
  182. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  183. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  184. data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
  185. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +13 -8
  186. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
  187. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  188. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +261 -0
  189. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  190. data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
  191. data/lib/rubocop/cop/lint/refinement_import_methods.rb +1 -1
  192. data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
  193. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  194. data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
  195. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  196. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -1
  197. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +109 -41
  198. data/lib/rubocop/cop/lint/self_assignment.rb +8 -10
  199. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  200. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +8 -1
  201. data/lib/rubocop/cop/lint/shared_mutable_default.rb +76 -0
  202. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  203. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
  204. data/lib/rubocop/cop/lint/symbol_conversion.rb +2 -2
  205. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  206. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
  207. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  208. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +88 -0
  209. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +3 -1
  210. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  211. data/lib/rubocop/cop/lint/unreachable_code.rb +52 -2
  212. data/lib/rubocop/cop/lint/unreachable_loop.rb +6 -6
  213. data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
  214. data/lib/rubocop/cop/lint/uri_regexp.rb +25 -7
  215. data/lib/rubocop/cop/lint/useless_access_modifier.rb +5 -4
  216. data/lib/rubocop/cop/lint/useless_assignment.rb +20 -11
  217. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +71 -0
  218. data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
  219. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +4 -0
  220. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  221. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +78 -0
  222. data/lib/rubocop/cop/lint/useless_rescue.rb +2 -2
  223. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  224. data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
  225. data/lib/rubocop/cop/lint/void.rb +40 -14
  226. data/lib/rubocop/cop/message_annotator.rb +7 -3
  227. data/lib/rubocop/cop/metrics/block_length.rb +7 -5
  228. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  229. data/lib/rubocop/cop/metrics/class_length.rb +15 -14
  230. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  231. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +5 -2
  232. data/lib/rubocop/cop/metrics/method_length.rb +15 -6
  233. data/lib/rubocop/cop/metrics/module_length.rb +7 -6
  234. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  235. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  236. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +3 -4
  237. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  238. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  239. data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
  240. data/lib/rubocop/cop/mixin/annotation_comment.rb +0 -2
  241. data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
  242. data/lib/rubocop/cop/mixin/check_line_breakable.rb +22 -12
  243. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
  244. data/lib/rubocop/cop/mixin/comments_help.rb +8 -3
  245. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  246. data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
  247. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  248. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
  249. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  250. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
  251. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +22 -11
  252. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
  253. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
  254. data/lib/rubocop/cop/mixin/hash_subset.rb +203 -0
  255. data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
  256. data/lib/rubocop/cop/mixin/line_length_help.rb +12 -6
  257. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  258. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +7 -9
  259. data/lib/rubocop/cop/mixin/percent_array.rb +1 -1
  260. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  261. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +68 -30
  262. data/lib/rubocop/cop/mixin/range_help.rb +15 -4
  263. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  264. data/lib/rubocop/cop/mixin/statement_modifier.rb +11 -5
  265. data/lib/rubocop/cop/mixin/string_help.rb +2 -2
  266. data/lib/rubocop/cop/mixin/string_literals_help.rb +12 -0
  267. data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
  268. data/lib/rubocop/cop/mixin/trailing_comma.rb +21 -5
  269. data/lib/rubocop/cop/naming/accessor_method_name.rb +11 -6
  270. data/lib/rubocop/cop/naming/block_forwarding.rb +20 -16
  271. data/lib/rubocop/cop/naming/constant_name.rb +6 -7
  272. data/lib/rubocop/cop/naming/file_name.rb +0 -2
  273. data/lib/rubocop/cop/naming/inclusive_language.rb +12 -3
  274. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +12 -13
  275. data/lib/rubocop/cop/naming/method_name.rb +64 -8
  276. data/lib/rubocop/cop/naming/predicate_name.rb +46 -2
  277. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +6 -14
  278. data/lib/rubocop/cop/naming/variable_name.rb +50 -6
  279. data/lib/rubocop/cop/naming/variable_number.rb +2 -3
  280. data/lib/rubocop/cop/offense.rb +4 -5
  281. data/lib/rubocop/cop/registry.rb +9 -6
  282. data/lib/rubocop/cop/security/compound_hash.rb +2 -0
  283. data/lib/rubocop/cop/security/yaml_load.rb +3 -2
  284. data/lib/rubocop/cop/style/access_modifier_declarations.rb +96 -28
  285. data/lib/rubocop/cop/style/accessor_grouping.rb +29 -7
  286. data/lib/rubocop/cop/style/alias.rb +1 -1
  287. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +79 -0
  288. data/lib/rubocop/cop/style/and_or.rb +1 -1
  289. data/lib/rubocop/cop/style/arguments_forwarding.rb +94 -30
  290. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  291. data/lib/rubocop/cop/style/array_intersect.rb +42 -30
  292. data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
  293. data/lib/rubocop/cop/style/block_delimiters.rb +51 -20
  294. data/lib/rubocop/cop/style/case_like_if.rb +8 -11
  295. data/lib/rubocop/cop/style/class_and_module_children.rb +52 -11
  296. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  297. data/lib/rubocop/cop/style/collection_compact.rb +10 -10
  298. data/lib/rubocop/cop/style/collection_methods.rb +2 -1
  299. data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
  300. data/lib/rubocop/cop/style/combinable_loops.rb +10 -2
  301. data/lib/rubocop/cop/style/commented_keyword.rb +25 -2
  302. data/lib/rubocop/cop/style/comparable_between.rb +78 -0
  303. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  304. data/lib/rubocop/cop/style/conditional_assignment.rb +40 -28
  305. data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
  306. data/lib/rubocop/cop/style/data_inheritance.rb +8 -1
  307. data/lib/rubocop/cop/style/dig_chain.rb +89 -0
  308. data/lib/rubocop/cop/style/documentation.rb +1 -1
  309. data/lib/rubocop/cop/style/double_negation.rb +4 -4
  310. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  311. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  312. data/lib/rubocop/cop/style/empty_else.rb +10 -7
  313. data/lib/rubocop/cop/style/empty_heredoc.rb +1 -14
  314. data/lib/rubocop/cop/style/empty_literal.rb +35 -22
  315. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  316. data/lib/rubocop/cop/style/endless_method.rb +150 -18
  317. data/lib/rubocop/cop/style/eval_with_location.rb +5 -5
  318. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -3
  319. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  320. data/lib/rubocop/cop/style/explicit_block_argument.rb +16 -3
  321. data/lib/rubocop/cop/style/exponential_notation.rb +3 -3
  322. data/lib/rubocop/cop/style/fetch_env_var.rb +2 -1
  323. data/lib/rubocop/cop/style/file_null.rb +89 -0
  324. data/lib/rubocop/cop/style/file_touch.rb +75 -0
  325. data/lib/rubocop/cop/style/float_division.rb +8 -4
  326. data/lib/rubocop/cop/style/for.rb +1 -1
  327. data/lib/rubocop/cop/style/format_string_token.rb +38 -11
  328. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  329. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  330. data/lib/rubocop/cop/style/global_vars.rb +1 -3
  331. data/lib/rubocop/cop/style/guard_clause.rb +20 -4
  332. data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
  333. data/lib/rubocop/cop/style/hash_each_methods.rb +12 -8
  334. data/lib/rubocop/cop/style/hash_except.rb +35 -147
  335. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  336. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  337. data/lib/rubocop/cop/style/hash_syntax.rb +11 -5
  338. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  339. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  340. data/lib/rubocop/cop/style/identical_conditional_branches.rb +26 -7
  341. data/lib/rubocop/cop/style/if_inside_else.rb +11 -15
  342. data/lib/rubocop/cop/style/if_unless_modifier.rb +25 -5
  343. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +3 -4
  344. data/lib/rubocop/cop/style/if_with_semicolon.rb +60 -6
  345. data/lib/rubocop/cop/style/in_pattern_then.rb +6 -2
  346. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  347. data/lib/rubocop/cop/style/inverse_methods.rb +15 -12
  348. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  349. data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
  350. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  351. data/lib/rubocop/cop/style/it_block_parameter.rb +100 -0
  352. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
  353. data/lib/rubocop/cop/style/keyword_parameters_order.rb +14 -8
  354. data/lib/rubocop/cop/style/lambda.rb +2 -1
  355. data/lib/rubocop/cop/style/lambda_call.rb +10 -4
  356. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  357. data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
  358. data/lib/rubocop/cop/style/map_into_array.rb +75 -14
  359. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  360. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  361. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +38 -23
  362. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  363. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +10 -13
  364. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
  365. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  366. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  367. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
  368. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -2
  369. data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
  370. data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
  371. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
  372. data/lib/rubocop/cop/style/multiple_comparison.rb +53 -60
  373. data/lib/rubocop/cop/style/mutable_constant.rb +7 -8
  374. data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -5
  375. data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
  376. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -2
  377. data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
  378. data/lib/rubocop/cop/style/next.rb +44 -0
  379. data/lib/rubocop/cop/style/not.rb +1 -1
  380. data/lib/rubocop/cop/style/numeric_predicate.rb +2 -2
  381. data/lib/rubocop/cop/style/object_then.rb +15 -15
  382. data/lib/rubocop/cop/style/one_line_conditional.rb +30 -5
  383. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  384. data/lib/rubocop/cop/style/operator_method_call.rb +25 -7
  385. data/lib/rubocop/cop/style/or_assignment.rb +3 -6
  386. data/lib/rubocop/cop/style/parallel_assignment.rb +14 -22
  387. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  388. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  389. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  390. data/lib/rubocop/cop/style/proc.rb +2 -2
  391. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -3
  392. data/lib/rubocop/cop/style/raise_args.rb +15 -13
  393. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  394. data/lib/rubocop/cop/style/redundant_argument.rb +3 -1
  395. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
  396. data/lib/rubocop/cop/style/redundant_begin.rb +6 -1
  397. data/lib/rubocop/cop/style/redundant_condition.rb +97 -24
  398. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +16 -5
  399. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  400. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  401. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  402. data/lib/rubocop/cop/style/redundant_format.rb +257 -0
  403. data/lib/rubocop/cop/style/redundant_freeze.rb +3 -3
  404. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  405. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +46 -0
  406. data/lib/rubocop/cop/style/redundant_line_continuation.rb +56 -20
  407. data/lib/rubocop/cop/style/redundant_parentheses.rb +57 -27
  408. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +8 -1
  409. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  410. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  411. data/lib/rubocop/cop/style/redundant_return.rb +2 -2
  412. data/lib/rubocop/cop/style/redundant_self.rb +9 -15
  413. data/lib/rubocop/cop/style/redundant_self_assignment.rb +20 -32
  414. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
  415. data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
  416. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  417. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  418. data/lib/rubocop/cop/style/require_order.rb +1 -1
  419. data/lib/rubocop/cop/style/rescue_modifier.rb +18 -4
  420. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  421. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +54 -12
  422. data/lib/rubocop/cop/style/safe_navigation.rb +123 -54
  423. data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
  424. data/lib/rubocop/cop/style/select_by_regexp.rb +14 -8
  425. data/lib/rubocop/cop/style/self_assignment.rb +11 -17
  426. data/lib/rubocop/cop/style/semicolon.rb +2 -2
  427. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  428. data/lib/rubocop/cop/style/signal_exception.rb +2 -3
  429. data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
  430. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  431. data/lib/rubocop/cop/style/single_line_do_end_block.rb +15 -4
  432. data/lib/rubocop/cop/style/single_line_methods.rb +6 -7
  433. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  434. data/lib/rubocop/cop/style/sole_nested_conditional.rb +42 -106
  435. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  436. data/lib/rubocop/cop/style/string_concatenation.rb +15 -15
  437. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  438. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  439. data/lib/rubocop/cop/style/struct_inheritance.rb +9 -2
  440. data/lib/rubocop/cop/style/super_arguments.rb +66 -19
  441. data/lib/rubocop/cop/style/swap_values.rb +4 -15
  442. data/lib/rubocop/cop/style/symbol_proc.rb +2 -0
  443. data/lib/rubocop/cop/style/ternary_parentheses.rb +26 -5
  444. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -1
  445. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +11 -2
  446. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  447. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  448. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
  449. data/lib/rubocop/cop/style/trivial_accessors.rb +2 -2
  450. data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
  451. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  452. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  453. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  454. data/lib/rubocop/cop/team.rb +14 -3
  455. data/lib/rubocop/cop/util.rb +12 -5
  456. data/lib/rubocop/cop/utils/format_string.rb +10 -5
  457. data/lib/rubocop/cop/variable_force/assignment.rb +18 -3
  458. data/lib/rubocop/cop/variable_force/branch.rb +1 -1
  459. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  460. data/lib/rubocop/cop/variable_force/variable.rb +14 -3
  461. data/lib/rubocop/cop/variable_force/variable_table.rb +5 -5
  462. data/lib/rubocop/cop/variable_force.rb +5 -11
  463. data/lib/rubocop/cops_documentation_generator.rb +117 -53
  464. data/lib/rubocop/directive_comment.rb +45 -11
  465. data/lib/rubocop/ext/regexp_node.rb +0 -1
  466. data/lib/rubocop/file_finder.rb +9 -4
  467. data/lib/rubocop/formatter/disabled_config_formatter.rb +3 -2
  468. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  469. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  470. data/lib/rubocop/formatter/junit_formatter.rb +70 -23
  471. data/lib/rubocop/formatter/pacman_formatter.rb +1 -1
  472. data/lib/rubocop/lockfile.rb +6 -4
  473. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  474. data/lib/rubocop/lsp/logger.rb +2 -2
  475. data/lib/rubocop/lsp/routes.rb +7 -23
  476. data/lib/rubocop/lsp/runtime.rb +19 -49
  477. data/lib/rubocop/lsp/server.rb +0 -3
  478. data/lib/rubocop/lsp/stdin_runner.rb +85 -0
  479. data/lib/rubocop/magic_comment.rb +11 -3
  480. data/lib/rubocop/options.rb +28 -12
  481. data/lib/rubocop/path_util.rb +15 -8
  482. data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
  483. data/lib/rubocop/plugin/load_error.rb +26 -0
  484. data/lib/rubocop/plugin/loader.rb +100 -0
  485. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  486. data/lib/rubocop/plugin.rb +46 -0
  487. data/lib/rubocop/rake_task.rb +4 -1
  488. data/lib/rubocop/remote_config.rb +5 -1
  489. data/lib/rubocop/result_cache.rb +15 -21
  490. data/lib/rubocop/rspec/cop_helper.rb +13 -1
  491. data/lib/rubocop/rspec/expect_offense.rb +7 -2
  492. data/lib/rubocop/rspec/shared_contexts.rb +40 -3
  493. data/lib/rubocop/rspec/support.rb +4 -2
  494. data/lib/rubocop/runner.rb +27 -13
  495. data/lib/rubocop/server/cache.rb +52 -11
  496. data/lib/rubocop/server/cli.rb +2 -2
  497. data/lib/rubocop/server/core.rb +1 -0
  498. data/lib/rubocop/target_finder.rb +7 -2
  499. data/lib/rubocop/target_ruby.rb +36 -17
  500. data/lib/rubocop/version.rb +54 -11
  501. data/lib/rubocop/yaml_duplication_checker.rb +20 -26
  502. data/lib/rubocop.rb +36 -2
  503. data/lib/ruby_lsp/rubocop/addon.rb +75 -0
  504. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +65 -0
  505. metadata +83 -40
  506. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  507. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -3,88 +3,156 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Check to make sure that if safe navigation is used for a method
7
- # call in an `&&` or `||` condition that safe navigation is used for all
8
- # method calls on that same object.
6
+ # Check to make sure that if safe navigation is used in an `&&` or `||` condition,
7
+ # consistent and appropriate safe navigation, without excess or deficiency,
8
+ # is used for all method calls on the same object.
9
9
  #
10
10
  # @example
11
11
  # # bad
12
- # foo&.bar && foo.baz
12
+ # foo&.bar && foo&.baz
13
13
  #
14
- # # bad
15
- # foo.bar || foo&.baz
14
+ # # good
15
+ # foo&.bar && foo.baz
16
16
  #
17
17
  # # bad
18
- # foo&.bar && (foobar.baz || foo.baz)
18
+ # foo.bar && foo&.baz
19
19
  #
20
20
  # # good
21
21
  # foo.bar && foo.baz
22
22
  #
23
+ # # bad
24
+ # foo&.bar || foo.baz
25
+ #
23
26
  # # good
24
27
  # foo&.bar || foo&.baz
25
28
  #
29
+ # # bad
30
+ # foo.bar || foo&.baz
31
+ #
26
32
  # # good
33
+ # foo.bar || foo.baz
34
+ #
35
+ # # bad
27
36
  # foo&.bar && (foobar.baz || foo&.baz)
28
37
  #
38
+ # # good
39
+ # foo&.bar && (foobar.baz || foo.baz)
40
+ #
29
41
  class SafeNavigationConsistency < Base
30
- include IgnoredNode
31
42
  include NilMethods
32
43
  extend AutoCorrector
33
44
 
34
- MSG = 'Ensure that safe navigation is used consistently inside of `&&` and `||`.'
45
+ USE_DOT_MSG = 'Use `.` instead of unnecessary `&.`.'
46
+ USE_SAFE_NAVIGATION_MSG = 'Use `&.` for consistency with safe navigation.'
35
47
 
36
- def on_csend(node)
37
- return unless node.parent&.operator_keyword?
48
+ def on_and(node)
49
+ all_operands = collect_operands(node, [])
50
+ operand_groups = all_operands.group_by { |operand| receiver_name_as_key(operand, +'') }
38
51
 
39
- check(node)
40
- end
52
+ operand_groups.each_value do |grouped_operands|
53
+ next unless (dot_op, begin_of_rest_operands = find_consistent_parts(grouped_operands))
41
54
 
42
- def check(node)
43
- ancestor = top_conditional_ancestor(node)
44
- conditions = ancestor.conditions
45
- safe_nav_receiver = node.receiver
55
+ rest_operands = grouped_operands[begin_of_rest_operands..]
56
+ rest_operands.each do |operand|
57
+ next if already_appropriate_call?(operand, dot_op)
46
58
 
47
- method_calls = conditions.select(&:send_type?)
48
- unsafe_method_calls = unsafe_method_calls(method_calls, safe_nav_receiver)
59
+ register_offense(operand, dot_op)
60
+ end
61
+ end
62
+ end
63
+ alias on_or on_and
49
64
 
50
- unsafe_method_calls.each do |unsafe_method_call|
51
- location = location(node, unsafe_method_call)
65
+ private
52
66
 
53
- add_offense(location) { |corrector| autocorrect(corrector, unsafe_method_call) }
67
+ def collect_operands(node, operand_nodes)
68
+ operand_nodes(node.lhs, operand_nodes)
69
+ operand_nodes(node.rhs, operand_nodes)
54
70
 
55
- ignore_node(unsafe_method_call)
71
+ operand_nodes
72
+ end
73
+
74
+ def receiver_name_as_key(method, fully_receivers)
75
+ if method.parent.call_type?
76
+ receiver(method.parent, fully_receivers)
77
+ else
78
+ fully_receivers << method.receiver&.source.to_s
56
79
  end
57
80
  end
58
81
 
59
- private
82
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
83
+ def find_consistent_parts(grouped_operands)
84
+ csend_in_and, csend_in_or, send_in_and, send_in_or = most_left_indices(grouped_operands)
60
85
 
61
- def autocorrect(corrector, node)
62
- return unless node.dot?
86
+ return if csend_in_and && csend_in_or && csend_in_and < csend_in_or
63
87
 
64
- corrector.insert_before(node.loc.dot, '&')
88
+ if csend_in_and
89
+ ['.', (send_in_and ? [send_in_and, csend_in_and].min : csend_in_and) + 1]
90
+ elsif send_in_or && csend_in_or
91
+ send_in_or < csend_in_or ? ['.', send_in_or + 1] : ['&.', csend_in_or + 1]
92
+ elsif send_in_and && csend_in_or && send_in_and < csend_in_or
93
+ ['.', csend_in_or]
94
+ end
65
95
  end
96
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
66
97
 
67
- def location(node, unsafe_method_call)
68
- node.source_range.join(unsafe_method_call.source_range)
98
+ def already_appropriate_call?(operand, dot_op)
99
+ return true if operand.safe_navigation? && dot_op == '&.'
100
+
101
+ (operand.dot? || operand.operator_method?) && dot_op == '.'
69
102
  end
70
103
 
71
- def top_conditional_ancestor(node)
72
- parent = node.parent
73
- unless parent &&
74
- (parent.operator_keyword? ||
75
- (parent.begin_type? && parent.parent && parent.parent.operator_keyword?))
76
- return node
104
+ def register_offense(operand, dot_operator)
105
+ offense_range = operand.operator_method? ? operand : operand.loc.dot
106
+ message = dot_operator == '.' ? USE_DOT_MSG : USE_SAFE_NAVIGATION_MSG
107
+
108
+ add_offense(offense_range, message: message) do |corrector|
109
+ next if operand.operator_method?
110
+
111
+ corrector.replace(operand.loc.dot, dot_operator)
77
112
  end
113
+ end
78
114
 
79
- top_conditional_ancestor(parent)
115
+ def operand_nodes(operand, operand_nodes)
116
+ if operand.operator_keyword?
117
+ collect_operands(operand, operand_nodes)
118
+ elsif operand.call_type?
119
+ operand_nodes << operand
120
+ end
80
121
  end
81
122
 
82
- def unsafe_method_calls(method_calls, safe_nav_receiver)
83
- method_calls.select do |method_call|
84
- safe_nav_receiver == method_call.receiver &&
85
- !nil_methods.include?(method_call.method_name) &&
86
- !ignored_node?(method_call)
123
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
124
+ def most_left_indices(grouped_operands)
125
+ indices = { csend_in_and: nil, csend_in_or: nil, send_in_and: nil, send_in_or: nil }
126
+
127
+ grouped_operands.each_with_index do |operand, index|
128
+ indices[:csend_in_and] ||= index if operand_in_and?(operand) && operand.csend_type?
129
+ indices[:csend_in_or] ||= index if operand_in_or?(operand) && operand.csend_type?
130
+ indices[:send_in_and] ||= index if operand_in_and?(operand) && !nilable?(operand)
131
+ indices[:send_in_or] ||= index if operand_in_or?(operand) && !nilable?(operand)
87
132
  end
133
+
134
+ indices.values
135
+ end
136
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
137
+
138
+ def operand_in_and?(node)
139
+ return true if node.parent.and_type?
140
+
141
+ parent = node.parent.parent while node.parent.begin_type?
142
+
143
+ parent&.and_type?
144
+ end
145
+
146
+ def operand_in_or?(node)
147
+ return true if node.parent.or_type?
148
+
149
+ parent = node.parent.parent while node.parent.begin_type?
150
+
151
+ parent&.or_type?
152
+ end
153
+
154
+ def nilable?(node)
155
+ node.csend_type? || nil_methods.include?(node.method_name)
88
156
  end
89
157
  end
90
158
  end
@@ -43,23 +43,21 @@ module RuboCop
43
43
  alias on_csend on_send
44
44
 
45
45
  def on_lvasgn(node)
46
- lhs, rhs = *node
47
- return unless rhs
46
+ return unless node.rhs
48
47
 
49
48
  rhs_type = ASSIGNMENT_TYPE_TO_RHS_TYPE[node.type]
50
49
 
51
- add_offense(node) if rhs.type == rhs_type && rhs.source == lhs.to_s
50
+ add_offense(node) if node.rhs.type == rhs_type && node.rhs.source == node.lhs.to_s
52
51
  end
53
52
  alias on_ivasgn on_lvasgn
54
53
  alias on_cvasgn on_lvasgn
55
54
  alias on_gvasgn on_lvasgn
56
55
 
57
56
  def on_casgn(node)
58
- lhs_scope, lhs_name, rhs = *node
59
- return unless rhs&.const_type?
57
+ return unless node.rhs&.const_type?
60
58
 
61
- rhs_scope, rhs_name = *rhs
62
- add_offense(node) if lhs_scope == rhs_scope && lhs_name == rhs_name
59
+ add_offense(node) if node.namespace == node.rhs.namespace &&
60
+ node.short_name == node.rhs.short_name
63
61
  end
64
62
 
65
63
  def on_masgn(node)
@@ -67,15 +65,15 @@ module RuboCop
67
65
  end
68
66
 
69
67
  def on_or_asgn(node)
70
- lhs, rhs = *node
71
- add_offense(node) if rhs_matches_lhs?(rhs, lhs)
68
+ add_offense(node) if rhs_matches_lhs?(node.rhs, node.lhs)
72
69
  end
73
70
  alias on_and_asgn on_or_asgn
74
71
 
75
72
  private
76
73
 
77
74
  def multiple_self_assignment?(node)
78
- lhs, rhs = *node
75
+ lhs = node.lhs
76
+ rhs = node.rhs
79
77
  return false unless rhs.array_type?
80
78
  return false unless lhs.children.size == rhs.children.size
81
79
 
@@ -67,7 +67,7 @@ module RuboCop
67
67
  def on_rescue(node)
68
68
  return if rescue_modifier?(node)
69
69
 
70
- _body, *rescues, _else = *node
70
+ rescues = node.resbody_branches
71
71
  rescued_groups = rescued_groups_for(rescues)
72
72
 
73
73
  rescue_group_rescues_multiple_levels = rescued_groups.any? do |group|
@@ -56,19 +56,26 @@ module RuboCop
56
56
 
57
57
  outer_local_variable = variable_table.find_variable(variable.name)
58
58
  return unless outer_local_variable
59
+ return if variable_used_in_declaration_of_outer?(variable, outer_local_variable)
59
60
  return if same_conditions_node_different_branch?(variable, outer_local_variable)
60
61
 
61
62
  message = format(MSG, variable: variable.name)
62
63
  add_offense(variable.declaration_node, message: message)
63
64
  end
64
65
 
66
+ private
67
+
68
+ def variable_used_in_declaration_of_outer?(variable, outer_local_variable)
69
+ variable.scope.node.each_ancestor.any?(outer_local_variable.declaration_node)
70
+ end
71
+
65
72
  def same_conditions_node_different_branch?(variable, outer_local_variable)
66
73
  variable_node = variable_node(variable)
67
74
  return false unless node_or_its_ascendant_conditional?(variable_node)
68
75
 
69
76
  outer_local_variable_node =
70
77
  find_conditional_node_from_ascendant(outer_local_variable.declaration_node)
71
- return true unless outer_local_variable_node
78
+ return false unless outer_local_variable_node
72
79
  return false unless outer_local_variable_node.conditional?
73
80
  return true if variable_node == outer_local_variable_node
74
81
 
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for `Hash` creation with a mutable default value.
7
+ # Creating a `Hash` in such a way will share the default value
8
+ # across all keys, causing unexpected behavior when modifying it.
9
+ #
10
+ # For example, when the `Hash` was created with an `Array` as the argument,
11
+ # calling `hash[:foo] << 'bar'` will also change the value of all
12
+ # other keys that have not been explicitly assigned to.
13
+ #
14
+ # @example
15
+ # # bad
16
+ # Hash.new([])
17
+ # Hash.new({})
18
+ # Hash.new(Array.new)
19
+ # Hash.new(Hash.new)
20
+ #
21
+ # # okay -- In rare cases that intentionally have this behavior,
22
+ # # without disabling the cop, you can set the default explicitly.
23
+ # h = Hash.new
24
+ # h.default = []
25
+ # h[:a] << 1
26
+ # h[:b] << 2
27
+ # h # => {:a => [1, 2], :b => [1, 2]}
28
+ #
29
+ # # okay -- beware this will discard mutations and only remember assignments
30
+ # Hash.new { Array.new }
31
+ # Hash.new { Hash.new }
32
+ # Hash.new { {} }
33
+ # Hash.new { [] }
34
+ #
35
+ # # good - frozen solution will raise an error when mutation attempted
36
+ # Hash.new([].freeze)
37
+ # Hash.new({}.freeze)
38
+ #
39
+ # # good - using a proc will create a new object for each key
40
+ # h = Hash.new
41
+ # h.default_proc = ->(h, k) { [] }
42
+ # h.default_proc = ->(h, k) { {} }
43
+ #
44
+ # # good - using a block will create a new object for each key
45
+ # Hash.new { |h, k| h[k] = [] }
46
+ # Hash.new { |h, k| h[k] = {} }
47
+ class SharedMutableDefault < Base
48
+ MSG = 'Do not create a Hash with a mutable default value ' \
49
+ 'as the default value can accidentally be changed.'
50
+ RESTRICT_ON_SEND = %i[new].freeze
51
+
52
+ # @!method hash_initialized_with_mutable_shared_object?(node)
53
+ def_node_matcher :hash_initialized_with_mutable_shared_object?, <<~PATTERN
54
+ {
55
+ (send (const {nil? cbase} :Hash) :new [
56
+ {array hash (send (const {nil? cbase} {:Array :Hash}) :new)}
57
+ !#capacity_keyword_argument?
58
+ ])
59
+ (send (const {nil? cbase} :Hash) :new hash #capacity_keyword_argument?)
60
+ }
61
+ PATTERN
62
+
63
+ # @!method capacity_keyword_argument?(node)
64
+ def_node_matcher :capacity_keyword_argument?, <<~PATTERN
65
+ (hash (pair (sym :capacity) _))
66
+ PATTERN
67
+
68
+ def on_send(node)
69
+ return unless hash_initialized_with_mutable_shared_object?(node)
70
+
71
+ add_offense(node)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -116,7 +116,7 @@ module RuboCop
116
116
  private
117
117
 
118
118
  def comment_between_rescue_and_end?(node)
119
- ancestor = node.each_ancestor(:kwbegin, :def, :defs, :block, :numblock).first
119
+ ancestor = node.each_ancestor(:kwbegin, :any_def, :any_block).first
120
120
  return false unless ancestor
121
121
 
122
122
  end_line = ancestor.loc.end&.line || ancestor.loc.last_line
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for cases where exceptions unrelated to the numeric constructors `Integer()`,
7
+ # `Float()`, `BigDecimal()`, `Complex()`, and `Rational()` may be unintentionally swallowed.
8
+ #
9
+ # @safety
10
+ # The cop is unsafe for autocorrection because unexpected errors occurring in the argument
11
+ # passed to numeric constructor (e.g., `Integer()`) can lead to incompatible behavior.
12
+ # For example, changing it to `Integer(potential_exception_method_call, exception: false)`
13
+ # ensures that exceptions raised by `potential_exception_method_call` are not ignored.
14
+ #
15
+ # [source,ruby]
16
+ # ----
17
+ # Integer(potential_exception_method_call) rescue nil
18
+ # ----
19
+ #
20
+ # @example
21
+ #
22
+ # # bad
23
+ # Integer(arg) rescue nil
24
+ #
25
+ # # bad
26
+ # begin
27
+ # Integer(arg)
28
+ # rescue
29
+ # nil
30
+ # end
31
+ #
32
+ # # bad
33
+ # begin
34
+ # Integer(arg)
35
+ # rescue
36
+ # end
37
+ #
38
+ # # good
39
+ # Integer(arg, exception: false)
40
+ #
41
+ class SuppressedExceptionInNumberConversion < Base
42
+ extend AutoCorrector
43
+ extend TargetRubyVersion
44
+
45
+ MSG = 'Use `%<prefer>s` instead.'
46
+ EXPECTED_EXCEPTION_CLASSES = %w[ArgumentError TypeError ::ArgumentError ::TypeError].freeze
47
+
48
+ # @!method numeric_constructor_rescue_nil(node)
49
+ def_node_matcher :numeric_constructor_rescue_nil, <<~PATTERN
50
+ (rescue
51
+ $#numeric_method?
52
+ (resbody nil? nil? (nil)) nil?)
53
+ PATTERN
54
+
55
+ # @!method begin_numeric_constructor_rescue_nil(node)
56
+ def_node_matcher :begin_numeric_constructor_rescue_nil, <<~PATTERN
57
+ (kwbegin
58
+ (rescue
59
+ $#numeric_method?
60
+ (resbody $_? nil?
61
+ {(nil) nil?}) nil?))
62
+ PATTERN
63
+
64
+ # @!method numeric_method?(node)
65
+ def_node_matcher :numeric_method?, <<~PATTERN
66
+ {
67
+ (call #constructor_receiver? {:Integer :BigDecimal :Complex :Rational}
68
+ _ _?)
69
+ (call #constructor_receiver? :Float
70
+ _)
71
+ }
72
+ PATTERN
73
+
74
+ # @!method constructor_receiver?(node)
75
+ def_node_matcher :constructor_receiver?, <<~PATTERN
76
+ {nil? (const {nil? cbase} :Kernel)}
77
+ PATTERN
78
+
79
+ minimum_target_ruby_version 2.6
80
+
81
+ # rubocop:disable Metrics/AbcSize
82
+ def on_rescue(node)
83
+ if (method, exception_classes = begin_numeric_constructor_rescue_nil(node.parent))
84
+ return unless expected_exception_classes_only?(exception_classes)
85
+
86
+ node = node.parent
87
+ else
88
+ return unless (method = numeric_constructor_rescue_nil(node))
89
+ end
90
+
91
+ arguments = method.arguments.map(&:source) << 'exception: false'
92
+ prefer = "#{method.method_name}(#{arguments.join(', ')})"
93
+ prefer = "#{method.receiver.source}#{method.loc.dot.source}#{prefer}" if method.receiver
94
+
95
+ add_offense(node, message: format(MSG, prefer: prefer)) do |corrector|
96
+ corrector.replace(node, prefer)
97
+ end
98
+ end
99
+ # rubocop:enable Metrics/AbcSize
100
+
101
+ private
102
+
103
+ def expected_exception_classes_only?(exception_classes)
104
+ return true unless (arguments = exception_classes.first)
105
+
106
+ (arguments.values.map(&:source) - EXPECTED_EXCEPTION_CLASSES).none?
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -78,7 +78,7 @@ module RuboCop
78
78
  def on_send(node)
79
79
  return unless node.receiver
80
80
 
81
- if node.receiver.str_type? || node.receiver.sym_type?
81
+ if node.receiver.type?(:str, :sym)
82
82
  register_offense(node, correction: node.receiver.value.to_sym.inspect)
83
83
  elsif node.receiver.dstr_type?
84
84
  register_offense(node, correction: ":\"#{node.receiver.value.to_sym}\"")
@@ -141,7 +141,7 @@ module RuboCop
141
141
  end
142
142
 
143
143
  def in_percent_literal_array?(node)
144
- node.parent&.array_type? && node.parent&.percent_literal?
144
+ node.parent&.array_type? && node.parent.percent_literal?
145
145
  end
146
146
 
147
147
  def correct_hash_key(node)
@@ -6,9 +6,12 @@ module RuboCop
6
6
  # Repacks Parser's diagnostics/errors
7
7
  # into RuboCop's offenses.
8
8
  class Syntax < Base
9
+ LEVELS = %i[error fatal].freeze
10
+
9
11
  def on_other_file
10
12
  add_offense_from_error(processed_source.parser_error) if processed_source.parser_error
11
- processed_source.diagnostics.each do |diagnostic|
13
+ syntax_errors = processed_source.diagnostics.select { |d| LEVELS.include?(d.level) }
14
+ syntax_errors.each do |diagnostic|
12
15
  add_offense_from_diagnostic(diagnostic, processed_source.ruby_version)
13
16
  end
14
17
  super
@@ -45,7 +45,7 @@ module RuboCop
45
45
  PATTERN
46
46
 
47
47
  def on_send(node)
48
- def_node = node.each_ancestor(:def, :defs).first
48
+ def_node = node.each_ancestor(:any_def).first
49
49
  return unless def_node
50
50
 
51
51
  enum_conversion_call?(node) do |method_node, arguments|
@@ -40,7 +40,7 @@ module RuboCop
40
40
  # top-level return node's ancestors should not be of block, def, or
41
41
  # defs type.
42
42
  def top_level_return?(return_node)
43
- return_node.each_ancestor(:block, :def, :defs).none?
43
+ return_node.each_ancestor(:block, :any_def).none?
44
44
  end
45
45
  end
46
46
  end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for Regexpes (both literals and via `Regexp.new` / `Regexp.compile`)
7
+ # that contain unescaped `]` characters.
8
+ #
9
+ # It emulates the following Ruby warning:
10
+ #
11
+ # [source,ruby]
12
+ # ----
13
+ # $ ruby -e '/abc]123/'
14
+ # -e:1: warning: regular expression has ']' without escape: /abc]123/
15
+ # ----
16
+ #
17
+ # @example
18
+ # # bad
19
+ # /abc]123/
20
+ # %r{abc]123}
21
+ # Regexp.new('abc]123')
22
+ # Regexp.compile('abc]123')
23
+ #
24
+ # # good
25
+ # /abc\]123/
26
+ # %r{abc\]123}
27
+ # Regexp.new('abc\]123')
28
+ # Regexp.compile('abc\]123')
29
+ #
30
+ class UnescapedBracketInRegexp < Base
31
+ extend AutoCorrector
32
+
33
+ MSG = 'Regular expression has `]` without escape.'
34
+ RESTRICT_ON_SEND = %i[new compile].freeze
35
+
36
+ # @!method regexp_constructor(node)
37
+ def_node_search :regexp_constructor, <<~PATTERN
38
+ (send
39
+ (const {nil? cbase} :Regexp) {:new :compile}
40
+ $str
41
+ ...
42
+ )
43
+ PATTERN
44
+
45
+ def on_regexp(node)
46
+ RuboCop::Util.silence_warnings do
47
+ node.parsed_tree&.each_expression do |expr|
48
+ detect_offenses(node, expr)
49
+ end
50
+ end
51
+ end
52
+
53
+ def on_send(node)
54
+ # Ignore nodes that contain interpolation
55
+ return if node.each_descendant(:dstr).any?
56
+
57
+ regexp_constructor(node) do |text|
58
+ parse_regexp(text.value)&.each_expression do |expr|
59
+ detect_offenses(text, expr)
60
+ end
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def detect_offenses(node, expr)
67
+ return unless expr.type?(:literal)
68
+
69
+ expr.text.scan(/(?<!\\)\]/) do
70
+ pos = Regexp.last_match.begin(0)
71
+ next if pos.zero? # if the unescaped bracket is the first character, Ruby does not warn
72
+
73
+ location = range_at_index(node, expr.ts, pos)
74
+
75
+ add_offense(location) do |corrector|
76
+ corrector.replace(location, '\]')
77
+ end
78
+ end
79
+ end
80
+
81
+ def range_at_index(node, index, offset)
82
+ adjustment = index + offset
83
+ node.loc.begin.end.adjust(begin_pos: adjustment, end_pos: adjustment + 1)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -53,6 +53,7 @@ module RuboCop
53
53
  end
54
54
 
55
55
  alias on_numblock on_block
56
+ alias on_itblock on_block
56
57
 
57
58
  private
58
59
 
@@ -74,6 +75,7 @@ module RuboCop
74
75
 
75
76
  def arg_count(node)
76
77
  return node.children[1] if node.numblock_type? # the maximum numbered param for the block
78
+ return 1 if node.itblock_type? # `it` block parameter is always one
77
79
 
78
80
  # Only `arg`, `optarg` and `mlhs` (destructuring) count as arguments that
79
81
  # can be used. Keyword arguments are not used for these methods so are
@@ -81,7 +83,7 @@ module RuboCop
81
83
  node.arguments.count do |arg|
82
84
  return Float::INFINITY if arg.restarg_type?
83
85
 
84
- arg.arg_type? || arg.optarg_type? || arg.mlhs_type?
86
+ arg.type?(:arg, :optarg, :mlhs)
85
87
  end
86
88
  end
87
89
  end
@@ -130,7 +130,7 @@ module RuboCop
130
130
 
131
131
  block_body_node.each_descendant(:next, :break) do |n|
132
132
  # Ignore `next`/`break` inside an inner block
133
- next if n.each_ancestor(:block).first != block_body_node.parent
133
+ next if n.each_ancestor(:any_block).first != block_body_node.parent
134
134
  next unless n.first_argument
135
135
 
136
136
  nodes << n.first_argument