rubocop 1.21.0 → 1.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +43 -6
  4. data/lib/rubocop/config.rb +5 -0
  5. data/lib/rubocop/config_loader.rb +2 -0
  6. data/lib/rubocop/config_validator.rb +9 -1
  7. data/lib/rubocop/cop/base.rb +1 -1
  8. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +34 -11
  9. data/lib/rubocop/cop/bundler/ordered_gems.rb +3 -12
  10. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +11 -10
  11. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +3 -12
  12. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +1 -1
  13. data/lib/rubocop/cop/generator.rb +14 -8
  14. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  15. data/lib/rubocop/cop/layout/dot_position.rb +25 -2
  16. data/lib/rubocop/cop/layout/line_length.rb +7 -5
  17. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -0
  18. data/lib/rubocop/cop/layout/space_inside_parens.rb +74 -24
  19. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +5 -1
  20. data/lib/rubocop/cop/lint/ambiguous_range.rb +7 -7
  21. data/lib/rubocop/cop/lint/assignment_in_condition.rb +7 -5
  22. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +18 -5
  23. data/lib/rubocop/cop/lint/boolean_symbol.rb +5 -0
  24. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
  25. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +24 -1
  26. data/lib/rubocop/cop/lint/else_layout.rb +9 -5
  27. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +12 -3
  28. data/lib/rubocop/cop/lint/interpolation_check.rb +5 -0
  29. data/lib/rubocop/cop/lint/loop.rb +4 -3
  30. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +5 -1
  31. data/lib/rubocop/cop/lint/number_conversion.rb +5 -0
  32. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  33. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +4 -2
  34. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -0
  35. data/lib/rubocop/cop/lint/percent_string_array.rb +10 -0
  36. data/lib/rubocop/cop/lint/raise_exception.rb +4 -0
  37. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +5 -4
  38. data/lib/rubocop/cop/lint/require_relative_self_path.rb +49 -0
  39. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
  40. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  41. data/lib/rubocop/cop/lint/triple_quotes.rb +1 -1
  42. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +8 -3
  43. data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -2
  44. data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
  45. data/lib/rubocop/cop/lint/useless_times.rb +3 -2
  46. data/lib/rubocop/cop/metrics/abc_size.rb +6 -0
  47. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +5 -1
  48. data/lib/rubocop/cop/mixin/heredoc.rb +1 -3
  49. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +9 -1
  50. data/lib/rubocop/cop/mixin/percent_array.rb +6 -1
  51. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  52. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +5 -4
  53. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +7 -0
  54. data/lib/rubocop/cop/security/io_methods.rb +49 -0
  55. data/lib/rubocop/cop/security/json_load.rb +8 -7
  56. data/lib/rubocop/cop/security/open.rb +4 -0
  57. data/lib/rubocop/cop/security/yaml_load.rb +4 -0
  58. data/lib/rubocop/cop/style/and_or.rb +4 -3
  59. data/lib/rubocop/cop/style/arguments_forwarding.rb +13 -2
  60. data/lib/rubocop/cop/style/array_coercion.rb +21 -3
  61. data/lib/rubocop/cop/style/case_like_if.rb +5 -0
  62. data/lib/rubocop/cop/style/class_and_module_children.rb +9 -0
  63. data/lib/rubocop/cop/style/collection_compact.rb +7 -5
  64. data/lib/rubocop/cop/style/collection_methods.rb +6 -5
  65. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  66. data/lib/rubocop/cop/style/commented_keyword.rb +4 -1
  67. data/lib/rubocop/cop/style/date_time.rb +5 -0
  68. data/lib/rubocop/cop/style/double_negation.rb +15 -5
  69. data/lib/rubocop/cop/style/float_division.rb +10 -2
  70. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +6 -1
  71. data/lib/rubocop/cop/style/global_std_stream.rb +4 -0
  72. data/lib/rubocop/cop/style/hash_each_methods.rb +5 -0
  73. data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -6
  74. data/lib/rubocop/cop/style/hash_transform_values.rb +4 -6
  75. data/lib/rubocop/cop/style/identical_conditional_branches.rb +18 -16
  76. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +15 -2
  77. data/lib/rubocop/cop/style/infinite_loop.rb +4 -3
  78. data/lib/rubocop/cop/style/inverse_methods.rb +9 -2
  79. data/lib/rubocop/cop/style/line_end_concatenation.rb +13 -0
  80. data/lib/rubocop/cop/style/module_function.rb +8 -9
  81. data/lib/rubocop/cop/style/mutable_constant.rb +12 -7
  82. data/lib/rubocop/cop/style/numbered_parameters.rb +46 -0
  83. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +50 -0
  84. data/lib/rubocop/cop/style/numeric_literals.rb +7 -8
  85. data/lib/rubocop/cop/style/numeric_predicate.rb +5 -0
  86. data/lib/rubocop/cop/style/optional_arguments.rb +4 -0
  87. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +14 -4
  88. data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -4
  89. data/lib/rubocop/cop/style/redundant_argument.rb +14 -7
  90. data/lib/rubocop/cop/style/redundant_fetch_block.rb +4 -0
  91. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +12 -3
  92. data/lib/rubocop/cop/style/redundant_freeze.rb +0 -1
  93. data/lib/rubocop/cop/style/redundant_self.rb +10 -0
  94. data/lib/rubocop/cop/style/redundant_self_assignment.rb +4 -3
  95. data/lib/rubocop/cop/style/redundant_sort.rb +47 -29
  96. data/lib/rubocop/cop/style/safe_navigation.rb +13 -2
  97. data/lib/rubocop/cop/style/select_by_regexp.rb +106 -0
  98. data/lib/rubocop/cop/style/single_argument_dig.rb +5 -0
  99. data/lib/rubocop/cop/style/slicing_with_range.rb +13 -0
  100. data/lib/rubocop/cop/style/special_global_vars.rb +4 -0
  101. data/lib/rubocop/cop/style/static_class.rb +4 -3
  102. data/lib/rubocop/cop/style/string_chars.rb +4 -2
  103. data/lib/rubocop/cop/style/string_concatenation.rb +4 -0
  104. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -0
  105. data/lib/rubocop/cop/style/struct_inheritance.rb +3 -2
  106. data/lib/rubocop/cop/style/swap_values.rb +4 -2
  107. data/lib/rubocop/cop/style/symbol_proc.rb +26 -0
  108. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +19 -0
  109. data/lib/rubocop/cop/style/yoda_condition.rb +20 -0
  110. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -0
  111. data/lib/rubocop/cop/util.rb +2 -2
  112. data/lib/rubocop/cops_documentation_generator.rb +17 -5
  113. data/lib/rubocop/options.rb +126 -112
  114. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  115. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  116. data/lib/rubocop/version.rb +1 -1
  117. data/lib/rubocop.rb +5 -0
  118. metadata +10 -5
@@ -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
@@ -6,8 +6,9 @@ module RuboCop
6
6
  # This cop checks for useless method definitions, specifically: empty constructors
7
7
  # and methods just delegating to `super`.
8
8
  #
9
- # This cop is marked as unsafe as it can trigger false positives for cases when
10
- # an empty constructor just overrides the parent constructor, which is bad anyway.
9
+ # @safety
10
+ # This cop is unsafe as it can register false positives for cases when an empty
11
+ # constructor just overrides the parent constructor, which is bad anyway.
11
12
  #
12
13
  # @example
13
14
  # # bad
@@ -5,11 +5,14 @@ module RuboCop
5
5
  module Lint
6
6
  # This cop checks for setter call to local variable as the final
7
7
  # expression of a function definition.
8
- # Its auto-correction is marked as unsafe because return value will be changed.
9
8
  #
10
- # NOTE: There are edge cases in which the local variable references a
11
- # value that is also accessible outside the local scope. This is not
12
- # detected by the cop, and it can yield a false positive.
9
+ # @safety
10
+ # There are edge cases in which the local variable references a
11
+ # value that is also accessible outside the local scope. This is not
12
+ # detected by the cop, and it can yield a false positive.
13
+ #
14
+ # As well, auto-correction is unsafe because the method's
15
+ # return value will be changed.
13
16
  #
14
17
  # @example
15
18
  #
@@ -7,8 +7,9 @@ module RuboCop
7
7
  # (when the integer <= 0) or that will only ever yield once
8
8
  # (`1.times`).
9
9
  #
10
- # This cop is marked as unsafe as `times` returns its receiver, which
11
- # is *usually* OK, but might change behavior.
10
+ # @safety
11
+ # This cop is unsafe as `times` returns its receiver, which is
12
+ # *usually* OK, but might change behavior.
12
13
  #
13
14
  # @example
14
15
  # # bad
@@ -8,6 +8,12 @@ module RuboCop
8
8
  # (method calls), and conditions. See http://c2.com/cgi/wiki?AbcMetric
9
9
  # and https://en.wikipedia.org/wiki/ABC_Software_Metric.
10
10
  #
11
+ # Interpreting ABC size:
12
+ #
13
+ # * <= 17 satisfactory
14
+ # * 18..30 unsatisfactory
15
+ # * > 30 dangerous
16
+ #
11
17
  # You can have repeated "attributes" calls count as a single "branch".
12
18
  # For this purpose, attributes are any method with no argument; no attempt
13
19
  # is meant to distinguish actual `attr_reader` from other methods.
@@ -20,7 +20,7 @@ module RuboCop
20
20
 
21
21
  def frozen_string_literal?(node)
22
22
  frozen_string = if target_ruby_version >= 3.0
23
- node.str_type? || frozen_heredoc?(node)
23
+ uninterpolated_string?(node) || frozen_heredoc?(node)
24
24
  else
25
25
  FROZEN_STRING_LITERAL_TYPES_RUBY27.include?(node.type)
26
26
  end
@@ -28,6 +28,10 @@ module RuboCop
28
28
  frozen_string && frozen_string_literals_enabled?
29
29
  end
30
30
 
31
+ def uninterpolated_string?(node)
32
+ node.str_type? || (node.dstr_type? && node.each_descendant(:begin).none?)
33
+ end
34
+
31
35
  def frozen_heredoc?(node)
32
36
  return false unless node.dstr_type? && node.heredoc?
33
37
 
@@ -21,9 +21,7 @@ module RuboCop
21
21
  private
22
22
 
23
23
  def indent_level(str)
24
- indentations = str.lines
25
- .map { |line| line[/^\s*/] }
26
- .reject { |line| line.end_with?("\n") }
24
+ indentations = str.lines.map { |line| line[/^\s*/] }.reject { |line| line.end_with?("\n") }
27
25
  indentations.empty? ? 0 : indentations.min_by(&:size).size
28
26
  end
29
27
 
@@ -35,7 +35,15 @@ module RuboCop
35
35
  previous: gem_name(current),
36
36
  current: gem_name(previous)
37
37
  )
38
- add_offense(current, message: message)
38
+
39
+ add_offense(current, message: message) do |corrector|
40
+ OrderedGemCorrector.correct(
41
+ processed_source,
42
+ current,
43
+ previous_declaration(current),
44
+ treat_comments_as_separators
45
+ ).call(corrector)
46
+ end
39
47
  end
40
48
 
41
49
  def gem_name(declaration_node)
@@ -36,7 +36,12 @@ module RuboCop
36
36
  def check_percent_array(node)
37
37
  array_style_detected(:percent, node.values.size)
38
38
 
39
- return unless style == :brackets || invalid_percent_array_contents?(node)
39
+ brackets_required = invalid_percent_array_contents?(node)
40
+ return unless style == :brackets || brackets_required
41
+
42
+ # If in percent style but brackets are required due to
43
+ # string content, the file should be excluded in auto-gen-config
44
+ no_acceptable_style! if brackets_required
40
45
 
41
46
  bracketed_array = build_bracketed_array(node)
42
47
  message = format(self.class::ARRAY_MSG, prefer: bracketed_array)
@@ -24,7 +24,7 @@ module RuboCop
24
24
  # # With `AllowNamesEndingInNumbers` set to false
25
25
  # foo { |num1, num2| num1 * num2 }
26
26
  #
27
- # # With `MinParamNameLength` set to number greater than 1
27
+ # # With `MinNameLength` set to number greater than 1
28
28
  # baz { |a, b, c| do_stuff(a, b, c) }
29
29
  #
30
30
  # # good
@@ -14,6 +14,11 @@ module RuboCop
14
14
  # convention that is used to implicitly indicate that an ivar should not
15
15
  # be set or referenced outside of the memoization method.
16
16
  #
17
+ # @safety
18
+ # This cop relies on the pattern `@instance_var ||= ...`,
19
+ # but this is sometimes used for other purposes than memoization
20
+ # so this cop is considered unsafe.
21
+ #
17
22
  # @example EnforcedStyleForLeadingUnderscores: disallowed (default)
18
23
  # # bad
19
24
  # # Method foo is memoized using an instance variable that is
@@ -139,10 +144,6 @@ module RuboCop
139
144
  # define_method(:foo) do
140
145
  # @_foo ||= calculate_expensive_thing
141
146
  # end
142
- #
143
- # This cop relies on the pattern `@instance_var ||= ...`,
144
- # but this is sometimes used for other purposes than memoization
145
- # so this cop is considered unsafe.
146
147
  class MemoizedInstanceVariableName < Base
147
148
  include ConfigurableEnforcedStyle
148
149
 
@@ -75,6 +75,9 @@ module RuboCop
75
75
  preferred_name = preferred_name(offending_name)
76
76
  return if preferred_name.to_sym == offending_name
77
77
 
78
+ # check variable shadowing for exception variable
79
+ return if shadowed_variable_name?(node)
80
+
78
81
  range = offense_range(node)
79
82
  message = message(node)
80
83
 
@@ -150,6 +153,10 @@ module RuboCop
150
153
  preferred_name = preferred_name(offending_name)
151
154
  format(MSG, preferred: preferred_name, bad: offending_name)
152
155
  end
156
+
157
+ def shadowed_variable_name?(node)
158
+ node.each_descendant(:lvar).any? { |n| n.children.first.to_s == preferred_name(n) }
159
+ end
153
160
  end
154
161
  end
155
162
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Security
6
+ # Checks for the first argument to `IO.read`, `IO.binread`, `IO.write`, `IO.binwrite`,
7
+ # `IO.foreach`, and `IO.readlines`.
8
+ #
9
+ # If argument starts with a pipe character (`'|'`) and the receiver is the `IO` class,
10
+ # a subprocess is created in the same way as `Kernel#open`, and its output is returned.
11
+ # `Kernel#open` may allow unintentional command injection, which is the reason these
12
+ # `IO` methods are a security risk.
13
+ # Consider to use `File.read` to disable the behavior of subprocess invocation.
14
+ #
15
+ # @safety
16
+ # This cop is unsafe because false positive will occur if the variable passed as
17
+ # the first argument is a command that is not a file path.
18
+ #
19
+ # @example
20
+ #
21
+ # # bad
22
+ # IO.read(path)
23
+ # IO.read('path')
24
+ #
25
+ # # good
26
+ # File.read(path)
27
+ # File.read('path')
28
+ # IO.read('| command') # Allow intentional command invocation.
29
+ #
30
+ class IoMethods < Base
31
+ extend AutoCorrector
32
+
33
+ MSG = '`File.%<method_name>s` is safer than `IO.%<method_name>s`.'
34
+ RESTRICT_ON_SEND = %i[read binread write binwrite foreach readlines].freeze
35
+
36
+ def on_send(node)
37
+ return unless (receiver = node.receiver) && receiver.source == 'IO'
38
+
39
+ argument = node.first_argument
40
+ return if argument.respond_to?(:value) && argument.value.strip.start_with?('|')
41
+
42
+ add_offense(node, message: format(MSG, method_name: node.method_name)) do |corrector|
43
+ corrector.replace(receiver, 'File')
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -6,13 +6,14 @@ module RuboCop
6
6
  # This cop checks for the use of JSON class methods which have potential
7
7
  # security issues.
8
8
  #
9
- # Autocorrect is disabled by default because it's potentially dangerous.
10
- # If using a stream, like `JSON.load(open('file'))`, it will need to call
11
- # `#read` manually, like `JSON.parse(open('file').read)`.
12
- # If reading single values (rather than proper JSON objects), like
13
- # `JSON.load('false')`, it will need to pass the `quirks_mode: true`
14
- # option, like `JSON.parse('false', quirks_mode: true)`.
15
- # Other similar issues may apply.
9
+ # @safety
10
+ # Autocorrect is disabled by default because it's potentially dangerous.
11
+ # If using a stream, like `JSON.load(open('file'))`, it will need to call
12
+ # `#read` manually, like `JSON.parse(open('file').read)`.
13
+ # If reading single values (rather than proper JSON objects), like
14
+ # `JSON.load('false')`, it will need to pass the `quirks_mode: true`
15
+ # option, like `JSON.parse('false', quirks_mode: true)`.
16
+ # Other similar issues may apply.
16
17
  #
17
18
  # @example
18
19
  # # bad
@@ -11,6 +11,10 @@ module RuboCop
11
11
  # the argument of `Kernel#open` and `URI.open`. It would be better to use
12
12
  # `File.open`, `IO.popen` or `URI.parse#open` explicitly.
13
13
  #
14
+ # @safety
15
+ # This cop could register false positives if `open` is redefined
16
+ # in a class and then used without a receiver in that class.
17
+ #
14
18
  # @example
15
19
  # # bad
16
20
  # open(something)
@@ -7,6 +7,10 @@ module RuboCop
7
7
  # potential security issues leading to remote code execution when
8
8
  # loading from an untrusted source.
9
9
  #
10
+ # @safety
11
+ # The behaviour of the code might change depending on what was
12
+ # in the YAML payload, since `YAML.safe_load` is more restrictive.
13
+ #
10
14
  # @example
11
15
  # # bad
12
16
  # YAML.load("--- foo")
@@ -7,9 +7,10 @@ module RuboCop
7
7
  # `||` instead. It can be configured to check only in conditions or in
8
8
  # all contexts.
9
9
  #
10
- # It is marked as unsafe auto-correction because it may change the
11
- # operator precedence between logical operators (`&&` and `||`) and
12
- # semantic operators (`and` and `or`).
10
+ # @safety
11
+ # Auto-correction is unsafe because there is a different operator precedence
12
+ # between logical operators (`&&` and `||`) and semantic operators (`and` and `or`),
13
+ # and that might change the behaviour.
13
14
  #
14
15
  # @example EnforcedStyle: always
15
16
  # # bad
@@ -30,6 +30,10 @@ module RuboCop
30
30
  # bar(*args)
31
31
  # end
32
32
  #
33
+ # def foo(**kwargs)
34
+ # bar(**kwargs)
35
+ # end
36
+ #
33
37
  # @example AllowOnlyRestArgument: false
34
38
  # # bad
35
39
  # # The following code can replace the arguments with `...`,
@@ -38,6 +42,10 @@ module RuboCop
38
42
  # bar(*args)
39
43
  # end
40
44
  #
45
+ # def foo(**kwargs)
46
+ # bar(**kwargs)
47
+ # end
48
+ #
41
49
  class ArgumentsForwarding < Base
42
50
  include RangeHelp
43
51
  extend AutoCorrector
@@ -49,12 +57,15 @@ module RuboCop
49
57
 
50
58
  # @!method use_rest_arguments?(node)
51
59
  def_node_matcher :use_rest_arguments?, <<~PATTERN
52
- (args (restarg $_) $...)
60
+ (args ({restarg kwrestarg} $_) $...)
53
61
  PATTERN
54
62
 
55
63
  # @!method only_rest_arguments?(node, name)
56
64
  def_node_matcher :only_rest_arguments?, <<~PATTERN
57
- (send _ _ (splat (lvar %1)))
65
+ {
66
+ (send _ _ (splat (lvar %1)))
67
+ (send _ _ (hash (kwsplat (lvar %1))))
68
+ }
58
69
  PATTERN
59
70
 
60
71
  # @!method forwarding_method_arguments?(node, rest_name, block_name, kwargs_name)
@@ -5,9 +5,27 @@ module RuboCop
5
5
  module Style
6
6
  # This cop enforces the use of `Array()` instead of explicit `Array` check or `[*var]`.
7
7
  #
8
- # This cop is disabled by default because false positive will occur if
9
- # the argument of `Array()` is not an array (e.g. Hash, Set),
10
- # an array will be returned as an incompatibility result.
8
+ # The cop is disabled by default due to safety concerns.
9
+ #
10
+ # @safety
11
+ # This cop is unsafe because a false positive may occur if
12
+ # the argument of `Array()` is (or could be) nil or depending
13
+ # on how the argument is handled by `Array()` (which can be
14
+ # different than just wrapping the argument in an array).
15
+ #
16
+ # For example:
17
+ #
18
+ # [source,ruby]
19
+ # ----
20
+ # [nil] #=> [nil]
21
+ # Array(nil) #=> []
22
+ #
23
+ # [{a: 'b'}] #= [{a: 'b'}]
24
+ # Array({a: 'b'}) #=> [[:a, 'b']]
25
+ #
26
+ # [Time.now] #=> [#<Time ...>]
27
+ # Array(Time.now) #=> [14, 16, 14, 16, 9, 2021, 4, 259, true, "EDT"]
28
+ # ----
11
29
  #
12
30
  # @example
13
31
  # # bad
@@ -6,6 +6,11 @@ module RuboCop
6
6
  # This cop identifies places where `if-elsif` constructions
7
7
  # can be replaced with `case-when`.
8
8
  #
9
+ # @safety
10
+ # This cop is unsafe. `case` statements use `===` for equality,
11
+ # so if the original conditional used a different equality operator, the
12
+ # behaviour may be different.
13
+ #
9
14
  # @example
10
15
  # # bad
11
16
  # if status == :active
@@ -6,6 +6,15 @@ module RuboCop
6
6
  # This cop checks the style of children definitions at classes and
7
7
  # modules. Basically there are two different styles:
8
8
  #
9
+ # @safety
10
+ # Autocorrection is unsafe.
11
+ #
12
+ # Moving from compact to nested children requires knowledge of whether the
13
+ # outer parent is a module or a class. Moving from nested to compact requires
14
+ # verification that the outer parent is defined elsewhere. Rubocop does not
15
+ # have the knowledge to perform either operation safely and thus requires
16
+ # manual oversight.
17
+ #
9
18
  # @example EnforcedStyle: nested (default)
10
19
  # # good
11
20
  # # have each child on its own line
@@ -6,11 +6,13 @@ module RuboCop
6
6
  # This cop checks for places where custom logic on rejection nils from arrays
7
7
  # and hashes can be replaced with `{Array,Hash}#{compact,compact!}`.
8
8
  #
9
- # It is marked as unsafe by default because false positives may occur in the
10
- # nil check of block arguments to the receiver object.
11
- # For example, `[[1, 2], [3, nil]].reject { |first, second| second.nil? }`
12
- # and `[[1, 2], [3, nil]].compact` are not compatible. This will work fine
13
- # when the receiver is a hash object.
9
+ # @safety
10
+ # It is unsafe by default because false positives may occur in the
11
+ # `nil` check of block arguments to the receiver object.
12
+ #
13
+ # For example, `[[1, 2], [3, nil]].reject { |first, second| second.nil? }`
14
+ # and `[[1, 2], [3, nil]].compact` are not compatible. This will work fine
15
+ # when the receiver is a hash object.
14
16
  #
15
17
  # @example
16
18
  # # bad
@@ -6,10 +6,6 @@ module RuboCop
6
6
  # This cop enforces the use of consistent method names
7
7
  # from the Enumerable module.
8
8
  #
9
- # Unfortunately we cannot actually know if a method is from
10
- # Enumerable or not (static analysis limitation), so this cop
11
- # can yield some false positives.
12
- #
13
9
  # You can customize the mapping from undesired method to desired method.
14
10
  #
15
11
  # e.g. to use `detect` over `find`:
@@ -18,9 +14,14 @@ module RuboCop
18
14
  # PreferredMethods:
19
15
  # find: detect
20
16
  #
21
- # The default mapping for `PreferredMethods` behaves as follows.
17
+ # @safety
18
+ # This cop is unsafe because it finds methods by name, without actually
19
+ # being able to determine if the receiver is an Enumerable or not, so
20
+ # this cop may register false positives.
22
21
  #
23
22
  # @example
23
+ # # These examples are based on the default mapping for `PreferredMethods`.
24
+ #
24
25
  # # bad
25
26
  # items.collect
26
27
  # items.collect!
@@ -7,8 +7,9 @@ module RuboCop
7
7
  # can be combined into a single loop. It is very likely that combining them
8
8
  # will make the code more efficient and more concise.
9
9
  #
10
- # It is marked as unsafe, because the first loop might modify
11
- # a state that the second loop depends on; these two aren't combinable.
10
+ # @safety
11
+ # The cop is unsafe, because the first loop might modify state that the
12
+ # second loop depends on; these two aren't combinable.
12
13
  #
13
14
  # @example
14
15
  # # bad
@@ -12,7 +12,10 @@ module RuboCop
12
12
  #
13
13
  # Auto-correction removes comments from `end` keyword and keeps comments
14
14
  # for `class`, `module`, `def` and `begin` above the keyword.
15
- # It is marked as unsafe auto-correction as it may remove meaningful comments.
15
+ #
16
+ # @safety
17
+ # Auto-correction is unsafe because it may remove a comment that is
18
+ # meaningful.
16
19
  #
17
20
  # @example
18
21
  # # bad
@@ -9,6 +9,11 @@ module RuboCop
9
9
  # replaceable in certain situations when dealing with multiple timezones
10
10
  # and/or DST.
11
11
  #
12
+ # @safety
13
+ # Autocorrection is not safe, because `DateTime` and `Time` do not have
14
+ # exactly the same behaviour, although in most cases the autocorrection
15
+ # will be fine.
16
+ #
12
17
  # @example
13
18
  #
14
19
  # # bad - uses `DateTime` for current time
@@ -9,6 +9,21 @@ module RuboCop
9
9
  # that use boolean as a return value. When using `EnforcedStyle: forbidden`, double negation
10
10
  # should be forbidden always.
11
11
  #
12
+ # NOTE: when `something` is a boolean value
13
+ # `!!something` and `!something.nil?` are not the same thing.
14
+ # As you're unlikely to write code that can accept values of any type
15
+ # this is rarely a problem in practice.
16
+ #
17
+ # @safety
18
+ # Autocorrection is unsafe when the value is `false`, because the result
19
+ # of the expression will change.
20
+ #
21
+ # [source,ruby]
22
+ # ----
23
+ # !!false #=> false
24
+ # !false.nil? #=> true
25
+ # ----
26
+ #
12
27
  # @example
13
28
  # # bad
14
29
  # !!something
@@ -27,11 +42,6 @@ module RuboCop
27
42
  # def foo?
28
43
  # !!return_value
29
44
  # end
30
- #
31
- # Please, note that when something is a boolean value
32
- # !!something and !something.nil? are not the same thing.
33
- # As you're unlikely to write code that can accept values of any type
34
- # this is rarely a problem in practice.
35
45
  class DoubleNegation < Base
36
46
  include ConfigurableEnforcedStyle
37
47
  extend AutoCorrector
@@ -7,8 +7,16 @@ module RuboCop
7
7
  # It is recommended to either always use `fdiv` or coerce one side only.
8
8
  # This cop also provides other options for code consistency.
9
9
  #
10
- # This cop is marked as unsafe, because if operand variable is a string object
11
- # then `.to_f` will be removed and an error will occur.
10
+ # @safety
11
+ # This cop is unsafe, because if the operand variable is a string object
12
+ # then `.to_f` will be removed and an error will occur.
13
+ #
14
+ # [source,ruby]
15
+ # ----
16
+ # a = '1.2'
17
+ # b = '3.4'
18
+ # a.to_f / b.to_f # Both `to_f` calls are required here
19
+ # ----
12
20
  #
13
21
  # @example EnforcedStyle: single_coerce (default)
14
22
  # # bad
@@ -10,12 +10,17 @@ module RuboCop
10
10
  # default in future Ruby. The comment will be added below a shebang and
11
11
  # encoding comment.
12
12
  #
13
- # Note that the cop will ignore files where the comment exists but is set
13
+ # Note that the cop will accept files where the comment exists but is set
14
14
  # to `false` instead of `true`.
15
15
  #
16
16
  # To require a blank line after this comment, please see
17
17
  # `Layout/EmptyLineAfterMagicComment` cop.
18
18
  #
19
+ # @safety
20
+ # This cop's autocorrection is unsafe since any strings mutations will
21
+ # change from being accepted to raising `FrozenError`, as all strings
22
+ # will become frozen by default, and will need to be manually refactored.
23
+ #
19
24
  # @example EnforcedStyle: always (default)
20
25
  # # The `always` style will always add the frozen string literal comment
21
26
  # # to a file, regardless of the Ruby version or if `freeze` or `<<` are
@@ -8,6 +8,10 @@ module RuboCop
8
8
  # reassign (possibly to redirect some stream) constants in Ruby, you'll get
9
9
  # an interpreter warning if you do so.
10
10
  #
11
+ # @safety
12
+ # Autocorrection is unsafe because `STDOUT` and `$stdout` may point to different
13
+ # objects, for example.
14
+ #
11
15
  # @example
12
16
  # # bad
13
17
  # STDOUT.puts('hello')
@@ -9,6 +9,11 @@ module RuboCop
9
9
  # parentheses around the block arguments to indicate that you're not
10
10
  # working with a hash, and suppress RuboCop offenses.
11
11
  #
12
+ # @safety
13
+ # This cop is unsafe because it cannot be guaranteed that the receiver
14
+ # is a `Hash`. The `AllowedReceivers` configuration can mitigate,
15
+ # but not fully resolve, this safety issue.
16
+ #
12
17
  # @example
13
18
  # # bad
14
19
  # hash.keys.each { |k| p k }
@@ -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