rubocop 1.55.0 → 1.56.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 +10 -0
- data/lib/rubocop/config_finder.rb +2 -2
- data/lib/rubocop/cop/base.rb +1 -1
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -0
- data/lib/rubocop/cop/bundler/duplicated_group.rb +81 -0
- data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
- data/lib/rubocop/cop/internal_affairs/example_description.rb +2 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +2 -2
- data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
- data/lib/rubocop/cop/lint/struct_new_override.rb +12 -12
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/mixin/def_node.rb +1 -1
- data/lib/rubocop/cop/mixin/string_help.rb +4 -2
- data/lib/rubocop/cop/style/alias.rb +9 -8
- data/lib/rubocop/cop/style/arguments_forwarding.rb +82 -49
- data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
- data/lib/rubocop/cop/style/class_equality_comparison.rb +2 -0
- data/lib/rubocop/cop/style/lambda_call.rb +5 -0
- data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
- data/lib/rubocop/cop/style/redundant_return.rb +7 -2
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +2 -0
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
- data/lib/rubocop/cop/style/symbol_array.rb +3 -3
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -3
- data/lib/rubocop/lsp/routes.rb +23 -17
- data/lib/rubocop/lsp/runtime.rb +8 -2
- data/lib/rubocop/lsp/server.rb +2 -2
- data/lib/rubocop/runner.rb +5 -3
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +1 -0
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76532b5c0c7ccf0baff454ad37e17c405e4f827a0c8323ce1a5aab0ee9e78c19
|
4
|
+
data.tar.gz: fe2f7d727d5addd930a762ebe7fb34a38845164fed801744a6802ab91e6ba779
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff206ac0d02084dd7014818da655f5f8d718ac1bb4bfc2f781d3c007839096a142236ded54d30084fa7b3e1689205ff7a8bc7ad7eee3ffea2d809e4610d6a1ae
|
7
|
+
data.tar.gz: aaa03f29b7669ffcf6fdcb16b7da4c38a6bc62187eb91d6347e3ada22f396370b6564177eb3a040fd5ddd3eeea9cf8b3ff51943e79c3d0ad410508a75bb3177b
|
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.56', 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
@@ -173,6 +173,16 @@ Bundler/DuplicatedGem:
|
|
173
173
|
- '**/Gemfile'
|
174
174
|
- '**/gems.rb'
|
175
175
|
|
176
|
+
Bundler/DuplicatedGroup:
|
177
|
+
Description: 'Checks for duplicate group entries in Gemfile.'
|
178
|
+
Enabled: true
|
179
|
+
Severity: warning
|
180
|
+
VersionAdded: '1.56'
|
181
|
+
Include:
|
182
|
+
- '**/*.gemfile'
|
183
|
+
- '**/Gemfile'
|
184
|
+
- '**/gems.rb'
|
185
|
+
|
176
186
|
Bundler/GemComment:
|
177
187
|
Description: 'Add a comment describing each gem.'
|
178
188
|
Enabled: false
|
@@ -46,14 +46,14 @@ module RuboCop
|
|
46
46
|
|
47
47
|
file = File.join(Dir.home, DOTFILE)
|
48
48
|
|
49
|
-
|
49
|
+
file if File.exist?(file)
|
50
50
|
end
|
51
51
|
|
52
52
|
def find_user_xdg_config
|
53
53
|
xdg_config_home = expand_path(ENV.fetch('XDG_CONFIG_HOME', '~/.config'))
|
54
54
|
xdg_config = File.join(xdg_config_home, 'rubocop', XDG_CONFIG)
|
55
55
|
|
56
|
-
|
56
|
+
xdg_config if File.exist?(xdg_config)
|
57
57
|
end
|
58
58
|
|
59
59
|
def expand_path(path)
|
data/lib/rubocop/cop/base.rb
CHANGED
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Bundler
|
6
|
+
# A Gem group, or a set of groups, should be listed only once in a Gemfile.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# group :development do
|
11
|
+
# gem 'rubocop'
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# group :development do
|
15
|
+
# gem 'rubocop-rails'
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # bad (same set of groups declared twice)
|
19
|
+
# group :development, :test do
|
20
|
+
# gem 'rubocop'
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# group :test, :development do
|
24
|
+
# gem 'rspec'
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# # good
|
28
|
+
# group :development do
|
29
|
+
# gem 'rubocop'
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# group :development, :test do
|
33
|
+
# gem 'rspec'
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# # good
|
37
|
+
# gem 'rubocop', groups: [:development, :test]
|
38
|
+
# gem 'rspec', groups: [:development, :test]
|
39
|
+
#
|
40
|
+
class DuplicatedGroup < Base
|
41
|
+
include RangeHelp
|
42
|
+
|
43
|
+
MSG = 'Gem group `%<group_name>s` already defined on line ' \
|
44
|
+
'%<line_of_first_occurrence>d of the Gemfile.'
|
45
|
+
|
46
|
+
def on_new_investigation
|
47
|
+
return if processed_source.blank?
|
48
|
+
|
49
|
+
duplicated_group_nodes.each do |nodes|
|
50
|
+
nodes[1..].each do |node|
|
51
|
+
register_offense(node, node.arguments.map(&:value).join(', '), nodes.first.first_line)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# @!method group_declarations(node)
|
59
|
+
def_node_search :group_declarations, '(send nil? :group ...)'
|
60
|
+
|
61
|
+
def duplicated_group_nodes
|
62
|
+
group_declarations(processed_source.ast)
|
63
|
+
.group_by { |node| node.arguments.map(&:value).map(&:to_s).sort }
|
64
|
+
.values
|
65
|
+
.select { |nodes| nodes.size > 1 }
|
66
|
+
end
|
67
|
+
|
68
|
+
def register_offense(node, group_name, line_of_first_occurrence)
|
69
|
+
line_range = node.loc.column...node.loc.last_column
|
70
|
+
offense_location = source_range(processed_source.buffer, node.first_line, line_range)
|
71
|
+
message = format(
|
72
|
+
MSG,
|
73
|
+
group_name: group_name,
|
74
|
+
line_of_first_occurrence: line_of_first_occurrence
|
75
|
+
)
|
76
|
+
add_offense(offense_location, message: message)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -19,7 +19,15 @@ module RuboCop
|
|
19
19
|
#
|
20
20
|
# gem 'rspec'
|
21
21
|
#
|
22
|
-
#
|
22
|
+
# @example TreatCommentsAsGroupSeparators: true (default)
|
23
|
+
# # good
|
24
|
+
# # For code quality
|
25
|
+
# gem 'rubocop'
|
26
|
+
# # For tests
|
27
|
+
# gem 'rspec'
|
28
|
+
#
|
29
|
+
# @example TreatCommentsAsGroupSeparators: false
|
30
|
+
# # bad
|
23
31
|
# # For code quality
|
24
32
|
# gem 'rubocop'
|
25
33
|
# # For tests
|
@@ -45,7 +45,15 @@ module RuboCop
|
|
45
45
|
#
|
46
46
|
# spec.add_runtime_dependency 'rspec'
|
47
47
|
#
|
48
|
-
#
|
48
|
+
# @example TreatCommentsAsGroupSeparators: true (default)
|
49
|
+
# # good
|
50
|
+
# # For code quality
|
51
|
+
# spec.add_dependency 'rubocop'
|
52
|
+
# # For tests
|
53
|
+
# spec.add_dependency 'rspec'
|
54
|
+
#
|
55
|
+
# @example TreatCommentsAsGroupSeparators: false
|
56
|
+
# # bad
|
49
57
|
# # For code quality
|
50
58
|
# spec.add_dependency 'rubocop'
|
51
59
|
# # For tests
|
@@ -46,7 +46,8 @@ module RuboCop
|
|
46
46
|
|
47
47
|
EXPECT_OFFENSE_INCORRECT_DESCRIPTIONS = [
|
48
48
|
/^(does not|doesn't) (register|find|flag|report)/,
|
49
|
-
/^(does not|doesn't) add (a|an|any )?offense
|
49
|
+
/^(does not|doesn't) add (a|an|any )?offense/,
|
50
|
+
/^accepts\b/
|
50
51
|
].freeze
|
51
52
|
|
52
53
|
EXPECT_NO_CORRECTIONS_INCORRECT_DESCRIPTIONS = [/^(auto[- ]?)?correct/].freeze
|
@@ -354,7 +354,7 @@ module RuboCop
|
|
354
354
|
# Don't check indentation if the line doesn't start with the body.
|
355
355
|
# For example, lines like "else do_something".
|
356
356
|
first_char_pos_on_line = body_node.source_range.source_line =~ /\S/
|
357
|
-
|
357
|
+
true unless body_node.loc.column == first_char_pos_on_line
|
358
358
|
end
|
359
359
|
|
360
360
|
def offending_range(body_node, indentation)
|
@@ -19,7 +19,7 @@ module RuboCop
|
|
19
19
|
# foo &. bar
|
20
20
|
# foo &. bar&. buzz
|
21
21
|
# RuboCop:: Cop
|
22
|
-
# RuboCop:: Cop::
|
22
|
+
# RuboCop:: Cop:: Base
|
23
23
|
# :: RuboCop::Cop
|
24
24
|
#
|
25
25
|
# # good
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
31
31
|
# foo&.bar
|
32
32
|
# foo&.bar&.buzz
|
33
33
|
# RuboCop::Cop
|
34
|
-
# RuboCop::Cop::
|
34
|
+
# RuboCop::Cop::Base
|
35
35
|
# ::RuboCop::Cop
|
36
36
|
#
|
37
37
|
class SpaceAroundMethodCallOperator < Base
|
@@ -168,7 +168,7 @@ module RuboCop
|
|
168
168
|
# follows, and that the rules for space inside don't apply.
|
169
169
|
return true if token2.comment?
|
170
170
|
|
171
|
-
|
171
|
+
true unless same_line?(token1, token2) && !token1.space_after?
|
172
172
|
end
|
173
173
|
end
|
174
174
|
end
|
@@ -32,25 +32,25 @@ module RuboCop
|
|
32
32
|
# @!method struct_new(node)
|
33
33
|
def_node_matcher :struct_new, <<~PATTERN
|
34
34
|
(send
|
35
|
-
(const
|
35
|
+
(const {nil? cbase} :Struct) :new ...)
|
36
36
|
PATTERN
|
37
37
|
|
38
38
|
def on_send(node)
|
39
|
-
return unless struct_new(node)
|
40
|
-
node.arguments.each_with_index do |arg, index|
|
41
|
-
# Ignore if the first argument is a class name
|
42
|
-
next if index.zero? && arg.str_type?
|
39
|
+
return unless struct_new(node)
|
43
40
|
|
44
|
-
|
45
|
-
|
41
|
+
node.arguments.each_with_index do |arg, index|
|
42
|
+
# Ignore if the first argument is a class name
|
43
|
+
next if index.zero? && arg.str_type?
|
46
44
|
|
47
|
-
|
45
|
+
# Ignore if the argument is not a member name
|
46
|
+
next unless STRUCT_MEMBER_NAME_TYPES.include?(arg.type)
|
48
47
|
|
49
|
-
|
48
|
+
member_name = arg.value
|
50
49
|
|
51
|
-
|
52
|
-
|
53
|
-
|
50
|
+
next unless STRUCT_METHOD_NAMES.include?(member_name.to_sym)
|
51
|
+
|
52
|
+
message = format(MSG, member_name: member_name.inspect, method_name: member_name.to_s)
|
53
|
+
add_offense(arg, message: message)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
@@ -119,7 +119,7 @@ module RuboCop
|
|
119
119
|
ancestor = node.each_ancestor(:kwbegin, :def, :defs, :block, :numblock).first
|
120
120
|
return false unless ancestor
|
121
121
|
|
122
|
-
end_line = ancestor.loc.end.
|
122
|
+
end_line = ancestor.loc.end&.line || ancestor.loc.last_line
|
123
123
|
processed_source[node.first_line...end_line].any? { |line| comment_line?(line) }
|
124
124
|
end
|
125
125
|
|
@@ -19,7 +19,7 @@ module RuboCop
|
|
19
19
|
|
20
20
|
# @!method non_public_modifier?(node)
|
21
21
|
def_node_matcher :non_public_modifier?, <<~PATTERN
|
22
|
-
(send nil? {:private :protected} ({def defs} ...))
|
22
|
+
(send nil? {:private :protected :private_class_method} ({def defs} ...))
|
23
23
|
PATTERN
|
24
24
|
end
|
25
25
|
end
|
@@ -30,8 +30,10 @@ module RuboCop
|
|
30
30
|
private
|
31
31
|
|
32
32
|
def inside_interpolation?(node)
|
33
|
-
# A :begin node inside a :dstr or :
|
34
|
-
node.ancestors
|
33
|
+
# A :begin node inside a :dstr, :dsym, or :regexp node is an interpolation.
|
34
|
+
node.ancestors
|
35
|
+
.drop_while { |a| !a.begin_type? }
|
36
|
+
.any? { |a| a.dstr_type? || a.dsym_type? || a.regexp_type? }
|
35
37
|
end
|
36
38
|
end
|
37
39
|
end
|
@@ -122,7 +122,7 @@ module RuboCop
|
|
122
122
|
end
|
123
123
|
|
124
124
|
def bareword?(sym_node)
|
125
|
-
!sym_node.source.start_with?(':')
|
125
|
+
!sym_node.source.start_with?(':') || sym_node.dsym_type?
|
126
126
|
end
|
127
127
|
|
128
128
|
def correct_alias_method_to_alias(corrector, send_node)
|
@@ -134,9 +134,7 @@ module RuboCop
|
|
134
134
|
|
135
135
|
def correct_alias_to_alias_method(corrector, node)
|
136
136
|
replacement =
|
137
|
-
|
138
|
-
":#{identifier(node.new_identifier)}, " \
|
139
|
-
":#{identifier(node.old_identifier)}"
|
137
|
+
"alias_method #{identifier(node.new_identifier)}, #{identifier(node.old_identifier)}"
|
140
138
|
|
141
139
|
corrector.replace(node, replacement)
|
142
140
|
end
|
@@ -146,10 +144,13 @@ module RuboCop
|
|
146
144
|
corrector.replace(node.old_identifier, node.old_identifier.source[1..])
|
147
145
|
end
|
148
146
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
147
|
+
def identifier(node)
|
148
|
+
if node.sym_type?
|
149
|
+
":#{node.children.first}"
|
150
|
+
else
|
151
|
+
node.source
|
152
|
+
end
|
153
|
+
end
|
153
154
|
end
|
154
155
|
end
|
155
156
|
end
|
@@ -100,7 +100,7 @@ module RuboCop
|
|
100
100
|
return if send_classifications.empty?
|
101
101
|
|
102
102
|
if only_forwards_all?(send_classifications)
|
103
|
-
add_forward_all_offenses(node, send_classifications)
|
103
|
+
add_forward_all_offenses(node, send_classifications, forwardable_args)
|
104
104
|
elsif target_ruby_version >= 3.2
|
105
105
|
add_post_ruby_32_offenses(node, send_classifications, forwardable_args)
|
106
106
|
end
|
@@ -118,12 +118,13 @@ module RuboCop
|
|
118
118
|
send_classifications.each_value.all? { |c, _, _| c == :all }
|
119
119
|
end
|
120
120
|
|
121
|
-
def add_forward_all_offenses(node, send_classifications)
|
122
|
-
send_classifications.
|
123
|
-
|
121
|
+
def add_forward_all_offenses(node, send_classifications, forwardable_args)
|
122
|
+
send_classifications.each do |send_node, (_c, forward_rest, _forward_kwrest)|
|
123
|
+
register_forward_all_offense(send_node, send_node, forward_rest)
|
124
124
|
end
|
125
125
|
|
126
|
-
|
126
|
+
rest_arg, _kwrest_arg, _block_arg = *forwardable_args
|
127
|
+
register_forward_all_offense(node, node.arguments, rest_arg)
|
127
128
|
end
|
128
129
|
|
129
130
|
def add_post_ruby_32_offenses(def_node, send_classifications, forwardable_args)
|
@@ -186,9 +187,7 @@ module RuboCop
|
|
186
187
|
|
187
188
|
def register_forward_args_offense(def_arguments_or_send, rest_arg_or_splat)
|
188
189
|
add_offense(rest_arg_or_splat, message: ARGS_MSG) do |corrector|
|
189
|
-
|
190
|
-
add_parentheses(def_arguments_or_send, corrector)
|
191
|
-
end
|
190
|
+
add_parens_if_missing(def_arguments_or_send, corrector)
|
192
191
|
|
193
192
|
corrector.replace(rest_arg_or_splat, '*')
|
194
193
|
end
|
@@ -196,36 +195,28 @@ module RuboCop
|
|
196
195
|
|
197
196
|
def register_forward_kwargs_offense(add_parens, def_arguments_or_send, kwrest_arg_or_splat)
|
198
197
|
add_offense(kwrest_arg_or_splat, message: KWARGS_MSG) do |corrector|
|
199
|
-
if add_parens
|
200
|
-
add_parentheses(def_arguments_or_send, corrector)
|
201
|
-
end
|
198
|
+
add_parens_if_missing(def_arguments_or_send, corrector) if add_parens
|
202
199
|
|
203
200
|
corrector.replace(kwrest_arg_or_splat, '**')
|
204
201
|
end
|
205
202
|
end
|
206
203
|
|
207
|
-
def
|
208
|
-
|
209
|
-
begin_pos = forwarding_method.loc.selector&.end_pos || forwarding_method.loc.dot.end_pos
|
210
|
-
range = range_between(begin_pos, forwarding_method.source_range.end_pos)
|
204
|
+
def register_forward_all_offense(def_or_send, send_or_arguments, rest_or_splat)
|
205
|
+
arg_range = arguments_range(def_or_send, rest_or_splat)
|
211
206
|
|
212
|
-
|
213
|
-
|
214
|
-
end
|
207
|
+
add_offense(arg_range, message: FORWARDING_MSG) do |corrector|
|
208
|
+
add_parens_if_missing(send_or_arguments, corrector)
|
215
209
|
|
216
|
-
|
217
|
-
add_offense(arguments_range(method_definition), message: FORWARDING_MSG) do |corrector|
|
218
|
-
arguments_range = range_with_surrounding_space(
|
219
|
-
method_definition.arguments.source_range, side: :left
|
220
|
-
)
|
221
|
-
corrector.replace(arguments_range, '(...)')
|
210
|
+
corrector.replace(arg_range, '...')
|
222
211
|
end
|
223
212
|
end
|
224
213
|
|
225
|
-
def arguments_range(node)
|
214
|
+
def arguments_range(node, first_node)
|
226
215
|
arguments = node.arguments
|
227
216
|
|
228
|
-
|
217
|
+
start_node = first_node || arguments.first
|
218
|
+
|
219
|
+
range_between(start_node.source_range.begin_pos, arguments.last.source_range.end_pos)
|
229
220
|
end
|
230
221
|
|
231
222
|
def allow_only_rest_arguments?
|
@@ -236,18 +227,24 @@ module RuboCop
|
|
236
227
|
cop_config.fetch('UseAnonymousForwarding', false)
|
237
228
|
end
|
238
229
|
|
230
|
+
def add_parens_if_missing(node, corrector)
|
231
|
+
return if parentheses?(node)
|
232
|
+
|
233
|
+
add_parentheses(node, corrector)
|
234
|
+
end
|
235
|
+
|
239
236
|
# Classifies send nodes for possible rest/kwrest/all (including block) forwarding.
|
240
237
|
class SendNodeClassifier
|
241
238
|
extend NodePattern::Macros
|
242
239
|
|
243
|
-
# @!method
|
244
|
-
|
240
|
+
# @!method forwarded_rest_arg?(node, rest_name)
|
241
|
+
def_node_matcher :forwarded_rest_arg?, '(splat (lvar %1))'
|
245
242
|
|
246
|
-
# @!method
|
247
|
-
|
243
|
+
# @!method extract_forwarded_kwrest_arg(node, kwrest_name)
|
244
|
+
def_node_matcher :extract_forwarded_kwrest_arg, '(hash <$(kwsplat (lvar %1)) ...>)'
|
248
245
|
|
249
|
-
# @!method
|
250
|
-
|
246
|
+
# @!method forwarded_block_arg?(node, block_name)
|
247
|
+
def_node_matcher :forwarded_block_arg?, '(block_pass {(lvar %1) nil?})'
|
251
248
|
|
252
249
|
def initialize(def_node, send_node, referenced_lvars, forwardable_args, **config)
|
253
250
|
@def_node = def_node
|
@@ -262,25 +259,25 @@ module RuboCop
|
|
262
259
|
def forwarded_rest_arg
|
263
260
|
return nil if referenced_rest_arg?
|
264
261
|
|
265
|
-
|
262
|
+
arguments.find { |arg| forwarded_rest_arg?(arg, @rest_arg_name) }
|
266
263
|
end
|
267
264
|
|
268
265
|
def forwarded_kwrest_arg
|
269
266
|
return nil if referenced_kwrest_arg?
|
270
267
|
|
271
|
-
|
268
|
+
arguments.filter_map { |arg| extract_forwarded_kwrest_arg(arg, @kwrest_arg_name) }.first
|
272
269
|
end
|
273
270
|
|
274
271
|
def forwarded_block_arg
|
275
272
|
return nil if referenced_block_arg?
|
276
273
|
|
277
|
-
|
274
|
+
arguments.find { |arg| forwarded_block_arg?(arg, @block_arg_name) }
|
278
275
|
end
|
279
276
|
|
280
277
|
def classification
|
281
278
|
return nil unless forwarded_rest_arg || forwarded_kwrest_arg
|
282
279
|
|
283
|
-
if
|
280
|
+
if can_forward_all?
|
284
281
|
:all
|
285
282
|
elsif target_ruby_version >= 3.2
|
286
283
|
:rest_or_kwrest
|
@@ -289,6 +286,31 @@ module RuboCop
|
|
289
286
|
|
290
287
|
private
|
291
288
|
|
289
|
+
def can_forward_all?
|
290
|
+
return false if any_arg_referenced?
|
291
|
+
return false if ruby_32_missing_rest_or_kwest?
|
292
|
+
return false unless offensive_block_forwarding?
|
293
|
+
return false if forward_additional_kwargs?
|
294
|
+
|
295
|
+
no_additional_args? || (target_ruby_version >= 3.0 && no_post_splat_args?)
|
296
|
+
end
|
297
|
+
|
298
|
+
def ruby_32_missing_rest_or_kwest?
|
299
|
+
target_ruby_version >= 3.2 && !forwarded_rest_and_kwrest_args
|
300
|
+
end
|
301
|
+
|
302
|
+
def offensive_block_forwarding?
|
303
|
+
@block_arg ? forwarded_block_arg : allow_offense_for_no_block?
|
304
|
+
end
|
305
|
+
|
306
|
+
def forwarded_rest_and_kwrest_args
|
307
|
+
forwarded_rest_arg && forwarded_kwrest_arg
|
308
|
+
end
|
309
|
+
|
310
|
+
def arguments
|
311
|
+
@send_node.arguments
|
312
|
+
end
|
313
|
+
|
292
314
|
def referenced_rest_arg?
|
293
315
|
@referenced_lvars.include?(@rest_arg_name)
|
294
316
|
end
|
@@ -301,25 +323,36 @@ module RuboCop
|
|
301
323
|
@referenced_lvars.include?(@block_arg_name)
|
302
324
|
end
|
303
325
|
|
304
|
-
def
|
305
|
-
|
306
|
-
end
|
307
|
-
|
308
|
-
def forwarded_exactly_all?
|
309
|
-
@send_node.arguments.size == 3 &&
|
310
|
-
forwarded_rest_arg &&
|
311
|
-
forwarded_kwrest_arg &&
|
312
|
-
forwarded_block_arg
|
326
|
+
def any_arg_referenced?
|
327
|
+
referenced_rest_arg? || referenced_kwrest_arg? || referenced_block_arg?
|
313
328
|
end
|
314
329
|
|
315
330
|
def target_ruby_version
|
316
331
|
@config.fetch(:target_ruby_version)
|
317
332
|
end
|
318
333
|
|
319
|
-
def
|
320
|
-
|
321
|
-
|
322
|
-
|
334
|
+
def no_post_splat_args?
|
335
|
+
splat_index = arguments.index(forwarded_rest_arg)
|
336
|
+
arg_after_splat = arguments[splat_index + 1]
|
337
|
+
|
338
|
+
[nil, :hash, :block_pass].include?(arg_after_splat&.type)
|
339
|
+
end
|
340
|
+
|
341
|
+
def forward_additional_kwargs?
|
342
|
+
return false unless forwarded_kwrest_arg
|
343
|
+
|
344
|
+
!forwarded_kwrest_arg.parent.children.one?
|
345
|
+
end
|
346
|
+
|
347
|
+
def allow_offense_for_no_block?
|
348
|
+
!@config.fetch(:allow_only_rest_arguments)
|
349
|
+
end
|
350
|
+
|
351
|
+
def no_additional_args?
|
352
|
+
forwardable_count = [@rest_arg, @kwrest_arg, @block_arg].compact.size
|
353
|
+
|
354
|
+
@def_node.arguments.size == forwardable_count &&
|
355
|
+
@send_node.arguments.size == forwardable_count
|
323
356
|
end
|
324
357
|
end
|
325
358
|
end
|
@@ -370,7 +370,8 @@ module RuboCop
|
|
370
370
|
def special_method_proper_block_style?(node)
|
371
371
|
method_name = node.method_name
|
372
372
|
return true if allowed_method?(method_name) || matches_allowed_pattern?(method_name)
|
373
|
-
|
373
|
+
|
374
|
+
node.braces? if braces_required_method?(method_name)
|
374
375
|
end
|
375
376
|
|
376
377
|
def braces_required_method?(method_name)
|
@@ -69,6 +69,8 @@ module RuboCop
|
|
69
69
|
matches_allowed_pattern?(def_node.method_name))
|
70
70
|
|
71
71
|
class_comparison_candidate?(node) do |receiver_node, class_node|
|
72
|
+
return if class_node.dstr_type?
|
73
|
+
|
72
74
|
range = offense_range(receiver_node, node)
|
73
75
|
class_argument = (class_name = class_name(class_node, node)) ? "(#{class_name})" : ''
|
74
76
|
|
@@ -20,6 +20,7 @@ module RuboCop
|
|
20
20
|
# lambda.(x, y)
|
21
21
|
class LambdaCall < Base
|
22
22
|
include ConfigurableEnforcedStyle
|
23
|
+
include IgnoredNode
|
23
24
|
extend AutoCorrector
|
24
25
|
|
25
26
|
MSG = 'Prefer the use of `%<prefer>s` over `%<current>s`.'
|
@@ -33,8 +34,12 @@ module RuboCop
|
|
33
34
|
current = node.source
|
34
35
|
|
35
36
|
add_offense(node, message: format(MSG, prefer: prefer, current: current)) do |corrector|
|
37
|
+
next if part_of_ignored_node?(node)
|
38
|
+
|
36
39
|
opposite_style_detected
|
37
40
|
corrector.replace(node, prefer)
|
41
|
+
|
42
|
+
ignore_node(node)
|
38
43
|
end
|
39
44
|
else
|
40
45
|
correct_style_detected
|
@@ -40,7 +40,7 @@ module RuboCop
|
|
40
40
|
def on_class(node)
|
41
41
|
begin_node = node.child_nodes.find(&:begin_type?) || node
|
42
42
|
begin_node.each_child_node(:send).select(&:macro?).each do |macro|
|
43
|
-
next
|
43
|
+
next if !MIXIN_METHODS.include?(macro.method_name) || macro.arguments.empty?
|
44
44
|
|
45
45
|
check(macro)
|
46
46
|
end
|
@@ -22,13 +22,18 @@ module RuboCop
|
|
22
22
|
# return something
|
23
23
|
# end
|
24
24
|
#
|
25
|
-
# #
|
25
|
+
# # bad
|
26
26
|
# def test
|
27
27
|
# return something if something_else
|
28
28
|
# end
|
29
29
|
#
|
30
30
|
# # good
|
31
31
|
# def test
|
32
|
+
# something if something_else
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# # good
|
36
|
+
# def test
|
32
37
|
# if x
|
33
38
|
# elsif y
|
34
39
|
# else
|
@@ -136,7 +141,7 @@ module RuboCop
|
|
136
141
|
end
|
137
142
|
|
138
143
|
def check_if_node(node)
|
139
|
-
return if node.
|
144
|
+
return if node.ternary?
|
140
145
|
|
141
146
|
check_branch(node.if_branch)
|
142
147
|
check_branch(node.else_branch)
|
@@ -77,6 +77,8 @@ module RuboCop
|
|
77
77
|
private
|
78
78
|
|
79
79
|
def nil_node_at_the_end_of_method_body(body)
|
80
|
+
return body if body.nil_type?
|
81
|
+
return unless body.begin_type?
|
80
82
|
return unless (last_child = body.children.last)
|
81
83
|
|
82
84
|
last_child if last_child.is_a?(AST::Node) && last_child.nil_type?
|
@@ -3,22 +3,42 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks that quotes inside
|
6
|
+
# Checks that quotes inside string, symbol, and regexp interpolations
|
7
7
|
# match the configured preference.
|
8
8
|
#
|
9
9
|
# @example EnforcedStyle: single_quotes (default)
|
10
10
|
# # bad
|
11
|
-
#
|
11
|
+
# string = "Tests #{success ? "PASS" : "FAIL"}"
|
12
|
+
# symbol = :"Tests #{success ? "PASS" : "FAIL"}"
|
13
|
+
# heredoc = <<~TEXT
|
14
|
+
# Tests #{success ? "PASS" : "FAIL"}
|
15
|
+
# TEXT
|
16
|
+
# regexp = /Tests #{success ? "PASS" : "FAIL"}/
|
12
17
|
#
|
13
18
|
# # good
|
14
|
-
#
|
19
|
+
# string = "Tests #{success ? 'PASS' : 'FAIL'}"
|
20
|
+
# symbol = :"Tests #{success ? 'PASS' : 'FAIL'}"
|
21
|
+
# heredoc = <<~TEXT
|
22
|
+
# Tests #{success ? 'PASS' : 'FAIL'}
|
23
|
+
# TEXT
|
24
|
+
# regexp = /Tests #{success ? 'PASS' : 'FAIL'}/
|
15
25
|
#
|
16
26
|
# @example EnforcedStyle: double_quotes
|
17
27
|
# # bad
|
18
|
-
#
|
28
|
+
# string = "Tests #{success ? 'PASS' : 'FAIL'}"
|
29
|
+
# symbol = :"Tests #{success ? 'PASS' : 'FAIL'}"
|
30
|
+
# heredoc = <<~TEXT
|
31
|
+
# Tests #{success ? 'PASS' : 'FAIL'}
|
32
|
+
# TEXT
|
33
|
+
# regexp = /Tests #{success ? 'PASS' : 'FAIL'}/
|
19
34
|
#
|
20
35
|
# # good
|
21
|
-
#
|
36
|
+
# string = "Tests #{success ? "PASS" : "FAIL"}"
|
37
|
+
# symbol = :"Tests #{success ? "PASS" : "FAIL"}"
|
38
|
+
# heredoc = <<~TEXT
|
39
|
+
# Tests #{success ? "PASS" : "FAIL"}
|
40
|
+
# TEXT
|
41
|
+
# regexp = /Tests #{success ? "PASS" : "FAIL"}/
|
22
42
|
class StringLiteralsInInterpolation < Base
|
23
43
|
include ConfigurableEnforcedStyle
|
24
44
|
include StringLiteralsHelp
|
@@ -29,6 +49,11 @@ module RuboCop
|
|
29
49
|
StringLiteralCorrector.correct(corrector, node, style)
|
30
50
|
end
|
31
51
|
|
52
|
+
# Cop classes that include the StringHelp module usually ignore regexp
|
53
|
+
# nodes. Not so for this cop, which is why we override the on_regexp
|
54
|
+
# definition with an empty one.
|
55
|
+
def on_regexp(node); end
|
56
|
+
|
32
57
|
private
|
33
58
|
|
34
59
|
def message(_node)
|
@@ -69,9 +69,9 @@ module RuboCop
|
|
69
69
|
|
70
70
|
def complex_content?(node)
|
71
71
|
node.children.any? do |sym|
|
72
|
-
content
|
73
|
-
content = content.
|
74
|
-
content_without_delimiter_pairs = content.gsub(/(\[\])|(\(\))/, '')
|
72
|
+
content = *sym
|
73
|
+
content = content.map { |c| c.is_a?(AST::Node) ? c.source : c }.join
|
74
|
+
content_without_delimiter_pairs = content.gsub(/(\[[^\s\[\]]*\])|(\([^\s\(\)]*\))/, '')
|
75
75
|
|
76
76
|
content.include?(' ') || DELIMITERS.any? do |delimiter|
|
77
77
|
content_without_delimiter_pairs.include?(delimiter)
|
data/lib/rubocop/lsp/routes.rb
CHANGED
@@ -112,23 +112,29 @@ module RuboCop
|
|
112
112
|
end
|
113
113
|
|
114
114
|
handle 'workspace/executeCommand' do |request|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
params: {
|
121
|
-
label: 'Format with RuboCop autocorrects',
|
122
|
-
edit: {
|
123
|
-
changes: {
|
124
|
-
uri => format_file(uri)
|
125
|
-
}
|
126
|
-
}
|
127
|
-
}
|
128
|
-
)
|
115
|
+
case (command = request[:params][:command])
|
116
|
+
when 'rubocop.formatAutocorrects'
|
117
|
+
label = 'Format with RuboCop autocorrects'
|
118
|
+
when 'rubocop.formatAutocorrectsAll'
|
119
|
+
label = 'Format all with RuboCop autocorrects'
|
129
120
|
else
|
130
|
-
handle_unsupported_method(request,
|
121
|
+
handle_unsupported_method(request, command)
|
122
|
+
return
|
131
123
|
end
|
124
|
+
|
125
|
+
uri = request[:params][:arguments][0][:uri]
|
126
|
+
@server.write(
|
127
|
+
id: request[:id],
|
128
|
+
method: 'workspace/applyEdit',
|
129
|
+
params: {
|
130
|
+
label: label,
|
131
|
+
edit: {
|
132
|
+
changes: {
|
133
|
+
uri => format_file(uri, command: command)
|
134
|
+
}
|
135
|
+
}
|
136
|
+
}
|
137
|
+
)
|
132
138
|
end
|
133
139
|
|
134
140
|
handle 'textDocument/willSave' do |_request|
|
@@ -176,14 +182,14 @@ module RuboCop
|
|
176
182
|
}
|
177
183
|
end
|
178
184
|
|
179
|
-
def format_file(file_uri)
|
185
|
+
def format_file(file_uri, command: nil)
|
180
186
|
unless (text = @text_cache[file_uri])
|
181
187
|
Logger.log("Format request arrived before text synchronized; skipping: `#{file_uri}'")
|
182
188
|
|
183
189
|
return []
|
184
190
|
end
|
185
191
|
|
186
|
-
new_text = @server.format(remove_file_protocol_from(file_uri), text)
|
192
|
+
new_text = @server.format(remove_file_protocol_from(file_uri), text, command: command)
|
187
193
|
|
188
194
|
return [] if new_text == text
|
189
195
|
|
data/lib/rubocop/lsp/runtime.rb
CHANGED
@@ -35,9 +35,15 @@ module RuboCop
|
|
35
35
|
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cli/command/execute_runner.rb#L95
|
36
36
|
# Setting `parallel: true` would break this here:
|
37
37
|
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/runner.rb#L72
|
38
|
-
def format(path, text)
|
38
|
+
def format(path, text, command:)
|
39
|
+
safe_autocorrect = if command
|
40
|
+
command == 'rubocop.formatAutocorrects'
|
41
|
+
else
|
42
|
+
@safe_autocorrect
|
43
|
+
end
|
44
|
+
|
39
45
|
formatting_options = {
|
40
|
-
stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect:
|
46
|
+
stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect: safe_autocorrect
|
41
47
|
}
|
42
48
|
formatting_options[:only] = config_only_options if @lint_mode || @layout_mode
|
43
49
|
|
data/lib/rubocop/lsp/server.rb
CHANGED
data/lib/rubocop/runner.rb
CHANGED
@@ -421,10 +421,10 @@ module RuboCop
|
|
421
421
|
end
|
422
422
|
|
423
423
|
def considered_failure?(offense)
|
424
|
-
# For :autocorrect level, any offense - corrected or not - is a failure.
|
425
424
|
return false if offense.disabled?
|
426
425
|
|
427
|
-
|
426
|
+
# For :autocorrect level, any correctable offense is a failure, regardless of severity
|
427
|
+
return true if @options[:fail_level] == :autocorrect && offense.correctable?
|
428
428
|
|
429
429
|
!offense.corrected? && offense.severity >= minimum_severity_to_fail
|
430
430
|
end
|
@@ -461,7 +461,9 @@ module RuboCop
|
|
461
461
|
@minimum_severity_to_fail ||= begin
|
462
462
|
# Unless given explicitly as `fail_level`, `:info` severity offenses do not fail
|
463
463
|
name = @options[:fail_level] || :refactor
|
464
|
-
|
464
|
+
|
465
|
+
# autocorrect is a fake level - use the default
|
466
|
+
RuboCop::Cop::Severity.new(name == :autocorrect ? :refactor : name)
|
465
467
|
end
|
466
468
|
end
|
467
469
|
|
data/lib/rubocop/version.rb
CHANGED
data/lib/rubocop.rb
CHANGED
@@ -162,6 +162,7 @@ require_relative 'rubocop/cop/correctors/string_literal_corrector'
|
|
162
162
|
require_relative 'rubocop/cop/correctors/unused_arg_corrector'
|
163
163
|
|
164
164
|
require_relative 'rubocop/cop/bundler/duplicated_gem'
|
165
|
+
require_relative 'rubocop/cop/bundler/duplicated_group'
|
165
166
|
require_relative 'rubocop/cop/bundler/gem_comment'
|
166
167
|
require_relative 'rubocop/cop/bundler/gem_filename'
|
167
168
|
require_relative 'rubocop/cop/bundler/gem_version'
|
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.56.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
@@ -10,8 +10,22 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-
|
13
|
+
date: 2023-08-09 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: base64
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - "~>"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.1.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - "~>"
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: 0.1.1
|
15
29
|
- !ruby/object:Gem::Dependency
|
16
30
|
name: json
|
17
31
|
requirement: !ruby/object:Gem::Requirement
|
@@ -240,6 +254,7 @@ files:
|
|
240
254
|
- lib/rubocop/cop/badge.rb
|
241
255
|
- lib/rubocop/cop/base.rb
|
242
256
|
- lib/rubocop/cop/bundler/duplicated_gem.rb
|
257
|
+
- lib/rubocop/cop/bundler/duplicated_group.rb
|
243
258
|
- lib/rubocop/cop/bundler/gem_comment.rb
|
244
259
|
- lib/rubocop/cop/bundler/gem_filename.rb
|
245
260
|
- lib/rubocop/cop/bundler/gem_version.rb
|
@@ -1023,7 +1038,7 @@ metadata:
|
|
1023
1038
|
homepage_uri: https://rubocop.org/
|
1024
1039
|
changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
|
1025
1040
|
source_code_uri: https://github.com/rubocop/rubocop/
|
1026
|
-
documentation_uri: https://docs.rubocop.org/rubocop/1.
|
1041
|
+
documentation_uri: https://docs.rubocop.org/rubocop/1.56/
|
1027
1042
|
bug_tracker_uri: https://github.com/rubocop/rubocop/issues
|
1028
1043
|
rubygems_mfa_required: 'true'
|
1029
1044
|
post_install_message:
|