rubocop 1.70.0 → 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 (195) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +17 -0
  4. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  5. data/lib/rubocop/comment_config.rb +1 -1
  6. data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
  7. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  8. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  9. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  10. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  11. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  12. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  13. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +229 -0
  14. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  15. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  16. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  17. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  18. data/lib/rubocop/cop/internal_affairs.rb +3 -0
  19. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  20. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  21. data/lib/rubocop/cop/layout/block_alignment.rb +1 -1
  22. data/lib/rubocop/cop/layout/class_structure.rb +9 -9
  23. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  24. data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
  25. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  26. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
  27. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  28. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
  29. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
  30. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  31. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  32. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +1 -1
  33. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  34. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +1 -0
  35. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
  36. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
  37. data/lib/rubocop/cop/layout/redundant_line_break.rb +6 -5
  38. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
  39. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  40. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  41. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  42. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  43. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -0
  44. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  45. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  46. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  47. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
  48. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  49. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +1 -1
  50. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  51. data/lib/rubocop/cop/lint/constant_reassignment.rb +2 -6
  52. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  53. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  54. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  55. data/lib/rubocop/cop/lint/duplicate_set_element.rb +1 -1
  56. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  57. data/lib/rubocop/cop/lint/float_comparison.rb +5 -2
  58. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  59. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  60. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  61. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +13 -3
  62. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  63. data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
  64. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  65. data/lib/rubocop/cop/lint/nested_method_definition.rb +3 -3
  66. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  67. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  68. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +13 -18
  69. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
  70. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  71. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  72. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  73. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  74. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -1
  75. data/lib/rubocop/cop/lint/shared_mutable_default.rb +3 -3
  76. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  77. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  78. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +1 -1
  79. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  80. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
  81. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
  82. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -4
  83. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  84. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  85. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  86. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  87. data/lib/rubocop/cop/lint/void.rb +2 -7
  88. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  89. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  90. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  91. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  92. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  93. data/lib/rubocop/cop/mixin/check_line_breakable.rb +5 -5
  94. data/lib/rubocop/cop/mixin/comments_help.rb +1 -1
  95. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  96. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +4 -4
  97. data/lib/rubocop/cop/mixin/hash_subset.rb +188 -0
  98. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  99. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +22 -8
  100. data/lib/rubocop/cop/mixin/statement_modifier.rb +7 -2
  101. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  102. data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
  103. data/lib/rubocop/cop/naming/block_forwarding.rb +18 -14
  104. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -3
  105. data/lib/rubocop/cop/security/compound_hash.rb +1 -0
  106. data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -4
  107. data/lib/rubocop/cop/style/arguments_forwarding.rb +38 -19
  108. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  109. data/lib/rubocop/cop/style/block_delimiters.rb +7 -20
  110. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  111. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  112. data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
  113. data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
  114. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  115. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
  116. data/lib/rubocop/cop/style/documentation.rb +1 -1
  117. data/lib/rubocop/cop/style/double_negation.rb +3 -3
  118. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  119. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  120. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  121. data/lib/rubocop/cop/style/exact_regexp_match.rb +1 -1
  122. data/lib/rubocop/cop/style/explicit_block_argument.rb +15 -2
  123. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  124. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  125. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -6
  126. data/lib/rubocop/cop/style/hash_except.rb +20 -131
  127. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  128. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  129. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  130. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  131. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
  132. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  133. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  134. data/lib/rubocop/cop/style/inverse_methods.rb +6 -6
  135. data/lib/rubocop/cop/style/it_assignment.rb +1 -1
  136. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  137. data/lib/rubocop/cop/style/map_into_array.rb +1 -1
  138. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  139. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  140. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +10 -13
  141. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
  142. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -4
  143. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  144. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  145. data/lib/rubocop/cop/style/mutable_constant.rb +2 -2
  146. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
  147. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  148. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  149. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -5
  150. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  151. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  152. data/lib/rubocop/cop/style/proc.rb +1 -2
  153. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  154. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  155. data/lib/rubocop/cop/style/redundant_condition.rb +2 -2
  156. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  157. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  158. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  159. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
  160. data/lib/rubocop/cop/style/redundant_line_continuation.rb +27 -10
  161. data/lib/rubocop/cop/style/redundant_parentheses.rb +9 -6
  162. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  163. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  164. data/lib/rubocop/cop/style/redundant_self_assignment.rb +12 -27
  165. data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
  166. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  167. data/lib/rubocop/cop/style/return_nil.rb +1 -1
  168. data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
  169. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  170. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  171. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  172. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
  173. data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
  174. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  175. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  176. data/lib/rubocop/cop/style/super_arguments.rb +4 -4
  177. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  178. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  179. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
  180. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  181. data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
  182. data/lib/rubocop/cop/util.rb +2 -2
  183. data/lib/rubocop/cop/variable_force/variable.rb +14 -2
  184. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  185. data/lib/rubocop/cops_documentation_generator.rb +13 -13
  186. data/lib/rubocop/directive_comment.rb +9 -8
  187. data/lib/rubocop/options.rb +2 -1
  188. data/lib/rubocop/result_cache.rb +13 -13
  189. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  190. data/lib/rubocop/rspec/support.rb +1 -2
  191. data/lib/rubocop/target_finder.rb +1 -0
  192. data/lib/rubocop/version.rb +1 -1
  193. data/lib/rubocop.rb +3 -0
  194. metadata +15 -11
  195. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Checks for semicolon (;) not followed by some kind of space.
6
+ # Checks for semicolon (`;`) not followed by some kind of space.
7
7
  #
8
8
  # @example
9
9
  # # bad
@@ -36,6 +36,7 @@ module RuboCop
36
36
  ACCEPT_LEFT_PAREN = %w[break defined? next not rescue return super yield].freeze
37
37
  ACCEPT_LEFT_SQUARE_BRACKET = %w[super yield].freeze
38
38
  ACCEPT_NAMESPACE_OPERATOR = 'super'
39
+ RESTRICT_ON_SEND = %i[!].freeze
39
40
 
40
41
  def on_and(node)
41
42
  check(node, [:operator].freeze) if node.keyword?
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Checks for comma (,) preceded by space.
6
+ # Checks for comma (`,`) preceded by space.
7
7
  #
8
8
  # @example
9
9
  # # bad
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Checks for semicolon (;) preceded by space.
6
+ # Checks for semicolon (`;`) preceded by space.
7
7
  #
8
8
  # @example
9
9
  # # bad
@@ -77,7 +77,7 @@ module RuboCop
77
77
  private
78
78
 
79
79
  def ambiguous_block_association?(send_node)
80
- send_node.last_argument.block_type? && !send_node.last_argument.send_node.arguments?
80
+ send_node.last_argument.any_block_type? && !send_node.last_argument.send_node.arguments?
81
81
  end
82
82
 
83
83
  def allowed_method_pattern?(node)
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for an array literal interpolated inside a regexp.
7
+ #
8
+ # When interpolating an array literal, it is converted to a string. This means
9
+ # that when inside a regexp, it acts as a character class but with additional
10
+ # quotes, spaces and commas that are likely not intended. For example,
11
+ # `/#{%w[a b c]}/` parses as `/["a", "b", "c"]/` (or `/["a, bc]/` without
12
+ # repeated characters).
13
+ #
14
+ # The cop can autocorrect to a character class (if all items in the array are a
15
+ # single character) or alternation (if the array contains longer items).
16
+ #
17
+ # NOTE: This only considers interpolated arrays that contain only strings, symbols,
18
+ # integers, and floats. Any other type is not easily convertible to a character class
19
+ # or regexp alternation.
20
+ #
21
+ # @safety
22
+ # Autocorrection is unsafe because it will change the regexp pattern, by
23
+ # removing the additional quotes, spaces and commas from the character class.
24
+ #
25
+ # @example
26
+ # # bad
27
+ # /#{%w[a b c]}/
28
+ #
29
+ # # good
30
+ # /[abc]/
31
+ #
32
+ # # bad
33
+ # /#{%w[foo bar baz]}/
34
+ #
35
+ # # good
36
+ # /(?:foo|bar|baz)/
37
+ #
38
+ # # bad - construct a regexp rather than interpolate an array of identifiers
39
+ # /#{[foo, bar]}/
40
+ #
41
+ class ArrayLiteralInRegexp < Base
42
+ include Interpolation
43
+ extend AutoCorrector
44
+
45
+ LITERAL_TYPES = %i[str sym int float true false nil].freeze
46
+ private_constant :LITERAL_TYPES
47
+
48
+ MSG_CHARACTER_CLASS = 'Use a character class instead of interpolating an array in a regexp.'
49
+ MSG_ALTERNATION = 'Use alternation instead of interpolating an array in a regexp.'
50
+ MSG_UNKNOWN = 'Use alternation or a character class instead of interpolating an array ' \
51
+ 'in a regexp.'
52
+
53
+ def on_interpolation(begin_node)
54
+ final_node = begin_node.children.last
55
+
56
+ return unless begin_node.parent.regexp_type?
57
+ return unless final_node.array_type?
58
+
59
+ if array_of_literal_values?(final_node)
60
+ register_array_of_literal_values(begin_node, final_node)
61
+ else
62
+ register_array_of_nonliteral_values(begin_node)
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def array_of_literal_values?(node)
69
+ node.each_value.all? { |value| value.type?(*LITERAL_TYPES) }
70
+ end
71
+
72
+ def register_array_of_literal_values(begin_node, node)
73
+ array_values = array_values(node)
74
+
75
+ if character_class?(array_values)
76
+ message = MSG_CHARACTER_CLASS
77
+ replacement = character_class_for(array_values)
78
+ else
79
+ message = MSG_ALTERNATION
80
+ replacement = alternation_for(array_values)
81
+ end
82
+
83
+ add_offense(begin_node, message: message) do |corrector|
84
+ corrector.replace(begin_node, replacement)
85
+ end
86
+ end
87
+
88
+ def register_array_of_nonliteral_values(node)
89
+ # Add offense but do not correct if the array contains any nonliteral values.
90
+ add_offense(node, message: MSG_UNKNOWN)
91
+ end
92
+
93
+ def array_values(node)
94
+ node.each_value.map do |value|
95
+ value.respond_to?(:value) ? value.value : value.source
96
+ end
97
+ end
98
+
99
+ def character_class?(values)
100
+ values.all? { |v| v.to_s.length == 1 }
101
+ end
102
+
103
+ def character_class_for(values)
104
+ "[#{escape_values(values).join}]"
105
+ end
106
+
107
+ def alternation_for(values)
108
+ "(?:#{escape_values(values).join('|')})"
109
+ end
110
+
111
+ def escape_values(values)
112
+ # This may add extraneous escape characters, but they can be cleaned up
113
+ # by `Style/RedundantRegexpEscape`.
114
+ values.map { |value| Regexp.escape(value.to_s) }
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -53,8 +53,6 @@ module RuboCop
53
53
  ASGN_TYPES = [:begin, *AST::Node::EQUALS_ASSIGNMENTS, :send, :csend].freeze
54
54
 
55
55
  def on_if(node)
56
- return if node.condition.block_type?
57
-
58
56
  traverse_node(node.condition) do |asgn_node|
59
57
  next :skip_children if skip_children?(asgn_node)
60
58
  next if allowed_construct?(asgn_node)
@@ -95,7 +93,7 @@ module RuboCop
95
93
 
96
94
  def traverse_node(node, &block)
97
95
  # if the node is a block, any assignments are irrelevant
98
- return if node.block_type?
96
+ return if node.any_block_type?
99
97
 
100
98
  result = yield node if ASGN_TYPES.include?(node.type)
101
99
 
@@ -14,7 +14,7 @@ module RuboCop
14
14
  # Although these can be rewritten in a different way, it should not be necessary to
15
15
  # do so. Operations such as `-` or `/` where the result will always be the same
16
16
  # (`x - x` will always be 0; `x / x` will always be 1) are offenses, but these
17
- # are covered by Lint/NumericOperationWithConstantResult instead.
17
+ # are covered by `Lint/NumericOperationWithConstantResult` instead.
18
18
  #
19
19
  # @safety
20
20
  # This cop is unsafe as it does not consider side effects when calling methods
@@ -68,12 +68,12 @@ module RuboCop
68
68
 
69
69
  # @!method constant_assigned_in_block?(node)
70
70
  def_node_matcher :constant_assigned_in_block?, <<~PATTERN
71
- ({^block_type? [^begin_type? ^^block_type?]} nil? ...)
71
+ ({^any_block [^begin ^^any_block]} nil? ...)
72
72
  PATTERN
73
73
 
74
74
  # @!method module_defined_in_block?(node)
75
75
  def_node_matcher :module_defined_in_block?, <<~PATTERN
76
- ({^block_type? [^begin_type? ^^block_type?]} ...)
76
+ ({^any_block [^begin ^^any_block]} ...)
77
77
  PATTERN
78
78
 
79
79
  def on_casgn(node)
@@ -92,7 +92,7 @@ module RuboCop
92
92
  private
93
93
 
94
94
  def method_name(node)
95
- node.ancestors.find(&:block_type?).method_name
95
+ node.ancestors.find(&:any_block_type?).method_name
96
96
  end
97
97
  end
98
98
  end
@@ -96,22 +96,18 @@ module RuboCop
96
96
  private
97
97
 
98
98
  def fixed_constant_path?(node)
99
- node.each_path.all? { |path| path.cbase_type? || path.const_type? || path.self_type? }
99
+ node.each_path.all? { |path| path.type?(:cbase, :const, :self) }
100
100
  end
101
101
 
102
102
  def simple_assignment?(node)
103
103
  node.ancestors.all? do |ancestor|
104
- return true if namespace_definition?(ancestor)
104
+ return true if ancestor.type?(:module, :class)
105
105
 
106
106
  ancestor.begin_type? || ancestor.literal? || ancestor.casgn_type? ||
107
107
  freeze_method?(ancestor)
108
108
  end
109
109
  end
110
110
 
111
- def namespace_definition?(node)
112
- node.module_type? || node.class_type?
113
- end
114
-
115
111
  def freeze_method?(node)
116
112
  node.send_type? && node.method?(:freeze)
117
113
  end
@@ -116,7 +116,7 @@ module RuboCop
116
116
 
117
117
  def assumed_usage_context?(node)
118
118
  # Basically, debugger methods are not used as a method argument without arguments.
119
- return false unless node.arguments.empty? && node.each_ancestor(:send, :csend).any?
119
+ return false unless node.arguments.empty? && node.each_ancestor(:call).any?
120
120
  return true if assumed_argument?(node)
121
121
 
122
122
  node.each_ancestor.none? do |ancestor|
@@ -106,7 +106,7 @@ module RuboCop
106
106
  private
107
107
 
108
108
  def pattern_identity(pattern)
109
- pattern_source = if pattern.hash_pattern_type? || pattern.match_alt_type?
109
+ pattern_source = if pattern.type?(:hash_pattern, :match_alt)
110
110
  pattern.children.map(&:source).sort.to_s
111
111
  else
112
112
  pattern.source
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for duplicate elements in Regexp character classes.
6
+ # Checks for duplicate elements in `Regexp` character classes.
7
7
  #
8
8
  # @example
9
9
  #
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for duplicate literal, constant, or variable elements in Set and SortedSet.
6
+ # Checks for duplicate literal, constant, or variable elements in `Set` and `SortedSet`.
7
7
  #
8
8
  # @example
9
9
  #
@@ -14,8 +14,6 @@ module RuboCop
14
14
  # bar
15
15
  # end
16
16
  #
17
- # @example
18
- #
19
17
  # # good
20
18
  #
21
19
  # foo = (some_expression)
@@ -36,7 +36,8 @@ module RuboCop
36
36
  # # https://www.embeddeduse.com/2019/08/26/qt-compare-two-floats/
37
37
  #
38
38
  class FloatComparison < Base
39
- MSG = 'Avoid (in)equality comparisons of floats as they are unreliable.'
39
+ MSG_EQUALITY = 'Avoid equality comparisons of floats as they are unreliable.'
40
+ MSG_INEQUALITY = 'Avoid inequality comparisons of floats as they are unreliable.'
40
41
 
41
42
  EQUALITY_METHODS = %i[== != eql? equal?].freeze
42
43
  FLOAT_RETURNING_METHODS = %i[to_f Float fdiv].freeze
@@ -52,8 +53,10 @@ module RuboCop
52
53
 
53
54
  return if literal_safe?(lhs) || literal_safe?(rhs)
54
55
 
55
- add_offense(node) if float?(lhs) || float?(rhs)
56
+ message = node.method?(:!=) ? MSG_INEQUALITY : MSG_EQUALITY
57
+ add_offense(node, message: message) if float?(lhs) || float?(rhs)
56
58
  end
59
+ alias on_csend on_send
57
60
 
58
61
  private
59
62
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Identifies Float literals which are, like, really really really
6
+ # Identifies `Float` literals which are, like, really really really
7
7
  # really really really really really big. Too big. No-one needs Floats
8
8
  # that big. If you need a float that big, something is wrong with you.
9
9
  #
@@ -73,7 +73,7 @@ module RuboCop
73
73
 
74
74
  first_arg = node.first_argument
75
75
  return false if num_of_expected_fields.zero? &&
76
- (first_arg.dstr_type? || first_arg.array_type?)
76
+ first_arg.type?(:dstr, :array)
77
77
 
78
78
  matched_arguments_count?(num_of_expected_fields, num_of_format_args)
79
79
  end
@@ -82,7 +82,7 @@ module RuboCop
82
82
  end
83
83
 
84
84
  def string_literal?(node)
85
- node.str_type? || node.dstr_type?
85
+ node.type?(:str, :dstr)
86
86
  end
87
87
 
88
88
  def string_literals?(node1, node2)
@@ -5,6 +5,9 @@ module RuboCop
5
5
  module Lint
6
6
  # Checks for interpolated literals.
7
7
  #
8
+ # NOTE: Array literals interpolated in regexps are not handled by this cop, but
9
+ # by `Lint/ArrayLiteralInRegexp` instead.
10
+ #
8
11
  # @example
9
12
  #
10
13
  # # bad
@@ -55,8 +58,10 @@ module RuboCop
55
58
  node &&
56
59
  !special_keyword?(node) &&
57
60
  prints_as_self?(node) &&
58
- # Special case for Layout/TrailingWhitespace
59
- !(space_literal?(node) && ends_heredoc_line?(node))
61
+ # Special case for `Layout/TrailingWhitespace`
62
+ !(space_literal?(node) && ends_heredoc_line?(node)) &&
63
+ # Handled by `Lint/ArrayLiteralInRegexp`
64
+ !array_in_regexp?(node)
60
65
  end
61
66
 
62
67
  def special_keyword?(node)
@@ -64,6 +69,11 @@ module RuboCop
64
69
  (node.str_type? && !node.loc.respond_to?(:begin)) || node.source_range.is?('__LINE__')
65
70
  end
66
71
 
72
+ def array_in_regexp?(node)
73
+ grandparent = node.parent.parent
74
+ node.array_type? && grandparent.regexp_type?
75
+ end
76
+
67
77
  # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
68
78
  def autocorrected_value(node)
69
79
  case node.type
@@ -189,7 +199,7 @@ module RuboCop
189
199
 
190
200
  def in_array_percent_literal?(node)
191
201
  parent = node.parent
192
- return false unless parent.dstr_type? || parent.dsym_type?
202
+ return false unless parent.type?(:dstr, :dsym)
193
203
 
194
204
  grandparent = parent.parent
195
205
  grandparent&.array_type? && grandparent.percent_literal?
@@ -97,7 +97,7 @@ module RuboCop
97
97
 
98
98
  # @!method class_new_block(node)
99
99
  def_node_matcher :class_new_block, <<~RUBY
100
- ({block numblock}
100
+ (any_block
101
101
  (send
102
102
  (const {nil? cbase} :Class) :new $_) ...)
103
103
  RUBY
@@ -135,7 +135,7 @@ module RuboCop
135
135
  end
136
136
 
137
137
  def inside_class_with_stateful_parent?(node)
138
- if (block_node = node.each_ancestor(:block, :numblock).first)
138
+ if (block_node = node.each_ancestor(:any_block).first)
139
139
  return false unless (super_class = class_new_block(block_node))
140
140
 
141
141
  !allowed_class?(super_class)
@@ -8,7 +8,7 @@ module RuboCop
8
8
  # Offenses are registered for regexp character classes like `/[A-z]/`
9
9
  # as well as range objects like `('A'..'z')`.
10
10
  #
11
- # NOTE: Range objects cannot be autocorrected.
11
+ # NOTE: `Range` objects cannot be autocorrected.
12
12
  #
13
13
  # @safety
14
14
  # The cop autocorrects regexp character classes
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Do not mix named captures and numbered captures in a Regexp literal
6
+ # Do not mix named captures and numbered captures in a `Regexp` literal
7
7
  # because numbered capture is ignored if they're mixed.
8
8
  # Replace numbered captures with non-capturing groupings or
9
9
  # named captures.
@@ -102,7 +102,7 @@ module RuboCop
102
102
  return unless def_ancestor
103
103
 
104
104
  within_scoping_def =
105
- node.each_ancestor(:block, :numblock, :sclass).any? do |ancestor|
105
+ node.each_ancestor(:any_block, :sclass).any? do |ancestor|
106
106
  scoping_method_call?(ancestor)
107
107
  end
108
108
 
@@ -129,12 +129,12 @@ module RuboCop
129
129
 
130
130
  # @!method eval_call?(node)
131
131
  def_node_matcher :eval_call?, <<~PATTERN
132
- ({block numblock} (send _ {:instance_eval :class_eval :module_eval} ...) ...)
132
+ (any_block (send _ {:instance_eval :class_eval :module_eval} ...) ...)
133
133
  PATTERN
134
134
 
135
135
  # @!method exec_call?(node)
136
136
  def_node_matcher :exec_call?, <<~PATTERN
137
- ({block numblock} (send _ {:instance_exec :class_exec :module_exec} ...) ...)
137
+ (any_block (send _ {:instance_exec :class_exec :module_exec} ...) ...)
138
138
  PATTERN
139
139
  end
140
140
  end
@@ -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
@@ -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)
@@ -9,10 +9,10 @@ module RuboCop
9
9
  # As such, they can be replaced with that result.
10
10
  # These are probably leftover from debugging, or are mistakes.
11
11
  # Other numeric operations that are similarly leftover from debugging or mistakes
12
- # are handled by Lint/UselessNumericOperation.
12
+ # are handled by `Lint/UselessNumericOperation`.
13
13
  #
14
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
15
+ # can't determine the type of `x`. If `x` is an `Array` or `String`, it doesn't perform
16
16
  # a numeric operation.
17
17
  #
18
18
  # @example
@@ -50,43 +50,38 @@ module RuboCop
50
50
 
51
51
  # @!method operation_with_constant_result?(node)
52
52
  def_node_matcher :operation_with_constant_result?,
53
- '(send (send nil? $_) $_ ({int | send nil?} $_))'
53
+ '(call (call nil? $_lhs) $_operation ({int | call nil?} $_rhs))'
54
54
 
55
55
  # @!method abbreviated_assignment_with_constant_result?(node)
56
56
  def_node_matcher :abbreviated_assignment_with_constant_result?,
57
- '(op-asgn (lvasgn $_) $_ ({int | lvar} $_))'
57
+ '(op-asgn (lvasgn $_lhs) $_operation ({int lvar} $_rhs))'
58
58
 
59
59
  def on_send(node)
60
- return unless operation_with_constant_result?(node)
61
-
62
- variable, operation, number = operation_with_constant_result?(node)
63
- result = constant_result?(variable, operation, number)
64
- return unless result
60
+ return unless (lhs, operation, rhs = operation_with_constant_result?(node))
61
+ return unless (result = constant_result?(lhs, operation, rhs))
65
62
 
66
63
  add_offense(node) do |corrector|
67
64
  corrector.replace(node, result.to_s)
68
65
  end
69
66
  end
67
+ alias on_csend on_send
70
68
 
71
69
  def on_op_asgn(node)
72
- return unless abbreviated_assignment_with_constant_result?(node)
73
-
74
- variable, operation, number = abbreviated_assignment_with_constant_result?(node)
75
- result = constant_result?(variable, operation, number)
76
- return unless result
70
+ return unless (lhs, operation, rhs = abbreviated_assignment_with_constant_result?(node))
71
+ return unless (result = constant_result?(lhs, operation, rhs))
77
72
 
78
73
  add_offense(node) do |corrector|
79
- corrector.replace(node, "#{variable} = #{result}")
74
+ corrector.replace(node, "#{lhs} = #{result}")
80
75
  end
81
76
  end
82
77
 
83
78
  private
84
79
 
85
- def constant_result?(variable, operation, number)
86
- if number.to_s == '0'
80
+ def constant_result?(lhs, operation, rhs)
81
+ if rhs.to_s == '0'
87
82
  return 0 if operation == :*
88
83
  return 1 if operation == :**
89
- elsif number == variable
84
+ elsif rhs == lhs
90
85
  return 1 if operation == :/
91
86
  end
92
87
  # If we weren't able to find any matches, return false so we can bail out.
@@ -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