rubocop 1.50.2 → 1.51.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/config/default.yml +18 -3
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_obsoletion.rb +2 -2
- data/lib/rubocop/cop/base.rb +4 -0
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
- data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -0
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +12 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +2 -2
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -2
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -1
- data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
- data/lib/rubocop/cop/lint/useless_assignment.rb +56 -1
- data/lib/rubocop/cop/lint/void.rb +62 -6
- data/lib/rubocop/cop/mixin/comments_help.rb +6 -2
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +1 -1
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +22 -7
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -3
- data/lib/rubocop/cop/style/attr.rb +11 -1
- data/lib/rubocop/cop/style/collection_compact.rb +10 -6
- data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
- data/lib/rubocop/cop/style/combinable_loops.rb +26 -6
- data/lib/rubocop/cop/style/conditional_assignment.rb +2 -2
- data/lib/rubocop/cop/style/copyright.rb +5 -2
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
- data/lib/rubocop/cop/style/exact_regexp_match.rb +62 -0
- data/lib/rubocop/cop/style/guard_clause.rb +2 -0
- data/lib/rubocop/cop/style/hash_except.rb +19 -8
- data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -0
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +9 -5
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +5 -1
- data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
- data/lib/rubocop/cop/style/require_order.rb +9 -4
- data/lib/rubocop/cop/style/semicolon.rb +12 -1
- data/lib/rubocop/cop/style/special_global_vars.rb +2 -2
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/variable_force/assignment.rb +4 -0
- data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/target_ruby.rb +3 -2
- data/lib/rubocop/version.rb +3 -3
- data/lib/rubocop.rb +1 -0
- metadata +5 -4
@@ -17,7 +17,8 @@ module RuboCop
|
|
17
17
|
# @safety
|
18
18
|
# This cop relies on the pattern `@instance_var ||= ...`,
|
19
19
|
# but this is sometimes used for other purposes than memoization
|
20
|
-
# so this cop is considered unsafe.
|
20
|
+
# so this cop is considered unsafe. Also, its autocorrection is unsafe
|
21
|
+
# because it may conflict with instance variable names already in use.
|
21
22
|
#
|
22
23
|
# @example EnforcedStyleForLeadingUnderscores: disallowed (default)
|
23
24
|
# # bad
|
@@ -145,6 +146,8 @@ module RuboCop
|
|
145
146
|
# @_foo ||= calculate_expensive_thing
|
146
147
|
# end
|
147
148
|
class MemoizedInstanceVariableName < Base
|
149
|
+
extend AutoCorrector
|
150
|
+
|
148
151
|
include ConfigurableEnforcedStyle
|
149
152
|
|
150
153
|
MSG = 'Memoized variable `%<var>s` does not match ' \
|
@@ -163,6 +166,7 @@ module RuboCop
|
|
163
166
|
PATTERN
|
164
167
|
|
165
168
|
# rubocop:disable Metrics/AbcSize
|
169
|
+
# rubocop:disable Metrics/MethodLength
|
166
170
|
def on_or_asgn(node)
|
167
171
|
lhs, _value = *node
|
168
172
|
return unless lhs.ivasgn_type?
|
@@ -175,14 +179,18 @@ module RuboCop
|
|
175
179
|
|
176
180
|
return if matches?(method_name, lhs)
|
177
181
|
|
182
|
+
suggested_var = suggested_var(method_name)
|
178
183
|
msg = format(
|
179
184
|
message(lhs.children.first.to_s),
|
180
185
|
var: lhs.children.first.to_s,
|
181
|
-
suggested_var: suggested_var
|
186
|
+
suggested_var: suggested_var,
|
182
187
|
method: method_name
|
183
188
|
)
|
184
|
-
add_offense(lhs, message: msg)
|
189
|
+
add_offense(lhs, message: msg) do |corrector|
|
190
|
+
corrector.replace(lhs.loc.name, "@#{suggested_var}")
|
191
|
+
end
|
185
192
|
end
|
193
|
+
# rubocop:enable Metrics/MethodLength
|
186
194
|
# rubocop:enable Metrics/AbcSize
|
187
195
|
|
188
196
|
# @!method defined_memoized?(node, ivar)
|
@@ -205,15 +213,22 @@ module RuboCop
|
|
205
213
|
defined_memoized?(method_node.body, var_name) do |defined_ivar, return_ivar, ivar_assign|
|
206
214
|
return if matches?(method_name, ivar_assign)
|
207
215
|
|
216
|
+
suggested_var = suggested_var(method_name)
|
208
217
|
msg = format(
|
209
218
|
message(var_name.to_s),
|
210
219
|
var: var_name.to_s,
|
211
|
-
suggested_var: suggested_var
|
220
|
+
suggested_var: suggested_var,
|
212
221
|
method: method_name
|
213
222
|
)
|
214
|
-
add_offense(defined_ivar, message: msg)
|
215
|
-
|
216
|
-
|
223
|
+
add_offense(defined_ivar, message: msg) do |corrector|
|
224
|
+
corrector.replace(defined_ivar, "@#{suggested_var}")
|
225
|
+
end
|
226
|
+
add_offense(return_ivar, message: msg) do |corrector|
|
227
|
+
corrector.replace(return_ivar, "@#{suggested_var}")
|
228
|
+
end
|
229
|
+
add_offense(ivar_assign.loc.name, message: msg) do |corrector|
|
230
|
+
corrector.replace(ivar_assign.loc.name, "@#{suggested_var}")
|
231
|
+
end
|
217
232
|
end
|
218
233
|
end
|
219
234
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
@@ -82,9 +82,7 @@ module RuboCop
|
|
82
82
|
message = message(node)
|
83
83
|
|
84
84
|
add_offense(range, message: message) do |corrector|
|
85
|
-
corrector
|
86
|
-
|
87
|
-
correct_node(corrector, node.body, offending_name, preferred_name)
|
85
|
+
autocorrect(corrector, node, range, offending_name, preferred_name)
|
88
86
|
end
|
89
87
|
end
|
90
88
|
|
@@ -95,6 +93,16 @@ module RuboCop
|
|
95
93
|
variable.source_range
|
96
94
|
end
|
97
95
|
|
96
|
+
def autocorrect(corrector, node, range, offending_name, preferred_name)
|
97
|
+
corrector.replace(range, preferred_name)
|
98
|
+
correct_node(corrector, node.body, offending_name, preferred_name)
|
99
|
+
return unless (kwbegin_node = node.parent.each_ancestor(:kwbegin).first)
|
100
|
+
|
101
|
+
kwbegin_node.right_siblings.each do |child_node|
|
102
|
+
correct_node(corrector, child_node, offending_name, preferred_name)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
98
106
|
def variable_name_matches?(node, name)
|
99
107
|
if node.masgn_type?
|
100
108
|
node.each_descendant(:lvasgn).any? do |lvasgn_node|
|
@@ -24,7 +24,7 @@ module RuboCop
|
|
24
24
|
def on_send(node)
|
25
25
|
return unless node.command?(:attr) && node.arguments?
|
26
26
|
# check only for method definitions in class/module body
|
27
|
-
return if
|
27
|
+
return if allowed_context?(node)
|
28
28
|
|
29
29
|
message = message(node)
|
30
30
|
add_offense(node.loc.selector, message: message) do |corrector|
|
@@ -34,6 +34,16 @@ module RuboCop
|
|
34
34
|
|
35
35
|
private
|
36
36
|
|
37
|
+
def allowed_context?(node)
|
38
|
+
return false unless (class_node = node.each_ancestor(:class, :block).first)
|
39
|
+
|
40
|
+
(!class_node.class_type? && !class_eval?(class_node)) || define_attr_method?(class_node)
|
41
|
+
end
|
42
|
+
|
43
|
+
def define_attr_method?(node)
|
44
|
+
node.each_descendant(:def).any? { |def_node| def_node.method?(:attr) }
|
45
|
+
end
|
46
|
+
|
37
47
|
def autocorrect(corrector, node)
|
38
48
|
attr_name, setter = *node.arguments
|
39
49
|
|
@@ -9,8 +9,8 @@ module RuboCop
|
|
9
9
|
# @safety
|
10
10
|
# It is unsafe by default because false positives may occur in the
|
11
11
|
# `nil` check of block arguments to the receiver object. Additionally,
|
12
|
-
#
|
13
|
-
#
|
12
|
+
# we can't know the type of the receiver object for sure, which may
|
13
|
+
# result in false positives as well.
|
14
14
|
#
|
15
15
|
# For example, `[[1, 2], [3, nil]].reject { |first, second| second.nil? }`
|
16
16
|
# and `[[1, 2], [3, nil]].compact` are not compatible. This will work fine
|
@@ -19,7 +19,9 @@ module RuboCop
|
|
19
19
|
# @example
|
20
20
|
# # bad
|
21
21
|
# array.reject(&:nil?)
|
22
|
+
# array.delete_if(&:nil?)
|
22
23
|
# array.reject { |e| e.nil? }
|
24
|
+
# array.delete_if { |e| e.nil? }
|
23
25
|
# array.select { |e| !e.nil? }
|
24
26
|
#
|
25
27
|
# # good
|
@@ -39,14 +41,14 @@ module RuboCop
|
|
39
41
|
extend TargetRubyVersion
|
40
42
|
|
41
43
|
MSG = 'Use `%<good>s` instead of `%<bad>s`.'
|
42
|
-
RESTRICT_ON_SEND = %i[reject reject! select select!].freeze
|
44
|
+
RESTRICT_ON_SEND = %i[reject delete_if reject! select select!].freeze
|
43
45
|
TO_ENUM_METHODS = %i[to_enum lazy].freeze
|
44
46
|
|
45
47
|
minimum_target_ruby_version 2.4
|
46
48
|
|
47
49
|
# @!method reject_method_with_block_pass?(node)
|
48
50
|
def_node_matcher :reject_method_with_block_pass?, <<~PATTERN
|
49
|
-
(send !nil? {:reject :reject!}
|
51
|
+
(send !nil? {:reject :delete_if :reject!}
|
50
52
|
(block_pass
|
51
53
|
(sym :nil?)))
|
52
54
|
PATTERN
|
@@ -55,7 +57,7 @@ module RuboCop
|
|
55
57
|
def_node_matcher :reject_method?, <<~PATTERN
|
56
58
|
(block
|
57
59
|
(send
|
58
|
-
!nil? {:reject :reject!})
|
60
|
+
!nil? {:reject :delete_if :reject!})
|
59
61
|
$(args ...)
|
60
62
|
(send
|
61
63
|
$(lvar _) :nil?))
|
@@ -74,7 +76,9 @@ module RuboCop
|
|
74
76
|
|
75
77
|
def on_send(node)
|
76
78
|
return unless (range = offense_range(node))
|
77
|
-
|
79
|
+
if (target_ruby_version <= 3.0 || node.method?(:delete_if)) && to_enum_method?(node)
|
80
|
+
return
|
81
|
+
end
|
78
82
|
|
79
83
|
good = good_method_name(node)
|
80
84
|
message = format(MSG, good: good, bad: range.source)
|
@@ -3,8 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for methods invoked via the
|
7
|
-
# of the
|
6
|
+
# Checks for methods invoked via the `::` operator instead
|
7
|
+
# of the `.` operator (like `FileUtils::rmdir` instead of `FileUtils.rmdir`).
|
8
8
|
#
|
9
9
|
# @example
|
10
10
|
# # bad
|
@@ -57,38 +57,58 @@ module RuboCop
|
|
57
57
|
# end
|
58
58
|
#
|
59
59
|
class CombinableLoops < Base
|
60
|
+
extend AutoCorrector
|
61
|
+
|
62
|
+
include RangeHelp
|
63
|
+
|
60
64
|
MSG = 'Combine this loop with the previous loop.'
|
61
65
|
|
62
66
|
def on_block(node)
|
63
67
|
return unless node.parent&.begin_type?
|
64
68
|
return unless collection_looping_method?(node)
|
69
|
+
return unless same_collection_looping_block?(node, node.left_sibling)
|
65
70
|
|
66
|
-
add_offense(node)
|
71
|
+
add_offense(node) do |corrector|
|
72
|
+
combine_with_left_sibling(corrector, node)
|
73
|
+
end
|
67
74
|
end
|
68
75
|
|
69
76
|
alias on_numblock on_block
|
70
77
|
|
71
78
|
def on_for(node)
|
72
79
|
return unless node.parent&.begin_type?
|
80
|
+
return unless same_collection_looping_for?(node, node.left_sibling)
|
73
81
|
|
74
|
-
|
75
|
-
|
82
|
+
add_offense(node) do |corrector|
|
83
|
+
combine_with_left_sibling(corrector, node)
|
84
|
+
end
|
76
85
|
end
|
77
86
|
|
78
87
|
private
|
79
88
|
|
80
89
|
def collection_looping_method?(node)
|
81
|
-
|
82
|
-
method_name = node.method_name.to_s
|
90
|
+
method_name = node.method_name
|
83
91
|
method_name.start_with?('each') || method_name.end_with?('_each')
|
84
92
|
end
|
85
93
|
|
86
|
-
def
|
94
|
+
def same_collection_looping_block?(node, sibling)
|
87
95
|
(sibling&.block_type? || sibling&.numblock_type?) &&
|
88
96
|
sibling.send_node.method?(node.method_name) &&
|
89
97
|
sibling.receiver == node.receiver &&
|
90
98
|
sibling.send_node.arguments == node.send_node.arguments
|
91
99
|
end
|
100
|
+
|
101
|
+
def same_collection_looping_for?(node, sibling)
|
102
|
+
sibling&.for_type? && node.collection == sibling.collection
|
103
|
+
end
|
104
|
+
|
105
|
+
def combine_with_left_sibling(corrector, node)
|
106
|
+
corrector.replace(
|
107
|
+
node.left_sibling.body,
|
108
|
+
"#{node.left_sibling.body.source}\n#{node.body.source}"
|
109
|
+
)
|
110
|
+
corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
|
111
|
+
end
|
92
112
|
end
|
93
113
|
end
|
94
114
|
end
|
@@ -350,7 +350,7 @@ module RuboCop
|
|
350
350
|
end
|
351
351
|
|
352
352
|
def ternary_condition?(node)
|
353
|
-
[node, node.children.first].any? { |n| n.if_type? && n.ternary? }
|
353
|
+
[node, node.children.first].compact.any? { |n| n.if_type? && n.ternary? }
|
354
354
|
end
|
355
355
|
|
356
356
|
def lhs_all_match?(branches)
|
@@ -386,7 +386,7 @@ module RuboCop
|
|
386
386
|
def allowed_statements?(branches)
|
387
387
|
return false unless branches.all?
|
388
388
|
|
389
|
-
statements = branches.
|
389
|
+
statements = branches.filter_map { |branch| tail(branch) }
|
390
390
|
|
391
391
|
lhs_all_match?(statements) && statements.none?(&:masgn_type?) &&
|
392
392
|
assignment_types_match?(*statements)
|
@@ -8,8 +8,11 @@ module RuboCop
|
|
8
8
|
# The default regexp for an acceptable copyright notice can be found in
|
9
9
|
# config/default.yml. The default can be changed as follows:
|
10
10
|
#
|
11
|
-
#
|
12
|
-
#
|
11
|
+
# [source,yaml]
|
12
|
+
# ----
|
13
|
+
# Style/Copyright:
|
14
|
+
# Notice: '^Copyright (\(c\) )?2\d{3} Acme Inc'
|
15
|
+
# ----
|
13
16
|
#
|
14
17
|
# This regex string is treated as an unanchored regex. For each file
|
15
18
|
# that RuboCop scans, a comment that matches this regex must be found or
|
@@ -10,7 +10,7 @@ module RuboCop
|
|
10
10
|
# declarations.
|
11
11
|
#
|
12
12
|
# The documentation requirement is annulled if the class or module has
|
13
|
-
# a
|
13
|
+
# a `#:nodoc:` comment next to it. Likewise, `#:nodoc: all` does the
|
14
14
|
# same for all its children.
|
15
15
|
#
|
16
16
|
# @example
|
@@ -210,7 +210,7 @@ module RuboCop
|
|
210
210
|
def add_offense_for_missing_line(node, code)
|
211
211
|
register_offense(node) do |corrector|
|
212
212
|
line_str = missing_line(node, code)
|
213
|
-
corrector.insert_after(node.source_range.end, ", #{line_str}")
|
213
|
+
corrector.insert_after(node.last_argument.source_range.end, ", #{line_str}")
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for exact regexp match inside Regexp literals.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
# string =~ /\Astring\z/
|
12
|
+
# string === /\Astring\z/
|
13
|
+
# string.match(/\Astring\z/)
|
14
|
+
# string.match?(/\Astring\z/)
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# string == 'string'
|
18
|
+
#
|
19
|
+
# # bad
|
20
|
+
# string !~ /\Astring\z/
|
21
|
+
#
|
22
|
+
# # good
|
23
|
+
# string != 'string'
|
24
|
+
#
|
25
|
+
class ExactRegexpMatch < Base
|
26
|
+
extend AutoCorrector
|
27
|
+
|
28
|
+
MSG = 'Use `%<prefer>s`.'
|
29
|
+
RESTRICT_ON_SEND = %i[=~ === !~ match match?].freeze
|
30
|
+
|
31
|
+
# @!method exact_regexp_match(node)
|
32
|
+
def_node_matcher :exact_regexp_match, <<~PATTERN
|
33
|
+
(send
|
34
|
+
_ {:=~ :=== :!~ :match :match?}
|
35
|
+
(regexp
|
36
|
+
(str $_)
|
37
|
+
(regopt)))
|
38
|
+
PATTERN
|
39
|
+
|
40
|
+
def on_send(node)
|
41
|
+
return unless (regexp = exact_regexp_match(node))
|
42
|
+
|
43
|
+
parsed_regexp = Regexp::Parser.parse(regexp)
|
44
|
+
tokens = parsed_regexp.map(&:token)
|
45
|
+
return unless tokens[0] == :bos && tokens[1] == :literal && tokens[2] == :eos
|
46
|
+
|
47
|
+
prefer = "#{node.receiver.source} #{new_method(node)} '#{parsed_regexp[1].text}'"
|
48
|
+
|
49
|
+
add_offense(node, message: format(MSG, prefer: prefer)) do |corrector|
|
50
|
+
corrector.replace(node, prefer)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def new_method(node)
|
57
|
+
node.method?(:!~) ? '!=' : '=='
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -187,6 +187,8 @@ module RuboCop
|
|
187
187
|
if_branch = node.if_branch
|
188
188
|
else_branch = node.else_branch
|
189
189
|
|
190
|
+
corrector.replace(node.loc.begin, "\n") if node.loc.begin&.is?('then')
|
191
|
+
|
190
192
|
if if_branch&.send_type? && heredoc?(if_branch.last_argument)
|
191
193
|
autocorrect_heredoc_argument(corrector, node, if_branch, else_branch, guard)
|
192
194
|
elsif else_branch&.send_type? && heredoc?(else_branch.last_argument)
|
@@ -45,13 +45,13 @@ module RuboCop
|
|
45
45
|
(block
|
46
46
|
(send _ _)
|
47
47
|
(args
|
48
|
-
(arg _)
|
48
|
+
$(arg _)
|
49
49
|
(arg _))
|
50
50
|
{
|
51
|
-
(send
|
51
|
+
$(send
|
52
52
|
_ {:== :!= :eql? :include?} _)
|
53
53
|
(send
|
54
|
-
(send
|
54
|
+
$(send
|
55
55
|
_ {:== :!= :eql? :include?} _) :!)
|
56
56
|
})
|
57
57
|
PATTERN
|
@@ -61,13 +61,13 @@ module RuboCop
|
|
61
61
|
(block
|
62
62
|
(send _ _)
|
63
63
|
(args
|
64
|
-
(arg _)
|
64
|
+
$(arg _)
|
65
65
|
(arg _))
|
66
66
|
{
|
67
|
-
(send
|
67
|
+
$(send
|
68
68
|
_ {:== :!= :eql? :in? :include? :exclude?} _)
|
69
69
|
(send
|
70
|
-
(send
|
70
|
+
$(send
|
71
71
|
_ {:== :!= :eql? :in? :include? :exclude?} _) :!)
|
72
72
|
})
|
73
73
|
PATTERN
|
@@ -89,13 +89,24 @@ module RuboCop
|
|
89
89
|
|
90
90
|
private
|
91
91
|
|
92
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
92
93
|
def bad_method?(block)
|
93
94
|
if active_support_extensions_enabled?
|
94
|
-
bad_method_with_active_support?(block)
|
95
|
+
bad_method_with_active_support?(block) do |key_arg, send_node|
|
96
|
+
if send_node.method?(:in?) && send_node.receiver&.source != key_arg.source
|
97
|
+
return false
|
98
|
+
end
|
99
|
+
return true if !send_node.method?(:include?) && !send_node.method?(:exclude?)
|
100
|
+
|
101
|
+
send_node.first_argument&.source == key_arg.source
|
102
|
+
end
|
95
103
|
else
|
96
|
-
bad_method_with_poro?(block)
|
104
|
+
bad_method_with_poro?(block) do |key_arg, send_node|
|
105
|
+
!send_node.method?(:include?) || send_node.first_argument&.source == key_arg.source
|
106
|
+
end
|
97
107
|
end
|
98
108
|
end
|
109
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
99
110
|
|
100
111
|
def semantically_except_method?(send, block)
|
101
112
|
body = block.body
|
@@ -59,11 +59,13 @@ module RuboCop
|
|
59
59
|
# end
|
60
60
|
#
|
61
61
|
class IfInsideElse < Base
|
62
|
+
include IgnoredNode
|
62
63
|
include RangeHelp
|
63
64
|
extend AutoCorrector
|
64
65
|
|
65
66
|
MSG = 'Convert `if` nested inside `else` to `elsif`.'
|
66
67
|
|
68
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
67
69
|
def on_if(node)
|
68
70
|
return if node.ternary? || node.unless?
|
69
71
|
|
@@ -73,9 +75,13 @@ module RuboCop
|
|
73
75
|
return if allow_if_modifier_in_else_branch?(else_branch)
|
74
76
|
|
75
77
|
add_offense(else_branch.loc.keyword) do |corrector|
|
78
|
+
next if part_of_ignored_node?(node)
|
79
|
+
|
76
80
|
autocorrect(corrector, else_branch)
|
81
|
+
ignore_node(node)
|
77
82
|
end
|
78
83
|
end
|
84
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
79
85
|
|
80
86
|
private
|
81
87
|
|
@@ -84,7 +84,10 @@ module RuboCop
|
|
84
84
|
return unless (msg = message(node))
|
85
85
|
|
86
86
|
add_offense(node.loc.keyword, message: format(msg, keyword: node.keyword)) do |corrector|
|
87
|
+
next if part_of_ignored_node?(node)
|
88
|
+
|
87
89
|
autocorrect(corrector, node)
|
90
|
+
ignore_node(node)
|
88
91
|
end
|
89
92
|
end
|
90
93
|
|
@@ -10,12 +10,16 @@ module RuboCop
|
|
10
10
|
# Methods that can be inverted should be defined in `InverseMethods`. Note that
|
11
11
|
# the relationship of inverse methods needs to be defined in both directions.
|
12
12
|
# For example,
|
13
|
-
# InverseMethods:
|
14
|
-
# :!=: :==
|
15
|
-
# :even?: :odd?
|
16
|
-
# :odd?: :even?
|
17
13
|
#
|
18
|
-
#
|
14
|
+
# [source,yaml]
|
15
|
+
# ----
|
16
|
+
# InverseMethods:
|
17
|
+
# :!=: :==
|
18
|
+
# :even?: :odd?
|
19
|
+
# :odd?: :even?
|
20
|
+
# ----
|
21
|
+
#
|
22
|
+
# will suggest both `even?` and `odd?` to be inverted, but only `!=` (and not `==`).
|
19
23
|
#
|
20
24
|
# @safety
|
21
25
|
# This cop is unsafe because it cannot be guaranteed that the method
|
@@ -93,7 +93,7 @@ module RuboCop
|
|
93
93
|
def contains_delimiter?(node, delimiters)
|
94
94
|
delimiters_regexp = Regexp.union(delimiters)
|
95
95
|
|
96
|
-
node.children.
|
96
|
+
node.children.filter_map { |n| string_source(n) }.any?(delimiters_regexp)
|
97
97
|
end
|
98
98
|
|
99
99
|
def string_source(node)
|
@@ -70,6 +70,10 @@ module RuboCop
|
|
70
70
|
|
71
71
|
MSG = 'Redundant line continuation.'
|
72
72
|
ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
|
73
|
+
ARGUMENT_TYPES = %i[
|
74
|
+
kFALSE kNIL kSELF kTRUE tCONSTANT tCVAR tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR
|
75
|
+
tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
|
76
|
+
].freeze
|
73
77
|
|
74
78
|
def on_new_investigation
|
75
79
|
return unless processed_source.ast
|
@@ -124,7 +128,7 @@ module RuboCop
|
|
124
128
|
# do_something \
|
125
129
|
# argument
|
126
130
|
def method_with_argument?(current_token, next_token)
|
127
|
-
current_token.type == :tIDENTIFIER && next_token.type
|
131
|
+
current_token.type == :tIDENTIFIER && ARGUMENT_TYPES.include?(next_token.type)
|
128
132
|
end
|
129
133
|
|
130
134
|
def argument_newline?(node)
|
@@ -3,7 +3,16 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Enforces using
|
6
|
+
# Enforces using `//` or `%r` around regular expressions.
|
7
|
+
#
|
8
|
+
# NOTE: The following `%r` cases using a regexp starts with a blank or `=`
|
9
|
+
# as a method argument allowed to prevent syntax errors.
|
10
|
+
#
|
11
|
+
# [source,ruby]
|
12
|
+
# ----
|
13
|
+
# do_something %r{ regexp} # `do_something / regexp/` is an invalid syntax.
|
14
|
+
# do_something %r{=regexp} # `do_something /=regexp/` is an invalid syntax.
|
15
|
+
# ----
|
7
16
|
#
|
8
17
|
# @example EnforcedStyle: slashes (default)
|
9
18
|
# # bad
|
@@ -151,7 +160,7 @@ module RuboCop
|
|
151
160
|
|
152
161
|
def allowed_omit_parentheses_with_percent_r_literal?(node)
|
153
162
|
return false unless node.parent&.call_type?
|
154
|
-
return true if node.content.start_with?(' ')
|
163
|
+
return true if node.content.start_with?(' ', '=')
|
155
164
|
|
156
165
|
enforced_style = config.for_cop('Style/MethodCallWithArgsParentheses')['EnforcedStyle']
|
157
166
|
|
@@ -88,10 +88,7 @@ module RuboCop
|
|
88
88
|
return unless previous_older_sibling
|
89
89
|
|
90
90
|
add_offense(node, message: format(MSG, name: node.method_name)) do |corrector|
|
91
|
-
corrector
|
92
|
-
range_with_comments_and_lines(previous_older_sibling),
|
93
|
-
range_with_comments_and_lines(node.parent.if_type? ? node.parent : node)
|
94
|
-
)
|
91
|
+
autocorrect(corrector, node, previous_older_sibling)
|
95
92
|
end
|
96
93
|
end
|
97
94
|
|
@@ -114,6 +111,14 @@ module RuboCop
|
|
114
111
|
end
|
115
112
|
end
|
116
113
|
|
114
|
+
def autocorrect(corrector, node, previous_older_sibling)
|
115
|
+
range1 = range_with_comments_and_lines(previous_older_sibling)
|
116
|
+
range2 = range_with_comments_and_lines(node.parent.if_type? ? node.parent : node)
|
117
|
+
|
118
|
+
corrector.remove(range2)
|
119
|
+
corrector.insert_before(range1, range2.source)
|
120
|
+
end
|
121
|
+
|
117
122
|
def search_node(node)
|
118
123
|
node.parent.if_type? ? node.parent : node
|
119
124
|
end
|
@@ -90,8 +90,11 @@ module RuboCop
|
|
90
90
|
0
|
91
91
|
elsif exist_semicolon_before_right_curly_brace?(tokens)
|
92
92
|
-3
|
93
|
-
elsif exist_semicolon_after_left_curly_brace?(tokens)
|
93
|
+
elsif exist_semicolon_after_left_curly_brace?(tokens) ||
|
94
|
+
exist_semicolon_after_left_string_interpolation_brace?(tokens)
|
94
95
|
2
|
96
|
+
elsif exist_semicolon_before_right_string_interpolation_brace?(tokens)
|
97
|
+
-4
|
95
98
|
end
|
96
99
|
end
|
97
100
|
|
@@ -103,6 +106,14 @@ module RuboCop
|
|
103
106
|
tokens[1]&.left_curly_brace? && tokens[2]&.semicolon?
|
104
107
|
end
|
105
108
|
|
109
|
+
def exist_semicolon_before_right_string_interpolation_brace?(tokens)
|
110
|
+
tokens[-3]&.type == :tSTRING_DEND && tokens[-4]&.semicolon?
|
111
|
+
end
|
112
|
+
|
113
|
+
def exist_semicolon_after_left_string_interpolation_brace?(tokens)
|
114
|
+
tokens[1]&.type == :tSTRING_DBEG && tokens[2]&.semicolon?
|
115
|
+
end
|
116
|
+
|
106
117
|
def register_semicolon(line, column, after_expression, token_before_semicolon = nil)
|
107
118
|
range = source_range(processed_source.buffer, line, column)
|
108
119
|
|
@@ -234,9 +234,9 @@ module RuboCop
|
|
234
234
|
end
|
235
235
|
|
236
236
|
def matching_styles(global)
|
237
|
-
STYLE_VARS_MAP.
|
237
|
+
STYLE_VARS_MAP.filter_map do |style, vars|
|
238
238
|
style if vars.values.flatten(1).include? global
|
239
|
-
end
|
239
|
+
end
|
240
240
|
end
|
241
241
|
|
242
242
|
def english_name_replacement(preferred_name, node)
|
data/lib/rubocop/cop/team.rb
CHANGED