rubocop 1.49.0 → 1.50.1
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 +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:
|