rubocop 1.63.0 → 1.64.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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -2
  3. data/config/default.yml +18 -3
  4. data/lib/rubocop/cached_data.rb +11 -3
  5. data/lib/rubocop/cli/command/show_docs_url.rb +2 -2
  6. data/lib/rubocop/cli.rb +4 -0
  7. data/lib/rubocop/config.rb +2 -3
  8. data/lib/rubocop/cop/base.rb +9 -14
  9. data/lib/rubocop/cop/bundler/gem_version.rb +3 -5
  10. data/lib/rubocop/cop/documentation.rb +16 -6
  11. data/lib/rubocop/cop/force.rb +12 -0
  12. data/lib/rubocop/cop/gemspec/dependency_version.rb +3 -5
  13. data/lib/rubocop/cop/internal_affairs/example_description.rb +1 -1
  14. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  15. data/lib/rubocop/cop/layout/empty_comment.rb +3 -1
  16. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -0
  17. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +3 -4
  18. data/lib/rubocop/cop/lint/assignment_in_condition.rb +3 -1
  19. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  20. data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
  21. data/lib/rubocop/cop/lint/erb_new_arguments.rb +21 -14
  22. data/lib/rubocop/cop/lint/mixed_case_range.rb +9 -4
  23. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
  24. data/lib/rubocop/cop/lint/unreachable_code.rb +4 -2
  25. data/lib/rubocop/cop/lint/unreachable_loop.rb +8 -2
  26. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +5 -5
  27. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +9 -2
  28. data/lib/rubocop/cop/security/compound_hash.rb +2 -2
  29. data/lib/rubocop/cop/style/access_modifier_declarations.rb +50 -0
  30. data/lib/rubocop/cop/style/arguments_forwarding.rb +5 -2
  31. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
  32. data/lib/rubocop/cop/style/copyright.rb +15 -10
  33. data/lib/rubocop/cop/style/documentation.rb +24 -24
  34. data/lib/rubocop/cop/style/documentation_method.rb +20 -0
  35. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  36. data/lib/rubocop/cop/style/hash_syntax.rb +18 -0
  37. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -3
  38. data/lib/rubocop/cop/style/map_into_array.rb +3 -3
  39. data/lib/rubocop/cop/style/numeric_predicate.rb +10 -2
  40. data/lib/rubocop/cop/style/one_line_conditional.rb +1 -1
  41. data/lib/rubocop/cop/style/redundant_line_continuation.rb +4 -1
  42. data/lib/rubocop/cop/style/require_order.rb +1 -1
  43. data/lib/rubocop/cop/style/send.rb +4 -4
  44. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +90 -0
  45. data/lib/rubocop/cop/style/special_global_vars.rb +1 -2
  46. data/lib/rubocop/cop/style/super_arguments.rb +156 -0
  47. data/lib/rubocop/cop/style/symbol_proc.rb +32 -5
  48. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  49. data/lib/rubocop/cop/team.rb +2 -0
  50. data/lib/rubocop/formatter/disabled_config_formatter.rb +13 -9
  51. data/lib/rubocop/formatter/formatter_set.rb +7 -1
  52. data/lib/rubocop/lockfile.rb +25 -6
  53. data/lib/rubocop/lsp/routes.rb +10 -13
  54. data/lib/rubocop/lsp/server.rb +2 -0
  55. data/lib/rubocop/lsp.rb +9 -2
  56. data/lib/rubocop/options.rb +3 -3
  57. data/lib/rubocop/rake_task.rb +1 -1
  58. data/lib/rubocop/runner.rb +5 -4
  59. data/lib/rubocop/version.rb +4 -4
  60. data/lib/rubocop.rb +2 -0
  61. metadata +10 -8
@@ -8,6 +8,17 @@ module RuboCop
8
8
  # EnforcedStyle config covers only method definitions.
9
9
  # Applications of visibility methods to symbols can be controlled
10
10
  # using AllowModifiersOnSymbols config.
11
+ # Also, the visibility of `attr*` methods can be controlled using
12
+ # AllowModifiersOnAttrs config.
13
+ #
14
+ # In Ruby 3.0, `attr*` methods now return an array of defined method names
15
+ # as symbols. So we can write the modifier and `attr*` in inline style.
16
+ # AllowModifiersOnAttrs config allows `attr*` methods to be written in
17
+ # inline style without modifying applications that have been maintained
18
+ # for a long time in group style. Furthermore, developers who are not very
19
+ # familiar with Ruby may know that the modifier applies to `def`, but they
20
+ # may not know that it also applies to `attr*` methods. It would be easier
21
+ # to understand if we could write `attr*` methods in inline style.
11
22
  #
12
23
  # @safety
13
24
  # Autocorrection is not safe, because the visibility of dynamically
@@ -67,6 +78,34 @@ module RuboCop
67
78
  # private :bar, :baz
68
79
  #
69
80
  # end
81
+ #
82
+ # @example AllowModifiersOnAttrs: true (default)
83
+ # # good
84
+ # class Foo
85
+ #
86
+ # public attr_reader :bar
87
+ # protected attr_writer :baz
88
+ # private attr_accessor :qux
89
+ # private attr :quux
90
+ #
91
+ # def public_method; end
92
+ #
93
+ # private
94
+ #
95
+ # def private_method; end
96
+ #
97
+ # end
98
+ #
99
+ # @example AllowModifiersOnAttrs: false
100
+ # # bad
101
+ # class Foo
102
+ #
103
+ # public attr_reader :bar
104
+ # protected attr_writer :baz
105
+ # private attr_accessor :qux
106
+ # private attr :quux
107
+ #
108
+ # end
70
109
  class AccessModifierDeclarations < Base
71
110
  extend AutoCorrector
72
111
 
@@ -92,10 +131,17 @@ module RuboCop
92
131
  (send nil? {:private :protected :public :module_function} (sym _))
93
132
  PATTERN
94
133
 
134
+ # @!method access_modifier_with_attr?(node)
135
+ def_node_matcher :access_modifier_with_attr?, <<~PATTERN
136
+ (send nil? {:private :protected :public :module_function}
137
+ (send nil? {:attr :attr_reader :attr_writer :attr_accessor} _))
138
+ PATTERN
139
+
95
140
  def on_send(node)
96
141
  return unless node.access_modifier?
97
142
  return if ALLOWED_NODE_TYPES.include?(node.parent&.type)
98
143
  return if allow_modifiers_on_symbols?(node)
144
+ return if allow_modifiers_on_attrs?(node)
99
145
 
100
146
  if offense?(node)
101
147
  add_offense(node.loc.selector) do |corrector|
@@ -128,6 +174,10 @@ module RuboCop
128
174
  cop_config['AllowModifiersOnSymbols'] && access_modifier_with_symbol?(node)
129
175
  end
130
176
 
177
+ def allow_modifiers_on_attrs?(node)
178
+ cop_config['AllowModifiersOnAttrs'] && access_modifier_with_attr?(node)
179
+ end
180
+
131
181
  def offense?(node)
132
182
  (group_style? && access_modifier_is_inlined?(node) &&
133
183
  !right_siblings_same_inline_method?(node)) ||
@@ -29,6 +29,8 @@ module RuboCop
29
29
  #
30
30
  # Names not on this list are likely to be meaningful and are allowed by default.
31
31
  #
32
+ # This cop handles not only method forwarding but also forwarding to `super`.
33
+ #
32
34
  # @example
33
35
  # # bad
34
36
  # def foo(*args, &block)
@@ -146,7 +148,7 @@ module RuboCop
146
148
 
147
149
  restarg, kwrestarg, blockarg = extract_forwardable_args(node.arguments)
148
150
  forwardable_args = redundant_forwardable_named_args(restarg, kwrestarg, blockarg)
149
- send_nodes = node.each_descendant(:send).to_a
151
+ send_nodes = node.each_descendant(:send, :csend, :super).to_a
150
152
 
151
153
  send_classifications = classify_send_nodes(
152
154
  node, send_nodes, non_splat_or_block_pass_lvar_references(node.body), forwardable_args
@@ -312,7 +314,8 @@ module RuboCop
312
314
  end
313
315
 
314
316
  def register_forward_block_arg_offense(add_parens, def_arguments_or_send, block_arg)
315
- return if target_ruby_version <= 3.0 || block_arg.source == '&' || explicit_block_name?
317
+ return if target_ruby_version <= 3.0 ||
318
+ block_arg.nil? || block_arg.source == '&' || explicit_block_name?
316
319
 
317
320
  add_offense(block_arg, message: BLOCK_MSG) do |corrector|
318
321
  add_parens_if_missing(def_arguments_or_send, corrector) if add_parens
@@ -214,7 +214,7 @@ module RuboCop
214
214
  extend AutoCorrector
215
215
 
216
216
  MSG = 'Use the return of the conditional for variable assignment and comparison.'
217
- ASSIGN_TO_CONDITION_MSG = 'Assign variables inside of conditionals'
217
+ ASSIGN_TO_CONDITION_MSG = 'Assign variables inside of conditionals.'
218
218
  VARIABLE_ASSIGNMENT_TYPES = %i[casgn cvasgn gvasgn ivasgn lvasgn].freeze
219
219
  ASSIGNMENT_TYPES = VARIABLE_ASSIGNMENT_TYPES + %i[and_asgn or_asgn op_asgn masgn].freeze
220
220
  LINE_LENGTH = 'Layout/LineLength'
@@ -58,12 +58,15 @@ module RuboCop
58
58
  end
59
59
 
60
60
  def verify_autocorrect_notice!
61
- raise Warning, AUTOCORRECT_EMPTY_WARNING if autocorrect_notice.empty?
61
+ if autocorrect_notice.nil? || autocorrect_notice.empty?
62
+ raise Warning, "#{cop_name}: #{AUTOCORRECT_EMPTY_WARNING}"
63
+ end
62
64
 
63
65
  regex = Regexp.new(notice)
64
- return if autocorrect_notice&.match?(regex)
66
+ return if autocorrect_notice.gsub(/^# */, '').match?(regex)
65
67
 
66
- raise Warning, "AutocorrectNotice '#{autocorrect_notice}' must match Notice /#{notice}/"
68
+ message = "AutocorrectNotice '#{autocorrect_notice}' must match Notice /#{notice}/"
69
+ raise Warning, "#{cop_name}: #{message}"
67
70
  end
68
71
 
69
72
  def insert_notice_before(processed_source)
@@ -77,26 +80,28 @@ module RuboCop
77
80
  return false if token_index >= processed_source.tokens.size
78
81
 
79
82
  token = processed_source.tokens[token_index]
80
- token.comment? && /^#!.*$/.match?(token.text)
83
+ token.comment? && /\A#!.*\z/.match?(token.text)
81
84
  end
82
85
 
83
86
  def encoding_token?(processed_source, token_index)
84
87
  return false if token_index >= processed_source.tokens.size
85
88
 
86
89
  token = processed_source.tokens[token_index]
87
- token.comment? && /^#.*coding\s?[:=]\s?(?:UTF|utf)-8/.match?(token.text)
90
+ token.comment? && /\A#.*coding\s?[:=]\s?(?:UTF|utf)-8/.match?(token.text)
88
91
  end
89
92
 
90
93
  def notice_found?(processed_source)
91
- notice_found = false
92
- notice_regexp = Regexp.new(notice)
94
+ notice_regexp = Regexp.new(notice.lines.map(&:strip).join)
95
+ multiline_notice = +''
93
96
  processed_source.tokens.each do |token|
94
97
  break unless token.comment?
95
98
 
96
- notice_found = notice_regexp.match?(token.text)
97
- break if notice_found
99
+ multiline_notice << token.text.sub(/\A# */, '')
100
+
101
+ break if notice_regexp.match?(token.text)
98
102
  end
99
- notice_found
103
+
104
+ multiline_notice.match?(notice_regexp)
100
105
  end
101
106
  end
102
107
  end
@@ -29,36 +29,36 @@ module RuboCop
29
29
  # end
30
30
  #
31
31
  # # allowed
32
- # # Class without body
32
+ # # Class without body
33
+ # class Person
34
+ # end
35
+ #
36
+ # # Namespace - A namespace can be a class or a module
37
+ # # Containing a class
38
+ # module Namespace
39
+ # # Description/Explanation of Person class
33
40
  # class Person
41
+ # # ...
34
42
  # end
43
+ # end
35
44
  #
36
- # # Namespace - A namespace can be a class or a module
37
- # # Containing a class
38
- # module Namespace
39
- # # Description/Explanation of Person class
40
- # class Person
41
- # # ...
42
- # end
45
+ # # Containing constant visibility declaration
46
+ # module Namespace
47
+ # class Private
43
48
  # end
44
49
  #
45
- # # Containing constant visibility declaration
46
- # module Namespace
47
- # class Private
48
- # end
49
- #
50
- # private_constant :Private
51
- # end
50
+ # private_constant :Private
51
+ # end
52
52
  #
53
- # # Containing constant definition
54
- # module Namespace
55
- # Public = Class.new
56
- # end
53
+ # # Containing constant definition
54
+ # module Namespace
55
+ # Public = Class.new
56
+ # end
57
57
  #
58
- # # Macro calls
59
- # module Namespace
60
- # extend Foo
61
- # end
58
+ # # Macro calls
59
+ # module Namespace
60
+ # extend Foo
61
+ # end
62
62
  #
63
63
  # @example AllowedConstants: ['ClassMethods']
64
64
  #
@@ -67,7 +67,7 @@ module RuboCop
67
67
  # module ClassMethods
68
68
  # # ...
69
69
  # end
70
- # end
70
+ # end
71
71
  #
72
72
  class Documentation < Base
73
73
  include DocumentationComment
@@ -95,6 +95,17 @@ module RuboCop
95
95
  # end
96
96
  # end
97
97
  #
98
+ # @example AllowedMethods: ['method_missing', 'respond_to_missing?']
99
+ #
100
+ # # good
101
+ # class Foo
102
+ # def method_missing(name, *args)
103
+ # end
104
+ #
105
+ # def respond_to_missing?(symbol, include_private)
106
+ # end
107
+ # end
108
+ #
98
109
  class DocumentationMethod < Base
99
110
  include DocumentationComment
100
111
  include DefNode
@@ -119,6 +130,7 @@ module RuboCop
119
130
  def check(node)
120
131
  return if non_public?(node) && !require_for_non_public_methods?
121
132
  return if documentation_comment?(node)
133
+ return if method_allowed?(node)
122
134
 
123
135
  add_offense(node)
124
136
  end
@@ -126,6 +138,14 @@ module RuboCop
126
138
  def require_for_non_public_methods?
127
139
  cop_config['RequireForNonPublicMethods']
128
140
  end
141
+
142
+ def method_allowed?(node)
143
+ allowed_methods.include?(node.method_name)
144
+ end
145
+
146
+ def allowed_methods
147
+ @allowed_methods ||= cop_config.fetch('AllowedMethods', []).map(&:to_sym)
148
+ end
129
149
  end
130
150
  end
131
151
  end
@@ -141,7 +141,7 @@ module RuboCop
141
141
  end
142
142
 
143
143
  def check_file(node, file_node)
144
- return true if special_file_keyword?(file_node)
144
+ return if special_file_keyword?(file_node)
145
145
 
146
146
  message = format(MSG_INCORRECT_FILE,
147
147
  method_name: node.method_name,
@@ -29,6 +29,8 @@ module RuboCop
29
29
  # * never - forces use of explicit hash literal value
30
30
  # * either - accepts both shorthand and explicit use of hash literal value
31
31
  # * consistent - forces use of the 3.1 syntax only if all values can be omitted in the hash
32
+ # * either_consistent - accepts both shorthand and explicit use of hash literal value,
33
+ # but they must be consistent
32
34
  #
33
35
  # @example EnforcedStyle: ruby19 (default)
34
36
  # # bad
@@ -110,6 +112,22 @@ module RuboCop
110
112
  # # good - can't omit `baz`
111
113
  # {foo: foo, bar: baz}
112
114
  #
115
+ # @example EnforcedShorthandSyntax: either_consistent
116
+ #
117
+ # # good - `foo` and `bar` values can be omitted, but they are consistent, so it's accepted
118
+ # {foo: foo, bar: bar}
119
+ #
120
+ # # bad - `bar` value can be omitted
121
+ # {foo:, bar: bar}
122
+ #
123
+ # # bad - mixed syntaxes
124
+ # {foo:, bar: baz}
125
+ #
126
+ # # good
127
+ # {foo:, bar:}
128
+ #
129
+ # # good - can't omit `baz`
130
+ # {foo: foo, bar: baz}
113
131
  class HashSyntax < Base
114
132
  include ConfigurableEnforcedStyle
115
133
  include HashShorthandSyntax
@@ -112,9 +112,11 @@ module RuboCop
112
112
  end
113
113
 
114
114
  def message(node, keyword)
115
- message_template = node.elsif? ? MSG_FOR_ELSIF : MSG
116
-
117
- format(message_template, keyword: keyword)
115
+ if node.elsif?
116
+ MSG_FOR_ELSIF
117
+ else
118
+ format(MSG, keyword: keyword)
119
+ end
118
120
  end
119
121
 
120
122
  def return_boolean_value?(condition)
@@ -20,8 +20,8 @@ module RuboCop
20
20
  #
21
21
  # [source,ruby]
22
22
  # ----
23
- # @dest = []
24
- # src.each { |e| @dest << e * 2 } # `src` method may mutate `@dest`
23
+ # ret = []
24
+ # src.each { |e| ret << e * 2 } # `<<` method may mutate `ret`
25
25
  #
26
26
  # dest = []
27
27
  # src.each { |e| dest << transform(e, dest) } # `transform` method may mutate `dest`
@@ -57,7 +57,7 @@ module RuboCop
57
57
  def_node_matcher :each_block_with_push?, <<-PATTERN
58
58
  [
59
59
  ^({begin kwbegin} ...)
60
- ({block numblock} (send _ :each) _
60
+ ({block numblock} (send !{nil? self} :each) _
61
61
  (send (lvar _) {:<< :push :append} _))
62
62
  ]
63
63
  PATTERN
@@ -118,12 +118,14 @@ module RuboCop
118
118
 
119
119
  return unless numeric && operator && replacement_supported?(operator)
120
120
 
121
- [numeric, replacement(numeric, operator)]
121
+ [numeric, replacement(node, numeric, operator)]
122
122
  end
123
123
 
124
- def replacement(numeric, operation)
124
+ def replacement(node, numeric, operation)
125
125
  if style == :predicate
126
126
  [parenthesized_source(numeric), REPLACEMENTS.invert[operation.to_s]].join('.')
127
+ elsif negated?(node)
128
+ "(#{numeric.source} #{REPLACEMENTS[operation.to_s]} 0)"
127
129
  else
128
130
  [numeric.source, REPLACEMENTS[operation.to_s], 0].join(' ')
129
131
  end
@@ -157,6 +159,12 @@ module RuboCop
157
159
  end
158
160
  end
159
161
 
162
+ def negated?(node)
163
+ return false unless (parent = node.parent)
164
+
165
+ parent.send_type? && parent.method?(:!)
166
+ end
167
+
160
168
  # @!method predicate(node)
161
169
  def_node_matcher :predicate, <<~PATTERN
162
170
  (send $(...) ${:zero? :positive? :negative?})
@@ -75,7 +75,7 @@ module RuboCop
75
75
  end
76
76
 
77
77
  def always_multiline?
78
- @config.for_cop('Style/OneLineConditional')['AlwaysCorrectToMultiline']
78
+ cop_config['AlwaysCorrectToMultiline']
79
79
  end
80
80
 
81
81
  def cannot_replace_to_ternary?(node)
@@ -74,6 +74,7 @@ module RuboCop
74
74
  kFALSE kNIL kSELF kTRUE tCONSTANT tCVAR tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR
75
75
  tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
76
76
  ].freeze
77
+ ARGUMENT_TAKING_FLOW_TOKEN_TYPES = %i[tIDENTIFIER kRETURN kBREAK kNEXT kYIELD].freeze
77
78
 
78
79
  def on_new_investigation
79
80
  return unless processed_source.ast
@@ -137,7 +138,9 @@ module RuboCop
137
138
  # do_something \
138
139
  # argument
139
140
  def method_with_argument?(current_token, next_token)
140
- current_token.type == :tIDENTIFIER && ARGUMENT_TYPES.include?(next_token.type)
141
+ return false unless ARGUMENT_TAKING_FLOW_TOKEN_TYPES.include?(current_token.type)
142
+
143
+ ARGUMENT_TYPES.include?(next_token.type)
141
144
  end
142
145
 
143
146
  # rubocop:disable Metrics/AbcSize
@@ -131,7 +131,7 @@ module RuboCop
131
131
  end
132
132
 
133
133
  def in_same_section?(node1, node2)
134
- !node1.source_range.with(end_pos: node2.source_range.end_pos).source.include?("\n\n")
134
+ !node1.source_range.join(node2.source_range.end).source.include?("\n\n")
135
135
  end
136
136
  end
137
137
  end
@@ -7,12 +7,12 @@ module RuboCop
7
7
  #
8
8
  # @example
9
9
  # # bad
10
- # Foo.send(:bar)
11
- # quuz.send(:fred)
10
+ # Foo.send(bar)
11
+ # quuz.send(fred)
12
12
  #
13
13
  # # good
14
- # Foo.__send__(:bar)
15
- # quuz.public_send(:fred)
14
+ # Foo.__send__(bar)
15
+ # quuz.public_send(fred)
16
16
  class Send < Base
17
17
  MSG = 'Prefer `Object#__send__` or `Object#public_send` to `send`.'
18
18
  RESTRICT_ON_SEND = %i[send].freeze
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Detects the use of the `public_send` method with a literal method name argument.
7
+ # Since the `send` method can be used to call private methods, by default,
8
+ # only the `public_send` method is detected.
9
+ #
10
+ # @safety
11
+ # This cop is not safe because it can incorrectly detect based on the receiver.
12
+ # Additionally, when `AllowSend` is set to `true`, it cannot determine whether
13
+ # the `send` method being detected is calling a private method.
14
+ #
15
+ # @example
16
+ # # bad
17
+ # obj.public_send(:method_name)
18
+ # obj.public_send('method_name')
19
+ #
20
+ # # good
21
+ # obj.method_name
22
+ #
23
+ # @example AllowSend: true (default)
24
+ # # good
25
+ # obj.send(:method_name)
26
+ # obj.send('method_name')
27
+ # obj.__send__(:method_name)
28
+ # obj.__send__('method_name')
29
+ #
30
+ # @example AllowSend: false
31
+ # # bad
32
+ # obj.send(:method_name)
33
+ # obj.send('method_name')
34
+ # obj.__send__(:method_name)
35
+ # obj.__send__('method_name')
36
+ #
37
+ # # good
38
+ # obj.method_name
39
+ #
40
+ class SendWithLiteralMethodName < Base
41
+ extend AutoCorrector
42
+
43
+ MSG = 'Use `%<method_name>s` method call directly instead.'
44
+ RESTRICT_ON_SEND = %i[public_send send __send__].freeze
45
+ STATIC_METHOD_NAME_NODE_TYPES = %i[sym str].freeze
46
+ METHOD_NAME_PATTERN = /\A[a-zA-Z_][a-zA-Z0-9_]*[!?=]?\z/.freeze
47
+ RESERVED_WORDS = %i[
48
+ BEGIN END alias and begin break case class def defined? do else elsif end ensure
49
+ false for if in module next nil not or redo rescue retry return self super then true
50
+ undef unless until when while yield
51
+ ].freeze
52
+
53
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
54
+ def on_send(node)
55
+ return if allow_send? && !node.method?(:public_send)
56
+ return unless (first_argument = node.first_argument)
57
+ return unless STATIC_METHOD_NAME_NODE_TYPES.include?(first_argument.type)
58
+
59
+ offense_range = offense_range(node)
60
+ method_name = first_argument.value
61
+ return if !METHOD_NAME_PATTERN.match?(method_name) || RESERVED_WORDS.include?(method_name)
62
+
63
+ add_offense(offense_range, message: format(MSG, method_name: method_name)) do |corrector|
64
+ if node.arguments.one?
65
+ corrector.replace(offense_range, method_name)
66
+ else
67
+ corrector.replace(node.loc.selector, method_name)
68
+ corrector.remove(removal_argument_range(first_argument, node.arguments[1]))
69
+ end
70
+ end
71
+ end
72
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
73
+
74
+ private
75
+
76
+ def allow_send?
77
+ !!cop_config['AllowSend']
78
+ end
79
+
80
+ def offense_range(node)
81
+ node.loc.selector.join(node.source_range.end)
82
+ end
83
+
84
+ def removal_argument_range(first_argument, second_argument)
85
+ first_argument.source_range.begin.join(second_argument.source_range.begin)
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -58,9 +58,8 @@ module RuboCop
58
58
  #
59
59
  # @example EnforcedStyle: use_builtin_english_names
60
60
  #
61
- # Like `use_perl_names` but allows builtin global vars.
62
- #
63
61
  # # good
62
+ # # Like `use_perl_names` but allows builtin global vars.
64
63
  # puts $LOAD_PATH
65
64
  # puts $LOADED_FEATURES
66
65
  # puts $PROGRAM_NAME