rubocop 1.19.0 → 1.22.0

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 (187) 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/documentation.rb +1 -1
  15. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +3 -12
  16. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +1 -1
  17. data/lib/rubocop/cop/generator.rb +14 -8
  18. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  19. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  20. data/lib/rubocop/cop/layout/class_structure.rb +2 -1
  21. data/lib/rubocop/cop/layout/dot_position.rb +25 -2
  22. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  23. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  24. data/lib/rubocop/cop/layout/line_length.rb +8 -6
  25. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
  26. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +3 -0
  27. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -0
  28. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +5 -4
  29. data/lib/rubocop/cop/layout/single_line_block_chain.rb +15 -4
  30. data/lib/rubocop/cop/layout/space_after_not.rb +1 -0
  31. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -1
  32. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
  33. data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -0
  34. data/lib/rubocop/cop/layout/space_inside_parens.rb +74 -24
  35. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -1
  36. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +111 -0
  37. data/lib/rubocop/cop/lint/ambiguous_range.rb +8 -8
  38. data/lib/rubocop/cop/lint/assignment_in_condition.rb +7 -5
  39. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +18 -5
  40. data/lib/rubocop/cop/lint/boolean_symbol.rb +5 -0
  41. data/lib/rubocop/cop/lint/debugger.rb +2 -4
  42. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
  43. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +24 -1
  44. data/lib/rubocop/cop/lint/else_layout.rb +9 -5
  45. data/lib/rubocop/cop/lint/empty_in_pattern.rb +1 -1
  46. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
  47. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  48. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +12 -3
  49. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +67 -0
  50. data/lib/rubocop/cop/lint/interpolation_check.rb +5 -0
  51. data/lib/rubocop/cop/lint/loop.rb +4 -3
  52. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +5 -1
  53. data/lib/rubocop/cop/lint/number_conversion.rb +12 -1
  54. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  55. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +4 -2
  56. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -0
  57. data/lib/rubocop/cop/lint/percent_string_array.rb +10 -0
  58. data/lib/rubocop/cop/lint/raise_exception.rb +4 -0
  59. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +5 -4
  60. data/lib/rubocop/cop/lint/require_relative_self_path.rb +49 -0
  61. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
  62. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  63. data/lib/rubocop/cop/lint/triple_quotes.rb +1 -1
  64. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +8 -3
  65. data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -3
  66. data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -2
  67. data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
  68. data/lib/rubocop/cop/lint/useless_times.rb +4 -3
  69. data/lib/rubocop/cop/metrics/abc_size.rb +6 -0
  70. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  71. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  72. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  73. data/lib/rubocop/cop/mixin/annotation_comment.rb +57 -34
  74. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  75. data/lib/rubocop/cop/mixin/documentation_comment.rb +5 -2
  76. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +23 -1
  77. data/lib/rubocop/cop/mixin/heredoc.rb +1 -3
  78. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
  79. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +9 -1
  80. data/lib/rubocop/cop/mixin/percent_array.rb +11 -3
  81. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +9 -1
  82. data/lib/rubocop/cop/naming/ascii_identifiers.rb +0 -3
  83. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  84. data/lib/rubocop/cop/naming/constant_name.rb +1 -1
  85. data/lib/rubocop/cop/naming/inclusive_language.rb +9 -9
  86. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +5 -4
  87. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +7 -0
  88. data/lib/rubocop/cop/security/io_methods.rb +49 -0
  89. data/lib/rubocop/cop/security/json_load.rb +8 -7
  90. data/lib/rubocop/cop/security/open.rb +4 -0
  91. data/lib/rubocop/cop/security/yaml_load.rb +4 -0
  92. data/lib/rubocop/cop/style/accessor_grouping.rb +2 -2
  93. data/lib/rubocop/cop/style/and_or.rb +5 -0
  94. data/lib/rubocop/cop/style/arguments_forwarding.rb +13 -2
  95. data/lib/rubocop/cop/style/array_coercion.rb +21 -3
  96. data/lib/rubocop/cop/style/ascii_comments.rb +0 -3
  97. data/lib/rubocop/cop/style/block_delimiters.rb +23 -6
  98. data/lib/rubocop/cop/style/case_equality.rb +6 -9
  99. data/lib/rubocop/cop/style/case_like_if.rb +5 -0
  100. data/lib/rubocop/cop/style/class_and_module_children.rb +9 -0
  101. data/lib/rubocop/cop/style/collection_compact.rb +7 -5
  102. data/lib/rubocop/cop/style/collection_methods.rb +8 -6
  103. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  104. data/lib/rubocop/cop/style/comment_annotation.rb +25 -39
  105. data/lib/rubocop/cop/style/commented_keyword.rb +4 -1
  106. data/lib/rubocop/cop/style/date_time.rb +5 -0
  107. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
  108. data/lib/rubocop/cop/style/documentation.rb +23 -8
  109. data/lib/rubocop/cop/style/double_negation.rb +27 -6
  110. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  111. data/lib/rubocop/cop/style/encoding.rb +26 -15
  112. data/lib/rubocop/cop/style/explicit_block_argument.rb +21 -11
  113. data/lib/rubocop/cop/style/float_division.rb +10 -2
  114. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +7 -2
  115. data/lib/rubocop/cop/style/global_std_stream.rb +4 -0
  116. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +11 -0
  117. data/lib/rubocop/cop/style/hash_each_methods.rb +5 -0
  118. data/lib/rubocop/cop/style/hash_except.rb +4 -3
  119. data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -6
  120. data/lib/rubocop/cop/style/hash_transform_values.rb +4 -6
  121. data/lib/rubocop/cop/style/identical_conditional_branches.rb +18 -16
  122. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +18 -4
  123. data/lib/rubocop/cop/style/infinite_loop.rb +4 -3
  124. data/lib/rubocop/cop/style/inverse_methods.rb +9 -2
  125. data/lib/rubocop/cop/style/lambda_call.rb +1 -1
  126. data/lib/rubocop/cop/style/line_end_concatenation.rb +13 -0
  127. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -6
  128. data/lib/rubocop/cop/style/module_function.rb +8 -9
  129. data/lib/rubocop/cop/style/mutable_constant.rb +73 -6
  130. data/lib/rubocop/cop/style/negated_if.rb +1 -1
  131. data/lib/rubocop/cop/style/negated_unless.rb +1 -1
  132. data/lib/rubocop/cop/style/non_nil_check.rb +2 -2
  133. data/lib/rubocop/cop/style/not.rb +2 -2
  134. data/lib/rubocop/cop/style/numbered_parameters.rb +46 -0
  135. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +50 -0
  136. data/lib/rubocop/cop/style/numeric_literals.rb +7 -8
  137. data/lib/rubocop/cop/style/numeric_predicate.rb +5 -0
  138. data/lib/rubocop/cop/style/optional_arguments.rb +4 -0
  139. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +14 -4
  140. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
  141. data/lib/rubocop/cop/style/percent_q_literals.rb +2 -2
  142. data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -4
  143. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  144. data/lib/rubocop/cop/style/redundant_argument.rb +14 -7
  145. data/lib/rubocop/cop/style/redundant_begin.rb +25 -0
  146. data/lib/rubocop/cop/style/redundant_condition.rb +2 -3
  147. data/lib/rubocop/cop/style/redundant_fetch_block.rb +4 -0
  148. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +12 -3
  149. data/lib/rubocop/cop/style/redundant_freeze.rb +4 -4
  150. data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
  151. data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -3
  152. data/lib/rubocop/cop/style/redundant_self.rb +10 -0
  153. data/lib/rubocop/cop/style/redundant_self_assignment.rb +4 -3
  154. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +23 -28
  155. data/lib/rubocop/cop/style/redundant_sort.rb +51 -18
  156. data/lib/rubocop/cop/style/regexp_literal.rb +3 -3
  157. data/lib/rubocop/cop/style/return_nil.rb +2 -1
  158. data/lib/rubocop/cop/style/safe_navigation.rb +13 -2
  159. data/lib/rubocop/cop/style/select_by_regexp.rb +106 -0
  160. data/lib/rubocop/cop/style/single_argument_dig.rb +5 -0
  161. data/lib/rubocop/cop/style/slicing_with_range.rb +13 -0
  162. data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -0
  163. data/lib/rubocop/cop/style/special_global_vars.rb +4 -0
  164. data/lib/rubocop/cop/style/static_class.rb +5 -5
  165. data/lib/rubocop/cop/style/string_chars.rb +4 -2
  166. data/lib/rubocop/cop/style/string_concatenation.rb +5 -1
  167. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -0
  168. data/lib/rubocop/cop/style/struct_inheritance.rb +4 -0
  169. data/lib/rubocop/cop/style/swap_values.rb +4 -2
  170. data/lib/rubocop/cop/style/symbol_array.rb +3 -3
  171. data/lib/rubocop/cop/style/symbol_proc.rb +26 -0
  172. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +19 -0
  173. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  174. data/lib/rubocop/cop/style/word_array.rb +3 -3
  175. data/lib/rubocop/cop/style/yoda_condition.rb +24 -7
  176. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -0
  177. data/lib/rubocop/cop/util.rb +2 -2
  178. data/lib/rubocop/cops_documentation_generator.rb +17 -5
  179. data/lib/rubocop/magic_comment.rb +44 -15
  180. data/lib/rubocop/options.rb +126 -112
  181. data/lib/rubocop/result_cache.rb +1 -1
  182. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  183. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  184. data/lib/rubocop/runner.rb +1 -2
  185. data/lib/rubocop/version.rb +1 -1
  186. data/lib/rubocop.rb +10 -2
  187. metadata +13 -5
@@ -10,12 +10,6 @@ module RuboCop
10
10
  # explicit by requiring parenthesis around complex range boundaries (anything
11
11
  # that is not a basic literal: numerics, strings, symbols, etc.).
12
12
  #
13
- # NOTE: The cop auto-corrects by wrapping the entire boundary in parentheses, which
14
- # makes the outcome more explicit but is possible to not be the intention of the
15
- # programmer. For this reason, this cop's auto-correct is marked as unsafe (it
16
- # will not change the behaviour of the code, but will not necessarily match the
17
- # intent of the program).
18
- #
19
13
  # This cop can be configured with `RequireParenthesesForMethodChains` in order to
20
14
  # specify whether method chains (including `self.foo`) should be wrapped in parens
21
15
  # by this cop.
@@ -23,6 +17,13 @@ module RuboCop
23
17
  # NOTE: Regardless of this configuration, if a method receiver is a basic literal
24
18
  # value, it will be wrapped in order to prevent the ambiguity of `1..2.to_a`.
25
19
  #
20
+ # @safety
21
+ # The cop auto-corrects by wrapping the entire boundary in parentheses, which
22
+ # makes the outcome more explicit but is possible to not be the intention of the
23
+ # programmer. For this reason, this cop's auto-correct is unsafe (it will not
24
+ # change the behaviour of the code, but will not necessarily match the
25
+ # intent of the program).
26
+ #
26
27
  # @example
27
28
  # # bad
28
29
  # x || 1..2
@@ -55,7 +56,6 @@ module RuboCop
55
56
  #
56
57
  # # good
57
58
  # (a.foo)..(b.bar)
58
- #
59
59
  class AmbiguousRange < Base
60
60
  extend AutoCorrector
61
61
 
@@ -83,7 +83,7 @@ module RuboCop
83
83
  node.begin_type? ||
84
84
  node.basic_literal? ||
85
85
  node.variable? || node.const_type? ||
86
- node.call_type? && acceptable_call?(node)
86
+ (node.call_type? && acceptable_call?(node))
87
87
  end
88
88
 
89
89
  def acceptable_call?(node)
@@ -49,7 +49,7 @@ module RuboCop
49
49
  def on_if(node)
50
50
  return if node.condition.block_type?
51
51
 
52
- traverse_node(node.condition, ASGN_TYPES) do |asgn_node|
52
+ traverse_node(node.condition) do |asgn_node|
53
53
  next :skip_children if skip_children?(asgn_node)
54
54
  next if allowed_construct?(asgn_node)
55
55
 
@@ -83,13 +83,15 @@ module RuboCop
83
83
  (safe_assignment_allowed? && safe_assignment?(asgn_node))
84
84
  end
85
85
 
86
- # each_node/visit_descendants_with_types with :skip_children
87
- def traverse_node(node, types, &block)
88
- result = yield node if types.include?(node.type)
86
+ def traverse_node(node, &block)
87
+ # if the node is a block, any assignments are irrelevant
88
+ return if node.block_type?
89
+
90
+ result = yield node if ASGN_TYPES.include?(node.type)
89
91
 
90
92
  return if result == :skip_children
91
93
 
92
- node.each_child_node { |child| traverse_node(child, types, &block) }
94
+ node.each_child_node { |child| traverse_node(child, &block) }
93
95
  end
94
96
  end
95
97
  end
@@ -5,15 +5,28 @@ module RuboCop
5
5
  module Lint
6
6
  # This cop checks for places where binary operator has identical operands.
7
7
  #
8
- # It covers arithmetic operators: `+`, `-`, `*`, `/`, `%`, `**`;
8
+ # It covers arithmetic operators: `-`, `/`, `%`;
9
9
  # comparison operators: `==`, `===`, `=~`, `>`, `>=`, `<`, `<=`;
10
- # bitwise operators: `|`, `^`, `&`, `<<`, `>>`;
10
+ # bitwise operators: `|`, `^`, `&`;
11
11
  # boolean operators: `&&`, `||`
12
12
  # and "spaceship" operator - `<=>`.
13
13
  #
14
- # This cop is marked as unsafe as it does not consider side effects when calling methods
15
- # and thus can generate false positives:
14
+ # Simple arithmetic operations are allowed by this cop: `+`, `*`, `**`, `<<` and `>>`.
15
+ # Although these can be rewritten in a different way, it should not be necessary to
16
+ # do so. This does not include operations such as `-` or `/` where the result will
17
+ # always be the same (`x - x` will always be 0; `x / x` will always be 1), and
18
+ # thus are legitimate offenses.
19
+ #
20
+ # @safety
21
+ # This cop is unsafe as it does not consider side effects when calling methods
22
+ # and thus can generate false positives, for example:
23
+ #
24
+ # [source,ruby]
25
+ # ----
16
26
  # if wr.take_char == '\0' && wr.take_char == '\0'
27
+ # # ...
28
+ # end
29
+ # ----
17
30
  #
18
31
  # @example
19
32
  # # bad
@@ -24,7 +37,7 @@ module RuboCop
24
37
  # do_something
25
38
  # end
26
39
  #
27
- # def childs?
40
+ # def child?
28
41
  # left_child || left_child
29
42
  # end
30
43
  #
@@ -6,6 +6,11 @@ module RuboCop
6
6
  # This cop checks for `:true` and `:false` symbols.
7
7
  # In most cases it would be a typo.
8
8
  #
9
+ # @safety
10
+ # Autocorrection is unsafe for this cop because code relying
11
+ # on `:true` or `:false` symbols will break when those are
12
+ # changed to actual booleans.
13
+ #
9
14
  # @example
10
15
  #
11
16
  # # bad
@@ -7,8 +7,8 @@ module RuboCop
7
7
  # not be kept for production code.
8
8
  #
9
9
  # The cop can be configured using `DebuggerMethods`. By default, a number of gems
10
- # debug entrypoints are configured (`Kernel`, `Byebug`, `Capybara`, `Pry`, `Rails`,
11
- # and `WebConsole`). Additional methods can be added.
10
+ # debug entrypoints are configured (`Kernel`, `Byebug`, `Capybara`, `debug.rb`,
11
+ # `Pry`, `Rails`, `RubyJard`, and `WebConsole`). Additional methods can be added.
12
12
  #
13
13
  # Specific default groups can be disabled if necessary:
14
14
  #
@@ -57,8 +57,6 @@ module RuboCop
57
57
  class Debugger < Base
58
58
  MSG = 'Remove debugger entry point `%<source>s`.'
59
59
 
60
- RESTRICT_ON_SEND = [].freeze
61
-
62
60
  # @!method kernel?(node)
63
61
  def_node_matcher :kernel?, <<~PATTERN
64
62
  (const {nil? cbase} :Kernel)
@@ -58,12 +58,12 @@ module RuboCop
58
58
  end
59
59
 
60
60
  def to_s
61
- [class_constant, method].compact.join(delimeter)
61
+ [class_constant, method].compact.join(delimiter)
62
62
  end
63
63
 
64
64
  private
65
65
 
66
- def delimeter
66
+ def delimiter
67
67
  CLASS_METHOD_DELIMETER
68
68
  end
69
69
  end
@@ -81,12 +81,12 @@ module RuboCop
81
81
  end
82
82
 
83
83
  def to_s
84
- [class_constant, method].compact.join(delimeter)
84
+ [class_constant, method].compact.join(delimiter)
85
85
  end
86
86
 
87
87
  private
88
88
 
89
- def delimeter
89
+ def delimiter
90
90
  instance_method? ? INSTANCE_METHOD_DELIMETER : CLASS_METHOD_DELIMETER
91
91
  end
92
92
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # This cop checks constructors for disjunctive assignments that should
6
+ # This cop checks constructors for disjunctive assignments (`||=`) that should
7
7
  # be plain assignments.
8
8
  #
9
9
  # So far, this cop is only concerned with disjunctive assignment of
@@ -12,6 +12,29 @@ module RuboCop
12
12
  # In ruby, an instance variable is nil until a value is assigned, so the
13
13
  # disjunction is unnecessary. A plain assignment has the same effect.
14
14
  #
15
+ # @safety
16
+ # This cop is unsafe because it can register a false positive when a
17
+ # method is redefined in a subclass that calls super. For example:
18
+ #
19
+ # [source,ruby]
20
+ # ----
21
+ # class Base
22
+ # def initialize
23
+ # @config ||= 'base'
24
+ # end
25
+ # end
26
+ #
27
+ # class Derived < Base
28
+ # def initialize
29
+ # @config = 'derived'
30
+ # super
31
+ # end
32
+ # end
33
+ # ----
34
+ #
35
+ # Without the disjunctive assignment, `Derived` will be unable to override
36
+ # the value for `@config`.
37
+ #
15
38
  # @example
16
39
  # # bad
17
40
  # def initialize
@@ -49,6 +49,9 @@ module RuboCop
49
49
  def on_if(node)
50
50
  return if node.ternary?
51
51
 
52
+ # If the if is on a single line, it'll be handled by `Style/OneLineConditional`
53
+ return if node.single_line?
54
+
52
55
  check(node)
53
56
  end
54
57
 
@@ -66,10 +69,7 @@ module RuboCop
66
69
 
67
70
  def check_else(node)
68
71
  else_branch = node.else_branch
69
-
70
- return unless else_branch.begin_type?
71
-
72
- first_else = else_branch.children.first
72
+ first_else = else_branch.begin_type? ? else_branch.children.first : else_branch
73
73
 
74
74
  return unless first_else
75
75
  return unless first_else.source_range.line == node.loc.else.line
@@ -81,9 +81,13 @@ module RuboCop
81
81
  corrector.insert_after(node.loc.else, "\n")
82
82
 
83
83
  blank_range = range_between(node.loc.else.end_pos, first_else.loc.expression.begin_pos)
84
- indentation = indent(node.else_branch.children[1])
84
+ indentation = indent(node, offset: indentation_width)
85
85
  corrector.replace(blank_range, indentation)
86
86
  end
87
+
88
+ def indentation_width
89
+ @config.for_cop('Layout/IndentationWidth')['Width'] || 2
90
+ end
87
91
  end
88
92
  end
89
93
  end
@@ -51,7 +51,7 @@ module RuboCop
51
51
 
52
52
  def on_case_match(node)
53
53
  node.in_pattern_branches.each do |branch|
54
- next if branch.body || cop_config['AllowComments'] && comment_lines?(node)
54
+ next if branch.body || (cop_config['AllowComments'] && comment_lines?(node))
55
55
 
56
56
  add_offense(branch)
57
57
  end
@@ -118,7 +118,7 @@ module RuboCop
118
118
  end
119
119
 
120
120
  def correct_arguments?(arguments)
121
- arguments.size == 1 || arguments.size == 2 && arguments[1].hash_type?
121
+ arguments.size == 1 || (arguments.size == 2 && arguments[1].hash_type?)
122
122
  end
123
123
 
124
124
  def build_kwargs(node)
@@ -24,7 +24,7 @@ module RuboCop
24
24
  def on_float(node)
25
25
  value, = *node
26
26
 
27
- return unless value.infinite? || value.zero? && /[1-9]/.match?(node.source)
27
+ return unless value.infinite? || (value.zero? && /[1-9]/.match?(node.source))
28
28
 
29
29
  add_offense(node)
30
30
  end
@@ -3,10 +3,19 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Prefer using `Hash#compare_by_identity` than using `object_id` for hash keys.
6
+ # Prefer using `Hash#compare_by_identity` rather than using `object_id`
7
+ # for hash keys.
7
8
  #
8
- # This cop is marked as unsafe as a hash possibly can contain other keys
9
- # besides `object_id`s.
9
+ # This cop looks for hashes being keyed by objects' `object_id`, using
10
+ # one of these methods: `key?`, `has_key?`, `fetch`, `[]` and `[]=`.
11
+ #
12
+ # @safety
13
+ # This cop is unsafe. Although unlikely, the hash could store both object
14
+ # ids and other values that need be compared by value, and thus
15
+ # could be a false positive.
16
+ #
17
+ # Furthermore, this cop cannot guarantee that the receiver of one of the
18
+ # methods (`key?`, etc.) is actually a hash.
10
19
  #
11
20
  # @example
12
21
  # # bad
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ #
7
+ # This cop checks for `IO.select` that is incompatible with Fiber Scheduler since Ruby 3.0.
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # IO.select([io], [], [], timeout)
13
+ #
14
+ # # good
15
+ # io.wait_readable(timeout)
16
+ #
17
+ # # bad
18
+ # IO.select([], [io], [], timeout)
19
+ #
20
+ # # good
21
+ # io.wait_writable(timeout)
22
+ #
23
+ class IncompatibleIoSelectWithFiberScheduler < Base
24
+ extend AutoCorrector
25
+
26
+ MSG = 'Use `%<preferred>s` instead of `%<current>s`.'
27
+ RESTRICT_ON_SEND = %i[select].freeze
28
+
29
+ # @!method io_select(node)
30
+ def_node_matcher :io_select, <<~PATTERN
31
+ (send
32
+ (const {nil? cbase} :IO) :select $_ $_ {(array) nil} $...)
33
+ PATTERN
34
+
35
+ def on_send(node)
36
+ return unless (read, write, timeout = io_select(node))
37
+ return unless scheduler_compatible?(read, write) || scheduler_compatible?(write, read)
38
+
39
+ preferred = preferred_method(read, write, timeout)
40
+ message = format(MSG, preferred: preferred, current: node.source)
41
+
42
+ add_offense(node, message: message) do |corrector|
43
+ corrector.replace(node, preferred)
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def scheduler_compatible?(io1, io2)
50
+ return false unless io1.array_type? && io1.values.size == 1
51
+
52
+ io2.array_type? ? io2.values.empty? : io2.nil_type?
53
+ end
54
+
55
+ def preferred_method(read, write, timeout)
56
+ timeout_argument = timeout.empty? ? '' : "(#{timeout[0].source})"
57
+
58
+ if read.array_type? && read.values[0]
59
+ "#{read.values[0].source}.wait_readable#{timeout_argument}"
60
+ else
61
+ "#{write.values[0].source}.wait_writable#{timeout_argument}"
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -5,6 +5,11 @@ module RuboCop
5
5
  module Lint
6
6
  # This cop checks for interpolation in a single quoted string.
7
7
  #
8
+ # @safety
9
+ # This cop is generally safe, but is marked as unsafe because
10
+ # it is possible to actually intentionally have text inside
11
+ # `#{...}` in a single quoted string.
12
+ #
8
13
  # @example
9
14
  #
10
15
  # # bad
@@ -5,9 +5,10 @@ module RuboCop
5
5
  module Lint
6
6
  # This cop checks for uses of `begin...end while/until something`.
7
7
  #
8
- # The cop is marked as unsafe because behaviour can change in some cases, including
9
- # if a local variable inside the loop body is accessed outside of it, or if the
10
- # loop body raises a `StopIteration` exception (which `Kernel#loop` rescues).
8
+ # @safety
9
+ # The cop is unsafe because behaviour can change in some cases, including
10
+ # if a local variable inside the loop body is accessed outside of it, or if the
11
+ # loop body raises a `StopIteration` exception (which `Kernel#loop` rescues).
11
12
  #
12
13
  # @example
13
14
  #
@@ -14,7 +14,11 @@ module RuboCop
14
14
  # `Dir.glob` and `Dir[]` sort globbed results by default in Ruby 3.0.
15
15
  # So all bad cases are acceptable when Ruby 3.0 or higher are used.
16
16
  #
17
- # This cop will be deprecated and removed when supporting only Ruby 3.0 and higher.
17
+ # NOTE: This cop will be deprecated and removed when supporting only Ruby 3.0 and higher.
18
+ #
19
+ # @safety
20
+ # This cop is unsafe in the case where sorting files changes existing
21
+ # expected behaviour.
18
22
  #
19
23
  # @example
20
24
  #
@@ -18,6 +18,11 @@ module RuboCop
18
18
  # cop by default). Similarly, Rails' duration methods do not work well
19
19
  # with `Integer()` and can be ignored with `IgnoredMethods`.
20
20
  #
21
+ # @safety
22
+ # Autocorrection is unsafe because it is not guaranteed that the
23
+ # replacement `Kernel` methods are able to properly handle the
24
+ # input if it is not a standard class.
25
+ #
21
26
  # @example
22
27
  #
23
28
  # # bad
@@ -60,6 +65,7 @@ module RuboCop
60
65
  'class parsing, instead of using '\
61
66
  '`%<current>s`, use stricter '\
62
67
  '`%<corrected_method>s`.'
68
+ CONVERSION_METHODS = %i[Integer Float Complex to_i to_f to_c].freeze
63
69
  METHODS = CONVERSION_METHOD_CLASS_MAPPING.keys.map(&:inspect).join(' ')
64
70
 
65
71
  # @!method to_method(node)
@@ -127,7 +133,8 @@ module RuboCop
127
133
  end
128
134
 
129
135
  def ignore_receiver?(receiver)
130
- if receiver.send_type? && ignored_method?(receiver.method_name)
136
+ if receiver.numeric_type? || (receiver.send_type? &&
137
+ (conversion_method?(receiver.method_name) || ignored_method?(receiver.method_name)))
131
138
  true
132
139
  elsif (receiver = top_receiver(receiver))
133
140
  receiver.const_type? && ignored_class?(receiver.const_name)
@@ -142,6 +149,10 @@ module RuboCop
142
149
  receiver
143
150
  end
144
151
 
152
+ def conversion_method?(method_name)
153
+ CONVERSION_METHODS.include?(method_name)
154
+ end
155
+
145
156
  def ignored_classes
146
157
  cop_config.fetch('IgnoredClasses', [])
147
158
  end
@@ -10,7 +10,7 @@ module RuboCop
10
10
  # ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin19]
11
11
  # -e:1: warning: `_1' is reserved for numbered parameter; consider another name
12
12
  #
13
- # Assiging to numbered parameter (from `_1` to `_9`) cause an error in Ruby 3.0.
13
+ # Assigning to a numbered parameter (from `_1` to `_9`) causes an error in Ruby 3.0.
14
14
  #
15
15
  # % ruby -ve '_1 = :value'
16
16
  # ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
@@ -9,8 +9,10 @@ module RuboCop
9
9
  # should always be the same. If constants are assigned in multiple
10
10
  # locations, the result may vary depending on the order of `require`.
11
11
  #
12
- # Also, if you already have such an implementation, auto-correction may
13
- # change the result.
12
+ # @safety
13
+ # This cop is unsafe because code that is already conditionally
14
+ # assigning a constant may have its behaviour changed by
15
+ # auto-correction.
14
16
  #
15
17
  # @example
16
18
  #
@@ -6,6 +6,23 @@ module RuboCop
6
6
  # This cops looks for references of Regexp captures that are out of range
7
7
  # and thus always returns nil.
8
8
  #
9
+ # @safety
10
+ # This cop is unsafe because it is naive in how it determines what
11
+ # references are available based on the last encountered regexp, but
12
+ # it cannot handle some cases, such as conditional regexp matches, which
13
+ # leads to false positives, such as:
14
+ #
15
+ # [source,ruby]
16
+ # ----
17
+ # foo ? /(c)(b)/ =~ str : /(b)/ =~ str
18
+ # do_something if $2
19
+ # # $2 is defined for the first condition but not the second, however
20
+ # # the cop will mark this as an offense.
21
+ # ----
22
+ #
23
+ # This might be a good indication of code that should be refactored,
24
+ # however.
25
+ #
9
26
  # @example
10
27
  #
11
28
  # /(foo)bar/ =~ 'foobar'
@@ -9,6 +9,16 @@ module RuboCop
9
9
  # example, mistranslating an array of literals to percent string notation)
10
10
  # rather than meant to be part of the resulting strings.
11
11
  #
12
+ # @safety
13
+ # The cop is unsafe because the correction changes the values in the array
14
+ # and that might have been done purposely.
15
+ #
16
+ # [source,ruby]
17
+ # ----
18
+ # %w('foo', "bar") #=> ["'foo',", '"bar"']
19
+ # %w(foo bar) #=> ['foo', 'bar']
20
+ # ----
21
+ #
12
22
  # @example
13
23
  #
14
24
  # # bad
@@ -13,6 +13,10 @@ module RuboCop
13
13
  # `Exception`. Alternatively, make `Exception` a fully qualified class
14
14
  # name with an explicit namespace.
15
15
  #
16
+ # @safety
17
+ # This cop is unsafe because it will change the exception class being
18
+ # raised, which is a change in behaviour.
19
+ #
16
20
  # @example
17
21
  # # bad
18
22
  # raise Exception, 'Error message here'
@@ -7,13 +7,14 @@ module RuboCop
7
7
  # `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`, and `equal?` methods
8
8
  # are checked by default. These are customizable with `AllowedMethods` option.
9
9
  #
10
- # This cop is marked as unsafe, because auto-correction can change the
11
- # return type of the expression. An offending expression that previously
12
- # could return `nil` will be auto-corrected to never return `nil`.
13
- #
14
10
  # In the example below, the safe navigation operator (`&.`) is unnecessary
15
11
  # because `NilClass` has methods like `respond_to?` and `is_a?`.
16
12
  #
13
+ # @safety
14
+ # This cop is unsafe, because auto-correction can change the return type of
15
+ # the expression. An offending expression that previously could return `nil`
16
+ # will be auto-corrected to never return `nil`.
17
+ #
17
18
  # @example
18
19
  # # bad
19
20
  # do_something if attrs&.respond_to?(:[])
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for uses a file requiring itself with `require_relative`.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ #
12
+ # # foo.rb
13
+ # require_relative 'foo'
14
+ # require_relative 'bar'
15
+ #
16
+ # # good
17
+ #
18
+ # # foo.rb
19
+ # require_relative 'bar'
20
+ #
21
+ class RequireRelativeSelfPath < Base
22
+ include RangeHelp
23
+ extend AutoCorrector
24
+
25
+ MSG = 'Remove the `require_relative` that requires itself.'
26
+ RESTRICT_ON_SEND = %i[require_relative].freeze
27
+
28
+ def on_send(node)
29
+ return unless (required_feature = node.first_argument)
30
+ return unless same_file?(processed_source.file_path, required_feature.value)
31
+
32
+ add_offense(node) do |corrector|
33
+ corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def same_file?(file_path, required_feature)
40
+ file_path == required_feature || remove_ext(file_path) == required_feature
41
+ end
42
+
43
+ def remove_ext(file_path)
44
+ File.basename(file_path, File.extname(file_path))
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -10,7 +10,7 @@ module RuboCop
10
10
  #
11
11
  # NOTE: Shadowing of variables in block passed to `Ractor.new` is allowed
12
12
  # because `Ractor` should not access outer variables.
13
- # eg. following syle is encouraged:
13
+ # eg. following style is encouraged:
14
14
  #
15
15
  # worker_id, pipe = env
16
16
  # Ractor.new(worker_id, pipe) do |worker_id, pipe|
@@ -143,7 +143,7 @@ module RuboCop
143
143
  # Although some operators can be converted to symbols normally
144
144
  # (ie. `:==`), these are not accepted as hash keys and will
145
145
  # raise a syntax error (eg. `{ ==: ... }`). Therefore, if the
146
- # symbol does not start with an alpha-numeric or underscore, it
146
+ # symbol does not start with an alphanumeric or underscore, it
147
147
  # will be ignored.
148
148
  return unless node.value.to_s.match?(/\A[a-z0-9_]/i)
149
149
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # This cop checks for "triple quotes" (strings delimted by any odd number
6
+ # This cop checks for "triple quotes" (strings delimited by any odd number
7
7
  # of quotes greater than 1).
8
8
  #
9
9
  # Ruby allows multiple strings to be implicitly concatenated by just
@@ -13,14 +13,19 @@ module RuboCop
13
13
  # Keyword arguments (including `**kwargs`) do not get counted towards
14
14
  # this, as they are not used by the methods in question.
15
15
  #
16
- # NOTE: This cop matches for method names only and hence cannot tell apart
17
- # methods with same name in different classes.
18
- #
19
16
  # Method names and their expected arity can be configured like this:
20
17
  #
18
+ # [source,yaml]
19
+ # ----
21
20
  # Methods:
22
21
  # inject: 2
23
22
  # reduce: 2
23
+ # ----
24
+ #
25
+ # @safety
26
+ # This cop matches for method names only and hence cannot tell apart
27
+ # methods with same name in different classes, which may lead to a
28
+ # false positive.
24
29
  #
25
30
  # @example
26
31
  # # bad