rubocop 1.69.2 → 1.71.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +36 -2
  5. data/lib/rubocop/cli/command/execute_runner.rb +3 -3
  6. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  7. data/lib/rubocop/comment_config.rb +1 -1
  8. data/lib/rubocop/config.rb +13 -4
  9. data/lib/rubocop/config_loader.rb +4 -0
  10. data/lib/rubocop/config_loader_resolver.rb +14 -3
  11. data/lib/rubocop/config_validator.rb +18 -8
  12. data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
  13. data/lib/rubocop/cop/base.rb +6 -0
  14. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  15. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  16. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  17. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  18. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  19. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  20. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  21. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  22. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +229 -0
  23. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  24. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  25. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  26. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  27. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  28. data/lib/rubocop/cop/internal_affairs.rb +4 -0
  29. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  30. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -8
  31. data/lib/rubocop/cop/layout/block_alignment.rb +1 -1
  32. data/lib/rubocop/cop/layout/class_structure.rb +9 -9
  33. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  34. data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
  35. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  36. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
  37. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
  38. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  39. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  40. data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
  41. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  42. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  43. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  44. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  45. data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
  46. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -0
  47. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  48. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  49. data/lib/rubocop/cop/layout/line_length.rb +1 -0
  50. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  51. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  52. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
  53. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
  54. data/lib/rubocop/cop/layout/redundant_line_break.rb +7 -6
  55. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
  56. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  57. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  58. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  59. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  60. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  61. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -0
  62. data/lib/rubocop/cop/layout/space_around_operators.rb +3 -3
  63. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  64. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  65. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  66. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  67. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
  68. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  69. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +1 -1
  70. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  71. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  72. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  73. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  74. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  75. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  76. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  77. data/lib/rubocop/cop/lint/float_comparison.rb +5 -2
  78. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  79. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  80. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  81. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
  82. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  83. data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
  84. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  85. data/lib/rubocop/cop/lint/nested_method_definition.rb +8 -4
  86. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  87. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -3
  88. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  89. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +18 -31
  90. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
  91. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  92. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  93. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  94. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  95. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -1
  96. data/lib/rubocop/cop/lint/shared_mutable_default.rb +65 -0
  97. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  98. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  99. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  100. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -4
  101. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +1 -1
  102. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  103. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
  104. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
  105. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -4
  106. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  107. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  108. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  109. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  110. data/lib/rubocop/cop/lint/void.rb +5 -9
  111. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  112. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  113. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  114. data/lib/rubocop/cop/metrics/method_length.rb +8 -1
  115. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  116. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  117. data/lib/rubocop/cop/mixin/check_line_breakable.rb +11 -11
  118. data/lib/rubocop/cop/mixin/comments_help.rb +3 -1
  119. data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
  120. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  121. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +4 -4
  122. data/lib/rubocop/cop/mixin/hash_subset.rb +188 -0
  123. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  124. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +48 -24
  125. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  126. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
  127. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  128. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  129. data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
  130. data/lib/rubocop/cop/naming/block_forwarding.rb +19 -15
  131. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -3
  132. data/lib/rubocop/cop/security/compound_hash.rb +1 -0
  133. data/lib/rubocop/cop/style/access_modifier_declarations.rb +34 -5
  134. data/lib/rubocop/cop/style/and_or.rb +1 -1
  135. data/lib/rubocop/cop/style/arguments_forwarding.rb +39 -23
  136. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  137. data/lib/rubocop/cop/style/block_delimiters.rb +7 -20
  138. data/lib/rubocop/cop/style/class_and_module_children.rb +6 -3
  139. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  140. data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
  141. data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
  142. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  143. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
  144. data/lib/rubocop/cop/style/documentation.rb +1 -1
  145. data/lib/rubocop/cop/style/double_negation.rb +3 -3
  146. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  147. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  148. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  149. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  150. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  151. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  152. data/lib/rubocop/cop/style/exact_regexp_match.rb +3 -10
  153. data/lib/rubocop/cop/style/explicit_block_argument.rb +15 -2
  154. data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
  155. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  156. data/lib/rubocop/cop/style/float_division.rb +8 -4
  157. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  158. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -6
  159. data/lib/rubocop/cop/style/hash_except.rb +24 -148
  160. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  161. data/lib/rubocop/cop/style/hash_syntax.rb +6 -3
  162. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  163. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  164. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
  165. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  166. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  167. data/lib/rubocop/cop/style/inverse_methods.rb +6 -6
  168. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  169. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  170. data/lib/rubocop/cop/style/map_into_array.rb +1 -1
  171. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  172. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  173. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +19 -12
  174. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  175. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
  176. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -4
  177. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  178. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  179. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  180. data/lib/rubocop/cop/style/multiple_comparison.rb +26 -20
  181. data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
  182. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
  183. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  184. data/lib/rubocop/cop/style/object_then.rb +13 -15
  185. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  186. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -5
  187. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  188. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  189. data/lib/rubocop/cop/style/proc.rb +1 -2
  190. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  191. data/lib/rubocop/cop/style/raise_args.rb +6 -4
  192. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  193. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  194. data/lib/rubocop/cop/style/redundant_condition.rb +2 -2
  195. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
  196. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  197. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  198. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  199. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
  200. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  201. data/lib/rubocop/cop/style/redundant_line_continuation.rb +34 -13
  202. data/lib/rubocop/cop/style/redundant_parentheses.rb +10 -10
  203. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
  204. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  205. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  206. data/lib/rubocop/cop/style/redundant_self_assignment.rb +14 -28
  207. data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
  208. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  209. data/lib/rubocop/cop/style/return_nil.rb +1 -1
  210. data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
  211. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  212. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  213. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  214. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
  215. data/lib/rubocop/cop/style/single_line_methods.rb +3 -4
  216. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  217. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
  218. data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
  219. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  220. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  221. data/lib/rubocop/cop/style/super_arguments.rb +65 -17
  222. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  223. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  224. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
  225. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  226. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  227. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  228. data/lib/rubocop/cop/util.rb +11 -4
  229. data/lib/rubocop/cop/variable_force/variable.rb +14 -2
  230. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  231. data/lib/rubocop/cops_documentation_generator.rb +13 -13
  232. data/lib/rubocop/directive_comment.rb +9 -8
  233. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  234. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  235. data/lib/rubocop/lsp/logger.rb +2 -2
  236. data/lib/rubocop/lsp/routes.rb +7 -23
  237. data/lib/rubocop/lsp/runtime.rb +15 -49
  238. data/lib/rubocop/lsp/stdin_runner.rb +83 -0
  239. data/lib/rubocop/options.rb +2 -1
  240. data/lib/rubocop/path_util.rb +11 -8
  241. data/lib/rubocop/result_cache.rb +13 -13
  242. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  243. data/lib/rubocop/rspec/shared_contexts.rb +4 -1
  244. data/lib/rubocop/rspec/support.rb +1 -2
  245. data/lib/rubocop/runner.rb +5 -6
  246. data/lib/rubocop/target_finder.rb +1 -0
  247. data/lib/rubocop/target_ruby.rb +15 -0
  248. data/lib/rubocop/version.rb +1 -1
  249. data/lib/rubocop.rb +6 -0
  250. data/lib/ruby_lsp/rubocop/addon.rb +78 -0
  251. data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +50 -0
  252. metadata +23 -11
  253. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -43,7 +43,7 @@ module RuboCop
43
43
  PATTERN
44
44
 
45
45
  def parent_block_node(node)
46
- node.each_ancestor(:block, :numblock).first
46
+ node.each_ancestor(:any_block).first
47
47
  end
48
48
  end
49
49
  end
@@ -59,12 +59,12 @@ module RuboCop
59
59
 
60
60
  # @!method send_exist_node(node)
61
61
  def_node_search :send_exist_node, <<~PATTERN
62
- $(send (const nil? {:FileTest :File :Dir :Shell}) {:exist? :exists?} ...)
62
+ $(send (const {cbase nil?} {:FileTest :File :Dir :Shell}) {:exist? :exists?} ...)
63
63
  PATTERN
64
64
 
65
65
  # @!method receiver_and_method_name(node)
66
66
  def_node_matcher :receiver_and_method_name, <<~PATTERN
67
- (send (const nil? $_) $_ ...)
67
+ (send (const {cbase nil?} $_) $_ ...)
68
68
  PATTERN
69
69
 
70
70
  # @!method force?(node)
@@ -78,7 +78,7 @@ module RuboCop
78
78
  PATTERN
79
79
 
80
80
  def on_send(node)
81
- return unless node.receiver
81
+ return unless node.receiver&.const_type?
82
82
  return unless if_node_child?(node)
83
83
  return if explicit_not_force?(node)
84
84
  return unless (exist_node = send_exist_node(node.parent).first)
@@ -116,6 +116,7 @@ module RuboCop
116
116
 
117
117
  def message_remove_file_exist_check(node)
118
118
  receiver, method_name = receiver_and_method_name(node)
119
+
119
120
  format(MSG_REMOVE_FILE_EXIST_CHECK, receiver: receiver, method_name: method_name)
120
121
  end
121
122
 
@@ -66,7 +66,7 @@ module RuboCop
66
66
  private
67
67
 
68
68
  def scoped_node?(node)
69
- node.def_type? || node.defs_type? || node.lambda?
69
+ node.type?(:def, :defs) || node.lambda?
70
70
  end
71
71
 
72
72
  def return_value?(return_node)
@@ -4,30 +4,27 @@ module RuboCop
4
4
  module Cop
5
5
  module Lint
6
6
  # Certain numeric operations have a constant result, usually 0 or 1.
7
- # Subtracting a number from itself or multiplying it by 0 will always return 0.
8
- # Additionally, a variable modulo 0 or itself will always return 0.
7
+ # Multiplying a number by 0 will always return 0.
9
8
  # Dividing a number by itself or raising it to the power of 0 will always return 1.
10
9
  # As such, they can be replaced with that result.
11
10
  # These are probably leftover from debugging, or are mistakes.
12
11
  # Other numeric operations that are similarly leftover from debugging or mistakes
13
- # are handled by Lint/UselessNumericOperation.
12
+ # are handled by `Lint/UselessNumericOperation`.
13
+ #
14
+ # NOTE: This cop doesn't detect offenses for the `-` and `%` operator because it
15
+ # can't determine the type of `x`. If `x` is an `Array` or `String`, it doesn't perform
16
+ # a numeric operation.
14
17
  #
15
18
  # @example
16
19
  #
17
20
  # # bad
18
- # x - x
19
21
  # x * 0
20
- # x % 1
21
- # x % x
22
22
  #
23
23
  # # good
24
24
  # 0
25
25
  #
26
26
  # # bad
27
- # x -= x
28
27
  # x *= 0
29
- # x %= 1
30
- # x %= x
31
28
  #
32
29
  # # good
33
30
  # x = 0
@@ -49,57 +46,47 @@ module RuboCop
49
46
  class NumericOperationWithConstantResult < Base
50
47
  extend AutoCorrector
51
48
  MSG = 'Numeric operation with a constant result detected.'
52
- RESTRICT_ON_SEND = %i[- * / % **].freeze
49
+ RESTRICT_ON_SEND = %i[* / **].freeze
53
50
 
54
51
  # @!method operation_with_constant_result?(node)
55
52
  def_node_matcher :operation_with_constant_result?,
56
- '(send (send nil? $_) $_ ({int | send nil?} $_))'
53
+ '(call (call nil? $_lhs) $_operation ({int | call nil?} $_rhs))'
57
54
 
58
55
  # @!method abbreviated_assignment_with_constant_result?(node)
59
56
  def_node_matcher :abbreviated_assignment_with_constant_result?,
60
- '(op-asgn (lvasgn $_) $_ ({int | lvar} $_))'
57
+ '(op-asgn (lvasgn $_lhs) $_operation ({int lvar} $_rhs))'
61
58
 
62
59
  def on_send(node)
63
- return unless operation_with_constant_result?(node)
64
-
65
- variable, operation, number = operation_with_constant_result?(node)
66
- result = constant_result?(variable, operation, number)
67
- return unless result
60
+ return unless (lhs, operation, rhs = operation_with_constant_result?(node))
61
+ return unless (result = constant_result?(lhs, operation, rhs))
68
62
 
69
63
  add_offense(node) do |corrector|
70
64
  corrector.replace(node, result.to_s)
71
65
  end
72
66
  end
67
+ alias on_csend on_send
73
68
 
74
69
  def on_op_asgn(node)
75
- return unless abbreviated_assignment_with_constant_result?(node)
76
-
77
- variable, operation, number = abbreviated_assignment_with_constant_result?(node)
78
- result = constant_result?(variable, operation, number)
79
- return unless result
70
+ return unless (lhs, operation, rhs = abbreviated_assignment_with_constant_result?(node))
71
+ return unless (result = constant_result?(lhs, operation, rhs))
80
72
 
81
73
  add_offense(node) do |corrector|
82
- corrector.replace(node, "#{variable} = #{result}")
74
+ corrector.replace(node, "#{lhs} = #{result}")
83
75
  end
84
76
  end
85
77
 
86
78
  private
87
79
 
88
- # rubocop :disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
89
- def constant_result?(variable, operation, number)
90
- if number.to_s == '0'
80
+ def constant_result?(lhs, operation, rhs)
81
+ if rhs.to_s == '0'
91
82
  return 0 if operation == :*
92
83
  return 1 if operation == :**
93
- elsif number.to_s == '1'
94
- return 0 if operation == :%
95
- elsif number == variable
96
- return 0 if %i[- %].include?(operation)
84
+ elsif rhs == lhs
97
85
  return 1 if operation == :/
98
86
  end
99
87
  # If we weren't able to find any matches, return false so we can bail out.
100
88
  false
101
89
  end
102
- # rubocop :enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
103
90
  end
104
91
  end
105
92
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Looks for references of Regexp captures that are out of range
6
+ # Looks for references of `Regexp` captures that are out of range
7
7
  # and thus always returns nil.
8
8
  #
9
9
  # @safety
@@ -61,6 +61,7 @@ module RuboCop
61
61
  check_regexp(node.receiver)
62
62
  end
63
63
  end
64
+ alias after_csend after_send
64
65
 
65
66
  def on_when(node)
66
67
  regexp_conditions = node.conditions.select(&:regexp_type?)
@@ -38,16 +38,12 @@ module RuboCop
38
38
 
39
39
  def valid_context?(node)
40
40
  return true unless node.arguments.one? && node.first_argument.parenthesized_call?
41
- return true if first_argument_block_type?(node.first_argument)
41
+ return true if node.first_argument.any_block_type?
42
42
 
43
43
  node.operator_method? || node.setter_method? || chained_calls?(node) ||
44
44
  valid_first_argument?(node.first_argument)
45
45
  end
46
46
 
47
- def first_argument_block_type?(first_arg)
48
- first_arg.block_type? || first_arg.numblock_type?
49
- end
50
-
51
47
  def valid_first_argument?(first_arg)
52
48
  first_arg.operator_keyword? || first_arg.hash_type? || ternary_expression?(first_arg) ||
53
49
  compound_range?(first_arg)
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for redundant quantifiers inside Regexp literals.
6
+ # Checks for redundant quantifiers inside `Regexp` literals.
7
7
  #
8
8
  # It is always allowed when interpolation is used in a regexp literal,
9
9
  # because it's unknown what kind of string will be expanded as a result:
@@ -29,7 +29,7 @@ module RuboCop
29
29
  RESTRICT_ON_SEND = %i[print puts warn].freeze
30
30
 
31
31
  # @!method to_s_without_args?(node)
32
- def_node_matcher :to_s_without_args?, '(send _ :to_s)'
32
+ def_node_matcher :to_s_without_args?, '(call _ :to_s)'
33
33
 
34
34
  def on_interpolation(begin_node)
35
35
  final_node = begin_node.children.last
@@ -42,7 +42,7 @@ module RuboCop
42
42
  def on_send(node)
43
43
  return if node.receiver
44
44
 
45
- node.each_child_node(:send) do |child|
45
+ node.each_child_node(:call) do |child|
46
46
  next if !child.method?(:to_s) || child.arguments.any?
47
47
 
48
48
  register_offense(child, "`#{node.method_name}`")
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for `rescue` blocks targeting the Exception class.
6
+ # Checks for `rescue` blocks targeting the `Exception` class.
7
7
  #
8
8
  # @example
9
9
  #
@@ -33,7 +33,7 @@ module RuboCop
33
33
  def_node_matcher :bad_method?, <<~PATTERN
34
34
  {
35
35
  (send $(csend ...) $_ ...)
36
- (send $({block numblock} (csend ...) ...) $_ ...)
36
+ (send $(any_block (csend ...) ...) $_ ...)
37
37
  }
38
38
  PATTERN
39
39
 
@@ -97,12 +97,19 @@ module RuboCop
97
97
  end
98
98
 
99
99
  def require_parentheses?(send_node)
100
+ return true if operator_inside_hash?(send_node)
100
101
  return false unless send_node.comparison_method?
101
102
  return false unless (node = send_node.parent)
102
103
 
103
104
  (node.respond_to?(:logical_operator?) && node.logical_operator?) ||
104
105
  (node.respond_to?(:comparison_method?) && node.comparison_method?)
105
106
  end
107
+
108
+ def operator_inside_hash?(send_node)
109
+ # If an operator call (without a dot) is inside a hash, it needs
110
+ # to be parenthesized when converted to safe navigation.
111
+ send_node.parent&.pair_type? && !send_node.loc.dot
112
+ end
106
113
  end
107
114
  end
108
115
  end
@@ -0,0 +1,65 @@
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
+ (send (const {nil? cbase} :Hash) :new {array hash (send (const {nil? cbase} {:Array :Hash}) :new)})
55
+ PATTERN
56
+
57
+ def on_send(node)
58
+ return unless hash_initialized_with_mutable_shared_object?(node)
59
+
60
+ add_offense(node)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ 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, :def, :defs, :any_block).first
120
120
  return false unless ancestor
121
121
 
122
122
  end_line = ancestor.loc.end&.line || ancestor.loc.last_line
@@ -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}\"")
@@ -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
@@ -55,12 +55,9 @@ module RuboCop
55
55
  return if node.each_descendant(:dstr).any?
56
56
 
57
57
  regexp_constructor(node) do |text|
58
- Regexp::Parser.parse(text.value)&.each_expression do |expr|
58
+ parse_regexp(text.value)&.each_expression do |expr|
59
59
  detect_offenses(text, expr)
60
60
  end
61
- rescue Regexp::Parser::Error
62
- # Upon encountering an invalid regular expression,
63
- # we aim to proceed and identify any remaining potential offenses.
64
61
  end
65
62
  end
66
63
 
@@ -81,7 +81,7 @@ module RuboCop
81
81
  node.arguments.count do |arg|
82
82
  return Float::INFINITY if arg.restarg_type?
83
83
 
84
- arg.arg_type? || arg.optarg_type? || arg.mlhs_type?
84
+ arg.type?(:arg, :optarg, :mlhs)
85
85
  end
86
86
  end
87
87
  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
@@ -117,7 +117,7 @@ module RuboCop
117
117
  end
118
118
 
119
119
  def instance_eval_block?(node)
120
- node.block_type? && node.method?(:instance_eval)
120
+ node.any_block_type? && node.method?(:instance_eval)
121
121
  end
122
122
 
123
123
  def report_on_flow_command?(node)
@@ -108,7 +108,7 @@ module RuboCop
108
108
  private
109
109
 
110
110
  def loop_method?(node)
111
- return false unless node.block_type? || node.numblock_type?
111
+ return false unless node.any_block_type?
112
112
 
113
113
  send_node = node.send_node
114
114
  loopable = send_node.enumerable_method? || send_node.enumerator_method? ||
@@ -159,12 +159,12 @@ module RuboCop
159
159
 
160
160
  # @!method dynamic_method_definition?(node)
161
161
  def_node_matcher :dynamic_method_definition?, <<~PATTERN
162
- {(send nil? :define_method ...) ({block numblock} (send nil? :define_method ...) ...)}
162
+ {(send nil? :define_method ...) (any_block (send nil? :define_method ...) ...)}
163
163
  PATTERN
164
164
 
165
165
  # @!method class_or_instance_eval?(node)
166
166
  def_node_matcher :class_or_instance_eval?, <<~PATTERN
167
- ({block numblock} (send _ {:class_eval :instance_eval}) ...)
167
+ (any_block (send _ {:class_eval :instance_eval}) ...)
168
168
  PATTERN
169
169
 
170
170
  def check_node(node)
@@ -268,7 +268,7 @@ module RuboCop
268
268
  end
269
269
 
270
270
  def start_of_new_scope?(child)
271
- child.module_type? || child.class_type? || child.sclass_type? || eval_call?(child)
271
+ child.type?(:module, :class, :sclass) || eval_call?(child)
272
272
  end
273
273
 
274
274
  def eval_call?(child)
@@ -282,7 +282,7 @@ module RuboCop
282
282
  matcher_name = :"#{m}_block?"
283
283
  unless respond_to?(matcher_name)
284
284
  self.class.def_node_matcher matcher_name, <<~PATTERN
285
- ({block numblock} (send {nil? const} {:#{m}} ...) ...)
285
+ (any_block (send {nil? const} {:#{m}} ...) ...)
286
286
  PATTERN
287
287
  end
288
288
 
@@ -17,7 +17,7 @@ module RuboCop
17
17
  # rescue, ensure, etc.
18
18
  #
19
19
  # This cop's autocorrection avoids cases like `a ||= 1` because removing assignment from
20
- # operator assignment can cause NameError if this assignment has been used to declare
20
+ # operator assignment can cause `NameError` if this assignment has been used to declare
21
21
  # a local variable. For example, replacing `a ||= 1` with `a || 1` may cause
22
22
  # "undefined local variable or method `a' for main:Object (NameError)".
23
23
  #
@@ -59,7 +59,7 @@ module RuboCop
59
59
  end
60
60
 
61
61
  def use_rest_or_optional_args?(node)
62
- node.arguments.any? { |arg| arg.restarg_type? || arg.optarg_type? || arg.kwoptarg_type? }
62
+ node.arguments.any? { |arg| arg.type?(:restarg, :optarg, :kwoptarg) }
63
63
  end
64
64
 
65
65
  def delegating?(node, def_node)
@@ -35,7 +35,7 @@ module RuboCop
35
35
  RESTRICT_ON_SEND = %i[+ - * / **].freeze
36
36
 
37
37
  # @!method useless_operation?(node)
38
- def_node_matcher :useless_operation?, '(send (send nil? $_) $_ (int $_))'
38
+ def_node_matcher :useless_operation?, '(call (call nil? $_) $_ (int $_))'
39
39
 
40
40
  # @!method useless_abbreviated_assignment?(node)
41
41
  def_node_matcher :useless_abbreviated_assignment?, '(op-asgn (lvasgn $_) $_ (int $_))'
@@ -50,6 +50,7 @@ module RuboCop
50
50
  corrector.replace(node, variable)
51
51
  end
52
52
  end
53
+ alias on_csend on_send
53
54
 
54
55
  def on_op_asgn(node)
55
56
  return unless useless_abbreviated_assignment?(node)
@@ -72,7 +72,7 @@ module RuboCop
72
72
  def_node_matcher :method_definition, <<~PATTERN
73
73
  {
74
74
  (def %1 ...)
75
- ({block numblock} (send _ :define_method (sym %1)) ...)
75
+ (any_block (send _ :define_method (sym %1)) ...)
76
76
  }
77
77
  PATTERN
78
78
 
@@ -108,7 +108,7 @@ module RuboCop
108
108
 
109
109
  def find_method_definition(node, method_name)
110
110
  node.each_ancestor.lazy.map do |ancestor|
111
- ancestor.each_child_node(:def, :block, :numblock).find do |child|
111
+ ancestor.each_child_node(:def, :any_block).find do |child|
112
112
  method_definition(child, method_name)
113
113
  end
114
114
  end.find(&:itself)
@@ -103,7 +103,7 @@ module RuboCop
103
103
  expressions.pop unless in_void_context?(node)
104
104
  expressions.each do |expr|
105
105
  check_void_op(expr) do
106
- block_node = node.each_ancestor(:block).first
106
+ block_node = node.each_ancestor(:any_block).first
107
107
 
108
108
  block_node&.method?(:each)
109
109
  end
@@ -113,7 +113,8 @@ module RuboCop
113
113
  end
114
114
 
115
115
  def check_expression(expr)
116
- expr = expr.body if expr.if_type? && expr.modifier_form?
116
+ expr = expr.body if expr.if_type?
117
+ return unless expr
117
118
 
118
119
  check_literal(expr)
119
120
  check_var(expr)
@@ -178,7 +179,7 @@ module RuboCop
178
179
  end
179
180
 
180
181
  def check_nonmutating(node)
181
- return if !node.send_type? && !node.block_type? && !node.numblock_type?
182
+ return unless node.type?(:send, :any_block)
182
183
 
183
184
  method_name = node.method_name
184
185
  return unless NONMUTATING_METHODS.include?(method_name)
@@ -200,11 +201,6 @@ module RuboCop
200
201
  # NOTE: the `begin` node case is already handled via `on_begin`
201
202
  return if body.begin_type?
202
203
 
203
- check_void_op(body) do
204
- block_node = node.each_ancestor(:block).first
205
- block_node&.method?(:each)
206
- end
207
-
208
204
  check_expression(body)
209
205
  end
210
206
 
@@ -229,7 +225,7 @@ module RuboCop
229
225
  end
230
226
 
231
227
  def autocorrect_void_expression(corrector, node)
232
- return if node.parent.if_type? && node.parent.modifier_form?
228
+ return if node.parent.if_type?
233
229
 
234
230
  corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
235
231
  end
@@ -52,7 +52,7 @@ module RuboCop
52
52
  def consider_node?(node)
53
53
  return true if NESTING_BLOCKS.include?(node.type)
54
54
 
55
- count_blocks? && (node.block_type? || node.numblock_type?)
55
+ count_blocks? && node.any_block_type?
56
56
  end
57
57
 
58
58
  def message(max)
@@ -52,12 +52,19 @@ module RuboCop
52
52
  'Prefer reading the data from an external source.'
53
53
  RESTRICT_ON_SEND = [:[]].freeze
54
54
 
55
+ # @!method set_const?(node)
56
+ def_node_matcher :set_const?, <<~PATTERN
57
+ (const {cbase nil?} :Set)
58
+ PATTERN
59
+
55
60
  def on_array(node)
56
61
  add_offense(node) if node.children.length >= collection_threshold
57
62
  end
58
63
  alias on_hash on_array
59
64
 
60
65
  def on_index(node)
66
+ return unless set_const?(node.receiver)
67
+
61
68
  add_offense(node) if node.arguments.length >= collection_threshold
62
69
  end
63
70
 
@@ -36,7 +36,7 @@ module RuboCop
36
36
  include MethodComplexity
37
37
  include Utils::IteratingBlock
38
38
 
39
- MSG = 'Cyclomatic complexity for %<method>s is too high. [%<complexity>d/%<max>d]'
39
+ MSG = 'Cyclomatic complexity for `%<method>s` is too high. [%<complexity>d/%<max>d]'
40
40
  COUNTED_NODES = %i[if while until for csend block block_pass
41
41
  rescue when in_pattern and or or_asgn and_asgn].freeze
42
42
 
@@ -48,7 +48,7 @@ module RuboCop
48
48
  LABEL = 'Method'
49
49
 
50
50
  def on_def(node)
51
- return if allowed_method?(node.method_name) || matches_allowed_pattern?(node.method_name)
51
+ return if allowed?(node.method_name)
52
52
 
53
53
  check_code_length(node)
54
54
  end
@@ -57,6 +57,9 @@ module RuboCop
57
57
  def on_block(node)
58
58
  return unless node.method?(:define_method)
59
59
 
60
+ method_name = node.send_node.first_argument
61
+ return if method_name.basic_literal? && allowed?(method_name.value)
62
+
60
63
  check_code_length(node)
61
64
  end
62
65
  alias on_numblock on_block
@@ -66,6 +69,10 @@ module RuboCop
66
69
  def cop_label
67
70
  LABEL
68
71
  end
72
+
73
+ def allowed?(method_name)
74
+ allowed_method?(method_name) || matches_allowed_pattern?(method_name)
75
+ end
69
76
  end
70
77
  end
71
78
  end
@@ -50,7 +50,7 @@ module RuboCop
50
50
 
51
51
  # @!method module_definition?(node)
52
52
  def_node_matcher :module_definition?, <<~PATTERN
53
- (casgn nil? _ ({block numblock} (send (const {nil? cbase} :Module) :new) ...))
53
+ (casgn nil? _ (any_block (send (const {nil? cbase} :Module) :new) ...))
54
54
  PATTERN
55
55
 
56
56
  def message(length, max_length)
@@ -27,7 +27,7 @@ module RuboCop
27
27
  # end # ===
28
28
  # end # 7 complexity points
29
29
  class PerceivedComplexity < CyclomaticComplexity
30
- MSG = 'Perceived complexity for %<method>s is too high. [%<complexity>d/%<max>d]'
30
+ MSG = 'Perceived complexity for `%<method>s` is too high. [%<complexity>d/%<max>d]'
31
31
 
32
32
  COUNTED_NODES = (CyclomaticComplexity::COUNTED_NODES - [:when] + [:case]).freeze
33
33