rubocop 1.19.1 → 1.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +86 -14
  4. data/lib/rubocop/config.rb +5 -0
  5. data/lib/rubocop/config_loader.rb +4 -2
  6. data/lib/rubocop/config_validator.rb +9 -1
  7. data/lib/rubocop/cop/base.rb +3 -3
  8. data/lib/rubocop/cop/bundler/gem_filename.rb +103 -0
  9. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +45 -21
  10. data/lib/rubocop/cop/bundler/ordered_gems.rb +3 -12
  11. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +2 -2
  12. data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
  13. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +11 -10
  14. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +3 -12
  15. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +1 -1
  16. data/lib/rubocop/cop/generator.rb +14 -8
  17. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  18. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  19. data/lib/rubocop/cop/layout/class_structure.rb +2 -1
  20. data/lib/rubocop/cop/layout/dot_position.rb +31 -4
  21. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  22. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  23. data/lib/rubocop/cop/layout/line_length.rb +8 -6
  24. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
  25. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +3 -0
  26. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -0
  27. data/lib/rubocop/cop/layout/single_line_block_chain.rb +15 -4
  28. data/lib/rubocop/cop/layout/space_after_not.rb +1 -0
  29. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -1
  30. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
  31. data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -0
  32. data/lib/rubocop/cop/layout/space_inside_parens.rb +74 -24
  33. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -1
  34. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +111 -0
  35. data/lib/rubocop/cop/lint/ambiguous_range.rb +8 -8
  36. data/lib/rubocop/cop/lint/assignment_in_condition.rb +7 -5
  37. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +18 -5
  38. data/lib/rubocop/cop/lint/boolean_symbol.rb +5 -0
  39. data/lib/rubocop/cop/lint/debugger.rb +2 -4
  40. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
  41. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +24 -1
  42. data/lib/rubocop/cop/lint/else_layout.rb +9 -5
  43. data/lib/rubocop/cop/lint/empty_in_pattern.rb +1 -1
  44. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
  45. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  46. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +12 -3
  47. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +67 -0
  48. data/lib/rubocop/cop/lint/interpolation_check.rb +5 -0
  49. data/lib/rubocop/cop/lint/loop.rb +4 -3
  50. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +5 -1
  51. data/lib/rubocop/cop/lint/number_conversion.rb +12 -1
  52. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  53. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +4 -2
  54. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -0
  55. data/lib/rubocop/cop/lint/percent_string_array.rb +10 -0
  56. data/lib/rubocop/cop/lint/raise_exception.rb +4 -0
  57. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +5 -4
  58. data/lib/rubocop/cop/lint/require_relative_self_path.rb +50 -0
  59. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
  60. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  61. data/lib/rubocop/cop/lint/triple_quotes.rb +1 -1
  62. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +8 -3
  63. data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -3
  64. data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -2
  65. data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
  66. data/lib/rubocop/cop/lint/useless_times.rb +4 -3
  67. data/lib/rubocop/cop/metrics/abc_size.rb +6 -0
  68. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  69. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  70. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  71. data/lib/rubocop/cop/mixin/annotation_comment.rb +57 -34
  72. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  73. data/lib/rubocop/cop/mixin/documentation_comment.rb +5 -2
  74. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +23 -1
  75. data/lib/rubocop/cop/mixin/heredoc.rb +1 -3
  76. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
  77. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +9 -1
  78. data/lib/rubocop/cop/mixin/percent_array.rb +6 -1
  79. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +9 -1
  80. data/lib/rubocop/cop/mixin/string_literals_help.rb +5 -1
  81. data/lib/rubocop/cop/naming/ascii_identifiers.rb +0 -3
  82. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  83. data/lib/rubocop/cop/naming/constant_name.rb +1 -1
  84. data/lib/rubocop/cop/naming/inclusive_language.rb +9 -9
  85. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +5 -4
  86. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +7 -0
  87. data/lib/rubocop/cop/security/io_methods.rb +49 -0
  88. data/lib/rubocop/cop/security/json_load.rb +8 -7
  89. data/lib/rubocop/cop/security/open.rb +4 -0
  90. data/lib/rubocop/cop/security/yaml_load.rb +4 -0
  91. data/lib/rubocop/cop/style/accessor_grouping.rb +2 -2
  92. data/lib/rubocop/cop/style/and_or.rb +5 -0
  93. data/lib/rubocop/cop/style/arguments_forwarding.rb +13 -2
  94. data/lib/rubocop/cop/style/array_coercion.rb +21 -3
  95. data/lib/rubocop/cop/style/ascii_comments.rb +0 -3
  96. data/lib/rubocop/cop/style/block_delimiters.rb +23 -6
  97. data/lib/rubocop/cop/style/case_equality.rb +6 -9
  98. data/lib/rubocop/cop/style/case_like_if.rb +5 -0
  99. data/lib/rubocop/cop/style/class_and_module_children.rb +9 -0
  100. data/lib/rubocop/cop/style/collection_compact.rb +7 -5
  101. data/lib/rubocop/cop/style/collection_methods.rb +8 -6
  102. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  103. data/lib/rubocop/cop/style/comment_annotation.rb +25 -39
  104. data/lib/rubocop/cop/style/commented_keyword.rb +4 -1
  105. data/lib/rubocop/cop/style/date_time.rb +5 -0
  106. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
  107. data/lib/rubocop/cop/style/documentation.rb +23 -8
  108. data/lib/rubocop/cop/style/double_negation.rb +15 -5
  109. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  110. data/lib/rubocop/cop/style/explicit_block_argument.rb +21 -11
  111. data/lib/rubocop/cop/style/float_division.rb +10 -2
  112. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +7 -2
  113. data/lib/rubocop/cop/style/global_std_stream.rb +4 -0
  114. data/lib/rubocop/cop/style/hash_each_methods.rb +5 -0
  115. data/lib/rubocop/cop/style/hash_except.rb +4 -3
  116. data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -6
  117. data/lib/rubocop/cop/style/hash_transform_values.rb +4 -6
  118. data/lib/rubocop/cop/style/identical_conditional_branches.rb +18 -16
  119. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +18 -4
  120. data/lib/rubocop/cop/style/infinite_loop.rb +4 -3
  121. data/lib/rubocop/cop/style/inverse_methods.rb +9 -2
  122. data/lib/rubocop/cop/style/lambda_call.rb +1 -1
  123. data/lib/rubocop/cop/style/line_end_concatenation.rb +13 -0
  124. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -6
  125. data/lib/rubocop/cop/style/module_function.rb +8 -9
  126. data/lib/rubocop/cop/style/mutable_constant.rb +73 -6
  127. data/lib/rubocop/cop/style/negated_if.rb +1 -1
  128. data/lib/rubocop/cop/style/negated_unless.rb +1 -1
  129. data/lib/rubocop/cop/style/non_nil_check.rb +2 -2
  130. data/lib/rubocop/cop/style/not.rb +2 -2
  131. data/lib/rubocop/cop/style/numbered_parameters.rb +46 -0
  132. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +50 -0
  133. data/lib/rubocop/cop/style/numeric_literals.rb +7 -8
  134. data/lib/rubocop/cop/style/numeric_predicate.rb +5 -0
  135. data/lib/rubocop/cop/style/optional_arguments.rb +4 -0
  136. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +14 -4
  137. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
  138. data/lib/rubocop/cop/style/percent_q_literals.rb +2 -2
  139. data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -4
  140. data/lib/rubocop/cop/style/quoted_symbols.rb +10 -6
  141. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  142. data/lib/rubocop/cop/style/redundant_argument.rb +19 -9
  143. data/lib/rubocop/cop/style/redundant_condition.rb +2 -3
  144. data/lib/rubocop/cop/style/redundant_fetch_block.rb +4 -0
  145. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +12 -3
  146. data/lib/rubocop/cop/style/redundant_freeze.rb +4 -4
  147. data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
  148. data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -3
  149. data/lib/rubocop/cop/style/redundant_self.rb +10 -0
  150. data/lib/rubocop/cop/style/redundant_self_assignment.rb +4 -3
  151. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +1 -1
  152. data/lib/rubocop/cop/style/redundant_sort.rb +51 -18
  153. data/lib/rubocop/cop/style/regexp_literal.rb +3 -3
  154. data/lib/rubocop/cop/style/return_nil.rb +2 -1
  155. data/lib/rubocop/cop/style/safe_navigation.rb +13 -2
  156. data/lib/rubocop/cop/style/select_by_regexp.rb +133 -0
  157. data/lib/rubocop/cop/style/single_argument_dig.rb +5 -0
  158. data/lib/rubocop/cop/style/slicing_with_range.rb +13 -0
  159. data/lib/rubocop/cop/style/special_global_vars.rb +4 -0
  160. data/lib/rubocop/cop/style/static_class.rb +5 -5
  161. data/lib/rubocop/cop/style/string_chars.rb +4 -2
  162. data/lib/rubocop/cop/style/string_concatenation.rb +5 -1
  163. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -0
  164. data/lib/rubocop/cop/style/struct_inheritance.rb +4 -0
  165. data/lib/rubocop/cop/style/swap_values.rb +4 -2
  166. data/lib/rubocop/cop/style/symbol_proc.rb +26 -0
  167. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +19 -0
  168. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  169. data/lib/rubocop/cop/style/yoda_condition.rb +24 -7
  170. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -0
  171. data/lib/rubocop/cop/util.rb +4 -3
  172. data/lib/rubocop/cops_documentation_generator.rb +17 -5
  173. data/lib/rubocop/options.rb +126 -112
  174. data/lib/rubocop/rake_task.rb +1 -1
  175. data/lib/rubocop/result_cache.rb +3 -3
  176. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  177. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  178. data/lib/rubocop/runner.rb +2 -3
  179. data/lib/rubocop/version.rb +1 -1
  180. data/lib/rubocop.rb +10 -2
  181. metadata +17 -9
@@ -49,7 +49,7 @@ module RuboCop
49
49
  return unless bad_method?(block) && semantically_except_method?(node, block)
50
50
 
51
51
  except_key = except_key(block)
52
- return unless safe_to_register_offense?(block, except_key)
52
+ return if except_key.nil? || !safe_to_register_offense?(block, except_key)
53
53
 
54
54
  range = offense_range(node)
55
55
  preferred_method = "except(#{except_key.source})"
@@ -81,10 +81,11 @@ module RuboCop
81
81
  end
82
82
 
83
83
  def except_key(node)
84
- key_argument = node.argument_list.first
84
+ key_argument = node.argument_list.first.source
85
85
  lhs, _method_name, rhs = *node.body
86
+ return if [lhs, rhs].map(&:source).none?(key_argument)
86
87
 
87
- [lhs, rhs].find { |operand| operand.source != key_argument.source }
88
+ [lhs, rhs].find { |operand| operand.source != key_argument }
88
89
  end
89
90
 
90
91
  def offense_range(node)
@@ -8,12 +8,10 @@ module RuboCop
8
8
  # transforming the keys of a hash, and tries to use a simpler & faster
9
9
  # call to `transform_keys` instead.
10
10
  #
11
- # This can produce false positives if we are transforming an enumerable
12
- # of key-value-like pairs that isn't actually a hash, e.g.:
13
- # `[[k1, v1], [k2, v2], ...]`
14
- #
15
- # This cop should only be enabled on Ruby version 2.5 or newer
16
- # (`transform_keys` was added in Ruby 2.5.)
11
+ # @safety
12
+ # This cop is unsafe, as it can produce false positives if we are
13
+ # transforming an enumerable of key-value-like pairs that isn't actually
14
+ # a hash, e.g.: `[[k1, v1], [k2, v2], ...]`
17
15
  #
18
16
  # @example
19
17
  # # bad
@@ -8,12 +8,10 @@ module RuboCop
8
8
  # transforming the values of a hash, and tries to use a simpler & faster
9
9
  # call to `transform_values` instead.
10
10
  #
11
- # This can produce false positives if we are transforming an enumerable
12
- # of key-value-like pairs that isn't actually a hash, e.g.:
13
- # `[[k1, v1], [k2, v2], ...]`
14
- #
15
- # This cop should only be enabled on Ruby version 2.4 or newer
16
- # (`transform_values` was added in Ruby 2.4.)
11
+ # @safety
12
+ # This cop is unsafe, as it can produce false positives if we are
13
+ # transforming an enumerable of key-value-like pairs that isn't actually
14
+ # a hash, e.g.: `[[k1, v1], [k2, v2], ...]`
17
15
  #
18
16
  # @example
19
17
  # # bad
@@ -7,26 +7,28 @@ module RuboCop
7
7
  # each branch of a conditional expression. Such expressions should normally
8
8
  # be placed outside the conditional expression - before or after it.
9
9
  #
10
- # This cop is marked unsafe auto-correction as the order of method invocations
11
- # must be guaranteed in the following case:
12
- #
13
- # [source,ruby]
14
- # ----
15
- # if method_that_modifies_global_state # 1
16
- # method_that_relies_on_global_state # 2
17
- # foo # 3
18
- # else
19
- # method_that_relies_on_global_state # 2
20
- # bar # 3
21
- # end
22
- # ----
23
- #
24
- # In such a case, auto-correction may change the invocation order.
25
- #
26
10
  # NOTE: The cop is poorly named and some people might think that it actually
27
11
  # checks for duplicated conditional branches. The name will probably be changed
28
12
  # in a future major RuboCop release.
29
13
  #
14
+ # @safety
15
+ # Auto-correction is unsafe because changing the order of method invocations
16
+ # may change the behaviour of the code. For example:
17
+ #
18
+ # [source,ruby]
19
+ # ----
20
+ # if method_that_modifies_global_state # 1
21
+ # method_that_relies_on_global_state # 2
22
+ # foo # 3
23
+ # else
24
+ # method_that_relies_on_global_state # 2
25
+ # bar # 3
26
+ # end
27
+ # ----
28
+ #
29
+ # In this example, `method_that_relies_on_global_state` will be moved before
30
+ # `method_that_modifies_global_state`, which changes the behaviour of the program.
31
+ #
30
32
  # @example
31
33
  # # bad
32
34
  # if condition
@@ -6,8 +6,10 @@ module RuboCop
6
6
  # This cop checks for redundant `if` with boolean literal branches.
7
7
  # It checks only conditions to return boolean value (`true` or `false`) for safe detection.
8
8
  # The conditions to be checked are comparison methods, predicate methods, and double negative.
9
- # However, auto-correction is unsafe because there is no guarantee that all predicate methods
10
- # will return boolean value. Those methods can be allowed with `AllowedMethods` config.
9
+ #
10
+ # @safety
11
+ # Auto-correction is unsafe because there is no guarantee that all predicate methods
12
+ # will return a boolean value. Those methods can be allowed with `AllowedMethods` config.
11
13
  #
12
14
  # @example
13
15
  # # bad
@@ -23,6 +25,17 @@ module RuboCop
23
25
  # # good
24
26
  # foo == bar
25
27
  #
28
+ # @example
29
+ # # bad
30
+ # if foo.do_something?
31
+ # true
32
+ # else
33
+ # false
34
+ # end
35
+ #
36
+ # # good (but potentially an unsafe correction)
37
+ # foo.do_something?
38
+ #
26
39
  # @example AllowedMethods: ['nonzero?']
27
40
  # # good
28
41
  # num.nonzero? ? true : false
@@ -109,12 +122,13 @@ module RuboCop
109
122
  end
110
123
 
111
124
  def opposite_condition?(node)
112
- !node.unless? && node.if_branch.false_type? || node.unless? && node.if_branch.true_type?
125
+ (!node.unless? && node.if_branch.false_type?) ||
126
+ (node.unless? && node.if_branch.true_type?)
113
127
  end
114
128
 
115
129
  def require_parentheses?(condition)
116
130
  condition.and_type? || condition.or_type? ||
117
- condition.send_type? && condition.comparison_method?
131
+ (condition.send_type? && condition.comparison_method?)
118
132
  end
119
133
  end
120
134
  end
@@ -5,9 +5,10 @@ module RuboCop
5
5
  module Style
6
6
  # Use `Kernel#loop` for infinite loops.
7
7
  #
8
- # This cop is marked as unsafe as the rule does not necessarily
9
- # apply if the body might raise a `StopIteration` exception; contrary to
10
- # other infinite loops, `Kernel#loop` silently rescues that and returns `nil`.
8
+ # @safety
9
+ # This cop is unsafe as the rule should not necessarily apply if the loop
10
+ # body might raise a `StopIteration` exception; contrary to other infinite
11
+ # loops, `Kernel#loop` silently rescues that and returns `nil`.
11
12
  #
12
13
  # @example
13
14
  # # bad
@@ -5,11 +5,18 @@ module RuboCop
5
5
  module Style
6
6
  # This cop check for usages of not (`not` or `!`) called on a method
7
7
  # when an inverse of that method can be used instead.
8
+ #
8
9
  # Methods that can be inverted by a not (`not` or `!`) should be defined
9
- # in `InverseMethods`
10
+ # in `InverseMethods`.
11
+ #
10
12
  # Methods that are inverted by inverting the return
11
13
  # of the block that is passed to the method should be defined in
12
- # `InverseBlocks`
14
+ # `InverseBlocks`.
15
+ #
16
+ # @safety
17
+ # This cop is unsafe because it cannot be guaranteed that the method
18
+ # and its inverse method are both defined on receiver, and also are
19
+ # actually inverse of each other.
13
20
  #
14
21
  # @example
15
22
  # # bad
@@ -52,7 +52,7 @@ module RuboCop
52
52
  private
53
53
 
54
54
  def offense?(node)
55
- explicit_style? && node.implicit_call? || implicit_style? && !node.implicit_call?
55
+ (explicit_style? && node.implicit_call?) || (implicit_style? && !node.implicit_call?)
56
56
  end
57
57
 
58
58
  def message(_node)
@@ -6,6 +6,19 @@ module RuboCop
6
6
  # This cop checks for string literal concatenation at
7
7
  # the end of a line.
8
8
  #
9
+ # @safety
10
+ # This cop is unsafe because it cannot be guaranteed that the
11
+ # receiver is a string, in which case replacing `<<` with `\`
12
+ # would result in a syntax error.
13
+ #
14
+ # For example, this would be a false positive:
15
+ # [source,ruby]
16
+ # ----
17
+ # array << 'foo' <<
18
+ # 'bar' <<
19
+ # 'baz'
20
+ # ----
21
+ #
9
22
  # @example
10
23
  #
11
24
  # # bad
@@ -93,8 +93,8 @@ module RuboCop
93
93
  parent = node.parent&.block_type? ? node.parent.parent : node.parent
94
94
  parent &&
95
95
  (logical_operator?(parent) ||
96
- parent.send_type? &&
97
- parent.arguments.any? { |argument| logical_operator?(argument) })
96
+ (parent.send_type? &&
97
+ parent.arguments.any? { |argument| logical_operator?(argument) }))
98
98
  end
99
99
 
100
100
  def call_in_optional_arguments?(node)
@@ -122,14 +122,14 @@ module RuboCop
122
122
 
123
123
  def call_as_argument_or_chain?(node)
124
124
  node.parent &&
125
- (node.parent.send_type? && !assigned_before?(node.parent, node) ||
125
+ ((node.parent.send_type? && !assigned_before?(node.parent, node)) ||
126
126
  node.parent.csend_type? || node.parent.super_type? || node.parent.yield_type?)
127
127
  end
128
128
 
129
129
  def hash_literal_in_arguments?(node)
130
130
  node.arguments.any? do |n|
131
131
  hash_literal?(n) ||
132
- n.send_type? && node.descendants.any? { |descendant| hash_literal?(descendant) }
132
+ (n.send_type? && node.descendants.any? { |descendant| hash_literal?(descendant) })
133
133
  end
134
134
  end
135
135
 
@@ -171,8 +171,8 @@ module RuboCop
171
171
  end
172
172
 
173
173
  def unary_literal?(node)
174
- node.numeric_type? && node.sign? ||
175
- node.parent&.send_type? && node.parent&.unary_operation?
174
+ (node.numeric_type? && node.sign?) ||
175
+ (node.parent&.send_type? && node.parent&.unary_operation?)
176
176
  end
177
177
 
178
178
  def assigned_before?(node, target)
@@ -6,7 +6,14 @@ module RuboCop
6
6
  # This cop checks for use of `extend self` or `module_function` in a
7
7
  # module.
8
8
  #
9
- # Supported styles are: module_function, extend_self, forbidden.
9
+ # Supported styles are: module_function, extend_self, forbidden. `forbidden`
10
+ # style prohibits the usage of both styles.
11
+ #
12
+ # NOTE: the cop won't be activated when the module contains any private methods.
13
+ #
14
+ # @safety
15
+ # Autocorrection is unsafe (and is disabled by default) because `extend self`
16
+ # and `module_function` do not behave exactly the same.
10
17
  #
11
18
  # @example EnforcedStyle: module_function (default)
12
19
  # # bad
@@ -21,9 +28,6 @@ module RuboCop
21
28
  # # ...
22
29
  # end
23
30
  #
24
- # In case there are private methods, the cop won't be activated.
25
- # Otherwise, it forces to change the flow of the default code.
26
- #
27
31
  # @example EnforcedStyle: module_function (default)
28
32
  # # good
29
33
  # module Test
@@ -46,8 +50,6 @@ module RuboCop
46
50
  # # ...
47
51
  # end
48
52
  #
49
- # The option `forbidden` prohibits the usage of both styles.
50
- #
51
53
  # @example EnforcedStyle: forbidden
52
54
  # # bad
53
55
  # module Test
@@ -68,9 +70,6 @@ module RuboCop
68
70
  # private
69
71
  # # ...
70
72
  # end
71
- #
72
- # These offenses are not safe to auto-correct since there are different
73
- # implications to each approach.
74
73
  class ModuleFunction < Base
75
74
  include ConfigurableEnforcedStyle
76
75
  extend AutoCorrector
@@ -14,8 +14,25 @@ module RuboCop
14
14
  # positives. Luckily, there is no harm in freezing an already
15
15
  # frozen object.
16
16
  #
17
+ # From Ruby 3.0, this cop honours the magic comment
18
+ # 'shareable_constant_value'. When this magic comment is set to any
19
+ # acceptable value other than none, it will suppress the offenses
20
+ # raised by this cop. It enforces frozen state.
21
+ #
17
22
  # NOTE: Regexp and Range literals are frozen objects since Ruby 3.0.
18
23
  #
24
+ # NOTE: From Ruby 3.0, interpolated strings are not frozen when
25
+ # `# frozen-string-literal: true` is used, so this cop enforces explicit
26
+ # freezing for such strings.
27
+ #
28
+ # NOTE: From Ruby 3.0, this cop allows explicit freezing of constants when
29
+ # the `shareable_constant_value` directive is used.
30
+ #
31
+ # @safety
32
+ # This cop's autocorrection is unsafe since any mutations on objects that
33
+ # are made frozen will change from being accepted to raising `FrozenError`,
34
+ # and will need to be manually refactored.
35
+ #
19
36
  # @example EnforcedStyle: literals (default)
20
37
  # # bad
21
38
  # CONST = [1, 2, 3]
@@ -52,7 +69,55 @@ module RuboCop
52
69
  # puts 1
53
70
  # end
54
71
  # end.freeze
72
+ #
73
+ # @example
74
+ # # Magic comment - shareable_constant_value: literal
75
+ #
76
+ # # bad
77
+ # CONST = [1, 2, 3]
78
+ #
79
+ # # good
80
+ # # shareable_constant_value: literal
81
+ # CONST = [1, 2, 3]
82
+ #
55
83
  class MutableConstant < Base
84
+ # Handles magic comment shareable_constant_value with O(n ^ 2) complexity
85
+ # n - number of lines in the source
86
+ # Iterates over all lines before a CONSTANT
87
+ # until it reaches shareable_constant_value
88
+ module ShareableConstantValue
89
+ module_function
90
+
91
+ def recent_shareable_value?(node)
92
+ shareable_constant_comment = magic_comment_in_scope node
93
+ return false if shareable_constant_comment.nil?
94
+
95
+ shareable_constant_value = MagicComment.parse(shareable_constant_comment)
96
+ .shareable_constant_value
97
+ shareable_constant_value_enabled? shareable_constant_value
98
+ end
99
+
100
+ # Identifies the most recent magic comment with valid shareable constant values
101
+ # that's in scope for this node
102
+ def magic_comment_in_scope(node)
103
+ processed_source_till_node(node).reverse_each.find do |line|
104
+ MagicComment.parse(line).valid_shareable_constant_value?
105
+ end
106
+ end
107
+
108
+ private
109
+
110
+ def processed_source_till_node(node)
111
+ processed_source.lines[0..(node.last_line - 1)]
112
+ end
113
+
114
+ def shareable_constant_value_enabled?(value)
115
+ %w[literal experimental_everything experimental_copy].include? value
116
+ end
117
+ end
118
+ private_constant :ShareableConstantValue
119
+
120
+ include ShareableConstantValue
56
121
  include FrozenStringLiteral
57
122
  include ConfigurableEnforcedStyle
58
123
  extend AutoCorrector
@@ -85,18 +150,18 @@ module RuboCop
85
150
  return if immutable_literal?(value)
86
151
  return if operation_produces_immutable_object?(value)
87
152
  return if frozen_string_literal?(value)
153
+ return if shareable_constant_value?(value)
88
154
 
89
155
  add_offense(value) { |corrector| autocorrect(corrector, value) }
90
156
  end
91
157
 
92
158
  def check(value)
93
159
  range_enclosed_in_parentheses = range_enclosed_in_parentheses?(value)
94
-
95
160
  return unless mutable_literal?(value) ||
96
- target_ruby_version <= 2.7 && range_enclosed_in_parentheses
161
+ (target_ruby_version <= 2.7 && range_enclosed_in_parentheses)
97
162
 
98
- return if FROZEN_STRING_LITERAL_TYPES.include?(value.type) &&
99
- frozen_string_literals_enabled?
163
+ return if frozen_string_literal?(value)
164
+ return if shareable_constant_value?(value)
100
165
 
101
166
  add_offense(value) { |corrector| autocorrect(corrector, value) }
102
167
  end
@@ -126,8 +191,10 @@ module RuboCop
126
191
  frozen_regexp_or_range_literals?(node) || node.immutable_literal?
127
192
  end
128
193
 
129
- def frozen_string_literal?(node)
130
- FROZEN_STRING_LITERAL_TYPES.include?(node.type) && frozen_string_literals_enabled?
194
+ def shareable_constant_value?(node)
195
+ return false if target_ruby_version < 3.0
196
+
197
+ recent_shareable_value? node
131
198
  end
132
199
 
133
200
  def frozen_regexp_or_range_literals?(node)
@@ -90,7 +90,7 @@ module RuboCop
90
90
  end
91
91
 
92
92
  def correct_style?(node)
93
- style == :prefix && node.modifier_form? || style == :postfix && !node.modifier_form?
93
+ (style == :prefix && node.modifier_form?) || (style == :postfix && !node.modifier_form?)
94
94
  end
95
95
  end
96
96
  end
@@ -80,7 +80,7 @@ module RuboCop
80
80
  end
81
81
 
82
82
  def correct_style?(node)
83
- style == :prefix && node.modifier_form? || style == :postfix && !node.modifier_form?
83
+ (style == :prefix && node.modifier_form?) || (style == :postfix && !node.modifier_form?)
84
84
  end
85
85
  end
86
86
  end
@@ -63,7 +63,7 @@ module RuboCop
63
63
 
64
64
  def on_send(node)
65
65
  return if ignored_node?(node) ||
66
- !include_semantic_changes? && nil_comparison_style == 'comparison'
66
+ (!include_semantic_changes? && nil_comparison_style == 'comparison')
67
67
  return unless register_offense?(node)
68
68
 
69
69
  message = message(node)
@@ -87,7 +87,7 @@ module RuboCop
87
87
 
88
88
  def register_offense?(node)
89
89
  not_equal_to_nil?(node) ||
90
- include_semantic_changes? && (not_and_nil_check?(node) || unless_and_nil_check?(node))
90
+ (include_semantic_changes? && (not_and_nil_check?(node) || unless_and_nil_check?(node)))
91
91
  end
92
92
 
93
93
  def autocorrect(corrector, node)
@@ -53,8 +53,8 @@ module RuboCop
53
53
 
54
54
  def requires_parens?(child)
55
55
  child.and_type? || child.or_type? ||
56
- child.send_type? && child.binary_operation? ||
57
- child.if_type? && child.ternary?
56
+ (child.send_type? && child.binary_operation?) ||
57
+ (child.if_type? && child.ternary?)
58
58
  end
59
59
 
60
60
  def correct_opposite_method(corrector, range, child)
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for numbered parameters.
7
+ #
8
+ # It can either restrict the use of numbered parameters to
9
+ # single-lined blocks, or disallow completely numbered parameters.
10
+ #
11
+ # @example EnforcedStyle: allow_single_line (default)
12
+ # # bad
13
+ # collection.each do
14
+ # puts _1
15
+ # end
16
+ #
17
+ # # good
18
+ # collection.each { puts _1 }
19
+ #
20
+ # @example EnforcedStyle: disallow
21
+ # # bad
22
+ # collection.each { puts _1 }
23
+ #
24
+ # # good
25
+ # collection.each { |item| puts item }
26
+ #
27
+ class NumberedParameters < Base
28
+ include ConfigurableEnforcedStyle
29
+ extend TargetRubyVersion
30
+
31
+ MSG_DISALLOW = 'Avoid using numbered parameters.'
32
+ MSG_MULTI_LINE = 'Avoid using numbered parameters for multi-line blocks.'
33
+
34
+ minimum_target_ruby_version 2.7
35
+
36
+ def on_numblock(node)
37
+ if style == :disallow
38
+ add_offense(node, message: MSG_DISALLOW)
39
+ elsif node.multiline?
40
+ add_offense(node, message: MSG_MULTI_LINE)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cop detects use of an excessive amount of numbered parameters in a
7
+ # single block. Having too many numbered parameters can make code too
8
+ # cryptic and hard to read.
9
+ #
10
+ # The cop defaults to registering an offense if there is more than 1 numbered
11
+ # parameter but this maximum can be configured by setting `Max`.
12
+ #
13
+ # @example Max: 1 (default)
14
+ # # bad
15
+ # foo { _1.call(_2, _3, _4) }
16
+ #
17
+ # # good
18
+ # foo { do_something(_1) }
19
+ class NumberedParametersLimit < Base
20
+ extend TargetRubyVersion
21
+ extend ExcludeLimit
22
+
23
+ DEFAULT_MAX_VALUE = 1
24
+
25
+ minimum_target_ruby_version 2.7
26
+ exclude_limit 'Max'
27
+
28
+ MSG = 'Avoid using more than %<max>i numbered %<parameter>s; %<count>i detected.'
29
+
30
+ def on_numblock(node)
31
+ _send_node, param_count, * = *node
32
+ return if param_count <= max_count
33
+
34
+ parameter = max_count > 1 ? 'parameters' : 'parameter'
35
+ message = format(MSG, max: max_count, parameter: parameter, count: param_count)
36
+ add_offense(node, message: message) { self.max = param_count }
37
+ end
38
+
39
+ private
40
+
41
+ def max_count
42
+ max = cop_config.fetch('Max', DEFAULT_MAX_VALUE)
43
+
44
+ # Ruby does not allow more than 9 numbered parameters
45
+ [max, 9].min
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -58,18 +58,17 @@ module RuboCop
58
58
 
59
59
  case int
60
60
  when /^\d+$/
61
- return unless (self.min_digits = int.size + 1)
62
-
63
- register_offense(node)
61
+ register_offense(node) { self.min_digits = int.size + 1 }
64
62
  when /\d{4}/, short_group_regex
65
- return unless (self.config_to_allow_offenses = { 'Enabled' => false })
66
-
67
- register_offense(node)
63
+ register_offense(node) { self.config_to_allow_offenses = { 'Enabled' => false } }
68
64
  end
69
65
  end
70
66
 
71
- def register_offense(node)
72
- add_offense(node) { |corrector| corrector.replace(node, format_number(node)) }
67
+ def register_offense(node, &_block)
68
+ add_offense(node) do |corrector|
69
+ yield
70
+ corrector.replace(node, format_number(node))
71
+ end
73
72
  end
74
73
 
75
74
  def short_group_regex
@@ -16,6 +16,11 @@ module RuboCop
16
16
  # populated with objects which can be compared with integers, but are
17
17
  # not themselves `Integer` polymorphic.
18
18
  #
19
+ # @safety
20
+ # This cop is unsafe because it cannot be guaranteed that the receiver
21
+ # defines the predicates or can be compared to a number, which may lead
22
+ # to a false positive for non-standard classes.
23
+ #
19
24
  # @example EnforcedStyle: predicate (default)
20
25
  # # bad
21
26
  #
@@ -6,6 +6,10 @@ module RuboCop
6
6
  # This cop checks for optional arguments to methods
7
7
  # that do not come at the end of the argument list.
8
8
  #
9
+ # @safety
10
+ # This cop is unsafe because changing a method signature will
11
+ # implicitly change behaviour.
12
+ #
9
13
  # @example
10
14
  # # bad
11
15
  # def foo(a = 1, b, c)
@@ -7,6 +7,10 @@ module RuboCop
7
7
  # boolean arguments when defining methods. `respond_to_missing?` method is allowed by default.
8
8
  # These are customizable with `AllowedMethods` option.
9
9
  #
10
+ # @safety
11
+ # This cop is unsafe because changing a method signature will
12
+ # implicitly change behaviour.
13
+ #
10
14
  # @example
11
15
  # # bad
12
16
  # def some_method(bar = false)
@@ -33,8 +37,8 @@ module RuboCop
33
37
  class OptionalBooleanParameter < Base
34
38
  include AllowedMethods
35
39
 
36
- MSG = 'Use keyword arguments when defining method with boolean argument.'
37
- BOOLEAN_TYPES = %i[true false].freeze
40
+ MSG = 'Prefer keyword arguments for arguments with a boolean default value; ' \
41
+ 'use `%<replacement>s` instead of `%<original>s`.'
38
42
 
39
43
  def on_def(node)
40
44
  return if allowed_method?(node.method_name)
@@ -42,11 +46,17 @@ module RuboCop
42
46
  node.arguments.each do |arg|
43
47
  next unless arg.optarg_type?
44
48
 
45
- _name, value = *arg
46
- add_offense(arg) if BOOLEAN_TYPES.include?(value.type)
49
+ add_offense(arg, message: format_message(arg)) if arg.default_value.boolean_type?
47
50
  end
48
51
  end
49
52
  alias on_defs on_def
53
+
54
+ private
55
+
56
+ def format_message(argument)
57
+ source = argument.source
58
+ format(MSG, original: source, replacement: source.sub(/\s+=/, ':'))
59
+ end
50
60
  end
51
61
  end
52
62
  end