rubocop 1.49.0 → 1.50.1
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 +6 -5
- data/lib/rubocop/config_loader.rb +8 -8
- data/lib/rubocop/cop/layout/class_structure.rb +1 -0
- data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines.rb +1 -1
- data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +122 -0
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +35 -15
- data/lib/rubocop/cop/metrics/class_length.rb +1 -0
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
- data/lib/rubocop/cop/naming/ascii_identifiers.rb +1 -1
- data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
- data/lib/rubocop/cop/style/class_equality_comparison.rb +27 -7
- data/lib/rubocop/cop/style/copyright.rb +1 -1
- data/lib/rubocop/cop/style/file_empty.rb +3 -3
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +6 -3
- data/lib/rubocop/cop/style/parallel_assignment.rb +26 -18
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +42 -5
- data/lib/rubocop/cop/style/trailing_body_on_class.rb +1 -0
- data/lib/rubocop/cops_documentation_generator.rb +10 -3
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +1 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc74785ce6643999994c7595e6ab7b6508abc7ab33532032d09fb854808d3ab5
|
4
|
+
data.tar.gz: 3313880579d587260cae9f718b148160a597da1a239464c9ae86ce8a773065fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b4ea0d9447499f45e99d333c05f72edd634980d506717117cb35029ac2f185de08681c68ce40a2d319efe163b23a168e6c9a55f8178dbf25f847ecc7710cb04
|
7
|
+
data.tar.gz: e1c57df60ec75958f78eec411b0697496ea34b0a10626b3fa79453a64328162292cb621319557b0aac59fe88d447fa32a5e3fbcf1d4d4efcf9ef9388191a6fee
|
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.50', 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
@@ -1016,8 +1016,6 @@ Layout/LineContinuationLeadingSpace:
|
|
1016
1016
|
Layout/LineContinuationSpacing:
|
1017
1017
|
Description: 'Checks the spacing in front of backslash in line continuations.'
|
1018
1018
|
Enabled: pending
|
1019
|
-
AutoCorrect: true
|
1020
|
-
SafeAutoCorrect: true
|
1021
1019
|
VersionAdded: '1.31'
|
1022
1020
|
EnforcedStyle: space
|
1023
1021
|
SupportedStyles:
|
@@ -1752,6 +1750,11 @@ Lint/DuplicateMagicComment:
|
|
1752
1750
|
Enabled: pending
|
1753
1751
|
VersionAdded: '1.37'
|
1754
1752
|
|
1753
|
+
Lint/DuplicateMatchPattern:
|
1754
|
+
Description: 'Do not repeat patterns in `in` keywords.'
|
1755
|
+
Enabled: pending
|
1756
|
+
VersionAdded: '1.50'
|
1757
|
+
|
1755
1758
|
Lint/DuplicateMethods:
|
1756
1759
|
Description: 'Check for duplicate method definitions.'
|
1757
1760
|
Enabled: true
|
@@ -3743,7 +3746,6 @@ Style/FileEmpty:
|
|
3743
3746
|
Prefer to use `File.empty?('path/to/file')` when checking if a file is empty.
|
3744
3747
|
Enabled: pending
|
3745
3748
|
Safe: false
|
3746
|
-
SafeAutoCorrect: false
|
3747
3749
|
VersionAdded: '1.48'
|
3748
3750
|
|
3749
3751
|
Style/FileRead:
|
@@ -4571,11 +4573,10 @@ Style/NumericPredicate:
|
|
4571
4573
|
Checks for the use of predicate- or comparison methods for
|
4572
4574
|
numeric comparisons.
|
4573
4575
|
StyleGuide: '#predicate-methods'
|
4574
|
-
Safe: false
|
4575
4576
|
# This will change to a new method call which isn't guaranteed to be on the
|
4576
4577
|
# object. Switching these methods has to be done with knowledge of the types
|
4577
4578
|
# of the variables which rubocop doesn't have.
|
4578
|
-
|
4579
|
+
Safe: false
|
4579
4580
|
Enabled: true
|
4580
4581
|
VersionAdded: '0.42'
|
4581
4582
|
VersionChanged: '0.59'
|
@@ -23,6 +23,14 @@ module RuboCop
|
|
23
23
|
class << self
|
24
24
|
include FileFinder
|
25
25
|
|
26
|
+
PENDING_BANNER = <<~BANNER
|
27
|
+
The following cops were added to RuboCop, but are not configured. Please set Enabled to either `true` or `false` in your `.rubocop.yml` file.
|
28
|
+
|
29
|
+
Please also note that you can opt-in to new cops by default by adding this to your config:
|
30
|
+
AllCops:
|
31
|
+
NewCops: enable
|
32
|
+
BANNER
|
33
|
+
|
26
34
|
attr_accessor :debug, :ignore_parent_exclusion, :disable_pending_cops, :enable_pending_cops,
|
27
35
|
:ignore_unrecognized_cops
|
28
36
|
attr_writer :default_configuration
|
@@ -165,14 +173,6 @@ module RuboCop
|
|
165
173
|
ConfigFinder.project_root
|
166
174
|
end
|
167
175
|
|
168
|
-
PENDING_BANNER = <<~BANNER
|
169
|
-
The following cops were added to RuboCop, but are not configured. Please set Enabled to either `true` or `false` in your `.rubocop.yml` file.
|
170
|
-
|
171
|
-
Please also note that you can opt-in to new cops by default by adding this to your config:
|
172
|
-
AllCops:
|
173
|
-
NewCops: enable
|
174
|
-
BANNER
|
175
|
-
|
176
176
|
def warn_on_pending_cops(pending_cops)
|
177
177
|
warn Rainbow(PENDING_BANNER).yellow
|
178
178
|
|
@@ -137,7 +137,7 @@ module RuboCop
|
|
137
137
|
end
|
138
138
|
|
139
139
|
def current_token(comment)
|
140
|
-
processed_source.
|
140
|
+
processed_source.tokens.find { |token| token.pos == comment.source_range }
|
141
141
|
end
|
142
142
|
|
143
143
|
def previous_token(node)
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
31
31
|
return unless processed_source.raw_source.include?("\n\n\n")
|
32
32
|
|
33
33
|
lines = Set.new
|
34
|
-
processed_source.
|
34
|
+
processed_source.tokens.each { |token| lines << token.line }
|
35
35
|
|
36
36
|
each_extra_empty_line(lines.sort) do |range|
|
37
37
|
add_offense(range) do |corrector|
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# Checks that there are no repeated patterns used in `in` keywords.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
# case x
|
12
|
+
# in 'first'
|
13
|
+
# do_something
|
14
|
+
# in 'first'
|
15
|
+
# do_something_else
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# case x
|
20
|
+
# in 'first'
|
21
|
+
# do_something
|
22
|
+
# in 'second'
|
23
|
+
# do_something_else
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# # bad - repeated alternate patterns with the same conditions don't depend on the order
|
27
|
+
# case x
|
28
|
+
# in foo | bar
|
29
|
+
# first_method
|
30
|
+
# in bar | foo
|
31
|
+
# second_method
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# # good
|
35
|
+
# case x
|
36
|
+
# in foo | bar
|
37
|
+
# first_method
|
38
|
+
# in bar | baz
|
39
|
+
# second_method
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # bad - repeated hash patterns with the same conditions don't depend on the order
|
43
|
+
# case x
|
44
|
+
# in foo: a, bar: b
|
45
|
+
# first_method
|
46
|
+
# in bar: b, foo: a
|
47
|
+
# second_method
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# # good
|
51
|
+
# case x
|
52
|
+
# in foo: a, bar: b
|
53
|
+
# first_method
|
54
|
+
# in bar: b, baz: c
|
55
|
+
# second_method
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# # bad - repeated array patterns with elements in the same order
|
59
|
+
# case x
|
60
|
+
# in [foo, bar]
|
61
|
+
# first_method
|
62
|
+
# in [foo, bar]
|
63
|
+
# second_method
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# # good
|
67
|
+
# case x
|
68
|
+
# in [foo, bar]
|
69
|
+
# first_method
|
70
|
+
# in [bar, foo]
|
71
|
+
# second_method
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# # bad - repeated the same patterns and guard conditions
|
75
|
+
# case x
|
76
|
+
# in foo if bar
|
77
|
+
# first_method
|
78
|
+
# in foo if bar
|
79
|
+
# second_method
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# # good
|
83
|
+
# case x
|
84
|
+
# in foo if bar
|
85
|
+
# first_method
|
86
|
+
# in foo if baz
|
87
|
+
# second_method
|
88
|
+
# end
|
89
|
+
#
|
90
|
+
class DuplicateMatchPattern < Base
|
91
|
+
extend TargetRubyVersion
|
92
|
+
|
93
|
+
MSG = 'Duplicate `in` pattern detected.'
|
94
|
+
|
95
|
+
minimum_target_ruby_version 2.7
|
96
|
+
|
97
|
+
def on_case_match(case_node)
|
98
|
+
case_node.in_pattern_branches.each_with_object(Set.new) do |in_pattern_node, previous|
|
99
|
+
pattern = in_pattern_node.pattern
|
100
|
+
next if previous.add?(pattern_identity(pattern))
|
101
|
+
|
102
|
+
add_offense(pattern)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def pattern_identity(pattern)
|
109
|
+
pattern_source = if pattern.hash_pattern_type? || pattern.match_alt_type?
|
110
|
+
pattern.children.map(&:source).sort
|
111
|
+
else
|
112
|
+
pattern.source
|
113
|
+
end
|
114
|
+
|
115
|
+
return pattern_source unless (guard = pattern.parent.children[1])
|
116
|
+
|
117
|
+
pattern_source + guard.source
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Lint
|
6
|
-
# Checks for string conversion in string interpolation,
|
6
|
+
# Checks for string conversion in string interpolation, `print`, `puts`, and `warn` arguments,
|
7
7
|
# which is redundant.
|
8
8
|
#
|
9
9
|
# @example
|
@@ -11,18 +11,26 @@ module RuboCop
|
|
11
11
|
# # bad
|
12
12
|
#
|
13
13
|
# "result is #{something.to_s}"
|
14
|
+
# print something.to_s
|
15
|
+
# puts something.to_s
|
16
|
+
# warn something.to_s
|
14
17
|
#
|
15
18
|
# @example
|
16
19
|
#
|
17
20
|
# # good
|
18
21
|
#
|
19
22
|
# "result is #{something}"
|
23
|
+
# print something
|
24
|
+
# puts something
|
25
|
+
# warn something
|
26
|
+
#
|
20
27
|
class RedundantStringCoercion < Base
|
21
28
|
include Interpolation
|
22
29
|
extend AutoCorrector
|
23
30
|
|
24
|
-
MSG_DEFAULT = 'Redundant use of `Object#to_s` in
|
25
|
-
MSG_SELF = 'Use `self` instead of `Object#to_s` in
|
31
|
+
MSG_DEFAULT = 'Redundant use of `Object#to_s` in %<context>s.'
|
32
|
+
MSG_SELF = 'Use `self` instead of `Object#to_s` in %<context>s.'
|
33
|
+
RESTRICT_ON_SEND = %i[print puts warn].freeze
|
26
34
|
|
27
35
|
# @!method to_s_without_args?(node)
|
28
36
|
def_node_matcher :to_s_without_args?, '(send _ :to_s)'
|
@@ -32,18 +40,30 @@ module RuboCop
|
|
32
40
|
|
33
41
|
return unless to_s_without_args?(final_node)
|
34
42
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
register_offense(final_node, 'interpolation')
|
44
|
+
end
|
45
|
+
|
46
|
+
def on_send(node)
|
47
|
+
return if node.receiver
|
48
|
+
|
49
|
+
node.each_child_node(:send) do |child|
|
50
|
+
next unless child.method?(:to_s)
|
51
|
+
|
52
|
+
register_offense(child, "`#{node.method_name}`")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def register_offense(node, context)
|
59
|
+
receiver = node.receiver
|
60
|
+
template = receiver ? MSG_DEFAULT : MSG_SELF
|
61
|
+
message = format(template, context: context)
|
62
|
+
|
63
|
+
add_offense(node.loc.selector, message: message) do |corrector|
|
64
|
+
replacement = receiver ? receiver.source : 'self'
|
65
|
+
|
66
|
+
corrector.replace(node, replacement)
|
47
67
|
end
|
48
68
|
end
|
49
69
|
end
|
@@ -10,7 +10,7 @@ module RuboCop
|
|
10
10
|
include Util
|
11
11
|
|
12
12
|
FOLDABLE_TYPES = %i[array hash heredoc send csend].freeze
|
13
|
-
CLASSLIKE_TYPES = %i[class module].freeze
|
13
|
+
CLASSLIKE_TYPES = %i[class module sclass].freeze
|
14
14
|
private_constant :FOLDABLE_TYPES, :CLASSLIKE_TYPES
|
15
15
|
|
16
16
|
def initialize(node, processed_source, count_comments: false, foldable_types: [])
|
@@ -69,7 +69,7 @@ module RuboCop
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def first_line_comment(node)
|
72
|
-
comment = processed_source.
|
72
|
+
comment = processed_source.comments.find { |c| same_line?(c, node) }
|
73
73
|
return unless comment
|
74
74
|
|
75
75
|
comment_source = comment.source
|
@@ -57,7 +57,7 @@ module RuboCop
|
|
57
57
|
CONSTANT_MSG = 'Use only ascii symbols in constants.'
|
58
58
|
|
59
59
|
def on_new_investigation
|
60
|
-
processed_source.
|
60
|
+
processed_source.tokens.each do |token|
|
61
61
|
next if !should_check?(token) || token.text.ascii_only?
|
62
62
|
|
63
63
|
message = token.type == :tIDENTIFIER ? IDENTIFIER_MSG : CONSTANT_MSG
|
@@ -72,7 +72,7 @@ module RuboCop
|
|
72
72
|
include AllowedPattern
|
73
73
|
extend AutoCorrector
|
74
74
|
|
75
|
-
MSG = 'Use `instance_of
|
75
|
+
MSG = 'Use `instance_of?%<class_argument>s` instead of comparing classes.'
|
76
76
|
|
77
77
|
RESTRICT_ON_SEND = %i[== equal? eql?].freeze
|
78
78
|
CLASS_NAME_METHODS = %i[name to_s inspect].freeze
|
@@ -92,10 +92,12 @@ module RuboCop
|
|
92
92
|
|
93
93
|
class_comparison_candidate?(node) do |receiver_node, class_node|
|
94
94
|
range = offense_range(receiver_node, node)
|
95
|
-
class_name = class_name(class_node, node)
|
95
|
+
class_argument = (class_name = class_name(class_node, node)) ? "(#{class_name})" : ''
|
96
96
|
|
97
|
-
add_offense(range, message: format(MSG,
|
98
|
-
|
97
|
+
add_offense(range, message: format(MSG, class_argument: class_argument)) do |corrector|
|
98
|
+
next unless class_name
|
99
|
+
|
100
|
+
corrector.replace(range, "instance_of?#{class_argument}")
|
99
101
|
end
|
100
102
|
end
|
101
103
|
end
|
@@ -104,12 +106,18 @@ module RuboCop
|
|
104
106
|
|
105
107
|
def class_name(class_node, node)
|
106
108
|
if class_name_method?(node.children.first.method_name)
|
107
|
-
|
109
|
+
if (receiver = class_node.receiver) && class_name_method?(class_node.method_name)
|
110
|
+
return receiver.source
|
111
|
+
end
|
108
112
|
|
109
113
|
if class_node.str_type?
|
110
|
-
value = class_node
|
111
|
-
value.prepend('::') if class_node
|
114
|
+
value = trim_string_quotes(class_node)
|
115
|
+
value.prepend('::') if require_cbase?(class_node)
|
112
116
|
return value
|
117
|
+
elsif unable_to_determine_type?(class_node)
|
118
|
+
# When a variable or return value of a method is used, it returns nil
|
119
|
+
# because the type is not known and cannot be suggested.
|
120
|
+
return
|
113
121
|
end
|
114
122
|
end
|
115
123
|
|
@@ -120,6 +128,18 @@ module RuboCop
|
|
120
128
|
CLASS_NAME_METHODS.include?(method_name)
|
121
129
|
end
|
122
130
|
|
131
|
+
def require_cbase?(class_node)
|
132
|
+
class_node.each_ancestor(:class, :module).any?
|
133
|
+
end
|
134
|
+
|
135
|
+
def unable_to_determine_type?(class_node)
|
136
|
+
class_node.variable? || class_node.call_type?
|
137
|
+
end
|
138
|
+
|
139
|
+
def trim_string_quotes(class_node)
|
140
|
+
class_node.source.delete('"').delete("'")
|
141
|
+
end
|
142
|
+
|
123
143
|
def offense_range(receiver_node, node)
|
124
144
|
range_between(receiver_node.loc.selector.begin_pos, node.source_range.end_pos)
|
125
145
|
end
|
@@ -82,7 +82,7 @@ module RuboCop
|
|
82
82
|
def notice_found?(processed_source)
|
83
83
|
notice_found = false
|
84
84
|
notice_regexp = Regexp.new(notice)
|
85
|
-
processed_source.
|
85
|
+
processed_source.tokens.each do |token|
|
86
86
|
break unless token.comment?
|
87
87
|
|
88
88
|
notice_found = notice_regexp.match?(token.text)
|
@@ -6,9 +6,9 @@ module RuboCop
|
|
6
6
|
# Prefer to use `File.empty?('path/to/file')` when checking if a file is empty.
|
7
7
|
#
|
8
8
|
# @safety
|
9
|
-
# This cop
|
10
|
-
#
|
11
|
-
#
|
9
|
+
# This cop is unsafe, because `File.size`, `File.read`, and `File.binread`
|
10
|
+
# raise `ENOENT` exception when there is no file corresponding to the path,
|
11
|
+
# while `File.empty?` does not raise an exception.
|
12
12
|
#
|
13
13
|
# @example
|
14
14
|
# # bad
|
@@ -28,14 +28,17 @@ module RuboCop
|
|
28
28
|
return unless node.arguments?
|
29
29
|
return if opening_line(node) == closing_line(node)
|
30
30
|
return if correction_exceeds_max_line_length?(node)
|
31
|
+
return unless (begin_of_arguments = node.arguments.loc.begin)
|
31
32
|
|
32
|
-
add_offense(node)
|
33
|
+
add_offense(node) do |corrector|
|
34
|
+
autocorrect(corrector, node, begin_of_arguments)
|
35
|
+
end
|
33
36
|
end
|
34
37
|
alias on_defs on_def
|
35
38
|
|
36
39
|
private
|
37
40
|
|
38
|
-
def autocorrect(corrector, node)
|
41
|
+
def autocorrect(corrector, node, begin_of_arguments)
|
39
42
|
arguments = node.arguments
|
40
43
|
joined_arguments = arguments.map(&:source).join(', ')
|
41
44
|
last_line_source_of_arguments = last_line_source_of_arguments(arguments)
|
@@ -47,7 +50,7 @@ module RuboCop
|
|
47
50
|
end
|
48
51
|
|
49
52
|
corrector.remove(arguments_range(node))
|
50
|
-
corrector.insert_after(
|
53
|
+
corrector.insert_after(begin_of_arguments, joined_arguments)
|
51
54
|
end
|
52
55
|
|
53
56
|
def last_line_source_of_arguments(arguments)
|
@@ -31,22 +31,26 @@ module RuboCop
|
|
31
31
|
def on_masgn(node)
|
32
32
|
lhs, rhs = *node
|
33
33
|
lhs_elements = *lhs
|
34
|
+
rhs = rhs.body if rhs.rescue_type?
|
34
35
|
rhs_elements = Array(rhs).compact # edge case for one constant
|
35
36
|
|
36
37
|
return if allowed_lhs?(lhs) || allowed_rhs?(rhs) ||
|
37
38
|
allowed_masign?(lhs_elements, rhs_elements)
|
38
39
|
|
39
|
-
|
40
|
+
range = node.source_range.begin.join(rhs.source_range.end)
|
41
|
+
|
42
|
+
add_offense(range) do |corrector|
|
43
|
+
autocorrect(corrector, node, lhs, rhs)
|
44
|
+
end
|
40
45
|
end
|
41
46
|
|
42
47
|
private
|
43
48
|
|
44
|
-
def autocorrect(corrector, node)
|
45
|
-
|
46
|
-
|
47
|
-
right_elements = Array(right).compact
|
49
|
+
def autocorrect(corrector, node, lhs, rhs)
|
50
|
+
left_elements = *lhs
|
51
|
+
right_elements = Array(rhs).compact
|
48
52
|
order = find_valid_order(left_elements, right_elements)
|
49
|
-
correction = assignment_corrector(node, order)
|
53
|
+
correction = assignment_corrector(node, rhs, order)
|
50
54
|
|
51
55
|
corrector.replace(correction.correction_range, correction.correction)
|
52
56
|
end
|
@@ -77,14 +81,19 @@ module RuboCop
|
|
77
81
|
node.block_type? || node.send_type?
|
78
82
|
end
|
79
83
|
|
80
|
-
def assignment_corrector(node, order)
|
81
|
-
|
84
|
+
def assignment_corrector(node, rhs, order)
|
85
|
+
if node.parent&.rescue_type?
|
86
|
+
_assignment, modifier = *node.parent
|
87
|
+
else
|
88
|
+
_assignment, modifier = *rhs.parent
|
89
|
+
end
|
90
|
+
|
82
91
|
if modifier_statement?(node.parent)
|
83
|
-
ModifierCorrector.new(node, config, order)
|
92
|
+
ModifierCorrector.new(node, rhs, modifier, config, order)
|
84
93
|
elsif rescue_modifier?(modifier)
|
85
|
-
RescueCorrector.new(node, config, order)
|
94
|
+
RescueCorrector.new(node, rhs, modifier, config, order)
|
86
95
|
else
|
87
|
-
GenericCorrector.new(node, config, order)
|
96
|
+
GenericCorrector.new(node, rhs, modifier, config, order)
|
88
97
|
end
|
89
98
|
end
|
90
99
|
|
@@ -181,10 +190,12 @@ module RuboCop
|
|
181
190
|
class GenericCorrector
|
182
191
|
include Alignment
|
183
192
|
|
184
|
-
attr_reader :
|
193
|
+
attr_reader :node, :rhs, :rescue_result, :config
|
185
194
|
|
186
|
-
def initialize(node, config, new_elements)
|
195
|
+
def initialize(node, rhs, modifier, config, new_elements)
|
187
196
|
@node = node
|
197
|
+
@rhs = rhs
|
198
|
+
_, _, @rescue_result = *modifier
|
188
199
|
@config = config
|
189
200
|
@new_elements = new_elements
|
190
201
|
end
|
@@ -228,13 +239,10 @@ module RuboCop
|
|
228
239
|
# protected by rescue
|
229
240
|
class RescueCorrector < GenericCorrector
|
230
241
|
def correction
|
231
|
-
_node, rescue_clause = *node.parent
|
232
|
-
_, _, rescue_result = *rescue_clause
|
233
|
-
|
234
242
|
# If the parallel assignment uses a rescue modifier and it is the
|
235
243
|
# only contents of a method, then we want to make use of the
|
236
244
|
# implicit begin
|
237
|
-
if
|
245
|
+
if rhs.parent.parent.parent&.def_type?
|
238
246
|
super + def_correction(rescue_result)
|
239
247
|
else
|
240
248
|
begin_correction(rescue_result)
|
@@ -242,7 +250,7 @@ module RuboCop
|
|
242
250
|
end
|
243
251
|
|
244
252
|
def correction_range
|
245
|
-
|
253
|
+
rhs.parent.parent.source_range
|
246
254
|
end
|
247
255
|
|
248
256
|
private
|
@@ -69,6 +69,7 @@ module RuboCop
|
|
69
69
|
extend AutoCorrector
|
70
70
|
|
71
71
|
MSG = 'Redundant line continuation.'
|
72
|
+
ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
|
72
73
|
|
73
74
|
def on_new_investigation
|
74
75
|
return unless processed_source.ast
|
@@ -88,7 +89,8 @@ module RuboCop
|
|
88
89
|
def require_line_continuation?(range)
|
89
90
|
!ends_with_backslash_without_comment?(range.source_line) ||
|
90
91
|
string_concatenation?(range.source_line) ||
|
91
|
-
|
92
|
+
start_with_arithmetic_operator?(processed_source[range.line]) ||
|
93
|
+
inside_string_literal_or_method_with_argument?(range)
|
92
94
|
end
|
93
95
|
|
94
96
|
def ends_with_backslash_without_comment?(source_line)
|
@@ -99,18 +101,42 @@ module RuboCop
|
|
99
101
|
/["']\s*\\\z/.match?(source_line)
|
100
102
|
end
|
101
103
|
|
104
|
+
def inside_string_literal_or_method_with_argument?(range)
|
105
|
+
processed_source.tokens.each_cons(2).any? do |token, next_token|
|
106
|
+
inside_string_literal?(range, token) || method_with_argument?(token, next_token)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
102
110
|
def redundant_line_continuation?(range)
|
103
111
|
return true unless (node = find_node_for_line(range.line))
|
104
112
|
return false if argument_newline?(node)
|
105
113
|
|
106
|
-
|
114
|
+
source = node.parent ? node.parent.source : node.source
|
115
|
+
parse(source.gsub(/\\\n/, "\n")).valid_syntax?
|
116
|
+
end
|
117
|
+
|
118
|
+
def inside_string_literal?(range, token)
|
119
|
+
ALLOWED_STRING_TOKENS.include?(token.type) && token.pos.overlaps?(range)
|
120
|
+
end
|
121
|
+
|
122
|
+
# A method call without parentheses such as the following cannot remove `\`:
|
123
|
+
#
|
124
|
+
# do_something \
|
125
|
+
# argument
|
126
|
+
def method_with_argument?(current_token, next_token)
|
127
|
+
current_token.type == :tIDENTIFIER && next_token.type == :tIDENTIFIER
|
107
128
|
end
|
108
129
|
|
109
130
|
def argument_newline?(node)
|
110
131
|
node = node.children.first if node.root? && node.begin_type?
|
111
|
-
return if !node.send_type? || node.arguments.empty?
|
112
132
|
|
113
|
-
|
133
|
+
if argument_is_method?(node)
|
134
|
+
argument_newline?(node.first_argument)
|
135
|
+
else
|
136
|
+
return false unless method_call_with_arguments?(node)
|
137
|
+
|
138
|
+
node.loc.selector.line != node.first_argument.loc.line
|
139
|
+
end
|
114
140
|
end
|
115
141
|
|
116
142
|
def find_node_for_line(line)
|
@@ -133,7 +159,18 @@ module RuboCop
|
|
133
159
|
end
|
134
160
|
end
|
135
161
|
|
136
|
-
def
|
162
|
+
def argument_is_method?(node)
|
163
|
+
return false unless node.send_type?
|
164
|
+
return false unless (first_argument = node.first_argument)
|
165
|
+
|
166
|
+
method_call_with_arguments?(first_argument)
|
167
|
+
end
|
168
|
+
|
169
|
+
def method_call_with_arguments?(node)
|
170
|
+
node.call_type? && !node.arguments.empty?
|
171
|
+
end
|
172
|
+
|
173
|
+
def start_with_arithmetic_operator?(source_line)
|
137
174
|
%r{\A\s*[+\-*/%]}.match?(source_line)
|
138
175
|
end
|
139
176
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'fileutils'
|
4
|
+
|
3
5
|
# Class for generating documentation of all cops departments
|
4
6
|
# @api private
|
5
7
|
class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
@@ -14,6 +16,8 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
14
16
|
@departments = departments.map(&:to_sym).sort!
|
15
17
|
@cops = RuboCop::Cop::Registry.global
|
16
18
|
@config = RuboCop::ConfigLoader.default_configuration
|
19
|
+
@docs_path = "#{Dir.pwd}/docs/modules/ROOT/pages/"
|
20
|
+
FileUtils.mkdir_p(@docs_path)
|
17
21
|
end
|
18
22
|
|
19
23
|
def call
|
@@ -27,7 +31,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
27
31
|
|
28
32
|
private
|
29
33
|
|
30
|
-
attr_reader :departments, :cops, :config
|
34
|
+
attr_reader :departments, :cops, :config, :docs_path
|
31
35
|
|
32
36
|
def cops_of_department(department)
|
33
37
|
cops.with_department(department).sort!
|
@@ -252,7 +256,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
252
256
|
content = +"= #{department}\n"
|
253
257
|
selected_cops.each { |cop| content << print_cop_with_doc(cop) }
|
254
258
|
content << footer_for_department(department)
|
255
|
-
file_name = "#{
|
259
|
+
file_name = "#{docs_path}/#{department_to_basename(department)}.adoc"
|
256
260
|
File.open(file_name, 'w') do |file|
|
257
261
|
puts "* generated #{file_name}"
|
258
262
|
file.write("#{content.strip}\n")
|
@@ -298,7 +302,10 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
298
302
|
end
|
299
303
|
|
300
304
|
def print_table_of_contents
|
301
|
-
path = "#{
|
305
|
+
path = "#{docs_path}/cops.adoc"
|
306
|
+
|
307
|
+
File.write(path, table_contents) and return unless File.exist?(path)
|
308
|
+
|
302
309
|
original = File.read(path)
|
303
310
|
content = +"// START_COP_LIST\n\n"
|
304
311
|
|
data/lib/rubocop/version.rb
CHANGED
data/lib/rubocop.rb
CHANGED
@@ -299,6 +299,7 @@ require_relative 'rubocop/cop/lint/duplicate_case_condition'
|
|
299
299
|
require_relative 'rubocop/cop/lint/duplicate_elsif_condition'
|
300
300
|
require_relative 'rubocop/cop/lint/duplicate_hash_key'
|
301
301
|
require_relative 'rubocop/cop/lint/duplicate_magic_comment'
|
302
|
+
require_relative 'rubocop/cop/lint/duplicate_match_pattern'
|
302
303
|
require_relative 'rubocop/cop/lint/duplicate_methods'
|
303
304
|
require_relative 'rubocop/cop/lint/duplicate_regexp_character_class_element'
|
304
305
|
require_relative 'rubocop/cop/lint/duplicate_require'
|
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.50.1
|
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: 2023-04-
|
13
|
+
date: 2023-04-12 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|
@@ -420,6 +420,7 @@ files:
|
|
420
420
|
- lib/rubocop/cop/lint/duplicate_elsif_condition.rb
|
421
421
|
- lib/rubocop/cop/lint/duplicate_hash_key.rb
|
422
422
|
- lib/rubocop/cop/lint/duplicate_magic_comment.rb
|
423
|
+
- lib/rubocop/cop/lint/duplicate_match_pattern.rb
|
423
424
|
- lib/rubocop/cop/lint/duplicate_methods.rb
|
424
425
|
- lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb
|
425
426
|
- lib/rubocop/cop/lint/duplicate_require.rb
|
@@ -990,7 +991,7 @@ metadata:
|
|
990
991
|
homepage_uri: https://rubocop.org/
|
991
992
|
changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
|
992
993
|
source_code_uri: https://github.com/rubocop/rubocop/
|
993
|
-
documentation_uri: https://docs.rubocop.org/rubocop/1.
|
994
|
+
documentation_uri: https://docs.rubocop.org/rubocop/1.50/
|
994
995
|
bug_tracker_uri: https://github.com/rubocop/rubocop/issues
|
995
996
|
rubygems_mfa_required: 'true'
|
996
997
|
post_install_message:
|