rubocop 1.28.2 → 1.29.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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/config/default.yml +36 -21
  4. data/lib/rubocop/cop/badge.rb +1 -1
  5. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  6. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  7. data/lib/rubocop/cop/gemspec/dependency_version.rb +156 -0
  8. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +3 -6
  9. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +1 -1
  10. data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +80 -0
  11. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  12. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  13. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +1 -1
  14. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  15. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -1
  16. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +1 -1
  17. data/lib/rubocop/cop/lint/ambiguous_range.rb +2 -2
  18. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
  19. data/lib/rubocop/cop/lint/loop.rb +1 -1
  20. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +5 -5
  21. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  22. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  23. data/lib/rubocop/cop/lint/raise_exception.rb +1 -1
  24. data/lib/rubocop/cop/lint/return_in_void_context.rb +5 -17
  25. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  26. data/lib/rubocop/cop/mixin/duplication.rb +1 -1
  27. data/lib/rubocop/cop/mixin/preferred_delimiters.rb +2 -2
  28. data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
  29. data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
  30. data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
  31. data/lib/rubocop/cop/naming/file_name.rb +1 -1
  32. data/lib/rubocop/cop/naming/inclusive_language.rb +3 -2
  33. data/lib/rubocop/cop/naming/predicate_name.rb +2 -2
  34. data/lib/rubocop/cop/naming/variable_name.rb +9 -0
  35. data/lib/rubocop/cop/naming/variable_number.rb +10 -0
  36. data/lib/rubocop/cop/security/yaml_load.rb +1 -1
  37. data/lib/rubocop/cop/style/alias.rb +3 -3
  38. data/lib/rubocop/cop/style/and_or.rb +1 -1
  39. data/lib/rubocop/cop/style/bisected_attr_accessor/macro.rb +1 -1
  40. data/lib/rubocop/cop/style/case_like_if.rb +1 -1
  41. data/lib/rubocop/cop/style/character_literal.rb +1 -1
  42. data/lib/rubocop/cop/style/collection_compact.rb +3 -3
  43. data/lib/rubocop/cop/style/date_time.rb +1 -1
  44. data/lib/rubocop/cop/style/double_negation.rb +28 -2
  45. data/lib/rubocop/cop/style/empty_case_condition.rb +1 -1
  46. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  47. data/lib/rubocop/cop/style/env_home.rb +56 -0
  48. data/lib/rubocop/cop/style/fetch_env_var.rb +240 -11
  49. data/lib/rubocop/cop/style/identical_conditional_branches.rb +2 -2
  50. data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
  51. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +5 -1
  52. data/lib/rubocop/cop/style/next.rb +1 -1
  53. data/lib/rubocop/cop/style/optional_arguments.rb +1 -1
  54. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +1 -1
  55. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  56. data/lib/rubocop/cop/style/raise_args.rb +4 -1
  57. data/lib/rubocop/cop/style/redundant_condition.rb +108 -11
  58. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  59. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  60. data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -2
  61. data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
  62. data/lib/rubocop/cop/style/string_chars.rb +1 -1
  63. data/lib/rubocop/cop/style/trivial_accessors.rb +7 -8
  64. data/lib/rubocop/cops_documentation_generator.rb +1 -1
  65. data/lib/rubocop/formatter/formatter_set.rb +1 -0
  66. data/lib/rubocop/formatter/html_formatter.rb +2 -9
  67. data/lib/rubocop/formatter/markdown_formatter.rb +76 -0
  68. data/lib/rubocop/magic_comment.rb +4 -3
  69. data/lib/rubocop/options.rb +4 -3
  70. data/lib/rubocop/result_cache.rb +1 -1
  71. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  72. data/lib/rubocop/rspec/parallel_formatter.rb +1 -1
  73. data/lib/rubocop/rspec/shared_contexts.rb +1 -1
  74. data/lib/rubocop/runner.rb +1 -1
  75. data/lib/rubocop/string_interpreter.rb +4 -4
  76. data/lib/rubocop/target_ruby.rb +7 -1
  77. data/lib/rubocop/version.rb +1 -1
  78. data/lib/rubocop.rb +3 -1
  79. metadata +16 -7
  80. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +0 -45
@@ -11,7 +11,7 @@ module RuboCop
11
11
  #
12
12
  # @safety
13
13
  # This cop is unsafe because code that is already conditionally
14
- # assigning a constant may have its behaviour changed by
14
+ # assigning a constant may have its behavior changed by
15
15
  # auto-correction.
16
16
  #
17
17
  # @example
@@ -69,7 +69,7 @@ module RuboCop
69
69
  else
70
70
  0
71
71
  end
72
- without_receiver = node.source[receiver_length..-1]
72
+ without_receiver = node.source[receiver_length..]
73
73
 
74
74
  # Escape question mark if any.
75
75
  method_regexp = Regexp.escape(node.method_name)
@@ -15,7 +15,7 @@ module RuboCop
15
15
  #
16
16
  # @safety
17
17
  # This cop is unsafe because it will change the exception class being
18
- # raised, which is a change in behaviour.
18
+ # raised, which is a change in behavior.
19
19
  #
20
20
  # @example
21
21
  # # bad
@@ -40,12 +40,12 @@ module RuboCop
40
40
  context_node = non_void_context(return_node)
41
41
 
42
42
  return unless context_node&.def_type?
43
+ return unless context_node&.void_context?
43
44
 
44
- method_name = method_name(context_node)
45
-
46
- return unless method_name && void_context_method?(method_name)
47
-
48
- add_offense(return_node.loc.keyword, message: format(message, method: method_name))
45
+ add_offense(
46
+ return_node.loc.keyword,
47
+ message: format(message, method: context_node.method_name)
48
+ )
49
49
  end
50
50
 
51
51
  private
@@ -53,18 +53,6 @@ module RuboCop
53
53
  def non_void_context(return_node)
54
54
  return_node.each_ancestor(:block, :def, :defs).first
55
55
  end
56
-
57
- def method_name(context_node)
58
- context_node.children.first
59
- end
60
-
61
- def void_context_method?(method_name)
62
- method_name == :initialize || setter_method?(method_name)
63
- end
64
-
65
- def setter_method?(method_name)
66
- method_name.to_s.end_with?('=') && !AST::Node::COMPARISON_OPERATORS.include?(method_name)
67
- end
68
56
  end
69
57
  end
70
58
  end
@@ -95,7 +95,7 @@ module RuboCop
95
95
  # Cleanup indentation in a multiline block
96
96
  source_lines = source.split("\n")
97
97
 
98
- source_lines[1..-1].each do |line|
98
+ source_lines[1..].each do |line|
99
99
  next if line.empty?
100
100
 
101
101
  line[range] = ''
@@ -29,7 +29,7 @@ module RuboCop
29
29
  # @param [Array] collection an array to return consecutive duplicates for
30
30
  # @return [Array] the consecutive duplicates
31
31
  def consecutive_duplicates(collection)
32
- grouped_duplicates(collection).flat_map { |items| items[1..-1] }
32
+ grouped_duplicates(collection).flat_map { |items| items[1..] }
33
33
  end
34
34
 
35
35
  # Returns a hash of grouped duplicates. The key will be the first
@@ -33,9 +33,9 @@ module RuboCop
33
33
  ensure_valid_preferred_delimiters
34
34
 
35
35
  if preferred_delimiters_config.key?('default')
36
- PERCENT_LITERAL_TYPES.map do |type|
36
+ PERCENT_LITERAL_TYPES.to_h do |type|
37
37
  [type, preferred_delimiters_config[type] || preferred_delimiters_config['default']]
38
- end.to_h
38
+ end
39
39
  else
40
40
  preferred_delimiters_config
41
41
  end
@@ -63,7 +63,7 @@ module RuboCop
63
63
 
64
64
  def code_after(node)
65
65
  end_element = node.loc.end
66
- code = end_element.source_line[end_element.last_column..-1]
66
+ code = end_element.source_line[end_element.last_column..]
67
67
  code unless code.empty?
68
68
  end
69
69
 
@@ -159,7 +159,7 @@ module RuboCop
159
159
  def autocorrect_range(item)
160
160
  expr = item.source_range
161
161
  ix = expr.source.rindex("\n") || 0
162
- ix += expr.source[ix..-1] =~ /\S/
162
+ ix += expr.source[ix..] =~ /\S/
163
163
 
164
164
  range_between(expr.begin_pos + ix, expr.end_pos)
165
165
  end
@@ -70,7 +70,7 @@ module RuboCop
70
70
  if style == :anonymous
71
71
  !explicit_block_argument?(last_argument) ||
72
72
  use_kwarg_in_method_definition?(node) ||
73
- use_block_argument_as_local_variable?(node, last_argument.source[1..-1])
73
+ use_block_argument_as_local_variable?(node, last_argument.source[1..])
74
74
  else
75
75
  !anonymous_block_argument?(last_argument)
76
76
  end
@@ -233,7 +233,7 @@ module RuboCop
233
233
  if start_index.nil?
234
234
  [to_module_name(components.last)]
235
235
  else
236
- components[start_index..-1].map { |c| to_module_name(c) }
236
+ components[start_index..].map { |c| to_module_name(c) }
237
237
  end
238
238
  end
239
239
 
@@ -214,13 +214,14 @@ module RuboCop
214
214
  end
215
215
 
216
216
  def mask_input(str)
217
- return str if @allowed_regex.nil?
218
-
219
217
  safe_str = if str.valid_encoding?
220
218
  str
221
219
  else
222
220
  str.encode('UTF-8', invalid: :replace, undef: :replace)
223
221
  end
222
+
223
+ return safe_str if @allowed_regex.nil?
224
+
224
225
  safe_str.gsub(@allowed_regex) { |match| '*' * match.size }
225
226
  end
226
227
 
@@ -70,7 +70,7 @@ module RuboCop
70
70
  !(method_name.start_with?(prefix) && # cheap check to avoid allocating Regexp
71
71
  method_name.match?(/^#{prefix}[^0-9]/)) ||
72
72
  method_name == expected_name(method_name, prefix) ||
73
- method_name.end_with?('=') ||
73
+ method_name.end_with?('=') || # rubocop:todo InternalAffairs/MethodNameEndWith
74
74
  allowed_method?(method_name)
75
75
  end
76
76
 
@@ -80,7 +80,7 @@ module RuboCop
80
80
  else
81
81
  method_name.dup
82
82
  end
83
- new_name << '?' unless method_name.end_with?('?')
83
+ new_name << '?' unless method_name.end_with?('?') # rubocop:todo InternalAffairs/MethodNameEndWith
84
84
  new_name
85
85
  end
86
86
 
@@ -19,12 +19,21 @@ module RuboCop
19
19
  #
20
20
  # # good
21
21
  # fooBar = 1
22
+ #
23
+ # @example AllowedPatterns: ['_v\d+\z']
24
+ # # good
25
+ # :release_v1
22
26
  class VariableName < Base
23
27
  include AllowedIdentifiers
24
28
  include ConfigurableNaming
29
+ include AllowedPattern
25
30
 
26
31
  MSG = 'Use %<style>s for variable names.'
27
32
 
33
+ def valid_name?(node, name, given_style = style)
34
+ super || matches_allowed_pattern?(name)
35
+ end
36
+
28
37
  def on_lvasgn(node)
29
38
  name, = *node
30
39
  return unless name
@@ -96,12 +96,21 @@ module RuboCop
96
96
  # # good
97
97
  # expect(Open3).to receive(:capture3)
98
98
  #
99
+ # @example AllowedPatterns: ['_v\d+\z']
100
+ # # good
101
+ # :some_sym_v1
102
+ #
99
103
  class VariableNumber < Base
100
104
  include AllowedIdentifiers
101
105
  include ConfigurableNumbering
106
+ include AllowedPattern
102
107
 
103
108
  MSG = 'Use %<style>s for %<identifier_type>s numbers.'
104
109
 
110
+ def valid_name?(node, name, given_style = style)
111
+ super || matches_allowed_pattern?(name)
112
+ end
113
+
105
114
  def on_arg(node)
106
115
  @node = node
107
116
  name, = *node
@@ -112,6 +121,7 @@ module RuboCop
112
121
  alias on_lvasgn on_arg
113
122
  alias on_ivasgn on_arg
114
123
  alias on_cvasgn on_arg
124
+ alias on_gvasgn on_arg
115
125
 
116
126
  def on_def(node)
117
127
  @node = node
@@ -10,7 +10,7 @@ module RuboCop
10
10
  # NOTE: Ruby 3.1+ (Psych 4) uses `Psych.load` as `Psych.safe_load` by default.
11
11
  #
12
12
  # @safety
13
- # The behaviour of the code might change depending on what was
13
+ # The behavior of the code might change depending on what was
14
14
  # in the YAML payload, since `YAML.safe_load` is more restrictive.
15
15
  #
16
16
  # @example
@@ -76,7 +76,7 @@ module RuboCop
76
76
 
77
77
  def add_offense_for_args(node, &block)
78
78
  existing_args = node.children.map(&:source).join(' ')
79
- preferred_args = node.children.map { |a| a.source[1..-1] }.join(' ')
79
+ preferred_args = node.children.map { |a| a.source[1..] }.join(' ')
80
80
  arg_ranges = node.children.map(&:source_range)
81
81
  msg = format(MSG_SYMBOL_ARGS, prefer: preferred_args, current: existing_args)
82
82
  add_offense(arg_ranges.reduce(&:join), message: msg, &block)
@@ -134,8 +134,8 @@ module RuboCop
134
134
  end
135
135
 
136
136
  def correct_alias_with_symbol_args(corrector, node)
137
- corrector.replace(node.new_identifier, node.new_identifier.source[1..-1])
138
- corrector.replace(node.old_identifier, node.old_identifier.source[1..-1])
137
+ corrector.replace(node.new_identifier, node.new_identifier.source[1..])
138
+ corrector.replace(node.old_identifier, node.old_identifier.source[1..])
139
139
  end
140
140
 
141
141
  # @!method identifier(node)
@@ -10,7 +10,7 @@ module RuboCop
10
10
  # @safety
11
11
  # Auto-correction is unsafe because there is a different operator precedence
12
12
  # between logical operators (`&&` and `||`) and semantic operators (`and` and `or`),
13
- # and that might change the behaviour.
13
+ # and that might change the behavior.
14
14
  #
15
15
  # @example EnforcedStyle: always
16
16
  # # bad
@@ -18,7 +18,7 @@ module RuboCop
18
18
 
19
19
  def initialize(node)
20
20
  @node = node
21
- @attrs = node.arguments.map { |attr| [attr.source, attr] }.to_h
21
+ @attrs = node.arguments.to_h { |attr| [attr.source, attr] }
22
22
  @bisection = []
23
23
  end
24
24
 
@@ -9,7 +9,7 @@ module RuboCop
9
9
  # @safety
10
10
  # This cop is unsafe. `case` statements use `===` for equality,
11
11
  # so if the original conditional used a different equality operator, the
12
- # behaviour may be different.
12
+ # behavior may be different.
13
13
  #
14
14
  # @example
15
15
  # # bad
@@ -33,7 +33,7 @@ module RuboCop
33
33
  end
34
34
 
35
35
  def autocorrect(corrector, node)
36
- string = node.source[1..-1]
36
+ string = node.source[1..]
37
37
 
38
38
  # special character like \n
39
39
  # or ' which needs to use "" or be escaped.
@@ -70,7 +70,7 @@ module RuboCop
70
70
  def on_send(node)
71
71
  return unless (range = offense_range(node))
72
72
 
73
- good = good_method_name(node.method_name)
73
+ good = good_method_name(node)
74
74
  message = format(MSG, good: good, bad: range.source)
75
75
 
76
76
  add_offense(range, message: message) { |corrector| corrector.replace(range, good) }
@@ -94,8 +94,8 @@ module RuboCop
94
94
  end
95
95
  end
96
96
 
97
- def good_method_name(method_name)
98
- if method_name.to_s.end_with?('!')
97
+ def good_method_name(node)
98
+ if node.bang_method?
99
99
  'compact!'
100
100
  else
101
101
  'compact'
@@ -11,7 +11,7 @@ module RuboCop
11
11
  #
12
12
  # @safety
13
13
  # Autocorrection is not safe, because `DateTime` and `Time` do not have
14
- # exactly the same behaviour, although in most cases the autocorrection
14
+ # exactly the same behavior, although in most cases the autocorrection
15
15
  # will be fine.
16
16
  #
17
17
  # @example
@@ -37,11 +37,27 @@ module RuboCop
37
37
  # !!return_value
38
38
  # end
39
39
  #
40
+ # define_method :foo? do
41
+ # !!return_value
42
+ # end
43
+ #
44
+ # define_singleton_method :foo? do
45
+ # !!return_value
46
+ # end
47
+ #
40
48
  # @example EnforcedStyle: forbidden
41
49
  # # bad
42
50
  # def foo?
43
51
  # !!return_value
44
52
  # end
53
+ #
54
+ # define_method :foo? do
55
+ # !!return_value
56
+ # end
57
+ #
58
+ # define_singleton_method :foo? do
59
+ # !!return_value
60
+ # end
45
61
  class DoubleNegation < Base
46
62
  include ConfigurableEnforcedStyle
47
63
  extend AutoCorrector
@@ -73,22 +89,32 @@ module RuboCop
73
89
  return false unless (def_node = find_def_node_from_ascendant(node))
74
90
 
75
91
  conditional_node = find_conditional_node_from_ascendant(node)
76
- last_child = find_last_child(def_node.body)
92
+ last_child = find_last_child(def_node.send_type? ? def_node : def_node.body)
77
93
 
78
94
  if conditional_node
79
95
  double_negative_condition_return_value?(node, last_child, conditional_node)
80
96
  else
81
- last_child.last_line == node.last_line
97
+ last_child.last_line <= node.last_line
82
98
  end
83
99
  end
84
100
 
85
101
  def find_def_node_from_ascendant(node)
86
102
  return unless (parent = node.parent)
87
103
  return parent if parent.def_type? || parent.defs_type?
104
+ return node.parent.child_nodes.first if define_mehod?(parent)
88
105
 
89
106
  find_def_node_from_ascendant(node.parent)
90
107
  end
91
108
 
109
+ def define_mehod?(node)
110
+ return false unless node.block_type?
111
+
112
+ child = node.child_nodes.first
113
+ return false unless child.send_type?
114
+
115
+ child.method?(:define_method) || child.method?(:define_singleton_method)
116
+ end
117
+
92
118
  def find_conditional_node_from_ascendant(node)
93
119
  return unless (parent = node.parent)
94
120
  return parent if parent.conditional?
@@ -69,7 +69,7 @@ module RuboCop
69
69
 
70
70
  keep_first_when_comment(case_range, corrector)
71
71
 
72
- when_nodes[1..-1].each do |when_node|
72
+ when_nodes[1..].each do |when_node|
73
73
  corrector.replace(when_node.loc.keyword, 'elsif')
74
74
  end
75
75
  end
@@ -119,7 +119,7 @@ module RuboCop
119
119
  # because the braces are interpreted as a block. We will have
120
120
  # to rewrite the arguments to wrap them in parenthesis.
121
121
  args = node.parent.arguments
122
- "(#{args[1..-1].map(&:source).unshift('{}').join(', ')})"
122
+ "(#{args[1..].map(&:source).unshift('{}').join(', ')})"
123
123
  else
124
124
  '{}'
125
125
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for consistent usage of `ENV['HOME']`. If `nil` is used as
7
+ # the second argument of `ENV.fetch`, it is treated as a bad case like `ENV[]`.
8
+ #
9
+ # @safety
10
+ # The cop is unsafe because the result when `nil` is assigned to `ENV['HOME']` changes:
11
+ #
12
+ # [source,ruby]
13
+ # ----
14
+ # ENV['HOME'] = nil
15
+ # ENV['HOME'] # => nil
16
+ # Dir.home # => '/home/foo'
17
+ # ----
18
+ #
19
+ # @example
20
+ #
21
+ # # bad
22
+ # ENV['HOME']
23
+ # ENV.fetch('HOME', nil)
24
+ #
25
+ # # good
26
+ # Dir.home
27
+ #
28
+ # # good
29
+ # ENV.fetch('HOME', default)
30
+ #
31
+ class EnvHome < Base
32
+ extend AutoCorrector
33
+
34
+ MSG = 'Use `Dir.home` instead.'
35
+ RESTRICT_ON_SEND = %i[[] fetch].freeze
36
+
37
+ # @!method env_home?(node)
38
+ def_node_matcher :env_home?, <<~PATTERN
39
+ (send
40
+ (const {cbase nil?} :ENV) {:[] :fetch}
41
+ (str "HOME")
42
+ ...)
43
+ PATTERN
44
+
45
+ def on_send(node)
46
+ return unless env_home?(node)
47
+ return if node.arguments.count == 2 && !node.arguments[1].nil_type?
48
+
49
+ add_offense(node) do |corrector|
50
+ corrector.replace(node, 'Dir.home')
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end