rubocop 1.26.1 → 1.27.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 +1 -1
- data/config/default.yml +15 -2
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +3 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +4 -0
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -5
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -5
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -2
- data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -4
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +6 -6
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
- data/lib/rubocop/cop/lint/empty_in_pattern.rb +3 -1
- data/lib/rubocop/cop/lint/empty_when.rb +3 -1
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +11 -4
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +8 -1
- data/lib/rubocop/cop/lint/refinement_import_methods.rb +51 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +10 -0
- data/lib/rubocop/cop/lint/syntax.rb +1 -2
- data/lib/rubocop/cop/lint/unused_method_argument.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -2
- data/lib/rubocop/cop/mixin/comments_help.rb +22 -2
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +1 -2
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -2
- data/lib/rubocop/cop/mixin/surrounding_space.rb +4 -2
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
- data/lib/rubocop/cop/style/double_negation.rb +32 -1
- data/lib/rubocop/cop/style/empty_case_condition.rb +1 -2
- data/lib/rubocop/cop/style/file_write.rb +12 -0
- data/lib/rubocop/cop/style/raise_args.rb +5 -2
- data/lib/rubocop/cop/style/redundant_capital_w.rb +1 -2
- data/lib/rubocop/cop/style/redundant_initialize.rb +119 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +12 -7
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -2
- data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -4
- data/lib/rubocop/formatter/offense_count_formatter.rb +6 -2
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -2
- data/lib/rubocop/result_cache.rb +9 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +2 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d48fd91bc57ba3589a331c3c0141d3e168c7631e5db47238a88cecbd10b12292
|
4
|
+
data.tar.gz: 9393d3cab7e09e86a9276ca4614f8f2c4fc2895f2070bd3364096569c2cd5828
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13d85485214ca48904b07a6da11f89d2e2ef33fceab05912fb4c4f4c1e025da4be79139845d13724a749f97eb837b943eef5515639a5116299b6a164d7517944
|
7
|
+
data.tar.gz: 668abbcaedb1f06c43a2e5f61774909d684767659979bc3787c0827ca22adf42be0edf1d30544909a74fc6aac18bcd3758c7c5f77352cb97b51fd96acd24ab18
|
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.27', require: false
|
57
57
|
```
|
58
58
|
|
59
59
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
data/config/default.yml
CHANGED
@@ -2058,6 +2058,12 @@ Lint/RedundantWithObject:
|
|
2058
2058
|
Enabled: true
|
2059
2059
|
VersionAdded: '0.51'
|
2060
2060
|
|
2061
|
+
Lint/RefinementImportMethods:
|
2062
|
+
Description: 'Use `Refinement#import_methods` when using `include` or `prepend` in `refine` block.'
|
2063
|
+
Enabled: pending
|
2064
|
+
SafeAutoCorrect: false
|
2065
|
+
VersionAdded: '1.27'
|
2066
|
+
|
2061
2067
|
Lint/RegexpAsCondition:
|
2062
2068
|
Description: >-
|
2063
2069
|
Do not use regexp literal as a condition.
|
@@ -2327,8 +2333,8 @@ Lint/UselessMethodDefinition:
|
|
2327
2333
|
Description: 'Checks for useless method definitions.'
|
2328
2334
|
Enabled: true
|
2329
2335
|
VersionAdded: '0.90'
|
2336
|
+
VersionChanged: '0.91'
|
2330
2337
|
Safe: false
|
2331
|
-
AllowComments: true
|
2332
2338
|
|
2333
2339
|
Lint/UselessRuby2Keywords:
|
2334
2340
|
Description: 'Finds unnecessary uses of `ruby2_keywords`.'
|
@@ -4524,6 +4530,11 @@ Style/RedundantFreeze:
|
|
4524
4530
|
VersionAdded: '0.34'
|
4525
4531
|
VersionChanged: '0.66'
|
4526
4532
|
|
4533
|
+
Style/RedundantInitialize:
|
4534
|
+
Description: 'Checks for redundant `initialize` methods.'
|
4535
|
+
Enabled: pending
|
4536
|
+
VersionAdded: '1.27'
|
4537
|
+
|
4527
4538
|
Style/RedundantInterpolation:
|
4528
4539
|
Description: 'Checks for strings that are just an interpolated expression.'
|
4529
4540
|
Enabled: true
|
@@ -4645,7 +4656,7 @@ Style/SafeNavigation:
|
|
4645
4656
|
be `nil` or truthy, but never `false`.
|
4646
4657
|
Enabled: true
|
4647
4658
|
VersionAdded: '0.43'
|
4648
|
-
VersionChanged: '
|
4659
|
+
VersionChanged: '1.27'
|
4649
4660
|
# Safe navigation may cause a statement to start returning `nil` in addition
|
4650
4661
|
# to whatever it used to return.
|
4651
4662
|
ConvertCodeThatCanStartToReturnNil: false
|
@@ -4656,6 +4667,8 @@ Style/SafeNavigation:
|
|
4656
4667
|
- try
|
4657
4668
|
- try!
|
4658
4669
|
SafeAutoCorrect: false
|
4670
|
+
# Maximum length of method chains for register an offense.
|
4671
|
+
MaxChainLength: 2
|
4659
4672
|
|
4660
4673
|
Style/Sample:
|
4661
4674
|
Description: >-
|
@@ -33,7 +33,9 @@ module RuboCop
|
|
33
33
|
return old_name unless old_name.end_with?('*')
|
34
34
|
|
35
35
|
# Handle whole departments (expressed as `Department/*`)
|
36
|
-
config.keys.
|
36
|
+
config.keys.select do |key|
|
37
|
+
key == department || key.start_with?("#{department}/")
|
38
|
+
end
|
37
39
|
end
|
38
40
|
|
39
41
|
def feature_loaded?
|
@@ -8,6 +8,10 @@ module RuboCop
|
|
8
8
|
autocorrect_requested? && correctable? && autocorrect_enabled?
|
9
9
|
end
|
10
10
|
|
11
|
+
def autocorrect_with_disable_uncorrectable?
|
12
|
+
autocorrect_requested? && disable_uncorrectable? && autocorrect_enabled?
|
13
|
+
end
|
14
|
+
|
11
15
|
def autocorrect_requested?
|
12
16
|
@options.fetch(:auto_correct, false)
|
13
17
|
end
|
@@ -46,11 +46,7 @@ module RuboCop
|
|
46
46
|
|
47
47
|
duplicated_gem_nodes.each do |nodes|
|
48
48
|
nodes[1..-1].each do |node|
|
49
|
-
register_offense(
|
50
|
-
node,
|
51
|
-
node.first_argument.to_a.first,
|
52
|
-
nodes.first.first_line
|
53
|
-
)
|
49
|
+
register_offense(node, node.first_argument.to_a.first, nodes.first.first_line)
|
54
50
|
end
|
55
51
|
end
|
56
52
|
end
|
@@ -52,11 +52,7 @@ module RuboCop
|
|
52
52
|
|
53
53
|
duplicated_assignment_method_nodes.each do |nodes|
|
54
54
|
nodes[1..-1].each do |node|
|
55
|
-
register_offense(
|
56
|
-
node,
|
57
|
-
node.method_name,
|
58
|
-
nodes.first.first_line
|
59
|
-
)
|
55
|
+
register_offense(node, node.method_name, nodes.first.first_line)
|
60
56
|
end
|
61
57
|
end
|
62
58
|
end
|
@@ -185,8 +185,7 @@ module RuboCop
|
|
185
185
|
|
186
186
|
def check_members_for_indented_internal_methods_style(members)
|
187
187
|
each_member(members) do |member, previous_modifier|
|
188
|
-
check_indentation(previous_modifier, member,
|
189
|
-
indentation_consistency_style)
|
188
|
+
check_indentation(previous_modifier, member, indentation_consistency_style)
|
190
189
|
end
|
191
190
|
end
|
192
191
|
|
@@ -105,10 +105,9 @@ module RuboCop
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def convertible_block?(node)
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
send_node.parenthesized? || !send_node.arguments?
|
108
|
+
parent = node.parent
|
109
|
+
parent&.block_type? && node == parent.send_node &&
|
110
|
+
(node.parenthesized? || !node.arguments?)
|
112
111
|
end
|
113
112
|
|
114
113
|
def comment_within?(node)
|
@@ -24,11 +24,11 @@ module RuboCop
|
|
24
24
|
extend AutoCorrector
|
25
25
|
|
26
26
|
AMBIGUITIES = {
|
27
|
-
'+' => { actual: 'positive number', possible: 'addition' },
|
28
|
-
'-' => { actual: 'negative number', possible: 'subtraction' },
|
29
|
-
'*' => { actual: 'splat', possible: 'multiplication' },
|
30
|
-
'&' => { actual: 'block', possible: 'binary AND' },
|
31
|
-
'**' => { actual: 'keyword splat', possible: 'exponent' }
|
27
|
+
'+' => { actual: 'positive number', possible: 'an addition' },
|
28
|
+
'-' => { actual: 'negative number', possible: 'a subtraction' },
|
29
|
+
'*' => { actual: 'splat', possible: 'a multiplication' },
|
30
|
+
'&' => { actual: 'block', possible: 'a binary AND' },
|
31
|
+
'**' => { actual: 'keyword splat', possible: 'an exponent' }
|
32
32
|
}.each do |key, hash|
|
33
33
|
hash[:operator] = key
|
34
34
|
end
|
@@ -36,7 +36,7 @@ module RuboCop
|
|
36
36
|
MSG_FORMAT = 'Ambiguous %<actual>s operator. Parenthesize the method ' \
|
37
37
|
"arguments if it's surely a %<actual>s operator, or add " \
|
38
38
|
'a whitespace to the right of the `%<operator>s` if it ' \
|
39
|
-
'should be
|
39
|
+
'should be %<possible>s.'
|
40
40
|
|
41
41
|
def on_new_investigation
|
42
42
|
processed_source.diagnostics.each do |diagnostic|
|
@@ -53,11 +53,13 @@ module RuboCop
|
|
53
53
|
# end
|
54
54
|
#
|
55
55
|
class EmptyConditionalBody < Base
|
56
|
+
include CommentsHelp
|
57
|
+
|
56
58
|
MSG = 'Avoid `%<keyword>s` branches without a body.'
|
57
59
|
|
58
60
|
def on_if(node)
|
59
61
|
return if node.body
|
60
|
-
return if cop_config['AllowComments'] &&
|
62
|
+
return if cop_config['AllowComments'] && contains_comments?(node)
|
61
63
|
|
62
64
|
add_offense(node, message: format(MSG, keyword: node.keyword))
|
63
65
|
end
|
@@ -44,6 +44,7 @@ module RuboCop
|
|
44
44
|
#
|
45
45
|
class EmptyInPattern < Base
|
46
46
|
extend TargetRubyVersion
|
47
|
+
include CommentsHelp
|
47
48
|
|
48
49
|
MSG = 'Avoid `in` branches without a body.'
|
49
50
|
|
@@ -51,7 +52,8 @@ module RuboCop
|
|
51
52
|
|
52
53
|
def on_case_match(node)
|
53
54
|
node.in_pattern_branches.each do |branch|
|
54
|
-
next if branch.body
|
55
|
+
next if branch.body
|
56
|
+
next if cop_config['AllowComments'] && contains_comments?(branch)
|
55
57
|
|
56
58
|
add_offense(branch)
|
57
59
|
end
|
@@ -45,12 +45,14 @@ module RuboCop
|
|
45
45
|
# end
|
46
46
|
#
|
47
47
|
class EmptyWhen < Base
|
48
|
+
include CommentsHelp
|
49
|
+
|
48
50
|
MSG = 'Avoid `when` branches without a body.'
|
49
51
|
|
50
52
|
def on_case(node)
|
51
53
|
node.each_when do |when_node|
|
52
54
|
next if when_node.body
|
53
|
-
next if cop_config['AllowComments'] &&
|
55
|
+
next if cop_config['AllowComments'] && contains_comments?(when_node)
|
54
56
|
|
55
57
|
add_offense(when_node)
|
56
58
|
end
|
@@ -6,6 +6,15 @@ 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
|
+
# NOTE: When the method is successful the return value of `IO.select` is `[[IO]]`,
|
10
|
+
# and the return value of `io.wait_readable` and `io.wait_writable` are `self`.
|
11
|
+
# They are not auto-corrected when assigning a return value because these types are different.
|
12
|
+
# It's up to user how to handle the return value.
|
13
|
+
#
|
14
|
+
# @safety
|
15
|
+
# This cop's autocorrection is unsafe because `NoMethodError` occurs
|
16
|
+
# if `require 'io/wait'` is not called.
|
17
|
+
#
|
9
18
|
# @example
|
10
19
|
#
|
11
20
|
# # bad
|
@@ -20,10 +29,6 @@ module RuboCop
|
|
20
29
|
# # good
|
21
30
|
# io.wait_writable(timeout)
|
22
31
|
#
|
23
|
-
# @safety
|
24
|
-
# This cop's autocorrection is unsafe because `NoMethodError` occurs
|
25
|
-
# if `require 'io/wait'` is not called.
|
26
|
-
#
|
27
32
|
class IncompatibleIoSelectWithFiberScheduler < Base
|
28
33
|
extend AutoCorrector
|
29
34
|
|
@@ -45,6 +50,8 @@ module RuboCop
|
|
45
50
|
message = format(MSG, preferred: preferred, current: node.source)
|
46
51
|
|
47
52
|
add_offense(node, message: message) do |corrector|
|
53
|
+
next if node.parent&.assignment?
|
54
|
+
|
48
55
|
corrector.replace(node, preferred)
|
49
56
|
end
|
50
57
|
end
|
@@ -31,8 +31,15 @@ module RuboCop
|
|
31
31
|
MSG = 'lambda without a literal block is deprecated; use the proc without lambda instead.'
|
32
32
|
RESTRICT_ON_SEND = %i[lambda].freeze
|
33
33
|
|
34
|
+
# @!method lambda_with_symbol_proc?(node)
|
35
|
+
def_node_matcher :lambda_with_symbol_proc?, <<~PATTERN
|
36
|
+
(send nil? :lambda (block_pass (sym _)))
|
37
|
+
PATTERN
|
38
|
+
|
34
39
|
def on_send(node)
|
35
|
-
|
40
|
+
if node.parent&.block_type? || !node.first_argument || lambda_with_symbol_proc?(node)
|
41
|
+
return
|
42
|
+
end
|
36
43
|
|
37
44
|
add_offense(node) do |corrector|
|
38
45
|
corrector.replace(node, node.first_argument.source.delete('&'))
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop checks if `include` or `prepend` is called in `refine` block.
|
7
|
+
# These methods are deprecated and should be replaced with `Refinement#import_methods`.
|
8
|
+
#
|
9
|
+
# It emulates deprecation warnings in Ruby 3.1.
|
10
|
+
#
|
11
|
+
# @safety
|
12
|
+
# This cop's autocorrection is unsafe because `include M` will affect the included class
|
13
|
+
# if any changes are made to module `M`.
|
14
|
+
# On the other hand, `import_methods M` uses a snapshot of method definitions,
|
15
|
+
# thus it will not be affected if module `M` changes.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
#
|
19
|
+
# # bad
|
20
|
+
# refine Foo do
|
21
|
+
# include Bar
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # bad
|
25
|
+
# refine Foo do
|
26
|
+
# prepend Bar
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# # good
|
30
|
+
# refine Foo do
|
31
|
+
# import_methods Bar
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
class RefinementImportMethods < Base
|
35
|
+
extend TargetRubyVersion
|
36
|
+
|
37
|
+
MSG = 'Use `import_methods` instead of `%<current>s` because it is deprecated in Ruby 3.1.'
|
38
|
+
RESTRICT_ON_SEND = %i[include prepend].freeze
|
39
|
+
|
40
|
+
minimum_target_ruby_version 3.1
|
41
|
+
|
42
|
+
def on_send(node)
|
43
|
+
return if node.receiver
|
44
|
+
return unless node.parent.block_type? && node.parent.method?(:refine)
|
45
|
+
|
46
|
+
add_offense(node.loc.selector, message: format(MSG, current: node.method_name))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -57,10 +57,20 @@ module RuboCop
|
|
57
57
|
|
58
58
|
outer_local_variable = variable_table.find_variable(variable.name)
|
59
59
|
return unless outer_local_variable
|
60
|
+
return if same_conditions_node_different_branch?(variable, outer_local_variable)
|
60
61
|
|
61
62
|
message = format(MSG, variable: variable.name)
|
62
63
|
add_offense(variable.declaration_node, message: message)
|
63
64
|
end
|
65
|
+
|
66
|
+
def same_conditions_node_different_branch?(variable, outer_local_variable)
|
67
|
+
variable_node = variable.scope.node.parent
|
68
|
+
return false unless variable_node.conditional?
|
69
|
+
|
70
|
+
outer_local_variable_node = outer_local_variable.scope.node
|
71
|
+
|
72
|
+
outer_local_variable_node.conditional? && variable_node == outer_local_variable_node
|
73
|
+
end
|
64
74
|
end
|
65
75
|
end
|
66
76
|
end
|
@@ -9,8 +9,7 @@ module RuboCop
|
|
9
9
|
def on_other_file
|
10
10
|
add_offense_from_error(processed_source.parser_error) if processed_source.parser_error
|
11
11
|
processed_source.diagnostics.each do |diagnostic|
|
12
|
-
add_offense_from_diagnostic(diagnostic,
|
13
|
-
processed_source.ruby_version)
|
12
|
+
add_offense_from_diagnostic(diagnostic, processed_source.ruby_version)
|
14
13
|
end
|
15
14
|
super
|
16
15
|
end
|
@@ -64,7 +64,7 @@ module RuboCop
|
|
64
64
|
|
65
65
|
# @!method not_implemented?(node)
|
66
66
|
def_node_matcher :not_implemented?, <<~PATTERN
|
67
|
-
{(send nil? :raise (const {nil? cbase} :NotImplementedError))
|
67
|
+
{(send nil? :raise (const {nil? cbase} :NotImplementedError) ...)
|
68
68
|
(send nil? :fail ...)}
|
69
69
|
PATTERN
|
70
70
|
|
@@ -101,8 +101,7 @@ module RuboCop
|
|
101
101
|
children = node.masgn_type? ? node.children[0].children : node.children
|
102
102
|
|
103
103
|
will_be_miscounted = children.count do |child|
|
104
|
-
child.respond_to?(:setter_method?) &&
|
105
|
-
!child.setter_method?
|
104
|
+
child.respond_to?(:setter_method?) && !child.setter_method?
|
106
105
|
end
|
107
106
|
@assignment += will_be_miscounted
|
108
107
|
|
@@ -4,8 +4,6 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
# Help methods for working with nodes containing comments.
|
6
6
|
module CommentsHelp
|
7
|
-
include VisibilityHelp
|
8
|
-
|
9
7
|
def source_range_with_comment(node)
|
10
8
|
begin_pos = begin_pos_with_comment(node)
|
11
9
|
end_pos = end_position_for(node)
|
@@ -13,6 +11,13 @@ module RuboCop
|
|
13
11
|
Parser::Source::Range.new(buffer, begin_pos, end_pos)
|
14
12
|
end
|
15
13
|
|
14
|
+
def contains_comments?(node)
|
15
|
+
start_line = node.source_range.line
|
16
|
+
end_line = find_end_line(node)
|
17
|
+
|
18
|
+
processed_source.each_comment_in_lines(start_line...end_line).any?
|
19
|
+
end
|
20
|
+
|
16
21
|
private
|
17
22
|
|
18
23
|
def end_position_for(node)
|
@@ -37,6 +42,21 @@ module RuboCop
|
|
37
42
|
def buffer
|
38
43
|
processed_source.buffer
|
39
44
|
end
|
45
|
+
|
46
|
+
# Returns the end line of a node, which might be a comment and not part of the AST
|
47
|
+
# End line is considered either the line at which another node starts, or
|
48
|
+
# the line at which the parent node ends.
|
49
|
+
def find_end_line(node)
|
50
|
+
if node.if_type? && node.loc.else
|
51
|
+
node.loc.else.line
|
52
|
+
elsif (next_sibling = node.right_sibling)
|
53
|
+
next_sibling.loc.line
|
54
|
+
elsif (parent = node.parent)
|
55
|
+
parent.loc.end.line
|
56
|
+
else
|
57
|
+
node.loc.end.line
|
58
|
+
end
|
59
|
+
end
|
40
60
|
end
|
41
61
|
end
|
42
62
|
end
|
@@ -65,9 +65,8 @@ module RuboCop
|
|
65
65
|
|
66
66
|
def use_modifier_form_without_parenthesized_method_call?(ancestor)
|
67
67
|
return false if ancestor.respond_to?(:parenthesized?) && ancestor.parenthesized?
|
68
|
-
return false unless (parent = ancestor.parent)
|
69
68
|
|
70
|
-
|
69
|
+
ancestor.ancestors.any? { |node| node.respond_to?(:modifier_form?) && node.modifier_form? }
|
71
70
|
end
|
72
71
|
|
73
72
|
def without_parentheses_call_expr_follows?(ancestor)
|
@@ -196,8 +196,7 @@ module RuboCop
|
|
196
196
|
|
197
197
|
def not_for_this_cop?(node)
|
198
198
|
node.ancestors.any? do |ancestor|
|
199
|
-
grouped_expression?(ancestor) ||
|
200
|
-
inside_arg_list_parentheses?(node, ancestor)
|
199
|
+
grouped_expression?(ancestor) || inside_arg_list_parentheses?(node, ancestor)
|
201
200
|
end
|
202
201
|
end
|
203
202
|
|
@@ -44,7 +44,8 @@ module RuboCop
|
|
44
44
|
if extra_space?(left_token, :left) && !start_ok
|
45
45
|
space_offense(node, left_token, :right, message, NO_SPACE_COMMAND)
|
46
46
|
end
|
47
|
-
return if !extra_space?(right_token, :right) || end_ok
|
47
|
+
return if (!extra_space?(right_token, :right) || end_ok) ||
|
48
|
+
(autocorrect_with_disable_uncorrectable? && !start_ok)
|
48
49
|
|
49
50
|
space_offense(node, right_token, :left, message, NO_SPACE_COMMAND)
|
50
51
|
end
|
@@ -58,7 +59,8 @@ module RuboCop
|
|
58
59
|
unless extra_space?(left_token, :left) || start_ok
|
59
60
|
space_offense(node, left_token, :none, message, SPACE_COMMAND)
|
60
61
|
end
|
61
|
-
return if extra_space?(right_token, :right) || end_ok
|
62
|
+
return if (extra_space?(right_token, :right) || end_ok) ||
|
63
|
+
(autocorrect_with_disable_uncorrectable? && !start_ok)
|
62
64
|
|
63
65
|
space_offense(node, right_token, :none, message, SPACE_COMMAND)
|
64
66
|
end
|
@@ -107,7 +107,7 @@ module RuboCop
|
|
107
107
|
def use_block_argument_as_local_variable?(node, last_argument)
|
108
108
|
return if node.body.nil?
|
109
109
|
|
110
|
-
node.body.each_descendant(:lvar).any? do |lvar|
|
110
|
+
node.body.each_descendant(:lvar, :lvasgn).any? do |lvar|
|
111
111
|
!lvar.parent.block_pass_type? && lvar.source == last_argument
|
112
112
|
end
|
113
113
|
end
|
@@ -72,9 +72,14 @@ module RuboCop
|
|
72
72
|
def end_of_method_definition?(node)
|
73
73
|
return false unless (def_node = find_def_node_from_ascendant(node))
|
74
74
|
|
75
|
+
conditional_node = find_conditional_node_from_ascendant(node)
|
75
76
|
last_child = find_last_child(def_node.body)
|
76
77
|
|
77
|
-
|
78
|
+
if conditional_node
|
79
|
+
double_negative_condition_return_value?(node, last_child, conditional_node)
|
80
|
+
else
|
81
|
+
last_child.last_line == node.last_line
|
82
|
+
end
|
78
83
|
end
|
79
84
|
|
80
85
|
def find_def_node_from_ascendant(node)
|
@@ -84,6 +89,13 @@ module RuboCop
|
|
84
89
|
find_def_node_from_ascendant(node.parent)
|
85
90
|
end
|
86
91
|
|
92
|
+
def find_conditional_node_from_ascendant(node)
|
93
|
+
return unless (parent = node.parent)
|
94
|
+
return parent if parent.conditional?
|
95
|
+
|
96
|
+
find_conditional_node_from_ascendant(parent)
|
97
|
+
end
|
98
|
+
|
87
99
|
def find_last_child(node)
|
88
100
|
case node.type
|
89
101
|
when :rescue
|
@@ -94,6 +106,25 @@ module RuboCop
|
|
94
106
|
node.child_nodes.last
|
95
107
|
end
|
96
108
|
end
|
109
|
+
|
110
|
+
def double_negative_condition_return_value?(node, last_child, conditional_node)
|
111
|
+
parent = find_parent_not_enumerable(node)
|
112
|
+
if parent.begin_type?
|
113
|
+
node.loc.line == parent.loc.last_line
|
114
|
+
else
|
115
|
+
last_child.last_line <= conditional_node.last_line
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def find_parent_not_enumerable(node)
|
120
|
+
return unless (parent = node.parent)
|
121
|
+
|
122
|
+
if parent.pair_type? || parent.hash_type? || parent.array_type?
|
123
|
+
find_parent_not_enumerable(parent)
|
124
|
+
else
|
125
|
+
parent
|
126
|
+
end
|
127
|
+
end
|
97
128
|
end
|
98
129
|
end
|
99
130
|
end
|
@@ -47,8 +47,7 @@ module RuboCop
|
|
47
47
|
branch_bodies = [*case_node.when_branches.map(&:body), case_node.else_branch].compact
|
48
48
|
|
49
49
|
return if branch_bodies.any? do |body|
|
50
|
-
body.return_type? ||
|
51
|
-
body.each_descendant.any?(&:return_type?)
|
50
|
+
body.return_type? || body.each_descendant.any?(&:return_type?)
|
52
51
|
end
|
53
52
|
|
54
53
|
add_offense(case_node.loc.keyword) { |corrector| autocorrect(corrector, case_node) }
|
@@ -5,6 +5,17 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Favor `File.(bin)write` convenience methods.
|
7
7
|
#
|
8
|
+
# NOTE: There are different method signatures between `File.write` (class method)
|
9
|
+
# and `File#write` (instance method). The following case will be allowed because
|
10
|
+
# static analysis does not know the contents of the splat argument:
|
11
|
+
#
|
12
|
+
# [source,ruby]
|
13
|
+
# ----
|
14
|
+
# File.open(filename, 'w') do |f|
|
15
|
+
# f.write(*objects)
|
16
|
+
# end
|
17
|
+
# ----
|
18
|
+
#
|
8
19
|
# @example
|
9
20
|
# ## text mode
|
10
21
|
# # bad
|
@@ -85,6 +96,7 @@ module RuboCop
|
|
85
96
|
content = send_write?(node) || block_write?(node) do |block_arg, lvar, write_arg|
|
86
97
|
write_arg if block_arg == lvar
|
87
98
|
end
|
99
|
+
return false if content&.splat_type?
|
88
100
|
|
89
101
|
yield(content) if content
|
90
102
|
end
|
@@ -107,8 +107,7 @@ module RuboCop
|
|
107
107
|
|
108
108
|
first_arg = node.first_argument
|
109
109
|
|
110
|
-
return
|
111
|
-
return if acceptable_exploded_args?(first_arg.arguments)
|
110
|
+
return if !use_new_method?(first_arg) || acceptable_exploded_args?(first_arg.arguments)
|
112
111
|
|
113
112
|
return if allowed_non_exploded_type?(first_arg)
|
114
113
|
|
@@ -120,6 +119,10 @@ module RuboCop
|
|
120
119
|
end
|
121
120
|
end
|
122
121
|
|
122
|
+
def use_new_method?(first_arg)
|
123
|
+
first_arg.send_type? && first_arg.receiver && first_arg.method?(:new)
|
124
|
+
end
|
125
|
+
|
123
126
|
def acceptable_exploded_args?(args)
|
124
127
|
# Allow code like `raise Ex.new(arg1, arg2)`.
|
125
128
|
return true if args.size > 1
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for `initialize` methods that are redundant.
|
7
|
+
#
|
8
|
+
# An initializer is redundant if it does not do anything, or if it only
|
9
|
+
# calls `super` with the same arguments given to it. If the initializer takes
|
10
|
+
# an argument that accepts multiple values (`restarg`, `kwrestarg`, etc.) it
|
11
|
+
# will not register an offense, because it allows the initializer to take a different
|
12
|
+
# number of arguments as its superclass potentially does.
|
13
|
+
#
|
14
|
+
# NOTE: If an initializer argument has a default value, RuboCop assumes it
|
15
|
+
# to *not* be redundant.
|
16
|
+
#
|
17
|
+
# NOTE: Empty initializers are registered as offenses, but it is possible
|
18
|
+
# to purposely create an empty `initialize` method to override a superclass's
|
19
|
+
# initializer.
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# # bad
|
23
|
+
# def initialize
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# # bad
|
27
|
+
# def initialize
|
28
|
+
# super
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# # bad
|
32
|
+
# def initialize(a, b)
|
33
|
+
# super
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# # bad
|
37
|
+
# def initialize(a, b)
|
38
|
+
# super(a, b)
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# # good
|
42
|
+
# def initialize
|
43
|
+
# do_something
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# # good
|
47
|
+
# def initialize
|
48
|
+
# do_something
|
49
|
+
# super
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# # good (different number of parameters)
|
53
|
+
# def initialize(a, b)
|
54
|
+
# super(a)
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# # good (default value)
|
58
|
+
# def initialize(a, b = 5)
|
59
|
+
# super
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# # good (default value)
|
63
|
+
# def initialize(a, b: 5)
|
64
|
+
# super
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# # good (changes the parameter requirements)
|
68
|
+
# def initialize(*)
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# # good (changes the parameter requirements)
|
72
|
+
# def initialize(**)
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# # good (changes the parameter requirements)
|
76
|
+
# def initialize(...)
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
class RedundantInitialize < Base
|
80
|
+
MSG = 'Remove unnecessary `initialize` method.'
|
81
|
+
MSG_EMPTY = 'Remove unnecessary empty `initialize` method.'
|
82
|
+
|
83
|
+
# @!method initialize_forwards?(node)
|
84
|
+
def_node_matcher :initialize_forwards?, <<~PATTERN
|
85
|
+
(def _ (args $arg*) $({super zsuper} ...))
|
86
|
+
PATTERN
|
87
|
+
|
88
|
+
def on_def(node)
|
89
|
+
return unless node.method?(:initialize)
|
90
|
+
return if forwards?(node)
|
91
|
+
|
92
|
+
if node.body.nil?
|
93
|
+
add_offense(node, message: MSG_EMPTY)
|
94
|
+
else
|
95
|
+
return if node.body.begin_type?
|
96
|
+
|
97
|
+
if (args, super_node = initialize_forwards?(node))
|
98
|
+
return unless same_args?(super_node, args)
|
99
|
+
|
100
|
+
add_offense(node)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def forwards?(node)
|
108
|
+
node.arguments.each_child_node(:restarg, :kwrestarg, :forward_args, :forward_arg).any?
|
109
|
+
end
|
110
|
+
|
111
|
+
def same_args?(super_node, args)
|
112
|
+
return true if super_node.zsuper_type?
|
113
|
+
|
114
|
+
args.map(&:name) == super_node.arguments.map { |a| a.children[0] }
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -7,8 +7,7 @@ module RuboCop
|
|
7
7
|
# check for the variable whose method is being called to
|
8
8
|
# safe navigation (`&.`). If there is a method chain, all of the methods
|
9
9
|
# in the chain need to be checked for safety, and all of the methods will
|
10
|
-
# need to be changed to use safe navigation.
|
11
|
-
# not register an offense for method chains that exceed 2 methods.
|
10
|
+
# need to be changed to use safe navigation.
|
12
11
|
#
|
13
12
|
# The default for `ConvertCodeThatCanStartToReturnNil` is `false`.
|
14
13
|
# When configured to `true`, this will
|
@@ -18,6 +17,10 @@ module RuboCop
|
|
18
17
|
# `foo&.bar` can start returning `nil` as well as what the method
|
19
18
|
# returns.
|
20
19
|
#
|
20
|
+
# The default for `MaxChainLength` is `2`
|
21
|
+
# We have limited the cop to not register an offense for method chains
|
22
|
+
# that exceed this option is set.
|
23
|
+
#
|
21
24
|
# @safety
|
22
25
|
# Autocorrection is unsafe because if a value is `false`, the resulting
|
23
26
|
# code will have different behaviour or raise an error.
|
@@ -116,9 +119,7 @@ module RuboCop
|
|
116
119
|
checked_variable, receiver, method_chain, method = extract_parts(node)
|
117
120
|
return unless receiver == checked_variable
|
118
121
|
return if use_var_only_in_unless_modifier?(node, checked_variable)
|
119
|
-
|
120
|
-
# chain greater than 2
|
121
|
-
return if chain_size(method_chain, method) > 1
|
122
|
+
return if chain_length(method_chain, method) > max_chain_length
|
122
123
|
return if unsafe_method_used?(method_chain, method)
|
123
124
|
return if method_chain.method?(:empty?)
|
124
125
|
|
@@ -225,8 +226,8 @@ module RuboCop
|
|
225
226
|
find_matching_receiver_invocation(receiver, checked_variable)
|
226
227
|
end
|
227
228
|
|
228
|
-
def
|
229
|
-
method.each_ancestor(:send).inject(
|
229
|
+
def chain_length(method_chain, method)
|
230
|
+
method.each_ancestor(:send).inject(1) do |total, ancestor|
|
230
231
|
break total + 1 if ancestor == method_chain
|
231
232
|
|
232
233
|
total + 1
|
@@ -281,6 +282,10 @@ module RuboCop
|
|
281
282
|
break if ancestor == method_chain
|
282
283
|
end
|
283
284
|
end
|
285
|
+
|
286
|
+
def max_chain_length
|
287
|
+
cop_config.fetch('MaxChainLength', 2)
|
288
|
+
end
|
284
289
|
end
|
285
290
|
end
|
286
291
|
end
|
@@ -184,8 +184,7 @@ module RuboCop
|
|
184
184
|
|
185
185
|
def unsafe_autocorrect?(condition)
|
186
186
|
condition.children.any? do |child|
|
187
|
-
unparenthesized_method_call?(child) ||
|
188
|
-
below_ternary_precedence?(child)
|
187
|
+
unparenthesized_method_call?(child) || below_ternary_precedence?(child)
|
189
188
|
end
|
190
189
|
end
|
191
190
|
|
@@ -42,10 +42,7 @@ module RuboCop
|
|
42
42
|
return if node.endless? || !trailing_end?(node)
|
43
43
|
|
44
44
|
add_offense(node.loc.end) do |corrector|
|
45
|
-
corrector.insert_before(
|
46
|
-
node.loc.end,
|
47
|
-
"\n#{' ' * node.loc.keyword.column}"
|
48
|
-
)
|
45
|
+
corrector.insert_before(node.loc.end, "\n#{' ' * node.loc.keyword.column}")
|
49
46
|
end
|
50
47
|
end
|
51
48
|
|
@@ -17,6 +17,7 @@ module RuboCop
|
|
17
17
|
def started(target_files)
|
18
18
|
super
|
19
19
|
@offense_counts = Hash.new(0)
|
20
|
+
@style_guide_links = {}
|
20
21
|
|
21
22
|
return unless output.tty?
|
22
23
|
|
@@ -37,6 +38,9 @@ module RuboCop
|
|
37
38
|
|
38
39
|
def file_finished(_file, offenses)
|
39
40
|
offenses.each { |o| @offense_counts[o.cop_name] += 1 }
|
41
|
+
if options[:display_style_guide]
|
42
|
+
offenses.each { |o| @style_guide_links[o.cop_name] ||= o.message[/ \(http\S+\)\Z/] }
|
43
|
+
end
|
40
44
|
@progressbar.increment if instance_variable_defined?(:@progressbar)
|
41
45
|
end
|
42
46
|
|
@@ -52,8 +56,8 @@ module RuboCop
|
|
52
56
|
output.puts
|
53
57
|
|
54
58
|
per_cop_counts.each do |cop_name, count|
|
55
|
-
output.puts "#{count.to_s.ljust(total_count.to_s.length + 2)}" \
|
56
|
-
"#{cop_name}\n"
|
59
|
+
output.puts "#{count.to_s.ljust(total_count.to_s.length + 2)}#{cop_name}" \
|
60
|
+
"#{@style_guide_links[cop_name]}\n"
|
57
61
|
end
|
58
62
|
output.puts '--'
|
59
63
|
output.puts "#{total_count} Total"
|
@@ -40,8 +40,7 @@ module RuboCop
|
|
40
40
|
output.puts
|
41
41
|
|
42
42
|
per_file_counts.each do |file_name, count|
|
43
|
-
output.puts "#{count.to_s.ljust(total_count.to_s.length + 2)}"
|
44
|
-
"#{file_name}\n"
|
43
|
+
output.puts "#{count.to_s.ljust(total_count.to_s.length + 2)}#{file_name}\n"
|
45
44
|
end
|
46
45
|
output.puts '--'
|
47
46
|
output.puts "#{total_count} Total"
|
data/lib/rubocop/result_cache.rb
CHANGED
@@ -73,7 +73,15 @@ module RuboCop
|
|
73
73
|
# access.
|
74
74
|
File.join(ENV['XDG_CACHE_HOME'], Process.uid.to_s)
|
75
75
|
else
|
76
|
-
|
76
|
+
# On FreeBSD, the /home path is a symbolic link to /usr/home
|
77
|
+
# and the $HOME environment variable returns the /home path.
|
78
|
+
#
|
79
|
+
# As $HOME is a built-in environment variable, FreeBSD users
|
80
|
+
# always get a warning message.
|
81
|
+
#
|
82
|
+
# To avoid raising warn log messages on FreeBSD, we retrieve
|
83
|
+
# the real path of the home folder.
|
84
|
+
File.join(File.realpath(ENV['HOME']), '.cache')
|
77
85
|
end
|
78
86
|
File.join(root, 'rubocop_cache')
|
79
87
|
end
|
data/lib/rubocop/version.rb
CHANGED
data/lib/rubocop.rb
CHANGED
@@ -348,6 +348,7 @@ require_relative 'rubocop/cop/lint/redundant_splat_expansion'
|
|
348
348
|
require_relative 'rubocop/cop/lint/redundant_string_coercion'
|
349
349
|
require_relative 'rubocop/cop/lint/redundant_with_index'
|
350
350
|
require_relative 'rubocop/cop/lint/redundant_with_object'
|
351
|
+
require_relative 'rubocop/cop/lint/refinement_import_methods'
|
351
352
|
require_relative 'rubocop/cop/lint/regexp_as_condition'
|
352
353
|
require_relative 'rubocop/cop/lint/require_parentheses'
|
353
354
|
require_relative 'rubocop/cop/lint/require_relative_self_path'
|
@@ -527,6 +528,7 @@ require_relative 'rubocop/cop/style/open_struct_use'
|
|
527
528
|
require_relative 'rubocop/cop/style/redundant_assignment'
|
528
529
|
require_relative 'rubocop/cop/style/redundant_fetch_block'
|
529
530
|
require_relative 'rubocop/cop/style/redundant_file_extension_in_require'
|
531
|
+
require_relative 'rubocop/cop/style/redundant_initialize'
|
530
532
|
require_relative 'rubocop/cop/style/redundant_self_assignment'
|
531
533
|
require_relative 'rubocop/cop/style/redundant_self_assignment_branch'
|
532
534
|
require_relative 'rubocop/cop/style/sole_nested_conditional'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.27.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-
|
13
|
+
date: 2022-04-08 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: parallel
|
@@ -460,6 +460,7 @@ files:
|
|
460
460
|
- lib/rubocop/cop/lint/redundant_string_coercion.rb
|
461
461
|
- lib/rubocop/cop/lint/redundant_with_index.rb
|
462
462
|
- lib/rubocop/cop/lint/redundant_with_object.rb
|
463
|
+
- lib/rubocop/cop/lint/refinement_import_methods.rb
|
463
464
|
- lib/rubocop/cop/lint/regexp_as_condition.rb
|
464
465
|
- lib/rubocop/cop/lint/require_parentheses.rb
|
465
466
|
- lib/rubocop/cop/lint/require_relative_self_path.rb
|
@@ -778,6 +779,7 @@ files:
|
|
778
779
|
- lib/rubocop/cop/style/redundant_fetch_block.rb
|
779
780
|
- lib/rubocop/cop/style/redundant_file_extension_in_require.rb
|
780
781
|
- lib/rubocop/cop/style/redundant_freeze.rb
|
782
|
+
- lib/rubocop/cop/style/redundant_initialize.rb
|
781
783
|
- lib/rubocop/cop/style/redundant_interpolation.rb
|
782
784
|
- lib/rubocop/cop/style/redundant_parentheses.rb
|
783
785
|
- lib/rubocop/cop/style/redundant_percent_q.rb
|
@@ -913,7 +915,7 @@ metadata:
|
|
913
915
|
homepage_uri: https://rubocop.org/
|
914
916
|
changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
|
915
917
|
source_code_uri: https://github.com/rubocop/rubocop/
|
916
|
-
documentation_uri: https://docs.rubocop.org/rubocop/1.
|
918
|
+
documentation_uri: https://docs.rubocop.org/rubocop/1.27/
|
917
919
|
bug_tracker_uri: https://github.com/rubocop/rubocop/issues
|
918
920
|
rubygems_mfa_required: 'true'
|
919
921
|
post_install_message:
|