rubocop 1.81.1 → 1.81.7
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/config/default.yml +4 -2
- data/lib/rubocop/config_loader_resolver.rb +5 -4
- data/lib/rubocop/cop/layout/hash_alignment.rb +2 -5
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +13 -7
- data/lib/rubocop/cop/lint/debugger.rb +0 -2
- data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +16 -6
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +1 -1
- data/lib/rubocop/cop/naming/method_name.rb +3 -1
- data/lib/rubocop/cop/naming/predicate_method.rb +4 -4
- data/lib/rubocop/cop/security/json_load.rb +33 -11
- data/lib/rubocop/cop/style/array_intersect.rb +2 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +7 -3
- data/lib/rubocop/cop/style/constant_visibility.rb +14 -9
- data/lib/rubocop/cop/style/endless_method.rb +15 -2
- data/lib/rubocop/cop/style/float_division.rb +15 -1
- data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
- data/lib/rubocop/cop/style/redundant_format.rb +10 -4
- data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
- data/lib/rubocop/cop/style/semicolon.rb +23 -7
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -1
- data/lib/rubocop/cops_documentation_generator.rb +4 -4
- data/lib/rubocop/version.rb +1 -1
- metadata +4 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8acfafa4ed4b94c367e6ef95c84d2d02f01222a1e8a813790948977476f34456
|
|
4
|
+
data.tar.gz: 0d2ad56c4a81da58046a098351606bfb8314f09f9e5f946ad1dd825aa70fe0f7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ae4edea22ca7511df39ec99591df3d537bfd3fa8974d5bb461d2b1c674b48f15296f22c81b1cd9329719a68b0d3f8d36442eaa5742cbf8e0974c6e3e2e56e29c
|
|
7
|
+
data.tar.gz: ffce467cec50d2ed0ef7b312a15dd17e9b7fd1622b70528d12f0cfe16056ae3b5111f2d360b4e855ea5811befd092a306ff56ad091b89a6050f3354f3db205a4
|
data/config/default.yml
CHANGED
|
@@ -275,7 +275,7 @@ Gemspec/AddRuntimeDependency:
|
|
|
275
275
|
Description: 'Prefer `add_dependency` over `add_runtime_dependency`.'
|
|
276
276
|
StyleGuide: '#add_dependency_vs_add_runtime_dependency'
|
|
277
277
|
References:
|
|
278
|
-
- https://github.com/
|
|
278
|
+
- https://github.com/ruby/rubygems/issues/7799#issuecomment-2192720316
|
|
279
279
|
Enabled: pending
|
|
280
280
|
VersionAdded: '1.65'
|
|
281
281
|
Include:
|
|
@@ -3207,6 +3207,7 @@ Security/JSONLoad:
|
|
|
3207
3207
|
security issues. See reference for more information.
|
|
3208
3208
|
References:
|
|
3209
3209
|
- 'https://ruby-doc.org/stdlib-2.7.0/libdoc/json/rdoc/JSON.html#method-i-load'
|
|
3210
|
+
- 'https://bugs.ruby-lang.org/issues/19528'
|
|
3210
3211
|
Enabled: true
|
|
3211
3212
|
VersionAdded: '0.43'
|
|
3212
3213
|
VersionChanged: '1.22'
|
|
@@ -4552,8 +4553,9 @@ Style/LambdaCall:
|
|
|
4552
4553
|
Description: 'Use lambda.call(...) instead of lambda.(...).'
|
|
4553
4554
|
StyleGuide: '#proc-call'
|
|
4554
4555
|
Enabled: true
|
|
4556
|
+
AutoCorrect: contextual
|
|
4555
4557
|
VersionAdded: '0.13'
|
|
4556
|
-
VersionChanged: '
|
|
4558
|
+
VersionChanged: '1.81'
|
|
4557
4559
|
EnforcedStyle: call
|
|
4558
4560
|
SupportedStyles:
|
|
4559
4561
|
- call
|
|
@@ -295,10 +295,11 @@ module RuboCop
|
|
|
295
295
|
begin
|
|
296
296
|
gem = Bundler.load.specs[gem_name].first
|
|
297
297
|
gem_path = gem.full_gem_path if gem
|
|
298
|
-
rescue
|
|
299
|
-
#
|
|
300
|
-
|
|
301
|
-
# The Gemfile exists but contains an uninstalled git source
|
|
298
|
+
rescue StandardError
|
|
299
|
+
# The Gemfile has a problem, which could be one of:
|
|
300
|
+
# - No Gemfile found. Bundler may be loaded manually
|
|
301
|
+
# - The Gemfile exists but contains an uninstalled git source
|
|
302
|
+
# - The Gemfile exists but cannot be loaded for some other reason
|
|
302
303
|
end
|
|
303
304
|
end
|
|
304
305
|
|
|
@@ -193,7 +193,6 @@ module RuboCop
|
|
|
193
193
|
SEPARATOR_ALIGNMENT_STYLES = %w[EnforcedColonStyle EnforcedHashRocketStyle].freeze
|
|
194
194
|
|
|
195
195
|
def on_send(node)
|
|
196
|
-
return if double_splat?(node)
|
|
197
196
|
return unless node.arguments?
|
|
198
197
|
|
|
199
198
|
last_argument = node.last_argument
|
|
@@ -233,6 +232,8 @@ module RuboCop
|
|
|
233
232
|
end
|
|
234
233
|
|
|
235
234
|
def argument_before_hash(hash_node)
|
|
235
|
+
return hash_node.children.first.children.first if hash_node.children.first.kwsplat_type?
|
|
236
|
+
|
|
236
237
|
hash_node.left_sibling.respond_to?(:loc) ? hash_node.left_sibling : nil
|
|
237
238
|
end
|
|
238
239
|
|
|
@@ -241,10 +242,6 @@ module RuboCop
|
|
|
241
242
|
self.column_deltas = Hash.new { |hash, key| hash[key] = {} }
|
|
242
243
|
end
|
|
243
244
|
|
|
244
|
-
def double_splat?(node)
|
|
245
|
-
node.children.last.is_a?(Symbol)
|
|
246
|
-
end
|
|
247
|
-
|
|
248
245
|
def check_pairs(node)
|
|
249
246
|
first_pair = node.pairs.first
|
|
250
247
|
reset!
|
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
|
31
31
|
|
|
32
32
|
# @!method overwritten_constant(node)
|
|
33
33
|
def_node_matcher :overwritten_constant, <<~PATTERN
|
|
34
|
-
(resbody nil? (casgn
|
|
34
|
+
(resbody nil? $(casgn _ _) nil?)
|
|
35
35
|
PATTERN
|
|
36
36
|
|
|
37
37
|
def self.autocorrect_incompatible_with
|
|
@@ -41,7 +41,8 @@ module RuboCop
|
|
|
41
41
|
def on_resbody(node)
|
|
42
42
|
return unless (constant = overwritten_constant(node))
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
message = format(MSG, constant: constant.source)
|
|
45
|
+
add_offense(node.loc.assoc, message: message) do |corrector|
|
|
45
46
|
corrector.remove(range_between(node.loc.keyword.end_pos, node.loc.assoc.end_pos))
|
|
46
47
|
end
|
|
47
48
|
end
|
|
@@ -13,28 +13,34 @@ module RuboCop
|
|
|
13
13
|
# @example
|
|
14
14
|
# # bad
|
|
15
15
|
# # rubocop:disable Layout/LineLength Style/Encoding
|
|
16
|
-
#
|
|
16
|
+
#
|
|
17
|
+
# # good
|
|
18
|
+
# # rubocop:disable Layout/LineLength, Style/Encoding
|
|
17
19
|
#
|
|
18
20
|
# # bad
|
|
19
21
|
# # rubocop:disable
|
|
20
22
|
#
|
|
23
|
+
# # good
|
|
24
|
+
# # rubocop:disable all
|
|
25
|
+
#
|
|
21
26
|
# # bad
|
|
22
27
|
# # rubocop:disable Layout/LineLength # rubocop:disable Style/Encoding
|
|
23
28
|
#
|
|
29
|
+
# # good
|
|
30
|
+
# # rubocop:disable Layout/LineLength
|
|
31
|
+
# # rubocop:disable Style/Encoding
|
|
32
|
+
#
|
|
24
33
|
# # bad
|
|
25
34
|
# # rubocop:wrongmode Layout/LineLength
|
|
26
35
|
#
|
|
27
36
|
# # good
|
|
28
37
|
# # rubocop:disable Layout/LineLength
|
|
29
38
|
#
|
|
30
|
-
# #
|
|
31
|
-
# # rubocop:disable Layout/LineLength
|
|
32
|
-
#
|
|
33
|
-
# # good
|
|
34
|
-
# # rubocop:disable all
|
|
39
|
+
# # bad
|
|
40
|
+
# # rubocop:disable Layout/LineLength comment
|
|
35
41
|
#
|
|
36
42
|
# # good
|
|
37
|
-
# # rubocop:disable Layout/LineLength --
|
|
43
|
+
# # rubocop:disable Layout/LineLength -- comment
|
|
38
44
|
#
|
|
39
45
|
class CopDirectiveSyntax < Base
|
|
40
46
|
COMMON_MSG = 'Malformed directive comment detected.'
|
|
@@ -19,12 +19,23 @@ module RuboCop
|
|
|
19
19
|
MSG = 'Empty interpolation detected.'
|
|
20
20
|
|
|
21
21
|
def on_interpolation(begin_node)
|
|
22
|
+
return if in_percent_literal_array?(begin_node)
|
|
23
|
+
|
|
22
24
|
node_children = begin_node.children.dup
|
|
23
25
|
node_children.delete_if { |e| e.nil_type? || (e.basic_literal? && e.str_content&.empty?) }
|
|
24
26
|
return unless node_children.empty?
|
|
25
27
|
|
|
26
28
|
add_offense(begin_node) { |corrector| corrector.remove(begin_node) }
|
|
27
29
|
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def in_percent_literal_array?(begin_node)
|
|
34
|
+
array_node = begin_node.each_ancestor(:array).first
|
|
35
|
+
return false unless array_node
|
|
36
|
+
|
|
37
|
+
array_node.percent_literal?
|
|
38
|
+
end
|
|
28
39
|
end
|
|
29
40
|
end
|
|
30
41
|
end
|
|
@@ -9,9 +9,21 @@ module RuboCop
|
|
|
9
9
|
# cop disables on wide ranges of code, that latter contributors to
|
|
10
10
|
# a file wouldn't be aware of.
|
|
11
11
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
12
|
+
# You can set `MaximumRangeSize` to define the maximum number of
|
|
13
|
+
# consecutive lines a cop can be disabled for.
|
|
14
|
+
#
|
|
15
|
+
# - `.inf` any size (default)
|
|
16
|
+
# - `0` allows only single-line disables
|
|
17
|
+
# - `1` means the maximum allowed is as follows:
|
|
18
|
+
#
|
|
19
|
+
# [source,ruby]
|
|
20
|
+
# ----
|
|
21
|
+
# # rubocop:disable SomeCop
|
|
22
|
+
# a = 1
|
|
23
|
+
# # rubocop:enable SomeCop
|
|
24
|
+
# ----
|
|
25
|
+
#
|
|
26
|
+
# @example MaximumRangeSize: .inf (default)
|
|
15
27
|
#
|
|
16
28
|
# # good
|
|
17
29
|
# # rubocop:disable Layout/SpaceAroundOperators
|
|
@@ -25,9 +37,7 @@ module RuboCop
|
|
|
25
37
|
# x= 0
|
|
26
38
|
# # EOF
|
|
27
39
|
#
|
|
28
|
-
# @example
|
|
29
|
-
# # Lint/MissingCopEnableDirective:
|
|
30
|
-
# # MaximumRangeSize: 2
|
|
40
|
+
# @example MaximumRangeSize: 2
|
|
31
41
|
#
|
|
32
42
|
# # good
|
|
33
43
|
# # rubocop:disable Layout/SpaceAroundOperators
|
|
@@ -24,10 +24,7 @@ module RuboCop
|
|
|
24
24
|
MSG = 'Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`?'
|
|
25
25
|
|
|
26
26
|
def on_resbody(node)
|
|
27
|
-
return unless node.
|
|
28
|
-
|
|
29
|
-
rescue_args = node.children.first.children
|
|
30
|
-
return unless rescue_args.any? { |a| targets_exception?(a) }
|
|
27
|
+
return unless node.exceptions.any? { |exception| targets_exception?(exception) }
|
|
31
28
|
|
|
32
29
|
add_offense(node)
|
|
33
30
|
end
|
|
@@ -108,7 +108,7 @@ module RuboCop
|
|
|
108
108
|
value_node = node.last_argument
|
|
109
109
|
node_arguments = node.arguments[0...-1]
|
|
110
110
|
|
|
111
|
-
if value_node.
|
|
111
|
+
if value_node.respond_to?(:method?) && value_node.method?(:[]) &&
|
|
112
112
|
node.receiver == value_node.receiver &&
|
|
113
113
|
node_arguments.none?(&:call_type?) &&
|
|
114
114
|
node_arguments == value_node.arguments
|
|
@@ -147,7 +147,9 @@ module RuboCop
|
|
|
147
147
|
alias on_defs on_def
|
|
148
148
|
|
|
149
149
|
def on_alias(node)
|
|
150
|
-
|
|
150
|
+
return unless (new_identifier = node.new_identifier).sym_type?
|
|
151
|
+
|
|
152
|
+
handle_method_name(new_identifier, new_identifier.value)
|
|
151
153
|
end
|
|
152
154
|
|
|
153
155
|
private
|
|
@@ -193,8 +193,7 @@ module RuboCop
|
|
|
193
193
|
return_values << extract_return_value(return_node)
|
|
194
194
|
end
|
|
195
195
|
|
|
196
|
-
|
|
197
|
-
return_values << last_value if last_value
|
|
196
|
+
return_values << last_value(node)
|
|
198
197
|
|
|
199
198
|
process_return_values(return_values)
|
|
200
199
|
end
|
|
@@ -247,8 +246,9 @@ module RuboCop
|
|
|
247
246
|
end
|
|
248
247
|
|
|
249
248
|
def last_value(node)
|
|
250
|
-
value = node.begin_type? ? node.children.last : node
|
|
251
|
-
|
|
249
|
+
value = node.begin_type? ? node.children.last || s(:nil) : node
|
|
250
|
+
|
|
251
|
+
value.return_type? ? extract_return_value(value) : value
|
|
252
252
|
end
|
|
253
253
|
|
|
254
254
|
def process_return_values(return_values)
|
|
@@ -6,22 +6,40 @@ module RuboCop
|
|
|
6
6
|
# Checks for the use of JSON class methods which have potential
|
|
7
7
|
# security issues.
|
|
8
8
|
#
|
|
9
|
+
# `JSON.load` and similar methods allow deserialization of arbitrary ruby objects:
|
|
10
|
+
#
|
|
11
|
+
# [source,ruby]
|
|
12
|
+
# ----
|
|
13
|
+
# require 'json/add/string'
|
|
14
|
+
# result = JSON.load('{ "json_class": "String", "raw": [72, 101, 108, 108, 111] }')
|
|
15
|
+
# pp result # => "Hello"
|
|
16
|
+
# ----
|
|
17
|
+
#
|
|
18
|
+
# Never use `JSON.load` for untrusted user input. Prefer `JSON.parse` unless you have
|
|
19
|
+
# a concrete use-case for `JSON.load`.
|
|
20
|
+
#
|
|
21
|
+
# NOTE: Starting with `json` gem version 2.8.0, triggering this behavior without explicitly
|
|
22
|
+
# passing the `create_additions` keyword argument emits a deprecation warning, with the
|
|
23
|
+
# goal of being secure by default in the next major version 3.0.0.
|
|
24
|
+
#
|
|
9
25
|
# @safety
|
|
10
26
|
# This cop's autocorrection is unsafe because it's potentially dangerous.
|
|
11
|
-
# If using a stream, like `JSON.load(open('file'))`,
|
|
27
|
+
# If using a stream, like `JSON.load(open('file'))`, you will need to call
|
|
12
28
|
# `#read` manually, like `JSON.parse(open('file').read)`.
|
|
13
|
-
# If reading single values (rather than proper JSON objects), like
|
|
14
|
-
# `JSON.load('false')`, it will need to pass the `quirks_mode: true`
|
|
15
|
-
# option, like `JSON.parse('false', quirks_mode: true)`.
|
|
16
29
|
# Other similar issues may apply.
|
|
17
30
|
#
|
|
18
31
|
# @example
|
|
19
32
|
# # bad
|
|
20
|
-
# JSON.load(
|
|
21
|
-
# JSON.restore(
|
|
33
|
+
# JSON.load('{}')
|
|
34
|
+
# JSON.restore('{}')
|
|
22
35
|
#
|
|
23
36
|
# # good
|
|
24
|
-
# JSON.parse(
|
|
37
|
+
# JSON.parse('{}')
|
|
38
|
+
# JSON.unsafe_load('{}')
|
|
39
|
+
#
|
|
40
|
+
# # good - explicit use of `create_additions` option
|
|
41
|
+
# JSON.load('{}', create_additions: true)
|
|
42
|
+
# JSON.load('{}', create_additions: false)
|
|
25
43
|
#
|
|
26
44
|
class JSONLoad < Base
|
|
27
45
|
extend AutoCorrector
|
|
@@ -29,13 +47,17 @@ module RuboCop
|
|
|
29
47
|
MSG = 'Prefer `JSON.parse` over `JSON.%<method>s`.'
|
|
30
48
|
RESTRICT_ON_SEND = %i[load restore].freeze
|
|
31
49
|
|
|
32
|
-
# @!method
|
|
33
|
-
def_node_matcher :
|
|
34
|
-
(
|
|
50
|
+
# @!method insecure_json_load(node)
|
|
51
|
+
def_node_matcher :insecure_json_load, <<~PATTERN
|
|
52
|
+
(
|
|
53
|
+
send (const {nil? cbase} :JSON) ${:load :restore}
|
|
54
|
+
...
|
|
55
|
+
!(hash `(sym $:create_additions))
|
|
56
|
+
)
|
|
35
57
|
PATTERN
|
|
36
58
|
|
|
37
59
|
def on_send(node)
|
|
38
|
-
|
|
60
|
+
insecure_json_load(node) do |method|
|
|
39
61
|
add_offense(node.loc.selector, message: format(MSG, method: method)) do |corrector|
|
|
40
62
|
corrector.replace(node.loc.selector, 'parse')
|
|
41
63
|
end
|
|
@@ -95,7 +95,7 @@ module RuboCop
|
|
|
95
95
|
$(call
|
|
96
96
|
{
|
|
97
97
|
(begin (send $_ :& $_))
|
|
98
|
-
(call
|
|
98
|
+
(call $!nil? :intersection $_)
|
|
99
99
|
}
|
|
100
100
|
$%1
|
|
101
101
|
)
|
|
@@ -107,7 +107,7 @@ module RuboCop
|
|
|
107
107
|
$(call
|
|
108
108
|
{
|
|
109
109
|
(begin (send $_ :& $_))
|
|
110
|
-
(call
|
|
110
|
+
(call $!nil? :intersection $_)
|
|
111
111
|
}
|
|
112
112
|
%ARRAY_SIZE_METHODS
|
|
113
113
|
)
|
|
@@ -444,7 +444,7 @@ module RuboCop
|
|
|
444
444
|
next if child.parent.dstr_type?
|
|
445
445
|
|
|
446
446
|
white_space = white_space_range(child, column)
|
|
447
|
-
corrector.remove(white_space) if white_space
|
|
447
|
+
corrector.remove(white_space) if white_space
|
|
448
448
|
end
|
|
449
449
|
|
|
450
450
|
if condition.loc.else && !same_line?(condition.else_branch, condition)
|
|
@@ -465,9 +465,13 @@ module RuboCop
|
|
|
465
465
|
|
|
466
466
|
def white_space_range(node, column)
|
|
467
467
|
expression = node.source_range
|
|
468
|
-
|
|
468
|
+
end_pos = expression.begin_pos
|
|
469
|
+
begin_pos = end_pos - (expression.column - column - 2)
|
|
469
470
|
|
|
470
|
-
|
|
471
|
+
return nil if begin_pos > end_pos
|
|
472
|
+
|
|
473
|
+
white_space = Parser::Source::Range.new(expression.source_buffer, begin_pos, end_pos)
|
|
474
|
+
white_space if white_space.source.strip.empty?
|
|
471
475
|
end
|
|
472
476
|
|
|
473
477
|
def assignment(node)
|
|
@@ -48,6 +48,11 @@ module RuboCop
|
|
|
48
48
|
MSG = 'Explicitly make `%<constant_name>s` public or private using ' \
|
|
49
49
|
'either `#public_constant` or `#private_constant`.'
|
|
50
50
|
|
|
51
|
+
# @!method visibility_declaration_for(node)
|
|
52
|
+
def_node_matcher :visibility_declaration_for, <<~PATTERN
|
|
53
|
+
(send nil? {:public_constant :private_constant} $...)
|
|
54
|
+
PATTERN
|
|
55
|
+
|
|
51
56
|
def on_casgn(node)
|
|
52
57
|
return unless class_or_module_scope?(node)
|
|
53
58
|
return if visibility_declaration?(node)
|
|
@@ -77,20 +82,20 @@ module RuboCop
|
|
|
77
82
|
end
|
|
78
83
|
end
|
|
79
84
|
|
|
85
|
+
# rubocop:disable Metrics/AbcSize
|
|
80
86
|
def visibility_declaration?(node)
|
|
81
87
|
node.parent.each_child_node(:send).any? do |child|
|
|
82
|
-
visibility_declaration_for
|
|
83
|
-
end
|
|
84
|
-
end
|
|
88
|
+
next false unless (arguments = visibility_declaration_for(child))
|
|
85
89
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
arguments = arguments.first.children.first.to_a if arguments.first&.splat_type?
|
|
91
|
+
constant_values = arguments.map do |argument|
|
|
92
|
+
argument.value.to_sym if argument.respond_to?(:value)
|
|
93
|
+
end
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
95
|
+
constant_values.include?(node.name)
|
|
96
|
+
end
|
|
93
97
|
end
|
|
98
|
+
# rubocop:enable Metrics/AbcSize
|
|
94
99
|
end
|
|
95
100
|
end
|
|
96
101
|
end
|
|
@@ -144,7 +144,7 @@ module RuboCop
|
|
|
144
144
|
MSG_REQUIRE_ALWAYS = 'Use endless method definitions.'
|
|
145
145
|
|
|
146
146
|
def on_def(node)
|
|
147
|
-
return if node.assignment_method?
|
|
147
|
+
return if node.assignment_method? || use_heredoc?(node)
|
|
148
148
|
|
|
149
149
|
case style
|
|
150
150
|
when :allow_single_line, :allow_always
|
|
@@ -198,6 +198,13 @@ module RuboCop
|
|
|
198
198
|
add_offense(node) { |corrector| correct_to_multiline(corrector, node) }
|
|
199
199
|
end
|
|
200
200
|
|
|
201
|
+
def use_heredoc?(node)
|
|
202
|
+
return false unless (body = node.body)
|
|
203
|
+
return true if body.str_type? && body.heredoc?
|
|
204
|
+
|
|
205
|
+
body.each_descendant(:str).any?(&:heredoc?)
|
|
206
|
+
end
|
|
207
|
+
|
|
201
208
|
def correct_to_multiline(corrector, node)
|
|
202
209
|
replacement = <<~RUBY.strip
|
|
203
210
|
def #{node.method_name}#{arguments(node)}
|
|
@@ -225,7 +232,13 @@ module RuboCop
|
|
|
225
232
|
def too_long_when_made_endless?(node)
|
|
226
233
|
return false unless config.cop_enabled?('Layout/LineLength')
|
|
227
234
|
|
|
228
|
-
|
|
235
|
+
offset = modifier_offset(node)
|
|
236
|
+
|
|
237
|
+
endless_replacement(node).length + offset > config.for_cop('Layout/LineLength')['Max']
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def modifier_offset(node)
|
|
241
|
+
same_line?(node.parent, node) ? node.loc.column - node.parent.loc.column : 0
|
|
229
242
|
end
|
|
230
243
|
end
|
|
231
244
|
end
|
|
@@ -7,9 +7,12 @@ module RuboCop
|
|
|
7
7
|
# It is recommended to either always use `fdiv` or coerce one side only.
|
|
8
8
|
# This cop also provides other options for code consistency.
|
|
9
9
|
#
|
|
10
|
+
# For `Regexp.last_match` and nth reference (e.g., `$1`), it assumes that the value
|
|
11
|
+
# is a string matched by a regular expression, and allows conversion with `#to_f`.
|
|
12
|
+
#
|
|
10
13
|
# @safety
|
|
11
14
|
# This cop is unsafe, because if the operand variable is a string object
|
|
12
|
-
# then
|
|
15
|
+
# then `#to_f` will be removed and an error will occur.
|
|
13
16
|
#
|
|
14
17
|
# [source,ruby]
|
|
15
18
|
# ----
|
|
@@ -84,6 +87,14 @@ module RuboCop
|
|
|
84
87
|
(send !nil? :to_f)
|
|
85
88
|
PATTERN
|
|
86
89
|
|
|
90
|
+
# @!method regexp_last_match?(node)
|
|
91
|
+
def_node_matcher :regexp_last_match?, <<~PATTERN
|
|
92
|
+
{
|
|
93
|
+
(send (const {nil? cbase} :Regexp) :last_match int)
|
|
94
|
+
(:nth_ref _)
|
|
95
|
+
}
|
|
96
|
+
PATTERN
|
|
97
|
+
|
|
87
98
|
def on_send(node)
|
|
88
99
|
return unless offense_condition?(node)
|
|
89
100
|
|
|
@@ -104,6 +115,9 @@ module RuboCop
|
|
|
104
115
|
private
|
|
105
116
|
|
|
106
117
|
def offense_condition?(node)
|
|
118
|
+
return false if regexp_last_match?(node.receiver.receiver) ||
|
|
119
|
+
regexp_last_match?(node.first_argument.receiver)
|
|
120
|
+
|
|
107
121
|
case style
|
|
108
122
|
when :left_coerce
|
|
109
123
|
right_coerce?(node)
|
|
@@ -55,19 +55,21 @@ module RuboCop
|
|
|
55
55
|
include OnNormalIfUnless
|
|
56
56
|
extend AutoCorrector
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
MSG_SUFFIX = 'over single-line `%<keyword>s/then/else/end` constructs.'
|
|
59
|
+
MSG_TERNARY = "Favor the ternary operator (`?:`) #{MSG_SUFFIX}"
|
|
60
|
+
MSG_MULTILINE = "Favor multi-line `%<keyword>s` #{MSG_SUFFIX}"
|
|
60
61
|
|
|
61
62
|
def on_normal_if_unless(node)
|
|
62
63
|
return unless node.single_line?
|
|
63
64
|
return unless node.else_branch
|
|
64
65
|
return if node.elsif? || node.if_branch&.begin_type?
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
multiline = multiline?(node)
|
|
68
|
+
|
|
69
|
+
add_offense(node, message: message(node, multiline)) do |corrector|
|
|
68
70
|
next if part_of_ignored_node?(node)
|
|
69
71
|
|
|
70
|
-
autocorrect(corrector, node)
|
|
72
|
+
autocorrect(corrector, node, multiline)
|
|
71
73
|
|
|
72
74
|
ignore_node(node)
|
|
73
75
|
end
|
|
@@ -75,12 +77,18 @@ module RuboCop
|
|
|
75
77
|
|
|
76
78
|
private
|
|
77
79
|
|
|
78
|
-
def
|
|
79
|
-
|
|
80
|
+
def multiline?(node)
|
|
81
|
+
always_multiline? || cannot_replace_to_ternary?(node)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def message(node, multiline)
|
|
85
|
+
template = multiline ? MSG_MULTILINE : MSG_TERNARY
|
|
86
|
+
|
|
87
|
+
format(template, keyword: node.keyword)
|
|
80
88
|
end
|
|
81
89
|
|
|
82
|
-
def autocorrect(corrector, node)
|
|
83
|
-
if
|
|
90
|
+
def autocorrect(corrector, node, multiline)
|
|
91
|
+
if multiline
|
|
84
92
|
IfThenCorrector.new(node, indentation: configured_indentation_width).call(corrector)
|
|
85
93
|
else
|
|
86
94
|
corrector.replace(node, ternary_correction(node))
|
|
@@ -89,7 +89,7 @@ module RuboCop
|
|
|
89
89
|
|
|
90
90
|
def on_send(node)
|
|
91
91
|
format_without_additional_args?(node) do |value|
|
|
92
|
-
replacement = value.source
|
|
92
|
+
replacement = escape_control_chars(value.source)
|
|
93
93
|
|
|
94
94
|
add_offense(node, message: message(node, replacement)) do |corrector|
|
|
95
95
|
corrector.replace(node, replacement)
|
|
@@ -134,7 +134,7 @@ module RuboCop
|
|
|
134
134
|
end
|
|
135
135
|
end
|
|
136
136
|
|
|
137
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
|
137
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
138
138
|
def all_fields_literal?(string, arguments)
|
|
139
139
|
count = 0
|
|
140
140
|
sequences = RuboCop::Cop::Utils::FormatString.new(string).format_sequences
|
|
@@ -147,13 +147,14 @@ module RuboCop
|
|
|
147
147
|
hash = arguments.detect(&:hash_type?)
|
|
148
148
|
next unless (argument = find_argument(sequence, arguments, hash))
|
|
149
149
|
next unless matching_argument?(sequence, argument)
|
|
150
|
+
next if (sequence.width || sequence.precision) && argument.dstr_type?
|
|
150
151
|
|
|
151
152
|
count += 1
|
|
152
153
|
end
|
|
153
154
|
|
|
154
155
|
sequences.size == count
|
|
155
156
|
end
|
|
156
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
|
157
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
157
158
|
|
|
158
159
|
# If the sequence has a variable (`*`) width, it cannot be autocorrected
|
|
159
160
|
# if the width is not given as a numeric literal argument
|
|
@@ -229,7 +230,12 @@ module RuboCop
|
|
|
229
230
|
end
|
|
230
231
|
end
|
|
231
232
|
|
|
232
|
-
"#{start_delimiter}#{string}#{end_delimiter}"
|
|
233
|
+
"#{start_delimiter}#{escape_control_chars(string)}#{end_delimiter}"
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Escape any control characters in the string (eg. `\t` or `\n` become `\\t` or `\\n`)
|
|
237
|
+
def escape_control_chars(string)
|
|
238
|
+
string.gsub(/\p{Cc}/) { |s| s.dump[1..-2] }
|
|
233
239
|
end
|
|
234
240
|
|
|
235
241
|
def argument_values(arguments)
|
|
@@ -49,9 +49,10 @@ module RuboCop
|
|
|
49
49
|
def on_dstr(node)
|
|
50
50
|
return unless single_interpolation?(node)
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
embedded_node = node.children.first
|
|
53
|
+
return if use_match_pattern?(embedded_node)
|
|
54
54
|
|
|
55
|
+
add_offense(node) do |corrector|
|
|
55
56
|
if variable_interpolation?(embedded_node)
|
|
56
57
|
autocorrect_variable_interpolation(corrector, embedded_node, node)
|
|
57
58
|
elsif single_variable_interpolation?(embedded_node)
|
|
@@ -71,6 +72,14 @@ module RuboCop
|
|
|
71
72
|
!embedded_in_percent_array?(node)
|
|
72
73
|
end
|
|
73
74
|
|
|
75
|
+
def use_match_pattern?(node)
|
|
76
|
+
return false if target_ruby_version <= 2.7
|
|
77
|
+
|
|
78
|
+
node.children.any? do |child|
|
|
79
|
+
child.respond_to?(:match_pattern_type?) && child.match_pattern_type?
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
74
83
|
def single_variable_interpolation?(node)
|
|
75
84
|
return false unless node.children.one?
|
|
76
85
|
|
|
@@ -69,10 +69,11 @@ module RuboCop
|
|
|
69
69
|
|
|
70
70
|
def each_semicolon
|
|
71
71
|
tokens_for_lines.each do |line, tokens|
|
|
72
|
-
semicolon_pos = semicolon_position(tokens)
|
|
72
|
+
next unless (semicolon_pos = semicolon_position(tokens))
|
|
73
|
+
|
|
73
74
|
after_expr_pos = semicolon_pos == -1 ? -2 : semicolon_pos
|
|
74
75
|
|
|
75
|
-
yield line, tokens[semicolon_pos].column, tokens[after_expr_pos]
|
|
76
|
+
yield line, tokens[semicolon_pos].column, tokens[after_expr_pos]
|
|
76
77
|
end
|
|
77
78
|
end
|
|
78
79
|
|
|
@@ -119,6 +120,7 @@ module RuboCop
|
|
|
119
120
|
tokens[1]&.type == :tSTRING_DBEG && tokens[2]&.semicolon?
|
|
120
121
|
end
|
|
121
122
|
|
|
123
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
122
124
|
def register_semicolon(line, column, after_expression, token_before_semicolon = nil)
|
|
123
125
|
range = source_range(processed_source.buffer, line, column)
|
|
124
126
|
|
|
@@ -130,14 +132,19 @@ module RuboCop
|
|
|
130
132
|
# without parentheses.
|
|
131
133
|
# See: https://github.com/rubocop/rubocop/issues/10791
|
|
132
134
|
if token_before_semicolon&.regexp_dots?
|
|
133
|
-
|
|
134
|
-
|
|
135
|
+
node = find_node(range_nodes, token_before_semicolon)
|
|
136
|
+
elsif token_before_semicolon&.type == :tLABEL
|
|
137
|
+
node = find_node(value_omission_pair_nodes, token_before_semicolon).parent
|
|
138
|
+
space = node.parent.loc.selector.end.join(node.source_range.begin)
|
|
139
|
+
corrector.remove(space)
|
|
135
140
|
end
|
|
136
141
|
|
|
142
|
+
corrector.wrap(node, '(', ')') if node
|
|
137
143
|
corrector.remove(range)
|
|
138
144
|
end
|
|
139
145
|
end
|
|
140
146
|
end
|
|
147
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
141
148
|
|
|
142
149
|
def expressions_per_line(exprs)
|
|
143
150
|
# create a map matching lines to the number of expressions on them
|
|
@@ -153,9 +160,9 @@ module RuboCop
|
|
|
153
160
|
end
|
|
154
161
|
end
|
|
155
162
|
|
|
156
|
-
def
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
def find_node(nodes, token_before_semicolon)
|
|
164
|
+
nodes.detect do |node|
|
|
165
|
+
node.source_range.overlaps?(token_before_semicolon.pos)
|
|
159
166
|
end
|
|
160
167
|
end
|
|
161
168
|
|
|
@@ -166,6 +173,15 @@ module RuboCop
|
|
|
166
173
|
@range_nodes = ast.range_type? ? [ast] : []
|
|
167
174
|
@range_nodes.concat(ast.each_descendant(:range).to_a)
|
|
168
175
|
end
|
|
176
|
+
|
|
177
|
+
def value_omission_pair_nodes
|
|
178
|
+
if instance_variable_defined?(:@value_omission_pair_nodes)
|
|
179
|
+
return @value_omission_pair_nodes
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
ast = processed_source.ast
|
|
183
|
+
@value_omission_pair_nodes = ast.each_descendant(:pair).to_a.select(&:value_omission?)
|
|
184
|
+
end
|
|
169
185
|
end
|
|
170
186
|
end
|
|
171
187
|
end
|
|
@@ -129,6 +129,7 @@ module RuboCop
|
|
|
129
129
|
corrector.remove(range_with_surrounding_space(range, newlines: false))
|
|
130
130
|
end
|
|
131
131
|
|
|
132
|
+
# rubocop:disable Metrics/AbcSize
|
|
132
133
|
def correct_for_basic_condition_style(corrector, node, if_branch)
|
|
133
134
|
range = range_between(
|
|
134
135
|
node.condition.source_range.end_pos, if_branch.condition.source_range.begin_pos
|
|
@@ -137,8 +138,14 @@ module RuboCop
|
|
|
137
138
|
|
|
138
139
|
corrector.replace(if_branch.condition, chainable_condition(if_branch))
|
|
139
140
|
|
|
140
|
-
|
|
141
|
+
end_range = if same_line?(node.loc.end, node.if_branch.loc.end)
|
|
142
|
+
node.loc.end
|
|
143
|
+
else
|
|
144
|
+
range_by_whole_lines(node.loc.end, include_final_newline: true)
|
|
145
|
+
end
|
|
146
|
+
corrector.remove(end_range)
|
|
141
147
|
end
|
|
148
|
+
# rubocop:enable Metrics/AbcSize
|
|
142
149
|
|
|
143
150
|
def autocorrect_outer_condition_modify_form(corrector, node, if_branch)
|
|
144
151
|
correct_node(corrector, if_branch)
|
|
@@ -194,10 +194,10 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
|
194
194
|
|
|
195
195
|
def configurations(department, cop, cop_config)
|
|
196
196
|
header = ['Name', 'Default value', 'Configurable values']
|
|
197
|
-
configs = cop_config
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
configs = cop_config.each_key.reject do |key|
|
|
198
|
+
key == 'AllowMultipleStyles' ||
|
|
199
|
+
(key != 'SupportedTypes' && key.start_with?('Supported'))
|
|
200
|
+
end
|
|
201
201
|
return '' if configs.empty?
|
|
202
202
|
|
|
203
203
|
content = configs.map do |name|
|
data/lib/rubocop/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubocop
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.81.
|
|
4
|
+
version: 1.81.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bozhidar Batsov
|
|
8
8
|
- Jonas Arvidsson
|
|
9
9
|
- Yuji Nakayama
|
|
10
|
-
autorequire:
|
|
11
10
|
bindir: exe
|
|
12
11
|
cert_chain: []
|
|
13
|
-
date: 2025-
|
|
12
|
+
date: 2025-10-31 00:00:00.000000000 Z
|
|
14
13
|
dependencies:
|
|
15
14
|
- !ruby/object:Gem::Dependency
|
|
16
15
|
name: json
|
|
@@ -1092,12 +1091,11 @@ licenses:
|
|
|
1092
1091
|
- MIT
|
|
1093
1092
|
metadata:
|
|
1094
1093
|
homepage_uri: https://rubocop.org/
|
|
1095
|
-
changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.81.
|
|
1094
|
+
changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.81.7
|
|
1096
1095
|
source_code_uri: https://github.com/rubocop/rubocop/
|
|
1097
1096
|
documentation_uri: https://docs.rubocop.org/rubocop/1.81/
|
|
1098
1097
|
bug_tracker_uri: https://github.com/rubocop/rubocop/issues
|
|
1099
1098
|
rubygems_mfa_required: 'true'
|
|
1100
|
-
post_install_message:
|
|
1101
1099
|
rdoc_options: []
|
|
1102
1100
|
require_paths:
|
|
1103
1101
|
- lib
|
|
@@ -1112,8 +1110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
1112
1110
|
- !ruby/object:Gem::Version
|
|
1113
1111
|
version: '0'
|
|
1114
1112
|
requirements: []
|
|
1115
|
-
rubygems_version: 3.
|
|
1116
|
-
signing_key:
|
|
1113
|
+
rubygems_version: 3.6.2
|
|
1117
1114
|
specification_version: 4
|
|
1118
1115
|
summary: Automatic Ruby code style checking tool.
|
|
1119
1116
|
test_files: []
|