rubocop 1.62.1 → 1.63.4

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +22 -3
  4. data/lib/rubocop/cached_data.rb +11 -3
  5. data/lib/rubocop/config.rb +33 -10
  6. data/lib/rubocop/config_obsoletion.rb +1 -1
  7. data/lib/rubocop/cop/base.rb +40 -1
  8. data/lib/rubocop/cop/internal_affairs/example_description.rb +2 -1
  9. data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -2
  10. data/lib/rubocop/cop/lint/debugger.rb +27 -2
  11. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  12. data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
  13. data/lib/rubocop/cop/lint/mixed_case_range.rb +9 -4
  14. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
  15. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  16. data/lib/rubocop/cop/lint/unreachable_code.rb +4 -2
  17. data/lib/rubocop/cop/lint/unreachable_loop.rb +8 -2
  18. data/lib/rubocop/cop/mixin/code_length.rb +12 -1
  19. data/lib/rubocop/cop/mixin/method_complexity.rb +15 -6
  20. data/lib/rubocop/cop/mixin/safe_assignment.rb +1 -1
  21. data/lib/rubocop/cop/naming/block_forwarding.rb +31 -12
  22. data/lib/rubocop/cop/naming/file_name.rb +2 -2
  23. data/lib/rubocop/cop/naming/inclusive_language.rb +1 -2
  24. data/lib/rubocop/cop/style/alias.rb +1 -0
  25. data/lib/rubocop/cop/style/arguments_forwarding.rb +2 -1
  26. data/lib/rubocop/cop/style/collection_compact.rb +3 -3
  27. data/lib/rubocop/cop/style/copyright.rb +16 -11
  28. data/lib/rubocop/cop/style/eval_with_location.rb +3 -1
  29. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -1
  30. data/lib/rubocop/cop/style/format_string.rb +9 -9
  31. data/lib/rubocop/cop/style/map_into_array.rb +175 -0
  32. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  33. data/lib/rubocop/cop/style/map_to_set.rb +1 -1
  34. data/lib/rubocop/cop/style/redundant_argument.rb +24 -1
  35. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +1 -1
  36. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  37. data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
  38. data/lib/rubocop/cop/style/redundant_line_continuation.rb +11 -15
  39. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  40. data/lib/rubocop/cop/style/require_order.rb +1 -1
  41. data/lib/rubocop/cop/style/send.rb +4 -4
  42. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  43. data/lib/rubocop/cop/team.rb +3 -0
  44. data/lib/rubocop/formatter/clang_style_formatter.rb +3 -7
  45. data/lib/rubocop/formatter/tap_formatter.rb +3 -7
  46. data/lib/rubocop/lockfile.rb +56 -7
  47. data/lib/rubocop/lsp/routes.rb +1 -3
  48. data/lib/rubocop/lsp/server.rb +2 -0
  49. data/lib/rubocop/options.rb +3 -3
  50. data/lib/rubocop/rspec/expect_offense.rb +8 -0
  51. data/lib/rubocop/rspec/shared_contexts.rb +13 -1
  52. data/lib/rubocop/runner.rb +5 -1
  53. data/lib/rubocop/version.rb +5 -5
  54. data/lib/rubocop.rb +1 -0
  55. metadata +5 -4
@@ -41,6 +41,7 @@ module RuboCop
41
41
  def on_send(node)
42
42
  return unless node.command?(:alias_method)
43
43
  return unless style == :prefer_alias && alias_keyword_possible?(node)
44
+ return unless node.arguments.count == 2
44
45
 
45
46
  msg = format(MSG_ALIAS_METHOD, current: lexical_scope_type(node))
46
47
  add_offense(node.loc.selector, message: msg) do |corrector|
@@ -312,7 +312,8 @@ module RuboCop
312
312
  end
313
313
 
314
314
  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?
315
+ return if target_ruby_version <= 3.0 ||
316
+ block_arg.nil? || block_arg.source == '&' || explicit_block_name?
316
317
 
317
318
  add_offense(block_arg, message: BLOCK_MSG) do |corrector|
318
319
  add_parens_if_missing(def_arguments_or_send, corrector) if add_parens
@@ -19,9 +19,7 @@ module RuboCop
19
19
  # @example
20
20
  # # bad
21
21
  # array.reject(&:nil?)
22
- # array.delete_if(&:nil?)
23
22
  # array.reject { |e| e.nil? }
24
- # array.delete_if { |e| e.nil? }
25
23
  # array.select { |e| !e.nil? }
26
24
  # array.grep_v(nil)
27
25
  # array.grep_v(NilClass)
@@ -31,7 +29,9 @@ module RuboCop
31
29
  #
32
30
  # # bad
33
31
  # hash.reject!(&:nil?)
32
+ # array.delete_if(&:nil?)
34
33
  # hash.reject! { |k, v| v.nil? }
34
+ # array.delete_if { |e| e.nil? }
35
35
  # hash.select! { |k, v| !v.nil? }
36
36
  #
37
37
  # # good
@@ -127,7 +127,7 @@ module RuboCop
127
127
  end
128
128
 
129
129
  def good_method_name(node)
130
- if node.bang_method?
130
+ if node.bang_method? || node.method?(:delete_if)
131
131
  'compact!'
132
132
  else
133
133
  'compact'
@@ -28,18 +28,27 @@ module RuboCop
28
28
  def on_new_investigation
29
29
  return if notice.empty? || notice_found?(processed_source)
30
30
 
31
- add_offense(offense_range, message: format(MSG, notice: notice)) do |corrector|
32
- verify_autocorrect_notice!
33
-
34
- token = insert_notice_before(processed_source)
35
- range = token.nil? ? range_between(0, 0) : token.pos
36
-
37
- corrector.insert_before(range, "#{autocorrect_notice}\n")
31
+ verify_autocorrect_notice!
32
+ message = format(MSG, notice: notice)
33
+ if processed_source.blank?
34
+ add_global_offense(message)
35
+ else
36
+ offense_range = source_range(processed_source.buffer, 1, 0)
37
+ add_offense(offense_range, message: message) do |corrector|
38
+ autocorrect(corrector)
39
+ end
38
40
  end
39
41
  end
40
42
 
41
43
  private
42
44
 
45
+ def autocorrect(corrector)
46
+ token = insert_notice_before(processed_source)
47
+ range = token.nil? ? range_between(0, 0) : token.pos
48
+
49
+ corrector.insert_before(range, "#{autocorrect_notice}\n")
50
+ end
51
+
43
52
  def notice
44
53
  cop_config['Notice']
45
54
  end
@@ -48,10 +57,6 @@ module RuboCop
48
57
  cop_config['AutocorrectNotice']
49
58
  end
50
59
 
51
- def offense_range
52
- source_range(processed_source.buffer, 1, 0)
53
- end
54
-
55
60
  def verify_autocorrect_notice!
56
61
  raise Warning, AUTOCORRECT_EMPTY_WARNING if autocorrect_notice.empty?
57
62
 
@@ -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,
@@ -155,6 +155,8 @@ module RuboCop
155
155
 
156
156
  def check_line(node, code)
157
157
  line_node = node.last_argument
158
+ return if line_node.variable? || (line_node.send_type? && !line_node.method?(:+))
159
+
158
160
  line_diff = line_difference(line_node, code)
159
161
  if line_diff.zero?
160
162
  add_offense_for_same_line(node, line_node)
@@ -38,12 +38,13 @@ module RuboCop
38
38
  PATTERN
39
39
 
40
40
  def on_send(node)
41
+ return unless (receiver = node.receiver)
41
42
  return unless (regexp = exact_regexp_match(node))
42
43
 
43
44
  parsed_regexp = Regexp::Parser.parse(regexp)
44
45
  return unless exact_match_pattern?(parsed_regexp)
45
46
 
46
- prefer = "#{node.receiver.source} #{new_method(node)} '#{parsed_regexp[1].text}'"
47
+ prefer = "#{receiver.source} #{new_method(node)} '#{parsed_regexp[1].text}'"
47
48
 
48
49
  add_offense(node, message: format(MSG, prefer: prefer)) do |corrector|
49
50
  corrector.replace(node, prefer)
@@ -25,27 +25,27 @@ module RuboCop
25
25
  #
26
26
  # @example EnforcedStyle: format (default)
27
27
  # # bad
28
- # puts sprintf('%10s', 'hoge')
29
- # puts '%10s' % 'hoge'
28
+ # puts sprintf('%10s', 'foo')
29
+ # puts '%10s' % 'foo'
30
30
  #
31
31
  # # good
32
- # puts format('%10s', 'hoge')
32
+ # puts format('%10s', 'foo')
33
33
  #
34
34
  # @example EnforcedStyle: sprintf
35
35
  # # bad
36
- # puts format('%10s', 'hoge')
37
- # puts '%10s' % 'hoge'
36
+ # puts format('%10s', 'foo')
37
+ # puts '%10s' % 'foo'
38
38
  #
39
39
  # # good
40
- # puts sprintf('%10s', 'hoge')
40
+ # puts sprintf('%10s', 'foo')
41
41
  #
42
42
  # @example EnforcedStyle: percent
43
43
  # # bad
44
- # puts format('%10s', 'hoge')
45
- # puts sprintf('%10s', 'hoge')
44
+ # puts format('%10s', 'foo')
45
+ # puts sprintf('%10s', 'foo')
46
46
  #
47
47
  # # good
48
- # puts '%10s' % 'hoge'
48
+ # puts '%10s' % 'foo'
49
49
  #
50
50
  class FormatString < Base
51
51
  include ConfigurableEnforcedStyle
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for usages of `each` with `<<`, `push`, or `append` which
7
+ # can be replaced by `map`.
8
+ #
9
+ # If `PreferredMethods` is configured for `map` in `Style/CollectionMethods`,
10
+ # this cop uses the specified method for replacement.
11
+ #
12
+ # NOTE: The return value of `Enumerable#each` is `self`, whereas the
13
+ # return value of `Enumerable#map` is an `Array`. They are not autocorrected
14
+ # when a return value could be used because these types differ.
15
+ #
16
+ # NOTE: It only detects when the mapping destination is a local variable
17
+ # initialized as an empty array and referred to only by the pushing operation.
18
+ # This is because, if not, it's challenging to statically guarantee that the
19
+ # mapping destination variable remains an empty array:
20
+ #
21
+ # [source,ruby]
22
+ # ----
23
+ # ret = []
24
+ # src.each { |e| ret << e * 2 } # `<<` method may mutate `ret`
25
+ #
26
+ # dest = []
27
+ # src.each { |e| dest << transform(e, dest) } # `transform` method may mutate `dest`
28
+ # ----
29
+ #
30
+ # @safety
31
+ # This cop is unsafe because not all objects that have an `each`
32
+ # method also have a `map` method (e.g. `ENV`). Additionally, for calls
33
+ # with a block, not all objects that have a `map` method return an array
34
+ # (e.g. `Enumerator::Lazy`).
35
+ #
36
+ # @example
37
+ # # bad
38
+ # dest = []
39
+ # src.each { |e| dest << e * 2 }
40
+ # dest
41
+ #
42
+ # # good
43
+ # dest = src.map { |e| e * 2 }
44
+ #
45
+ # # good - contains another operation
46
+ # dest = []
47
+ # src.each { |e| dest << e * 2; puts e }
48
+ # dest
49
+ #
50
+ class MapIntoArray < Base
51
+ include RangeHelp
52
+ extend AutoCorrector
53
+
54
+ MSG = 'Use `%<new_method_name>s` instead of `each` to map elements into an array.'
55
+
56
+ # @!method each_block_with_push?(node)
57
+ def_node_matcher :each_block_with_push?, <<-PATTERN
58
+ [
59
+ ^({begin kwbegin} ...)
60
+ ({block numblock} (send _ :each) _
61
+ (send (lvar _) {:<< :push :append} _))
62
+ ]
63
+ PATTERN
64
+
65
+ # @!method empty_array_asgn?(node)
66
+ def_node_matcher :empty_array_asgn?, '(lvasgn _ (array))'
67
+
68
+ # @!method lvar_ref?(node, name)
69
+ def_node_matcher :lvar_ref?, '(lvar %1)'
70
+
71
+ def self.joining_forces
72
+ VariableForce
73
+ end
74
+
75
+ def after_leaving_scope(scope, _variable_table)
76
+ (@scopes ||= []) << scope
77
+ end
78
+
79
+ def on_block(node)
80
+ return unless each_block_with_push?(node)
81
+
82
+ dest_var = find_dest_var(node)
83
+ return unless (asgn = find_closest_assignment(node, dest_var))
84
+ return unless empty_array_asgn?(asgn)
85
+ return unless dest_used_only_for_mapping?(node, dest_var, asgn)
86
+
87
+ register_offense(node, dest_var, asgn)
88
+ end
89
+
90
+ alias on_numblock on_block
91
+
92
+ private
93
+
94
+ def find_dest_var(block)
95
+ node = block.body.receiver
96
+ name = node.children.first
97
+
98
+ candidates = @scopes.lazy.filter_map { |s| s.variables[name] }
99
+ candidates.find { |v| v.references.any? { |n| n.node.equal?(node) } }
100
+ end
101
+
102
+ def find_closest_assignment(block, dest_var)
103
+ dest_var.assignments.reverse_each.lazy.map(&:node).find do |node|
104
+ node.source_range.end_pos < block.source_range.begin_pos
105
+ end
106
+ end
107
+
108
+ def dest_used_only_for_mapping?(block, dest_var, asgn)
109
+ range = asgn.source_range.join(block.source_range)
110
+
111
+ asgn.parent.equal?(block.parent) &&
112
+ dest_var.references.one? { |r| range.contains?(r.node.source_range) } &&
113
+ dest_var.assignments.one? { |a| range.contains?(a.node.source_range) }
114
+ end
115
+
116
+ def register_offense(block, dest_var, asgn)
117
+ add_offense(block, message: format(MSG, new_method_name: new_method_name)) do |corrector|
118
+ next if return_value_used?(block)
119
+
120
+ corrector.replace(block.send_node.selector, new_method_name)
121
+ remove_assignment(corrector, asgn)
122
+ correct_push_node(corrector, block.body)
123
+ correct_return_value_handling(corrector, block, dest_var)
124
+ end
125
+ end
126
+
127
+ def new_method_name
128
+ default = 'map'
129
+ alternative = config.for_cop('Style/CollectionMethods').dig('PreferredMethods', default)
130
+ alternative || default
131
+ end
132
+
133
+ def return_value_used?(node)
134
+ parent = node.parent
135
+
136
+ case parent&.type
137
+ when nil
138
+ false
139
+ when :begin, :kwbegin
140
+ !node.right_sibling && return_value_used?(parent)
141
+ when :block, :numblock
142
+ !parent.void_context?
143
+ else
144
+ true
145
+ end
146
+ end
147
+
148
+ def remove_assignment(corrector, asgn)
149
+ range = range_with_surrounding_space(asgn.source_range, side: :right)
150
+ range = range_with_surrounding_space(range, side: :right, newlines: false)
151
+
152
+ corrector.remove(range)
153
+ end
154
+
155
+ def correct_push_node(corrector, push_node)
156
+ range = push_node.source_range
157
+ arg_range = push_node.first_argument.source_range
158
+
159
+ corrector.remove(range_between(range.begin_pos, arg_range.begin_pos))
160
+ corrector.remove(range_between(arg_range.end_pos, range.end_pos))
161
+ end
162
+
163
+ def correct_return_value_handling(corrector, block, dest_var)
164
+ next_node = block.right_sibling
165
+
166
+ if lvar_ref?(next_node, dest_var.name)
167
+ corrector.remove(range_with_surrounding_space(next_node.source_range, side: :left))
168
+ end
169
+
170
+ corrector.insert_before(block, "#{dest_var.name} = ")
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
@@ -55,7 +55,7 @@ module RuboCop
55
55
  message = format(MSG, method: map_node.loc.selector.source, dot: to_h_node.loc.dot.source)
56
56
  add_offense(map_node.loc.selector, message: message) do |corrector|
57
57
  # If the `to_h` call already has a block, do not autocorrect.
58
- next if to_h_node.block_node
58
+ next if to_h_node.block_literal?
59
59
 
60
60
  autocorrect(corrector, to_h_node, map_node)
61
61
  end
@@ -44,7 +44,7 @@ module RuboCop
44
44
  message = format(MSG, method: map_node.loc.selector.source)
45
45
  add_offense(map_node.loc.selector, message: message) do |corrector|
46
46
  # If the `to_set` call already has a block, do not autocorrect.
47
- next if to_set_node.block_node
47
+ next if to_set_node.block_literal?
48
48
 
49
49
  autocorrect(corrector, to_set_node, map_node)
50
50
  end
@@ -81,7 +81,13 @@ module RuboCop
81
81
  redundant_argument = redundant_arg_for_method(node.method_name.to_s)
82
82
  return false if redundant_argument.nil?
83
83
 
84
- node.first_argument.source.sub(/\A'/, '"').sub(/'\z/, '"') == redundant_argument
84
+ target_argument = if node.first_argument.respond_to?(:value)
85
+ node.first_argument.value
86
+ else
87
+ node.first_argument
88
+ end
89
+
90
+ argument_matched?(target_argument, redundant_argument)
85
91
  end
86
92
 
87
93
  def redundant_arg_for_method(method_name)
@@ -98,6 +104,23 @@ module RuboCop
98
104
  range_with_surrounding_space(node.first_argument.source_range, newlines: false)
99
105
  end
100
106
  end
107
+
108
+ def argument_matched?(target_argument, redundant_argument)
109
+ argument = if target_argument.is_a?(AST::Node)
110
+ target_argument.source
111
+ elsif exclude_cntrl_character?(target_argument, redundant_argument)
112
+ target_argument.inspect
113
+ else
114
+ target_argument.to_s
115
+ end
116
+
117
+ argument == redundant_argument
118
+ end
119
+
120
+ def exclude_cntrl_character?(target_argument, redundant_argument)
121
+ !target_argument.to_s.sub(/\A'/, '"').sub(/'\z/, '"').match?(/[[:cntrl:]]/) ||
122
+ !redundant_argument.match?(/[[:cntrl:]]/)
123
+ end
101
124
  end
102
125
  end
103
126
  end
@@ -18,10 +18,10 @@ module RuboCop
18
18
  extend AutoCorrector
19
19
 
20
20
  MSG = 'Remove the redundant current directory path.'
21
+ RESTRICT_ON_SEND = %i[require_relative].freeze
21
22
  CURRENT_DIRECTORY_PATH = './'
22
23
 
23
24
  def on_send(node)
24
- return unless node.method?(:require_relative)
25
25
  return unless (first_argument = node.first_argument)
26
26
  return unless first_argument.str_content&.start_with?(CURRENT_DIRECTORY_PATH)
27
27
  return unless (index = first_argument.source.index(CURRENT_DIRECTORY_PATH))
@@ -86,7 +86,7 @@ module RuboCop
86
86
  def range(node)
87
87
  return node.selector unless node.method?(:each)
88
88
 
89
- if node.parent.call_type?
89
+ if node.parent&.call_type?
90
90
  node.selector.join(node.parent.loc.dot)
91
91
  else
92
92
  node.loc.dot.join(node.selector)
@@ -79,7 +79,7 @@ module RuboCop
79
79
  private_constant :REPLACEMENT_METHODS
80
80
 
81
81
  def on_send(node)
82
- return if node.arguments? || node.block_node
82
+ return if node.arguments? || node.block_literal?
83
83
 
84
84
  select_predicate?(node) do |select_node, filter_method|
85
85
  return if RAILS_METHODS.include?(filter_method) && !active_support_extensions_enabled?
@@ -72,7 +72,7 @@ module RuboCop
72
72
  ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
73
73
  ARGUMENT_TYPES = %i[
74
74
  kFALSE kNIL kSELF kTRUE tCONSTANT tCVAR tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR
75
- tLABEL tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
75
+ tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
76
76
  ].freeze
77
77
 
78
78
  def on_new_investigation
@@ -124,10 +124,8 @@ module RuboCop
124
124
  return true unless (node = find_node_for_line(range.line))
125
125
  return false if argument_newline?(node)
126
126
 
127
- continuation_node = node.parent || node
128
- return false if allowed_type?(node) || allowed_type?(continuation_node)
129
-
130
- continuation_node.source.include?("\n") || continuation_node.source.include?("\\\n")
127
+ source = node.parent ? node.parent.source : node.source
128
+ parse(source.gsub("\\\n", "\n")).valid_syntax?
131
129
  end
132
130
 
133
131
  def inside_string_literal?(range, token)
@@ -139,25 +137,27 @@ module RuboCop
139
137
  # do_something \
140
138
  # argument
141
139
  def method_with_argument?(current_token, next_token)
142
- current_token.type == :tIDENTIFIER && ARGUMENT_TYPES.include?(next_token.type)
140
+ return false if current_token.type != :tIDENTIFIER && current_token.type != :kRETURN
141
+
142
+ ARGUMENT_TYPES.include?(next_token.type)
143
143
  end
144
144
 
145
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
145
+ # rubocop:disable Metrics/AbcSize
146
146
  def argument_newline?(node)
147
147
  node = node.to_a.last if node.assignment?
148
148
  return false if node.parenthesized_call?
149
149
 
150
150
  node = node.children.first if node.root? && node.begin_type?
151
151
 
152
- if argument_is_method?(node) || node.begin_type?
153
- argument_newline?(node.children.first)
152
+ if argument_is_method?(node)
153
+ argument_newline?(node.first_argument)
154
154
  else
155
155
  return false unless method_call_with_arguments?(node)
156
156
 
157
- !same_line?(node, node.first_argument)
157
+ node.loc.selector.line != node.first_argument.loc.line
158
158
  end
159
159
  end
160
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
160
+ # rubocop:enable Metrics/AbcSize
161
161
 
162
162
  def find_node_for_line(line)
163
163
  processed_source.ast.each_node do |node|
@@ -165,10 +165,6 @@ module RuboCop
165
165
  end
166
166
  end
167
167
 
168
- def allowed_type?(node)
169
- node.and_type? || node.or_type? || (node.if_type? && node.ternary?)
170
- end
171
-
172
168
  def same_line?(node, line)
173
169
  return false unless (source_range = node.source_range)
174
170
 
@@ -53,7 +53,7 @@ module RuboCop
53
53
  return if interpolated_quotes?(node) || allowed_percent_q?(node)
54
54
 
55
55
  add_offense(node) do |corrector|
56
- delimiter = /^%Q[^"]+$|'/.match?(node.source) ? QUOTE : SINGLE_QUOTE
56
+ delimiter = /\A%Q[^"]+\z|'/.match?(node.source) ? QUOTE : SINGLE_QUOTE
57
57
 
58
58
  corrector.replace(node.loc.begin, delimiter)
59
59
  corrector.replace(node.loc.end, delimiter)
@@ -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
@@ -77,7 +77,7 @@ module RuboCop
77
77
 
78
78
  # @!method define_method_block?(node)
79
79
  def_node_matcher :define_method_block?, <<~PATTERN
80
- ({block numblock} (send _ {:define_method} _) ...)
80
+ ({block numblock} (send _ :define_method _) ...)
81
81
  PATTERN
82
82
  end
83
83
  end
@@ -174,6 +174,9 @@ module RuboCop
174
174
  end
175
175
 
176
176
  def support_target_rails_version?(cop)
177
+ # In this case, the rails version was already checked by `#excluded_file?`
178
+ return true if defined?(RuboCop::Rails::TargetRailsVersion::USES_REQUIRES_GEM_API)
179
+
177
180
  return true unless cop.class.respond_to?(:support_target_rails_version?)
178
181
 
179
182
  cop.class.support_target_rails_version?(cop.target_rails_version)
@@ -24,14 +24,10 @@ module RuboCop
24
24
  message: message(offense)
25
25
  )
26
26
 
27
- begin
28
- return unless valid_line?(offense)
27
+ return unless valid_line?(offense)
29
28
 
30
- report_line(offense.location)
31
- report_highlighted_area(offense.highlighted_area)
32
- rescue IndexError
33
- # range is not on a valid line; perhaps the source file is empty
34
- end
29
+ report_line(offense.location)
30
+ report_highlighted_area(offense.highlighted_area)
35
31
  end
36
32
 
37
33
  def valid_line?(offense)
@@ -53,14 +53,10 @@ module RuboCop
53
53
  message: message(offense)
54
54
  )
55
55
 
56
- begin
57
- return unless valid_line?(offense)
56
+ return unless valid_line?(offense)
58
57
 
59
- report_line(offense.location)
60
- report_highlighted_area(offense.highlighted_area)
61
- rescue IndexError
62
- # range is not on a valid line; perhaps the source file is empty
63
- end
58
+ report_line(offense.location)
59
+ report_highlighted_area(offense.highlighted_area)
64
60
  end
65
61
 
66
62
  def annotate_message(msg)