rubocop 1.38.0 → 1.39.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 +1 -1
- data/config/default.yml +4 -2
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +29 -8
- data/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb +3 -0
- data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +34 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +17 -8
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
- data/lib/rubocop/cop/mixin/range_help.rb +23 -0
- data/lib/rubocop/cop/mixin/visibility_help.rb +40 -5
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -25
- data/lib/rubocop/cop/style/class_equality_comparison.rb +7 -5
- data/lib/rubocop/cop/style/collection_compact.rb +1 -1
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +32 -10
- data/lib/rubocop/cop/style/hash_except.rb +4 -0
- data/lib/rubocop/cop/style/object_then.rb +3 -0
- data/lib/rubocop/cop/style/operator_method_call.rb +13 -0
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/redundant_each.rb +13 -8
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +12 -3
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cops_documentation_generator.rb +3 -4
- data/lib/rubocop/server/core.rb +15 -0
- data/lib/rubocop/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 881807be0f0f6eea20bd13bd8f08fdb158a5b155c8d3a22fd748683a68c1fef1
|
4
|
+
data.tar.gz: 2a8e7d4b02f1ba468e02a4c20f8e3b830ce2a1d8ff0210f86aaeafab597c8c88
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11ea36bec754b07912e06b5481f964d10a6dbf5bfd56f99d8a8842ca46d56ae03a342a283d843336f977760c28a697ee995aa98268254a55b1218fa57a9fb5c7
|
7
|
+
data.tar.gz: b5096cb4589d9bafdab0b6ab409ea9e7841dc06b274aeb7f7d5a26e703cb216c2a428d695fb2a087637467f1cdd5ac005398c66ee3e7d28d49cb4b203a87667d
|
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.39', 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
@@ -2808,6 +2808,7 @@ Naming/MethodParameterName:
|
|
2808
2808
|
- by
|
2809
2809
|
- db
|
2810
2810
|
- id
|
2811
|
+
- if
|
2811
2812
|
- in
|
2812
2813
|
- io
|
2813
2814
|
- ip
|
@@ -3448,7 +3449,7 @@ Style/Copyright:
|
|
3448
3449
|
|
3449
3450
|
Style/DateTime:
|
3450
3451
|
Description: 'Use Time over DateTime.'
|
3451
|
-
StyleGuide: '#date
|
3452
|
+
StyleGuide: '#date-time'
|
3452
3453
|
Enabled: false
|
3453
3454
|
VersionAdded: '0.51'
|
3454
3455
|
VersionChanged: '0.92'
|
@@ -3819,8 +3820,9 @@ Style/HashExcept:
|
|
3819
3820
|
Checks for usages of `Hash#reject`, `Hash#select`, and `Hash#filter` methods
|
3820
3821
|
that can be replaced with `Hash#except` method.
|
3821
3822
|
Enabled: pending
|
3823
|
+
Safe: false
|
3822
3824
|
VersionAdded: '1.7'
|
3823
|
-
VersionChanged: '1.
|
3825
|
+
VersionChanged: '1.39'
|
3824
3826
|
|
3825
3827
|
Style/HashLikeCase:
|
3826
3828
|
Description: >-
|
@@ -42,6 +42,14 @@ module RuboCop
|
|
42
42
|
# ' long'
|
43
43
|
class LineContinuationLeadingSpace < Base
|
44
44
|
include RangeHelp
|
45
|
+
extend AutoCorrector
|
46
|
+
|
47
|
+
LINE_1_ENDING = /['"]\s*\\\n/.freeze
|
48
|
+
LINE_2_BEGINNING = /\A\s*['"]/.freeze
|
49
|
+
LEADING_STYLE_OFFENSE = /(?<trailing_spaces>\s+)(?<ending>#{LINE_1_ENDING})/.freeze
|
50
|
+
TRAILING_STYLE_OFFENSE = /(?<beginning>#{LINE_2_BEGINNING})(?<leading_spaces>\s+)/.freeze
|
51
|
+
private_constant :LINE_1_ENDING, :LINE_2_BEGINNING,
|
52
|
+
:LEADING_STYLE_OFFENSE, :TRAILING_STYLE_OFFENSE
|
45
53
|
|
46
54
|
def on_dstr(node)
|
47
55
|
end_of_first_line = node.loc.expression.begin_pos - node.loc.expression.column
|
@@ -52,9 +60,9 @@ module RuboCop
|
|
52
60
|
next unless continuation?(raw_line_one)
|
53
61
|
|
54
62
|
if enforced_style_leading?
|
55
|
-
investigate_leading_style(raw_line_one, end_of_first_line)
|
63
|
+
investigate_leading_style(raw_line_one, raw_line_two, end_of_first_line)
|
56
64
|
else
|
57
|
-
investigate_trailing_style(raw_line_two, end_of_first_line)
|
65
|
+
investigate_trailing_style(raw_line_one, raw_line_two, end_of_first_line)
|
58
66
|
end
|
59
67
|
end
|
60
68
|
end
|
@@ -65,24 +73,37 @@ module RuboCop
|
|
65
73
|
processed_source.raw_source.lines[node.first_line - 1, line_range(node).size]
|
66
74
|
end
|
67
75
|
|
68
|
-
def investigate_leading_style(first_line, end_of_first_line)
|
69
|
-
matches = first_line.match(
|
76
|
+
def investigate_leading_style(first_line, second_line, end_of_first_line)
|
77
|
+
matches = first_line.match(LEADING_STYLE_OFFENSE)
|
70
78
|
return if matches.nil?
|
71
79
|
|
72
|
-
|
80
|
+
offense_range = leading_offense_range(end_of_first_line, matches)
|
81
|
+
add_offense(offense_range) do |corrector|
|
82
|
+
insert_pos = end_of_first_line + second_line[LINE_2_BEGINNING].length
|
83
|
+
autocorrect(corrector, offense_range, insert_pos, matches[:trailing_spaces])
|
84
|
+
end
|
73
85
|
end
|
74
86
|
|
75
|
-
def investigate_trailing_style(second_line, end_of_first_line)
|
76
|
-
matches = second_line.match(
|
87
|
+
def investigate_trailing_style(first_line, second_line, end_of_first_line)
|
88
|
+
matches = second_line.match(TRAILING_STYLE_OFFENSE)
|
77
89
|
return if matches.nil?
|
78
90
|
|
79
|
-
|
91
|
+
offense_range = trailing_offense_range(end_of_first_line, matches)
|
92
|
+
add_offense(offense_range) do |corrector|
|
93
|
+
insert_pos = end_of_first_line - first_line[LINE_1_ENDING].length
|
94
|
+
autocorrect(corrector, offense_range, insert_pos, matches[:leading_spaces])
|
95
|
+
end
|
80
96
|
end
|
81
97
|
|
82
98
|
def continuation?(line)
|
83
99
|
line.end_with?("\\\n")
|
84
100
|
end
|
85
101
|
|
102
|
+
def autocorrect(corrector, offense_range, insert_pos, spaces)
|
103
|
+
corrector.remove(offense_range)
|
104
|
+
corrector.replace(range_between(insert_pos, insert_pos), spaces)
|
105
|
+
end
|
106
|
+
|
86
107
|
def leading_offense_range(end_of_first_line, matches)
|
87
108
|
end_pos = end_of_first_line - matches[:ending].length
|
88
109
|
begin_pos = end_pos - matches[:trailing_spaces].length
|
@@ -6,6 +6,9 @@ module RuboCop
|
|
6
6
|
# Checks for unnecessary additional spaces inside array percent literals
|
7
7
|
# (i.e. %i/%w).
|
8
8
|
#
|
9
|
+
# Note that blank percent literals (e.g. `%i( )`) are checked by
|
10
|
+
# `Layout/SpaceInsidePercentLiteralDelimiters`.
|
11
|
+
#
|
9
12
|
# @example
|
10
13
|
#
|
11
14
|
# # bad
|
@@ -8,14 +8,31 @@ module RuboCop
|
|
8
8
|
#
|
9
9
|
# @example
|
10
10
|
#
|
11
|
+
# # bad
|
12
|
+
# %i( foo bar baz )
|
13
|
+
#
|
11
14
|
# # good
|
12
15
|
# %i(foo bar baz)
|
13
16
|
#
|
14
17
|
# # bad
|
15
18
|
# %w( foo bar baz )
|
16
19
|
#
|
20
|
+
# # good
|
21
|
+
# %w(foo bar baz)
|
22
|
+
#
|
17
23
|
# # bad
|
18
24
|
# %x( ls -l )
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# %x(ls -l)
|
28
|
+
#
|
29
|
+
# # bad
|
30
|
+
# %w( )
|
31
|
+
# %w(
|
32
|
+
# )
|
33
|
+
#
|
34
|
+
# # good
|
35
|
+
# %w()
|
19
36
|
class SpaceInsidePercentLiteralDelimiters < Base
|
20
37
|
include MatchRange
|
21
38
|
include PercentLiteral
|
@@ -34,11 +51,21 @@ module RuboCop
|
|
34
51
|
end
|
35
52
|
|
36
53
|
def on_percent_literal(node)
|
54
|
+
add_offenses_for_blank_spaces(node)
|
37
55
|
add_offenses_for_unnecessary_spaces(node)
|
38
56
|
end
|
39
57
|
|
40
58
|
private
|
41
59
|
|
60
|
+
def add_offenses_for_blank_spaces(node)
|
61
|
+
range = body_range(node)
|
62
|
+
return if range.source.empty? || !range.source.strip.empty?
|
63
|
+
|
64
|
+
add_offense(range) do |corrector|
|
65
|
+
corrector.remove(range)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
42
69
|
def add_offenses_for_unnecessary_spaces(node)
|
43
70
|
return unless node.single_line?
|
44
71
|
|
@@ -54,6 +81,13 @@ module RuboCop
|
|
54
81
|
each_match_range(contents_range(node), regex, &blk)
|
55
82
|
end
|
56
83
|
end
|
84
|
+
|
85
|
+
def body_range(node)
|
86
|
+
node.location.expression.with(
|
87
|
+
begin_pos: node.location.begin.end_pos,
|
88
|
+
end_pos: node.location.end.begin_pos
|
89
|
+
)
|
90
|
+
end
|
57
91
|
end
|
58
92
|
end
|
59
93
|
end
|
@@ -51,8 +51,8 @@ module RuboCop
|
|
51
51
|
# alias bar foo
|
52
52
|
class DuplicateMethods < Base
|
53
53
|
MSG = 'Method `%<method>s` is defined at both %<defined>s and %<current>s.'
|
54
|
-
|
55
54
|
RESTRICT_ON_SEND = %i[alias_method attr_reader attr_writer attr_accessor attr].freeze
|
55
|
+
DEF_TYPES = %i[def defs].freeze
|
56
56
|
|
57
57
|
def initialize(config = nil, options = nil)
|
58
58
|
super
|
@@ -127,8 +127,8 @@ module RuboCop
|
|
127
127
|
found_method(node, "#{enclosing}.#{name}")
|
128
128
|
end
|
129
129
|
|
130
|
-
def message_for_dup(node, method_name)
|
131
|
-
format(MSG, method: method_name, defined: source_location(@definitions[
|
130
|
+
def message_for_dup(node, method_name, key)
|
131
|
+
format(MSG, method: method_name, defined: source_location(@definitions[key]),
|
132
132
|
current: source_location(node))
|
133
133
|
end
|
134
134
|
|
@@ -156,18 +156,27 @@ module RuboCop
|
|
156
156
|
end
|
157
157
|
|
158
158
|
def found_method(node, method_name)
|
159
|
-
|
160
|
-
|
161
|
-
|
159
|
+
key = method_key(node, method_name)
|
160
|
+
|
161
|
+
if @definitions.key?(key)
|
162
|
+
loc = if DEF_TYPES.include?(node.type)
|
162
163
|
node.loc.keyword.join(node.loc.name)
|
163
164
|
else
|
164
165
|
node.loc.expression
|
165
166
|
end
|
166
|
-
message = message_for_dup(node, method_name)
|
167
|
+
message = message_for_dup(node, method_name, key)
|
167
168
|
|
168
169
|
add_offense(loc, message: message)
|
169
170
|
else
|
170
|
-
@definitions[
|
171
|
+
@definitions[key] = node
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def method_key(node, method_name)
|
176
|
+
if (ancestor_def = node.each_ancestor(*DEF_TYPES).first)
|
177
|
+
"#{ancestor_def.method_name}.#{method_name}"
|
178
|
+
else
|
179
|
+
method_name
|
171
180
|
end
|
172
181
|
end
|
173
182
|
|
@@ -116,7 +116,7 @@ module RuboCop
|
|
116
116
|
private
|
117
117
|
|
118
118
|
def comment_between_rescue_and_end?(node)
|
119
|
-
ancestor = node.each_ancestor(:kwbegin, :def, :defs, :block).first
|
119
|
+
ancestor = node.each_ancestor(:kwbegin, :def, :defs, :block, :numblock).first
|
120
120
|
return unless ancestor
|
121
121
|
|
122
122
|
end_line = ancestor.loc.end.line
|
@@ -20,7 +20,7 @@ module RuboCop
|
|
20
20
|
#
|
21
21
|
# @example CountRepeatedAttributes: false (default is true)
|
22
22
|
#
|
23
|
-
# # `model` and `current_user`,
|
23
|
+
# # `model` and `current_user`, referenced 3 times each,
|
24
24
|
# # are each counted as only 1 branch each if
|
25
25
|
# # `CountRepeatedAttributes` is set to 'false'
|
26
26
|
#
|
@@ -126,6 +126,29 @@ module RuboCop
|
|
126
126
|
pos += size * step while condition && src[pos + offset, size] == needle
|
127
127
|
pos.negative? ? 0 : pos
|
128
128
|
end
|
129
|
+
|
130
|
+
def range_with_comments_and_lines(node)
|
131
|
+
range_by_whole_lines(range_with_comments(node), include_final_newline: true)
|
132
|
+
end
|
133
|
+
|
134
|
+
def range_with_comments(node)
|
135
|
+
ranges = [
|
136
|
+
node,
|
137
|
+
*@processed_source.ast_with_comments[node]
|
138
|
+
].map do |element|
|
139
|
+
element.location.expression
|
140
|
+
end
|
141
|
+
ranges.reduce do |result, range|
|
142
|
+
add_range(result, range)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def add_range(range1, range2)
|
147
|
+
range1.with(
|
148
|
+
begin_pos: [range1.begin_pos, range2.begin_pos].min,
|
149
|
+
end_pos: [range1.end_pos, range2.end_pos].max
|
150
|
+
)
|
151
|
+
end
|
129
152
|
end
|
130
153
|
end
|
131
154
|
end
|
@@ -1,18 +1,43 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'set'
|
4
|
+
|
3
5
|
module RuboCop
|
4
6
|
module Cop
|
5
7
|
# Help methods for determining node visibility.
|
6
8
|
module VisibilityHelp
|
7
9
|
extend NodePattern::Macros
|
8
10
|
|
9
|
-
VISIBILITY_SCOPES =
|
11
|
+
VISIBILITY_SCOPES = ::Set[:private, :protected, :public].freeze
|
10
12
|
|
11
13
|
private
|
12
14
|
|
13
15
|
def node_visibility(node)
|
14
|
-
|
15
|
-
|
16
|
+
node_visibility_from_visibility_inline(node) ||
|
17
|
+
node_visibility_from_visibility_block(node) ||
|
18
|
+
:public
|
19
|
+
end
|
20
|
+
|
21
|
+
def node_visibility_from_visibility_inline(node)
|
22
|
+
return unless node.def_type?
|
23
|
+
|
24
|
+
node_visibility_from_visibility_inline_on_def(node) ||
|
25
|
+
node_visibility_from_visibility_inline_on_method_name(node)
|
26
|
+
end
|
27
|
+
|
28
|
+
def node_visibility_from_visibility_inline_on_def(node)
|
29
|
+
parent = node.parent
|
30
|
+
parent.method_name if visibility_inline_on_def?(parent)
|
31
|
+
end
|
32
|
+
|
33
|
+
def node_visibility_from_visibility_inline_on_method_name(node)
|
34
|
+
node.right_siblings.reverse.find do |sibling|
|
35
|
+
visibility_inline_on_method_name?(sibling, method_name: node.method_name)
|
36
|
+
end&.method_name
|
37
|
+
end
|
38
|
+
|
39
|
+
def node_visibility_from_visibility_block(node)
|
40
|
+
find_visibility_start(node)&.method_name
|
16
41
|
end
|
17
42
|
|
18
43
|
def find_visibility_start(node)
|
@@ -21,7 +46,7 @@ module RuboCop
|
|
21
46
|
|
22
47
|
# Navigate to find the last protected method
|
23
48
|
def find_visibility_end(node)
|
24
|
-
possible_visibilities = VISIBILITY_SCOPES - [node_visibility(node)]
|
49
|
+
possible_visibilities = VISIBILITY_SCOPES - ::Set[node_visibility(node)]
|
25
50
|
right = node.right_siblings
|
26
51
|
right.find do |child_node|
|
27
52
|
possible_visibilities.include?(node_visibility(child_node))
|
@@ -30,7 +55,17 @@ module RuboCop
|
|
30
55
|
|
31
56
|
# @!method visibility_block?(node)
|
32
57
|
def_node_matcher :visibility_block?, <<~PATTERN
|
33
|
-
(send nil?
|
58
|
+
(send nil? VISIBILITY_SCOPES)
|
59
|
+
PATTERN
|
60
|
+
|
61
|
+
# @!method visibility_inline_on_def?(node)
|
62
|
+
def_node_matcher :visibility_inline_on_def?, <<~PATTERN
|
63
|
+
(send nil? VISIBILITY_SCOPES def)
|
64
|
+
PATTERN
|
65
|
+
|
66
|
+
# @!method visibility_inline_on_method_name?(node, method_name:)
|
67
|
+
def_node_matcher :visibility_inline_on_method_name?, <<~PATTERN
|
68
|
+
(send nil? VISIBILITY_SCOPES (sym %method_name))
|
34
69
|
PATTERN
|
35
70
|
end
|
36
71
|
end
|
@@ -202,31 +202,7 @@ module RuboCop
|
|
202
202
|
end
|
203
203
|
|
204
204
|
def remove_node(corrector, node)
|
205
|
-
corrector.remove(
|
206
|
-
range_by_whole_lines(
|
207
|
-
range_with_comments(node),
|
208
|
-
include_final_newline: true
|
209
|
-
)
|
210
|
-
)
|
211
|
-
end
|
212
|
-
|
213
|
-
def range_with_comments(node)
|
214
|
-
ranges = [
|
215
|
-
node,
|
216
|
-
*processed_source.ast_with_comments[node]
|
217
|
-
].map do |element|
|
218
|
-
element.location.expression
|
219
|
-
end
|
220
|
-
ranges.reduce do |result, range|
|
221
|
-
add_range(result, range)
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
def add_range(range1, range2)
|
226
|
-
range1.with(
|
227
|
-
begin_pos: [range1.begin_pos, range2.begin_pos].min,
|
228
|
-
end_pos: [range1.end_pos, range2.end_pos].max
|
229
|
-
)
|
205
|
+
corrector.remove(range_with_comments_and_lines(node))
|
230
206
|
end
|
231
207
|
end
|
232
208
|
end
|
@@ -97,12 +97,14 @@ module RuboCop
|
|
97
97
|
if node.children.first.method?(:name)
|
98
98
|
return class_node.receiver.source if class_node.receiver
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
100
|
+
if class_node.str_type?
|
101
|
+
value = class_node.source.delete('"').delete("'")
|
102
|
+
value.prepend('::') if class_node.each_ancestor(:class, :module).any?
|
103
|
+
return value
|
104
|
+
end
|
105
105
|
end
|
106
|
+
|
107
|
+
class_node.source
|
106
108
|
end
|
107
109
|
|
108
110
|
def offense_range(receiver_node, node)
|
@@ -112,7 +112,7 @@ module RuboCop
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def range(begin_pos_node, end_pos_node)
|
115
|
-
range_between(begin_pos_node.loc.selector.begin_pos, end_pos_node.loc.
|
115
|
+
range_between(begin_pos_node.loc.selector.begin_pos, end_pos_node.loc.expression.end_pos)
|
116
116
|
end
|
117
117
|
end
|
118
118
|
end
|
@@ -38,28 +38,50 @@ module RuboCop
|
|
38
38
|
({block numblock} $(send (send _ ${:keys :values}) :each) ...)
|
39
39
|
PATTERN
|
40
40
|
|
41
|
+
# @!method kv_each_with_block_pass(node)
|
42
|
+
def_node_matcher :kv_each_with_block_pass, <<~PATTERN
|
43
|
+
(send $(send _ ${:keys :values}) :each (block_pass (sym _)))
|
44
|
+
PATTERN
|
45
|
+
|
41
46
|
def on_block(node)
|
42
|
-
|
47
|
+
kv_each(node) do |target, method|
|
48
|
+
register_kv_offense(target, method)
|
49
|
+
end
|
43
50
|
end
|
44
51
|
|
45
52
|
alias on_numblock on_block
|
46
53
|
|
54
|
+
def on_block_pass(node)
|
55
|
+
kv_each_with_block_pass(node.parent) do |target, method|
|
56
|
+
register_kv_with_block_pass_offense(node, target, method)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
47
60
|
private
|
48
61
|
|
49
|
-
def register_kv_offense(
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
62
|
+
def register_kv_offense(target, method)
|
63
|
+
return unless (parent_receiver = target.receiver.receiver)
|
64
|
+
return if allowed_receiver?(parent_receiver)
|
65
|
+
|
66
|
+
add_offense(kv_range(target), message: format_message(method)) do |corrector|
|
67
|
+
correct_key_value_each(target, corrector)
|
68
|
+
end
|
69
|
+
end
|
54
70
|
|
55
|
-
|
71
|
+
def register_kv_with_block_pass_offense(node, target, method)
|
72
|
+
return unless (parent_receiver = node.parent.receiver.receiver)
|
73
|
+
return if allowed_receiver?(parent_receiver)
|
56
74
|
|
57
|
-
|
58
|
-
|
59
|
-
|
75
|
+
range = target.loc.selector.with(end_pos: node.parent.loc.selector.end_pos)
|
76
|
+
add_offense(range, message: format_message(method)) do |corrector|
|
77
|
+
corrector.replace(range, "each_#{method[0..-2]}")
|
60
78
|
end
|
61
79
|
end
|
62
80
|
|
81
|
+
def format_message(method_name)
|
82
|
+
format(MSG, prefer: "each_#{method_name[0..-2]}", current: "#{method_name}.each")
|
83
|
+
end
|
84
|
+
|
63
85
|
def check_argument(variable)
|
64
86
|
return unless variable.block_argument?
|
65
87
|
|
@@ -13,6 +13,10 @@ module RuboCop
|
|
13
13
|
# when used `==`.
|
14
14
|
# And do not check `Hash#delete_if` and `Hash#keep_if` to change receiver object.
|
15
15
|
#
|
16
|
+
# @safety
|
17
|
+
# This cop is unsafe because it cannot be guaranteed that the receiver
|
18
|
+
# is a `Hash` or responds to the replacement method.
|
19
|
+
#
|
16
20
|
# @example
|
17
21
|
#
|
18
22
|
# # bad
|
@@ -31,9 +31,22 @@ module RuboCop
|
|
31
31
|
return if rhs.nil? || rhs.children.first
|
32
32
|
|
33
33
|
add_offense(dot) do |corrector|
|
34
|
+
wrap_in_parentheses_if_chained(corrector, node)
|
34
35
|
corrector.replace(dot, ' ')
|
35
36
|
end
|
36
37
|
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def wrap_in_parentheses_if_chained(corrector, node)
|
42
|
+
return unless node.parent&.call_type?
|
43
|
+
|
44
|
+
operator = node.loc.selector
|
45
|
+
|
46
|
+
ParenthesesCorrector.correct(corrector, node)
|
47
|
+
corrector.insert_after(operator, ' ')
|
48
|
+
corrector.wrap(node, '(', ')')
|
49
|
+
end
|
37
50
|
end
|
38
51
|
end
|
39
52
|
end
|
@@ -7,7 +7,7 @@ module RuboCop
|
|
7
7
|
#
|
8
8
|
# @safety
|
9
9
|
# This cop is unsafe, as it can produce false positives if the receiver
|
10
|
-
# is not an `
|
10
|
+
# is not an `Enumerator`.
|
11
11
|
#
|
12
12
|
# @example
|
13
13
|
#
|
@@ -61,19 +61,24 @@ module RuboCop
|
|
61
61
|
|
62
62
|
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
63
63
|
def redundant_each_method(node)
|
64
|
-
if node.
|
64
|
+
return if node.last_argument&.block_pass_type?
|
65
|
+
|
66
|
+
if node.method?(:each) && !node.parent&.block_type?
|
65
67
|
ancestor_node = node.each_ancestor(:send).detect do |ancestor|
|
66
|
-
|
68
|
+
ancestor.receiver == node &&
|
69
|
+
(RESTRICT_ON_SEND.include?(ancestor.method_name) || ancestor.method?(:reverse_each))
|
67
70
|
end
|
71
|
+
|
72
|
+
return ancestor_node if ancestor_node
|
68
73
|
end
|
69
74
|
|
70
|
-
|
71
|
-
|
75
|
+
return unless (prev_method = node.children.first)
|
76
|
+
return if !prev_method.send_type? ||
|
77
|
+
prev_method.parent.block_type? || prev_method.last_argument&.block_pass_type?
|
72
78
|
|
73
|
-
|
79
|
+
detected = prev_method.method_name.to_s.start_with?('each_') unless node.method?(:each)
|
74
80
|
|
75
|
-
|
76
|
-
end
|
81
|
+
prev_method if detected || prev_method.method?(:reverse_each)
|
77
82
|
end
|
78
83
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
79
84
|
|
@@ -44,7 +44,7 @@ module RuboCop
|
|
44
44
|
|
45
45
|
def on_regexp(node)
|
46
46
|
each_escape(node) do |char, index, within_character_class|
|
47
|
-
next if allowed_escape?(node, char, within_character_class)
|
47
|
+
next if allowed_escape?(node, char, index, within_character_class)
|
48
48
|
|
49
49
|
location = escape_range_at_index(node, index)
|
50
50
|
|
@@ -56,7 +56,7 @@ module RuboCop
|
|
56
56
|
|
57
57
|
private
|
58
58
|
|
59
|
-
def allowed_escape?(node, char, within_character_class)
|
59
|
+
def allowed_escape?(node, char, index, within_character_class)
|
60
60
|
# Strictly speaking a few single-letter metachars are currently
|
61
61
|
# unnecessary to "escape", e.g. i, E, F, but enumerating them is
|
62
62
|
# rather difficult, and their behavior could change over time with
|
@@ -65,12 +65,21 @@ module RuboCop
|
|
65
65
|
return true if ALLOWED_ALWAYS_ESCAPES.include?(char) || delimiter?(node, char)
|
66
66
|
|
67
67
|
if within_character_class
|
68
|
-
ALLOWED_WITHIN_CHAR_CLASS_METACHAR_ESCAPES.include?(char)
|
68
|
+
ALLOWED_WITHIN_CHAR_CLASS_METACHAR_ESCAPES.include?(char) &&
|
69
|
+
!char_class_begins_or_ends_with_escaped_hyphen?(node, index)
|
69
70
|
else
|
70
71
|
ALLOWED_OUTSIDE_CHAR_CLASS_METACHAR_ESCAPES.include?(char)
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
75
|
+
def char_class_begins_or_ends_with_escaped_hyphen?(node, index)
|
76
|
+
# The hyphen character is allowed to be escaped within a character class
|
77
|
+
# but it's not necessry to escape hyphen if it's the first or last character
|
78
|
+
# within the character class. This method checks if that's the case.
|
79
|
+
# e.g. "[0-9\\-]" or "[\\-0-9]" would return true
|
80
|
+
node.source[index] == '[' || node.source[index + 3] == ']'
|
81
|
+
end
|
82
|
+
|
74
83
|
def delimiter?(node, char)
|
75
84
|
delimiters = [node.loc.begin.source[-1], node.loc.end.source[0]]
|
76
85
|
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -183,11 +183,10 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
183
183
|
# rubocop:enable Metrics/CyclomaticComplexity,Metrics/MethodLength
|
184
184
|
|
185
185
|
def to_table(header, content)
|
186
|
-
|
187
|
-
# See: https://docs.asciidoctor.org/asciidoc/latest/tables/data-format/#escape-the-cell-separator
|
188
|
-
table = ['[separator=¦]', '|===', "| #{header.join(' | ')}\n\n"].join("\n")
|
186
|
+
table = ['|===', "| #{header.join(' | ')}\n\n"].join("\n")
|
189
187
|
marked_contents = content.map do |plain_content|
|
190
|
-
|
188
|
+
# Escape `|` with backslash to prevent the regexp `|` is not used as a table separator.
|
189
|
+
plain_content.map { |c| "| #{c.gsub(/\|/, '\|')}" }.join("\n")
|
191
190
|
end
|
192
191
|
table << marked_contents.join("\n\n")
|
193
192
|
table << "\n|===\n"
|
data/lib/rubocop/server/core.rb
CHANGED
@@ -17,6 +17,8 @@ module RuboCop
|
|
17
17
|
# The core of server process. It starts TCP server and perform socket communication.
|
18
18
|
# @api private
|
19
19
|
class Core
|
20
|
+
JSON_FORMATS = %w[json j].freeze
|
21
|
+
|
20
22
|
def self.token
|
21
23
|
@token ||= SecureRandom.hex(4)
|
22
24
|
end
|
@@ -57,6 +59,10 @@ module RuboCop
|
|
57
59
|
def start_server(host, port)
|
58
60
|
@server = TCPServer.open(host, port)
|
59
61
|
|
62
|
+
# JSON format does not expected output message when IDE integration with server mode.
|
63
|
+
# See: https://github.com/rubocop/rubocop/issues/11164
|
64
|
+
return if use_json_format?
|
65
|
+
|
60
66
|
output_stream = ARGV.include?('--stderr') ? $stderr : $stdout
|
61
67
|
output_stream.puts "RuboCop server starting on #{@server.addr[3]}:#{@server.addr[1]}."
|
62
68
|
end
|
@@ -76,6 +82,15 @@ module RuboCop
|
|
76
82
|
ensure
|
77
83
|
socket.close
|
78
84
|
end
|
85
|
+
|
86
|
+
def use_json_format?
|
87
|
+
return true if ARGV.include?('--format=json') || ARGV.include?('--format=j')
|
88
|
+
return false unless (index = ARGV.index('--format'))
|
89
|
+
|
90
|
+
format = ARGV[index + 1]
|
91
|
+
|
92
|
+
JSON_FORMATS.include?(format)
|
93
|
+
end
|
79
94
|
end
|
80
95
|
end
|
81
96
|
end
|
data/lib/rubocop/version.rb
CHANGED
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.39.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-11-
|
13
|
+
date: 2022-11-14 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|
@@ -985,7 +985,7 @@ metadata:
|
|
985
985
|
homepage_uri: https://rubocop.org/
|
986
986
|
changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
|
987
987
|
source_code_uri: https://github.com/rubocop/rubocop/
|
988
|
-
documentation_uri: https://docs.rubocop.org/rubocop/1.
|
988
|
+
documentation_uri: https://docs.rubocop.org/rubocop/1.39/
|
989
989
|
bug_tracker_uri: https://github.com/rubocop/rubocop/issues
|
990
990
|
rubygems_mfa_required: 'true'
|
991
991
|
post_install_message:
|