rubocop 1.50.2 → 1.51.0
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.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0863dd1792c6296e51bcdbbc4503423cbc61f66c40a7120b405f4eaf999349be'
|
4
|
+
data.tar.gz: a4998dfeef1e7f82ffac34fb409494859b28afba9ce6bb007f6ca5870a5e371b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ff6067cf16502e16e5bf6691717f97b5f0cf34bdd03e0d893ee90185af1a26d5622c394b5b586530a9d596f8f92cdff4b5eb351d305fc8a2206906f903c9606
|
7
|
+
data.tar.gz: 2ab3c9a30731adbd8818bfce7fba9f346ac8f66a3b0a52fe2ee65094a7ed580f617fa776664f59df71d6229cf35e3e9ad74a557ec6a760dcbc6d85ae1008a2bb
|
data/README.md
CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
53
53
|
in your `Gemfile`:
|
54
54
|
|
55
55
|
```rb
|
56
|
-
gem 'rubocop', '~> 1.
|
56
|
+
gem 'rubocop', '~> 1.51', require: false
|
57
57
|
```
|
58
58
|
|
59
59
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
@@ -75,8 +75,8 @@ You can read a lot more about RuboCop in its [official docs](https://docs.ruboco
|
|
75
75
|
|
76
76
|
RuboCop officially supports the following runtime Ruby implementations:
|
77
77
|
|
78
|
-
* MRI 2.
|
79
|
-
* JRuby 9.
|
78
|
+
* MRI 2.7+
|
79
|
+
* JRuby 9.4+
|
80
80
|
|
81
81
|
Targets Ruby 2.0+ code analysis.
|
82
82
|
|
data/config/default.yml
CHANGED
@@ -140,7 +140,7 @@ AllCops:
|
|
140
140
|
# or gems.locked file. (Although the Ruby version is specified in the Gemfile
|
141
141
|
# or gems.rb file, RuboCop reads the final value from the lock file.) If the
|
142
142
|
# Ruby version is still unresolved, RuboCop will use the oldest officially
|
143
|
-
# supported Ruby version (currently Ruby 2.
|
143
|
+
# supported Ruby version (currently Ruby 2.7).
|
144
144
|
TargetRubyVersion: ~
|
145
145
|
# Determines if a notification for extension libraries should be shown when
|
146
146
|
# rubocop is run. Keys are the name of the extension, and values are an array
|
@@ -154,6 +154,7 @@ AllCops:
|
|
154
154
|
rubocop-rake: [rake]
|
155
155
|
rubocop-graphql: [graphql]
|
156
156
|
rubocop-capybara: [capybara]
|
157
|
+
rubocop-factory_bot: [factory_bot, factory_bot_rails]
|
157
158
|
# Enable/Disable checking the methods extended by Active Support.
|
158
159
|
ActiveSupportExtensionsEnabled: false
|
159
160
|
|
@@ -2343,6 +2344,9 @@ Lint/TopLevelReturnWithArgument:
|
|
2343
2344
|
Description: 'Detects top level return statements with argument.'
|
2344
2345
|
Enabled: true
|
2345
2346
|
VersionAdded: '0.89'
|
2347
|
+
# These codes are `eval`-ed in method and their return values may be used.
|
2348
|
+
Exclude:
|
2349
|
+
- '**/*.jb'
|
2346
2350
|
|
2347
2351
|
Lint/TrailingCommaInAttributeDeclaration:
|
2348
2352
|
Description: 'Checks for trailing commas in attribute declarations.'
|
@@ -2451,6 +2455,8 @@ Lint/UselessAssignment:
|
|
2451
2455
|
StyleGuide: '#underscore-unused-vars'
|
2452
2456
|
Enabled: true
|
2453
2457
|
VersionAdded: '0.11'
|
2458
|
+
VersionChanged: '1.51'
|
2459
|
+
SafeAutoCorrect: false
|
2454
2460
|
|
2455
2461
|
Lint/UselessElseWithoutRescue:
|
2456
2462
|
Description: 'Checks for useless `else` in `begin..end` without `rescue`.'
|
@@ -2942,7 +2948,9 @@ Naming/VariableNumber:
|
|
2942
2948
|
Security/CompoundHash:
|
2943
2949
|
Description: 'When overwriting Object#hash to combine values, prefer delegating to Array#hash over writing a custom implementation.'
|
2944
2950
|
Enabled: pending
|
2951
|
+
Safe: false
|
2945
2952
|
VersionAdded: '1.28'
|
2953
|
+
VersionChanged: '1.51'
|
2946
2954
|
|
2947
2955
|
Security/Eval:
|
2948
2956
|
Description: 'The use of eval represents a serious security risk.'
|
@@ -3515,7 +3523,9 @@ Style/DataInheritance:
|
|
3515
3523
|
Description: 'Checks for inheritance from Data.define.'
|
3516
3524
|
StyleGuide: '#no-extend-data-define'
|
3517
3525
|
Enabled: pending
|
3526
|
+
SafeAutoCorrect: false
|
3518
3527
|
VersionAdded: '1.49'
|
3528
|
+
VersionChanged: '1.51'
|
3519
3529
|
|
3520
3530
|
Style/DateTime:
|
3521
3531
|
Description: 'Use Time over DateTime.'
|
@@ -3706,6 +3716,11 @@ Style/EvenOdd:
|
|
3706
3716
|
VersionAdded: '0.12'
|
3707
3717
|
VersionChanged: '0.29'
|
3708
3718
|
|
3719
|
+
Style/ExactRegexpMatch:
|
3720
|
+
Description: 'Checks for exact regexp match inside Regexp literals.'
|
3721
|
+
Enabled: pending
|
3722
|
+
VersionAdded: '1.51'
|
3723
|
+
|
3709
3724
|
Style/ExpandPathArguments:
|
3710
3725
|
Description: "Use `expand_path(__dir__)` instead of `expand_path('..', __FILE__)`."
|
3711
3726
|
Enabled: true
|
@@ -4092,8 +4107,6 @@ Style/InvertibleUnlessCondition:
|
|
4092
4107
|
# :blank?: :present?
|
4093
4108
|
# :include?: :exclude?
|
4094
4109
|
# :exclude?: :include?
|
4095
|
-
# :one?: :many?
|
4096
|
-
# :many?: :one?
|
4097
4110
|
|
4098
4111
|
Style/IpAddresses:
|
4099
4112
|
Description: "Don't include literal IP addresses in code."
|
@@ -4624,7 +4637,9 @@ Style/OpenStructUse:
|
|
4624
4637
|
- https://docs.ruby-lang.org/en/3.0.0/OpenStruct.html#class-OpenStruct-label-Caveats
|
4625
4638
|
|
4626
4639
|
Enabled: pending
|
4640
|
+
Safe: false
|
4627
4641
|
VersionAdded: '1.23'
|
4642
|
+
VersionChanged: '1.51'
|
4628
4643
|
|
4629
4644
|
Style/OperatorMethodCall:
|
4630
4645
|
Description: 'Checks for redundant dot before operator method call.'
|
data/lib/rubocop/config.rb
CHANGED
@@ -68,11 +68,11 @@ module RuboCop
|
|
68
68
|
# Cop rules are keyed by the name of the original cop
|
69
69
|
def load_cop_rules(rules)
|
70
70
|
rules.flat_map do |rule_type, data|
|
71
|
-
data.
|
71
|
+
data.filter_map do |cop_name, configuration|
|
72
72
|
next unless configuration # allow configurations to be disabled with `CopName: ~`
|
73
73
|
|
74
74
|
COP_RULE_CLASSES[rule_type].new(@config, cop_name, configuration)
|
75
|
-
end
|
75
|
+
end
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
data/lib/rubocop/cop/base.rb
CHANGED
@@ -54,7 +54,7 @@ module RuboCop
|
|
54
54
|
def inside_string_ranges(node)
|
55
55
|
return [] unless node.is_a?(Parser::AST::Node)
|
56
56
|
|
57
|
-
node.each_node(:str, :dstr, :xstr).
|
57
|
+
node.each_node(:str, :dstr, :xstr).filter_map { |n| inside_string_range(n) }
|
58
58
|
end
|
59
59
|
|
60
60
|
def inside_string_range(node)
|
@@ -75,7 +75,7 @@ module RuboCop
|
|
75
75
|
|
76
76
|
# @!method add_development_dependency?(node)
|
77
77
|
def_node_matcher :add_development_dependency?, <<~PATTERN
|
78
|
-
(send _ :add_development_dependency (str #forbidden_gem? ...))
|
78
|
+
(send _ :add_development_dependency (str #forbidden_gem? ...) _? _?)
|
79
79
|
PATTERN
|
80
80
|
|
81
81
|
# @!method gem?(node)
|
@@ -59,12 +59,12 @@ module RuboCop
|
|
59
59
|
def method_directives(node)
|
60
60
|
comments = processed_source.ast_with_comments[node]
|
61
61
|
|
62
|
-
comments.
|
62
|
+
comments.filter_map do |comment|
|
63
63
|
match = comment.text.match(REGEXP)
|
64
64
|
next unless match
|
65
65
|
|
66
66
|
{ node: comment, method_name: match[:method_name], args: match[:args] }
|
67
|
-
end
|
67
|
+
end
|
68
68
|
end
|
69
69
|
|
70
70
|
def too_many_directives(node)
|
@@ -228,9 +228,9 @@ module RuboCop
|
|
228
228
|
end
|
229
229
|
|
230
230
|
def find_most_bottom_of_heredoc_end(arguments)
|
231
|
-
arguments.
|
231
|
+
arguments.filter_map do |argument|
|
232
232
|
argument.loc.heredoc_end.end_pos if argument.loc.respond_to?(:heredoc_end)
|
233
|
-
end.
|
233
|
+
end.max
|
234
234
|
end
|
235
235
|
|
236
236
|
# Internal trailing comma helpers.
|
@@ -236,6 +236,8 @@ module RuboCop
|
|
236
236
|
end
|
237
237
|
|
238
238
|
def offense(begin_pos, end_pos, msg, style_param = 'EnforcedStyle')
|
239
|
+
return if begin_pos > end_pos
|
240
|
+
|
239
241
|
range = range_between(begin_pos, end_pos)
|
240
242
|
add_offense(range, message: msg) do |corrector|
|
241
243
|
case range.source
|
@@ -52,6 +52,8 @@ module RuboCop
|
|
52
52
|
# expect { do_something }.to not_change { object.attribute }
|
53
53
|
#
|
54
54
|
class AmbiguousBlockAssociation < Base
|
55
|
+
extend AutoCorrector
|
56
|
+
|
55
57
|
include AllowedMethods
|
56
58
|
include AllowedPattern
|
57
59
|
|
@@ -68,7 +70,9 @@ module RuboCop
|
|
68
70
|
|
69
71
|
message = message(node)
|
70
72
|
|
71
|
-
add_offense(node, message: message)
|
73
|
+
add_offense(node, message: message) do |corrector|
|
74
|
+
wrap_in_parentheses(corrector, node)
|
75
|
+
end
|
72
76
|
end
|
73
77
|
alias on_csend on_send
|
74
78
|
|
@@ -89,6 +93,13 @@ module RuboCop
|
|
89
93
|
|
90
94
|
format(MSG, param: block_param.source, method: block_param.send_node.source)
|
91
95
|
end
|
96
|
+
|
97
|
+
def wrap_in_parentheses(corrector, node)
|
98
|
+
range = node.loc.selector.end.join(node.first_argument.source_range.begin)
|
99
|
+
|
100
|
+
corrector.replace(range, '(')
|
101
|
+
corrector.insert_after(node.last_argument, ')')
|
102
|
+
end
|
92
103
|
end
|
93
104
|
end
|
94
105
|
end
|
@@ -8,9 +8,9 @@ module RuboCop
|
|
8
8
|
#
|
9
9
|
# [source,console]
|
10
10
|
# ----
|
11
|
-
#
|
11
|
+
# $ cat example.rb
|
12
12
|
# ERB.new('hi', nil, '-', '@output_buffer')
|
13
|
-
#
|
13
|
+
# $ ruby -rerb example.rb
|
14
14
|
# example.rb:1: warning: Passing safe_level with the 2nd argument of ERB.new is
|
15
15
|
# deprecated. Do not use it, and specify other arguments as keyword arguments.
|
16
16
|
# example.rb:1: warning: Passing trim_mode with the 3rd argument of ERB.new is
|
@@ -6,6 +6,9 @@ module RuboCop
|
|
6
6
|
#
|
7
7
|
# This cop checks for `IO.select` that is incompatible with Fiber Scheduler since Ruby 3.0.
|
8
8
|
#
|
9
|
+
# When an array of IO objects waiting for an exception (the third argument of `IO.select`)
|
10
|
+
# is used as an argument, there is no alternative API, so offenses are not registered.
|
11
|
+
#
|
9
12
|
# NOTE: When the method is successful the return value of `IO.select` is `[[IO]]`,
|
10
13
|
# and the return value of `io.wait_readable` and `io.wait_writable` are `self`.
|
11
14
|
# They are not autocorrected when assigning a return value because these types are different.
|
@@ -42,8 +45,8 @@ module RuboCop
|
|
42
45
|
PATTERN
|
43
46
|
|
44
47
|
def on_send(node)
|
45
|
-
read, write,
|
46
|
-
return
|
48
|
+
read, write, excepts, timeout = *io_select(node)
|
49
|
+
return if excepts && !excepts.children.empty?
|
47
50
|
return unless scheduler_compatible?(read, write) || scheduler_compatible?(write, read)
|
48
51
|
|
49
52
|
preferred = preferred_method(read, write, timeout)
|
@@ -6,7 +6,7 @@ module RuboCop
|
|
6
6
|
# Checks uses of lambda without a literal block.
|
7
7
|
# It emulates the following warning in Ruby 3.0:
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# $ ruby -vwe 'lambda(&proc {})'
|
10
10
|
# ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
|
11
11
|
# -e:1: warning: lambda without a literal block is deprecated; use the proc without
|
12
12
|
# lambda instead
|
@@ -6,13 +6,13 @@ module RuboCop
|
|
6
6
|
# Checks for uses of numbered parameter assignment.
|
7
7
|
# It emulates the following warning in Ruby 2.7:
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# $ ruby -ve '_1 = :value'
|
10
10
|
# ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin19]
|
11
11
|
# -e:1: warning: `_1' is reserved for numbered parameter; consider another name
|
12
12
|
#
|
13
13
|
# Assigning to a numbered parameter (from `_1` to `_9`) causes an error in Ruby 3.0.
|
14
14
|
#
|
15
|
-
#
|
15
|
+
# $ ruby -ve '_1 = :value'
|
16
16
|
# ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
|
17
17
|
# -e:1: _1 is reserved for numbered parameter
|
18
18
|
#
|
@@ -65,13 +65,13 @@ module RuboCop
|
|
65
65
|
def on_when(node)
|
66
66
|
regexp_conditions = node.conditions.select(&:regexp_type?)
|
67
67
|
|
68
|
-
@valid_ref = regexp_conditions.
|
68
|
+
@valid_ref = regexp_conditions.filter_map { |condition| check_regexp(condition) }.max
|
69
69
|
end
|
70
70
|
|
71
71
|
def on_in_pattern(node)
|
72
72
|
regexp_patterns = regexp_patterns(node)
|
73
73
|
|
74
|
-
@valid_ref = regexp_patterns.
|
74
|
+
@valid_ref = regexp_patterns.filter_map { |pattern| check_regexp(pattern) }.max
|
75
75
|
end
|
76
76
|
|
77
77
|
def on_nth_ref(node)
|
@@ -8,25 +8,39 @@ module RuboCop
|
|
8
8
|
# always ignored. This is detected automatically since Ruby 2.7.
|
9
9
|
#
|
10
10
|
# @example
|
11
|
+
# # bad
|
12
|
+
# return 1
|
11
13
|
#
|
12
|
-
# #
|
13
|
-
# return
|
14
|
+
# # good
|
15
|
+
# return
|
14
16
|
class TopLevelReturnWithArgument < Base
|
15
|
-
|
16
|
-
# top-level return node's ancestors should not be of block, def, or
|
17
|
-
# defs type.
|
17
|
+
extend AutoCorrector
|
18
18
|
|
19
19
|
MSG = 'Top level return with argument detected.'
|
20
20
|
|
21
21
|
def on_return(return_node)
|
22
|
-
|
22
|
+
return unless top_level_return_with_any_argument?(return_node)
|
23
|
+
|
24
|
+
add_offense(return_node) do |corrector|
|
25
|
+
remove_arguments(corrector, return_node)
|
26
|
+
end
|
23
27
|
end
|
24
28
|
|
25
29
|
private
|
26
30
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
31
|
+
def top_level_return_with_any_argument?(return_node)
|
32
|
+
top_level_return?(return_node) && return_node.arguments?
|
33
|
+
end
|
34
|
+
|
35
|
+
def remove_arguments(corrector, return_node)
|
36
|
+
corrector.replace(return_node, 'return')
|
37
|
+
end
|
38
|
+
|
39
|
+
# This cop works by validating the ancestors of the return node. A
|
40
|
+
# top-level return node's ancestors should not be of block, def, or
|
41
|
+
# defs type.
|
42
|
+
def top_level_return?(return_node)
|
43
|
+
return_node.each_ancestor(:block, :def, :defs).none?
|
30
44
|
end
|
31
45
|
end
|
32
46
|
end
|
@@ -13,6 +13,12 @@ module RuboCop
|
|
13
13
|
# reassignments and properly handles varied cases such as branch, loop,
|
14
14
|
# rescue, ensure, etc.
|
15
15
|
#
|
16
|
+
# @safety
|
17
|
+
# This cop's autocorrection is unsafe because removing assignment from
|
18
|
+
# operator assignment can cause NameError if this assignment has been used to declare
|
19
|
+
# local variable. For example, replacing `a ||= 1` to `a || 1` may cause
|
20
|
+
# "undefined local variable or method `a' for main:Object (NameError)".
|
21
|
+
#
|
16
22
|
# @example
|
17
23
|
#
|
18
24
|
# # bad
|
@@ -31,6 +37,10 @@ module RuboCop
|
|
31
37
|
# do_something(some_var)
|
32
38
|
# end
|
33
39
|
class UselessAssignment < Base
|
40
|
+
extend AutoCorrector
|
41
|
+
|
42
|
+
include RangeHelp
|
43
|
+
|
34
44
|
MSG = 'Useless assignment to variable - `%<variable>s`.'
|
35
45
|
|
36
46
|
def self.joining_forces
|
@@ -55,7 +65,9 @@ module RuboCop
|
|
55
65
|
assignment.node.loc.name
|
56
66
|
end
|
57
67
|
|
58
|
-
add_offense(location, message: message)
|
68
|
+
add_offense(location, message: message) do |corrector|
|
69
|
+
autocorrect(corrector, assignment)
|
70
|
+
end
|
59
71
|
end
|
60
72
|
end
|
61
73
|
|
@@ -119,6 +131,49 @@ module RuboCop
|
|
119
131
|
|
120
132
|
node.receiver.nil? && !node.arguments?
|
121
133
|
end
|
134
|
+
|
135
|
+
def autocorrect(corrector, assignment)
|
136
|
+
if assignment.exception_assignment?
|
137
|
+
remove_exception_assignment_part(corrector, assignment.node)
|
138
|
+
elsif assignment.multiple_assignment?
|
139
|
+
rename_variable_with_underscore(corrector, assignment.node)
|
140
|
+
elsif assignment.operator_assignment?
|
141
|
+
remove_trailing_character_from_operator(corrector, assignment.node)
|
142
|
+
elsif assignment.regexp_named_capture?
|
143
|
+
replace_named_capture_group_with_non_capturing_group(corrector, assignment.node,
|
144
|
+
assignment.variable.name)
|
145
|
+
else
|
146
|
+
remove_local_variable_assignment_part(corrector, assignment.node)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def remove_exception_assignment_part(corrector, node)
|
151
|
+
corrector.remove(
|
152
|
+
range_between(
|
153
|
+
(node.parent.children.first&.source_range || node.parent.location.keyword).end_pos,
|
154
|
+
node.source_range.end_pos
|
155
|
+
)
|
156
|
+
)
|
157
|
+
end
|
158
|
+
|
159
|
+
def rename_variable_with_underscore(corrector, node)
|
160
|
+
corrector.replace(node, '_')
|
161
|
+
end
|
162
|
+
|
163
|
+
def remove_trailing_character_from_operator(corrector, node)
|
164
|
+
corrector.remove(node.parent.location.operator.end.adjust(begin_pos: -1))
|
165
|
+
end
|
166
|
+
|
167
|
+
def replace_named_capture_group_with_non_capturing_group(corrector, node, variable_name)
|
168
|
+
corrector.replace(
|
169
|
+
node.children.first,
|
170
|
+
node.children.first.source.sub(/\(\?<#{variable_name}>/, '(?:')
|
171
|
+
)
|
172
|
+
end
|
173
|
+
|
174
|
+
def remove_local_variable_assignment_part(corrector, node)
|
175
|
+
corrector.replace(node, node.expression.source)
|
176
|
+
end
|
122
177
|
end
|
123
178
|
end
|
124
179
|
end
|
@@ -41,6 +41,10 @@ module RuboCop
|
|
41
41
|
# do_something(some_array)
|
42
42
|
# end
|
43
43
|
class Void < Base
|
44
|
+
extend AutoCorrector
|
45
|
+
|
46
|
+
include RangeHelp
|
47
|
+
|
44
48
|
OP_MSG = 'Operator `%<op>s` used in void context.'
|
45
49
|
VAR_MSG = 'Variable `%<var>s` used in void context.'
|
46
50
|
LIT_MSG = 'Literal `%<lit>s` used in void context.'
|
@@ -100,31 +104,43 @@ module RuboCop
|
|
100
104
|
def check_void_op(node)
|
101
105
|
return unless node.send_type? && OPERATORS.include?(node.method_name)
|
102
106
|
|
103
|
-
add_offense(node.loc.selector,
|
107
|
+
add_offense(node.loc.selector,
|
108
|
+
message: format(OP_MSG, op: node.method_name)) do |corrector|
|
109
|
+
autocorrect_void_op(corrector, node)
|
110
|
+
end
|
104
111
|
end
|
105
112
|
|
106
113
|
def check_var(node)
|
107
114
|
return unless node.variable? || node.const_type?
|
108
115
|
|
109
|
-
add_offense(node.loc.name,
|
116
|
+
add_offense(node.loc.name,
|
117
|
+
message: format(VAR_MSG, var: node.loc.name.source)) do |corrector|
|
118
|
+
autocorrect_void_var(corrector, node)
|
119
|
+
end
|
110
120
|
end
|
111
121
|
|
112
122
|
def check_literal(node)
|
113
123
|
return if !node.literal? || node.xstr_type? || node.range_type?
|
114
124
|
|
115
|
-
add_offense(node, message: format(LIT_MSG, lit: node.source))
|
125
|
+
add_offense(node, message: format(LIT_MSG, lit: node.source)) do |corrector|
|
126
|
+
autocorrect_void_literal(corrector, node)
|
127
|
+
end
|
116
128
|
end
|
117
129
|
|
118
130
|
def check_self(node)
|
119
131
|
return unless node.self_type?
|
120
132
|
|
121
|
-
add_offense(node, message: SELF_MSG)
|
133
|
+
add_offense(node, message: SELF_MSG) do |corrector|
|
134
|
+
autocorrect_void_self(corrector, node)
|
135
|
+
end
|
122
136
|
end
|
123
137
|
|
124
138
|
def check_void_expression(node)
|
125
139
|
return unless node.defined_type? || node.lambda_or_proc?
|
126
140
|
|
127
|
-
add_offense(node, message: format(EXPRESSION_MSG, expression: node.source))
|
141
|
+
add_offense(node, message: format(EXPRESSION_MSG, expression: node.source)) do |corrector|
|
142
|
+
autocorrect_void_expression(corrector, node)
|
143
|
+
end
|
128
144
|
end
|
129
145
|
|
130
146
|
def check_nonmutating(node)
|
@@ -139,7 +155,10 @@ module RuboCop
|
|
139
155
|
"#{method_name}!"
|
140
156
|
end
|
141
157
|
add_offense(node,
|
142
|
-
message: format(NONMUTATING_MSG, method: method_name,
|
158
|
+
message: format(NONMUTATING_MSG, method: method_name,
|
159
|
+
suggest: suggestion)) do |corrector|
|
160
|
+
autocorrect_nonmutating_send(corrector, node, suggestion)
|
161
|
+
end
|
143
162
|
end
|
144
163
|
|
145
164
|
def in_void_context?(node)
|
@@ -149,6 +168,43 @@ module RuboCop
|
|
149
168
|
|
150
169
|
VOID_CONTEXT_TYPES.include?(parent.type) && parent.void_context?
|
151
170
|
end
|
171
|
+
|
172
|
+
def autocorrect_void_op(corrector, node)
|
173
|
+
if node.arguments.empty?
|
174
|
+
corrector.replace(node, node.receiver.source)
|
175
|
+
else
|
176
|
+
corrector.replace(
|
177
|
+
range_with_surrounding_space(range: node.loc.selector, side: :both,
|
178
|
+
newlines: false),
|
179
|
+
"\n"
|
180
|
+
)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def autocorrect_void_var(corrector, node)
|
185
|
+
corrector.remove(range_with_surrounding_space(range: node.loc.name, side: :left))
|
186
|
+
end
|
187
|
+
|
188
|
+
def autocorrect_void_literal(corrector, node)
|
189
|
+
corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
|
190
|
+
end
|
191
|
+
|
192
|
+
def autocorrect_void_self(corrector, node)
|
193
|
+
corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
|
194
|
+
end
|
195
|
+
|
196
|
+
def autocorrect_void_expression(corrector, node)
|
197
|
+
corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
|
198
|
+
end
|
199
|
+
|
200
|
+
def autocorrect_nonmutating_send(corrector, node, suggestion)
|
201
|
+
send_node = if node.send_type?
|
202
|
+
node
|
203
|
+
else
|
204
|
+
node.send_node
|
205
|
+
end
|
206
|
+
corrector.replace(send_node.loc.selector, suggestion)
|
207
|
+
end
|
152
208
|
end
|
153
209
|
end
|
154
210
|
end
|
@@ -62,12 +62,16 @@ module RuboCop
|
|
62
62
|
# Returns the end line of a node, which might be a comment and not part of the AST
|
63
63
|
# End line is considered either the line at which another node starts, or
|
64
64
|
# the line at which the parent node ends.
|
65
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
65
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Lint/DuplicateBranch
|
66
66
|
def find_end_line(node)
|
67
67
|
if node.if_type? && node.else?
|
68
68
|
node.loc.else.line
|
69
69
|
elsif node.if_type? && node.ternary?
|
70
70
|
node.else_branch.loc.line
|
71
|
+
elsif node.if_type? && node.elsif?
|
72
|
+
node.each_ancestor(:if).find(&:if?).loc.end.line
|
73
|
+
elsif node.block_type? || node.numblock_type?
|
74
|
+
node.loc.end.line
|
71
75
|
elsif (next_sibling = node.right_sibling) && next_sibling.is_a?(AST::Node)
|
72
76
|
next_sibling.loc.line
|
73
77
|
elsif (parent = node.parent)
|
@@ -76,7 +80,7 @@ module RuboCop
|
|
76
80
|
node.loc.end.line
|
77
81
|
end
|
78
82
|
end
|
79
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
83
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Lint/DuplicateBranch
|
80
84
|
end
|
81
85
|
end
|
82
86
|
end
|