rubocop 1.60.2 → 1.61.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/assets/output.css.erb +159 -0
- data/assets/output.html.erb +1 -160
- data/config/default.yml +35 -12
- data/lib/rubocop/cli/command/lsp.rb +2 -2
- data/lib/rubocop/cli.rb +6 -1
- data/lib/rubocop/config_finder.rb +12 -2
- data/lib/rubocop/config_validator.rb +14 -5
- data/lib/rubocop/cop/autocorrect_logic.rb +6 -1
- data/lib/rubocop/cop/base.rb +12 -7
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +5 -13
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +2 -0
- data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
- data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/end_alignment.rb +3 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +14 -9
- data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
- data/lib/rubocop/cop/lint/script_permission.rb +3 -3
- data/lib/rubocop/cop/lint/syntax.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +6 -1
- data/lib/rubocop/cop/naming/predicate_name.rb +2 -2
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +29 -8
- data/lib/rubocop/cop/style/case_like_if.rb +1 -1
- data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +4 -5
- data/lib/rubocop/cop/style/hash_syntax.rb +6 -2
- data/lib/rubocop/cop/style/inverse_methods.rb +8 -8
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +10 -5
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +5 -8
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +4 -0
- data/lib/rubocop/cop/style/object_then.rb +5 -3
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -3
- data/lib/rubocop/cop/style/raise_args.rb +3 -0
- data/lib/rubocop/cop/style/redundant_argument.rb +2 -2
- data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +16 -5
- data/lib/rubocop/cop/style/redundant_return.rb +6 -0
- data/lib/rubocop/cop/style/sample.rb +1 -3
- data/lib/rubocop/cops_documentation_generator.rb +4 -2
- data/lib/rubocop/formatter/html_formatter.rb +30 -10
- data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
- data/lib/rubocop/lsp/logger.rb +1 -1
- data/lib/rubocop/lsp/routes.rb +1 -1
- data/lib/rubocop/lsp/runtime.rb +1 -1
- data/lib/rubocop/lsp/server.rb +5 -2
- data/lib/rubocop/lsp/severity.rb +1 -1
- data/lib/rubocop/lsp.rb +29 -0
- data/lib/rubocop/options.rb +11 -0
- data/lib/rubocop/path_util.rb +6 -2
- data/lib/rubocop/rspec/shared_contexts.rb +10 -6
- data/lib/rubocop/rspec/support.rb +1 -1
- data/lib/rubocop/target_ruby.rb +79 -79
- data/lib/rubocop/version.rb +1 -1
- metadata +11 -8
@@ -34,18 +34,14 @@ module RuboCop
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def offending_range
|
37
|
+
begin_range = block_node.source_range.begin
|
38
|
+
|
37
39
|
if block_node.arguments?
|
38
|
-
|
40
|
+
begin_range.join(argument_node.source_range.end)
|
39
41
|
else
|
40
|
-
|
42
|
+
begin_range.join(block_node.loc.begin.end)
|
41
43
|
end
|
42
44
|
end
|
43
|
-
|
44
|
-
def replacement_range(end_pos)
|
45
|
-
Parser::Source::Range.new(block_node.source_range.source_buffer,
|
46
|
-
block_node.source_range.begin_pos,
|
47
|
-
end_pos)
|
48
|
-
end
|
49
45
|
end
|
50
46
|
end
|
51
47
|
end
|
@@ -15,6 +15,8 @@ module RuboCop
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def call(corrector)
|
18
|
+
offending_range = for_node.source_range.begin.join(end_range)
|
19
|
+
|
18
20
|
corrector.replace(offending_range, correction)
|
19
21
|
end
|
20
22
|
|
@@ -40,11 +42,11 @@ module RuboCop
|
|
40
42
|
collection_node.range_type? || collection_node.or_type? || collection_node.and_type?
|
41
43
|
end
|
42
44
|
|
43
|
-
def
|
45
|
+
def end_range
|
44
46
|
if for_node.do?
|
45
|
-
keyword_begin.
|
47
|
+
keyword_begin.end
|
46
48
|
else
|
47
|
-
collection_end.
|
49
|
+
collection_end.end
|
48
50
|
end
|
49
51
|
end
|
50
52
|
|
@@ -59,16 +61,6 @@ module RuboCop
|
|
59
61
|
collection_node.source_range
|
60
62
|
end
|
61
63
|
end
|
62
|
-
|
63
|
-
def offending_range
|
64
|
-
replacement_range(end_position)
|
65
|
-
end
|
66
|
-
|
67
|
-
def replacement_range(end_pos)
|
68
|
-
Parser::Source::Range.new(for_node.source_range.source_buffer,
|
69
|
-
for_node.source_range.begin_pos,
|
70
|
-
end_pos)
|
71
|
-
end
|
72
64
|
end
|
73
65
|
end
|
74
66
|
end
|
@@ -30,6 +30,7 @@ module RuboCop
|
|
30
30
|
extend AutoCorrector
|
31
31
|
|
32
32
|
MSG = 'Use `%<method_name>s` instead of `%<method_suffix>s`.'
|
33
|
+
RESTRICT_ON_SEND = %i[end_with?].freeze
|
33
34
|
SUGGEST_METHOD_FOR_SUFFIX = {
|
34
35
|
'=' => 'assignment_method?',
|
35
36
|
'!' => 'bang_method?',
|
@@ -51,14 +52,15 @@ module RuboCop
|
|
51
52
|
|
52
53
|
def on_send(node)
|
53
54
|
method_name_end_with?(node) do |method_name_node, end_with_arg|
|
55
|
+
next unless method_name_node.receiver
|
56
|
+
|
57
|
+
preferred_method = SUGGEST_METHOD_FOR_SUFFIX[end_with_arg.value]
|
54
58
|
range = range(method_name_node, node)
|
55
|
-
message = format(
|
56
|
-
MSG,
|
57
|
-
method_name: SUGGEST_METHOD_FOR_SUFFIX[end_with_arg.value],
|
58
|
-
method_suffix: range.source
|
59
|
-
)
|
59
|
+
message = format(MSG, method_name: preferred_method, method_suffix: range.source)
|
60
60
|
|
61
|
-
add_offense(range, message: message)
|
61
|
+
add_offense(range, message: message) do |corrector|
|
62
|
+
corrector.replace(range, preferred_method)
|
63
|
+
end
|
62
64
|
end
|
63
65
|
end
|
64
66
|
alias on_csend on_send
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# Checks for redundant arguments of `RuboCop::RSpec::ExpectOffense`'s methods.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
# expect_no_offenses('code', keyword: keyword)
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# expect_no_offenses('code')
|
15
|
+
#
|
16
|
+
class RedundantExpectOffenseArguments < Base
|
17
|
+
extend AutoCorrector
|
18
|
+
|
19
|
+
MSG = 'Remove the redundant arguments.'
|
20
|
+
RESTRICT_ON_SEND = %i[expect_no_offenses].freeze
|
21
|
+
|
22
|
+
def on_send(node)
|
23
|
+
return if node.arguments.one? || !node.arguments[1]&.hash_type?
|
24
|
+
|
25
|
+
range = node.first_argument.source_range.end.join(node.last_argument.source_range.end)
|
26
|
+
|
27
|
+
add_offense(range) do |corrector|
|
28
|
+
corrector.remove(range)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -20,6 +20,7 @@ require_relative 'internal_affairs/offense_location_keyword'
|
|
20
20
|
require_relative 'internal_affairs/processed_source_buffer_name'
|
21
21
|
require_relative 'internal_affairs/redundant_context_config_parameter'
|
22
22
|
require_relative 'internal_affairs/redundant_described_class_as_subject'
|
23
|
+
require_relative 'internal_affairs/redundant_expect_offense_arguments'
|
23
24
|
require_relative 'internal_affairs/redundant_let_rubocop_config_new'
|
24
25
|
require_relative 'internal_affairs/redundant_location_argument'
|
25
26
|
require_relative 'internal_affairs/redundant_message_argument'
|
@@ -20,7 +20,9 @@ module RuboCop
|
|
20
20
|
# This `Layout/EndAlignment` cop aligns with keywords (e.g. `if`, `while`, `case`)
|
21
21
|
# by default. On the other hand, `Layout/BeginEndAlignment` cop aligns with
|
22
22
|
# `EnforcedStyleAlignWith: start_of_line` by default due to `||= begin` tends
|
23
|
-
# to align with the start of the line.
|
23
|
+
# to align with the start of the line. `Layout/DefEndAlignment` cop also aligns with
|
24
|
+
# `EnforcedStyleAlignWith: start_of_line` by default.
|
25
|
+
# These style can be configured by each cop.
|
24
26
|
#
|
25
27
|
# @example EnforcedStyleAlignWith: keyword (default)
|
26
28
|
# # bad
|
@@ -89,7 +89,9 @@ module RuboCop
|
|
89
89
|
end
|
90
90
|
|
91
91
|
def index_access_call_chained?(node)
|
92
|
-
|
92
|
+
return false unless node.send_type? && node.method?(:[])
|
93
|
+
|
94
|
+
node.children.first.send_type? && node.children.first.method?(:[])
|
93
95
|
end
|
94
96
|
|
95
97
|
def configured_to_not_be_inspected?(node)
|
@@ -81,19 +81,28 @@ module RuboCop
|
|
81
81
|
private
|
82
82
|
|
83
83
|
def check_empty(left_brace, space_plus_brace, used_style)
|
84
|
-
|
85
|
-
|
86
|
-
|
84
|
+
if style_for_empty_braces == used_style
|
85
|
+
handle_different_styles_for_empty_braces(used_style)
|
86
|
+
return
|
87
|
+
elsif !config_to_allow_offenses.key?('Enabled')
|
88
|
+
config_to_allow_offenses['EnforcedStyleForEmptyBraces'] = used_style.to_s
|
89
|
+
end
|
87
90
|
|
88
91
|
if style_for_empty_braces == :space
|
89
|
-
|
90
|
-
|
91
|
-
end
|
92
|
+
range = left_brace
|
93
|
+
msg = MISSING_MSG
|
92
94
|
else
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
95
|
+
range = range_between(space_plus_brace.begin_pos, left_brace.begin_pos)
|
96
|
+
msg = DETECTED_MSG
|
97
|
+
end
|
98
|
+
add_offense(range, message: msg) { |corrector| autocorrect(corrector, range) }
|
99
|
+
end
|
100
|
+
|
101
|
+
def handle_different_styles_for_empty_braces(used_style)
|
102
|
+
if config_to_allow_offenses['EnforcedStyleForEmptyBraces'] &&
|
103
|
+
config_to_allow_offenses['EnforcedStyleForEmptyBraces'].to_sym != used_style
|
104
|
+
config_to_allow_offenses.clear
|
105
|
+
config_to_allow_offenses['Enabled'] = false
|
97
106
|
end
|
98
107
|
end
|
99
108
|
|
@@ -104,7 +104,7 @@ module RuboCop
|
|
104
104
|
def correct_other_branches(corrector, node)
|
105
105
|
return unless require_other_branches_correction?(node)
|
106
106
|
|
107
|
-
if node.else_branch&.if_type?
|
107
|
+
if node.else_branch&.if_type? && !node.else_branch.modifier_form?
|
108
108
|
# Replace an orphaned `elsif` with `if`
|
109
109
|
corrector.replace(node.else_branch.loc.keyword, 'if')
|
110
110
|
else
|
@@ -5,7 +5,8 @@ module RuboCop
|
|
5
5
|
module Lint
|
6
6
|
# Checks for redundant safe navigation calls.
|
7
7
|
# Use cases where a constant, named in camel case for classes and modules is `nil` are rare,
|
8
|
-
# and an offense is not detected when the receiver is a
|
8
|
+
# and an offense is not detected when the receiver is a constant. The detection also applies
|
9
|
+
# to literal receivers, except for `nil`.
|
9
10
|
#
|
10
11
|
# For all receivers, the `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`,
|
11
12
|
# and `equal?` methods are checked by default.
|
@@ -76,10 +77,9 @@ module RuboCop
|
|
76
77
|
#
|
77
78
|
class RedundantSafeNavigation < Base
|
78
79
|
include AllowedMethods
|
79
|
-
include RangeHelp
|
80
80
|
extend AutoCorrector
|
81
81
|
|
82
|
-
MSG = 'Redundant safe navigation detected.'
|
82
|
+
MSG = 'Redundant safe navigation detected, use `.` instead.'
|
83
83
|
MSG_LITERAL = 'Redundant safe navigation with default literal detected.'
|
84
84
|
|
85
85
|
NIL_SPECIFIC_METHODS = (nil.methods - Object.new.methods).to_set.freeze
|
@@ -105,24 +105,23 @@ module RuboCop
|
|
105
105
|
|
106
106
|
# rubocop:disable Metrics/AbcSize
|
107
107
|
def on_csend(node)
|
108
|
-
unless
|
108
|
+
unless assume_receiver_instance_exists?(node.receiver)
|
109
109
|
return unless check?(node) && allowed_method?(node.method_name)
|
110
110
|
return if respond_to_nil_specific_method?(node)
|
111
111
|
end
|
112
112
|
|
113
|
-
range =
|
114
|
-
add_offense(range) { |corrector| corrector.replace(
|
113
|
+
range = node.loc.dot
|
114
|
+
add_offense(range) { |corrector| corrector.replace(range, '.') }
|
115
115
|
end
|
116
116
|
|
117
117
|
def on_or(node)
|
118
118
|
conversion_with_default?(node) do |send_node|
|
119
|
-
range =
|
119
|
+
range = send_node.loc.dot.begin.join(node.source_range.end)
|
120
120
|
|
121
121
|
add_offense(range, message: MSG_LITERAL) do |corrector|
|
122
122
|
corrector.replace(send_node.loc.dot, '.')
|
123
123
|
|
124
|
-
range_with_default =
|
125
|
-
node.source_range.end.end_pos)
|
124
|
+
range_with_default = node.lhs.source_range.end.begin.join(node.source_range.end)
|
126
125
|
corrector.remove(range_with_default)
|
127
126
|
end
|
128
127
|
end
|
@@ -131,6 +130,12 @@ module RuboCop
|
|
131
130
|
|
132
131
|
private
|
133
132
|
|
133
|
+
def assume_receiver_instance_exists?(receiver)
|
134
|
+
return true if receiver.const_type? && !receiver.source.match?(SNAKE_CASE)
|
135
|
+
|
136
|
+
receiver.literal? && !receiver.nil_type?
|
137
|
+
end
|
138
|
+
|
134
139
|
def check?(node)
|
135
140
|
parent = node.parent
|
136
141
|
return false unless parent
|
@@ -59,9 +59,7 @@ module RuboCop
|
|
59
59
|
|
60
60
|
def autocorrect(corrector, node)
|
61
61
|
rescued, _, _body = *node
|
62
|
-
range =
|
63
|
-
node.loc.keyword.end_pos,
|
64
|
-
rescued.source_range.end_pos)
|
62
|
+
range = node.loc.keyword.end.join(rescued.source_range.end)
|
65
63
|
|
66
64
|
corrector.replace(range, correction(*rescued))
|
67
65
|
end
|
@@ -46,14 +46,14 @@ module RuboCop
|
|
46
46
|
message = format_message_from(processed_source)
|
47
47
|
|
48
48
|
add_offense(comment, message: message) do
|
49
|
-
autocorrect
|
49
|
+
autocorrect if autocorrect_requested?
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
53
|
private
|
54
54
|
|
55
|
-
def autocorrect
|
56
|
-
FileUtils.chmod('+x',
|
55
|
+
def autocorrect
|
56
|
+
FileUtils.chmod('+x', processed_source.file_path)
|
57
57
|
end
|
58
58
|
|
59
59
|
def executable?(processed_source)
|
@@ -100,7 +100,12 @@ module RuboCop
|
|
100
100
|
expressions = *node
|
101
101
|
expressions.pop unless in_void_context?(node)
|
102
102
|
expressions.each do |expr|
|
103
|
-
check_void_op(expr)
|
103
|
+
check_void_op(expr) do
|
104
|
+
block_node = node.each_ancestor(:block).first
|
105
|
+
|
106
|
+
block_node&.method?(:each)
|
107
|
+
end
|
108
|
+
|
104
109
|
check_expression(expr)
|
105
110
|
end
|
106
111
|
end
|
@@ -99,7 +99,7 @@ module RuboCop
|
|
99
99
|
!(method_name.start_with?(prefix) && # cheap check to avoid allocating Regexp
|
100
100
|
method_name.match?(/^#{prefix}[^0-9]/)) ||
|
101
101
|
method_name == expected_name(method_name, prefix) ||
|
102
|
-
method_name.end_with?('=') ||
|
102
|
+
method_name.end_with?('=') ||
|
103
103
|
allowed_method?(method_name)
|
104
104
|
end
|
105
105
|
|
@@ -109,7 +109,7 @@ module RuboCop
|
|
109
109
|
else
|
110
110
|
method_name.dup
|
111
111
|
end
|
112
|
-
new_name << '?' unless method_name.end_with?('?')
|
112
|
+
new_name << '?' unless method_name.end_with?('?')
|
113
113
|
new_name
|
114
114
|
end
|
115
115
|
|
data/lib/rubocop/cop/registry.rb
CHANGED
@@ -300,7 +300,7 @@ module RuboCop
|
|
300
300
|
unless given_badge.match?(real_badge)
|
301
301
|
path = PathUtil.smart_path(source_path)
|
302
302
|
warn "#{path}: #{given_badge} has the wrong namespace - " \
|
303
|
-
"
|
303
|
+
"replace it with #{given_badge.with_department(real_badge.department)}"
|
304
304
|
end
|
305
305
|
|
306
306
|
real_badge.to_s
|
@@ -8,6 +8,12 @@ module RuboCop
|
|
8
8
|
# This cop identifies places where `do_something(*args, &block)`
|
9
9
|
# can be replaced by `do_something(...)`.
|
10
10
|
#
|
11
|
+
# In Ruby 3.1, anonymous block forwarding has been added.
|
12
|
+
#
|
13
|
+
# This cop identifies places where `do_something(&block)` can be replaced
|
14
|
+
# by `do_something(&)`; if desired, this functionality can be disabled
|
15
|
+
# by setting `UseAnonymousForwarding: false`.
|
16
|
+
#
|
11
17
|
# In Ruby 3.2, anonymous args/kwargs forwarding has been added.
|
12
18
|
#
|
13
19
|
# This cop also identifies places where `use_args(*args)`/`use_kwargs(**kwargs)` can be
|
@@ -41,22 +47,25 @@ module RuboCop
|
|
41
47
|
#
|
42
48
|
# @example UseAnonymousForwarding: true (default, only relevant for Ruby >= 3.2)
|
43
49
|
# # bad
|
44
|
-
# def foo(*args, **kwargs)
|
50
|
+
# def foo(*args, **kwargs, &block)
|
45
51
|
# args_only(*args)
|
46
52
|
# kwargs_only(**kwargs)
|
53
|
+
# block_only(&block)
|
47
54
|
# end
|
48
55
|
#
|
49
56
|
# # good
|
50
|
-
# def foo(*,
|
57
|
+
# def foo(*, **, &)
|
51
58
|
# args_only(*)
|
52
59
|
# kwargs_only(**)
|
60
|
+
# block_only(&)
|
53
61
|
# end
|
54
62
|
#
|
55
63
|
# @example UseAnonymousForwarding: false (only relevant for Ruby >= 3.2)
|
56
64
|
# # good
|
57
|
-
# def foo(*args, **kwargs)
|
65
|
+
# def foo(*args, **kwargs, &block)
|
58
66
|
# args_only(*args)
|
59
67
|
# kwargs_only(**kwargs)
|
68
|
+
# block_only(&block)
|
60
69
|
# end
|
61
70
|
#
|
62
71
|
# @example AllowOnlyRestArgument: true (default, only relevant for Ruby < 3.2)
|
@@ -179,9 +188,12 @@ module RuboCop
|
|
179
188
|
|
180
189
|
send_classifications.each do |send_node, _c, forward_rest, forward_kwrest, forward_block_arg| # rubocop:disable Layout/LineLength
|
181
190
|
if !forward_rest && !forward_kwrest
|
182
|
-
|
183
|
-
|
184
|
-
|
191
|
+
# Prevents `anonymous block parameter is also used within block (SyntaxError)` occurs
|
192
|
+
# in Ruby 3.3.0.
|
193
|
+
if outside_block?(forward_block_arg)
|
194
|
+
register_forward_block_arg_offense(!forward_rest, node.arguments, block_arg)
|
195
|
+
register_forward_block_arg_offense(!forward_rest, send_node, forward_block_arg)
|
196
|
+
end
|
185
197
|
registered_block_arg_offense = true
|
186
198
|
break
|
187
199
|
else
|
@@ -196,12 +208,13 @@ module RuboCop
|
|
196
208
|
end
|
197
209
|
# rubocop:enable Metrics/MethodLength
|
198
210
|
|
211
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
199
212
|
def add_post_ruby_32_offenses(def_node, send_classifications, forwardable_args)
|
200
213
|
return unless use_anonymous_forwarding?
|
201
214
|
|
202
|
-
rest_arg, kwrest_arg,
|
215
|
+
rest_arg, kwrest_arg, block_arg = *forwardable_args
|
203
216
|
|
204
|
-
send_classifications.each do |send_node, _c, forward_rest, forward_kwrest,
|
217
|
+
send_classifications.each do |send_node, _c, forward_rest, forward_kwrest, forward_block_arg| # rubocop:disable Layout/LineLength
|
205
218
|
if outside_block?(forward_rest)
|
206
219
|
register_forward_args_offense(def_node.arguments, rest_arg)
|
207
220
|
register_forward_args_offense(send_node, forward_rest)
|
@@ -211,8 +224,16 @@ module RuboCop
|
|
211
224
|
register_forward_kwargs_offense(!forward_rest, def_node.arguments, kwrest_arg)
|
212
225
|
register_forward_kwargs_offense(!forward_rest, send_node, forward_kwrest)
|
213
226
|
end
|
227
|
+
|
228
|
+
# Prevents `anonymous block parameter is also used within block (SyntaxError)` occurs
|
229
|
+
# in Ruby 3.3.0.
|
230
|
+
if outside_block?(forward_block_arg)
|
231
|
+
register_forward_block_arg_offense(!forward_rest, def_node.arguments, block_arg)
|
232
|
+
register_forward_block_arg_offense(!forward_rest, send_node, forward_block_arg)
|
233
|
+
end
|
214
234
|
end
|
215
235
|
end
|
236
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
216
237
|
|
217
238
|
def non_splat_or_block_pass_lvar_references(body)
|
218
239
|
body.each_descendant(:lvar, :lvasgn).filter_map do |lvar|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative '../../directive_comment'
|
4
|
+
|
3
5
|
module RuboCop
|
4
6
|
module Cop
|
5
7
|
module Style
|
@@ -49,8 +51,9 @@ module RuboCop
|
|
49
51
|
KEYWORDS = %w[begin class def end module].freeze
|
50
52
|
KEYWORD_REGEXES = KEYWORDS.map { |w| /^\s*#{w}\s/ }.freeze
|
51
53
|
|
52
|
-
ALLOWED_COMMENTS = %w[:nodoc: :yields:
|
53
|
-
ALLOWED_COMMENT_REGEXES = ALLOWED_COMMENTS.map { |c| /#\s*#{c}/ }
|
54
|
+
ALLOWED_COMMENTS = %w[:nodoc: :yields:].freeze
|
55
|
+
ALLOWED_COMMENT_REGEXES = (ALLOWED_COMMENTS.map { |c| /#\s*#{c}/ } +
|
56
|
+
[DirectiveComment::DIRECTIVE_COMMENT_REGEXP]).freeze
|
54
57
|
|
55
58
|
REGEXP = /(?<keyword>\S+).*#/.freeze
|
56
59
|
|
@@ -115,8 +115,8 @@ module RuboCop
|
|
115
115
|
end
|
116
116
|
|
117
117
|
# Check for `if` and `case` statements where each branch is used for
|
118
|
-
#
|
119
|
-
# condition can be used instead.
|
118
|
+
# both the assignment and comparison of the same variable
|
119
|
+
# when using the return of the condition can be used instead.
|
120
120
|
#
|
121
121
|
# @example EnforcedStyle: assign_to_condition (default)
|
122
122
|
# # bad
|
@@ -460,9 +460,8 @@ module RuboCop
|
|
460
460
|
|
461
461
|
def assignment(node)
|
462
462
|
*_, condition = *node
|
463
|
-
|
464
|
-
|
465
|
-
condition.source_range.begin_pos)
|
463
|
+
|
464
|
+
node.source_range.begin.join(condition.source_range.begin)
|
466
465
|
end
|
467
466
|
|
468
467
|
def correct_if_branches(corrector, cop, node)
|
@@ -195,6 +195,7 @@ module RuboCop
|
|
195
195
|
acceptable_19_syntax_symbol?(pair.key.source)
|
196
196
|
end
|
197
197
|
|
198
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
198
199
|
def acceptable_19_syntax_symbol?(sym_name)
|
199
200
|
sym_name.delete_prefix!(':')
|
200
201
|
|
@@ -209,9 +210,12 @@ module RuboCop
|
|
209
210
|
# Most hash keys can be matched against a simple regex.
|
210
211
|
return true if /\A[_a-z]\w*[?!]?\z/i.match?(sym_name)
|
211
212
|
|
212
|
-
|
213
|
-
|
213
|
+
return false if target_ruby_version <= 2.1
|
214
|
+
|
215
|
+
(sym_name.start_with?("'") && sym_name.end_with?("'")) ||
|
216
|
+
(sym_name.start_with?('"') && sym_name.end_with?('"'))
|
214
217
|
end
|
218
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
215
219
|
|
216
220
|
def check(pairs, delim, msg)
|
217
221
|
pairs.each do |pair|
|
@@ -76,9 +76,9 @@ module RuboCop
|
|
76
76
|
PATTERN
|
77
77
|
|
78
78
|
def on_send(node)
|
79
|
-
inverse_candidate?(node) do |
|
79
|
+
inverse_candidate?(node) do |method_call, lhs, method, rhs|
|
80
80
|
return unless inverse_methods.key?(method)
|
81
|
-
return if negated?(node)
|
81
|
+
return if negated?(node) || relational_comparison_with_safe_navigation?(method_call)
|
82
82
|
return if part_of_ignored_node?(node)
|
83
83
|
return if possible_class_hierarchy_check?(lhs, rhs, method)
|
84
84
|
|
@@ -155,16 +155,16 @@ module RuboCop
|
|
155
155
|
node.parent.respond_to?(:method?) && node.parent.method?(:!)
|
156
156
|
end
|
157
157
|
|
158
|
+
def relational_comparison_with_safe_navigation?(node)
|
159
|
+
node.csend_type? && CLASS_COMPARISON_METHODS.include?(node.method_name)
|
160
|
+
end
|
161
|
+
|
158
162
|
def not_to_receiver(node, method_call)
|
159
|
-
|
160
|
-
node.loc.selector.begin_pos,
|
161
|
-
method_call.source_range.begin_pos)
|
163
|
+
node.loc.selector.begin.join(method_call.source_range.begin)
|
162
164
|
end
|
163
165
|
|
164
166
|
def end_parentheses(node, method_call)
|
165
|
-
|
166
|
-
method_call.source_range.end_pos,
|
167
|
-
node.source_range.end_pos)
|
167
|
+
method_call.source_range.end.join(node.source_range.end)
|
168
168
|
end
|
169
169
|
|
170
170
|
# When comparing classes, `!(Integer < Numeric)` is not the same as
|
@@ -32,12 +32,14 @@ module RuboCop
|
|
32
32
|
# foo unless x != y
|
33
33
|
# foo unless x >= 10
|
34
34
|
# foo unless x.even?
|
35
|
+
# foo unless odd?
|
35
36
|
#
|
36
37
|
# # good
|
37
38
|
# foo if bar
|
38
39
|
# foo if x == y
|
39
40
|
# foo if x < 10
|
40
41
|
# foo if x.odd?
|
42
|
+
# foo if even?
|
41
43
|
#
|
42
44
|
# # bad (complex condition)
|
43
45
|
# foo unless x != y || x.even?
|
@@ -99,12 +101,15 @@ module RuboCop
|
|
99
101
|
end
|
100
102
|
end
|
101
103
|
|
102
|
-
def preferred_send_condition(node)
|
103
|
-
receiver_source = node.receiver
|
104
|
+
def preferred_send_condition(node) # rubocop:disable Metrics/CyclomaticComplexity
|
105
|
+
receiver_source = node.receiver&.source
|
104
106
|
return receiver_source if node.method?(:!)
|
105
107
|
|
108
|
+
# receiver may be implicit (self)
|
109
|
+
dotted_receiver_source = receiver_source ? "#{receiver_source}." : ''
|
110
|
+
|
106
111
|
inverse_method_name = inverse_methods[node.method_name]
|
107
|
-
return "#{
|
112
|
+
return "#{dotted_receiver_source}#{inverse_method_name}" unless node.arguments?
|
108
113
|
|
109
114
|
argument_list = node.arguments.map(&:source).join(', ')
|
110
115
|
if node.operator_method?
|
@@ -112,10 +117,10 @@ module RuboCop
|
|
112
117
|
end
|
113
118
|
|
114
119
|
if node.parenthesized?
|
115
|
-
return "#{
|
120
|
+
return "#{dotted_receiver_source}#{inverse_method_name}(#{argument_list})"
|
116
121
|
end
|
117
122
|
|
118
|
-
"#{
|
123
|
+
"#{dotted_receiver_source}#{inverse_method_name} #{argument_list}"
|
119
124
|
end
|
120
125
|
|
121
126
|
def preferred_logical_condition(node)
|
@@ -116,20 +116,17 @@ module RuboCop
|
|
116
116
|
def truthy_branch_for_guard?(node)
|
117
117
|
if_node = node.left_sibling
|
118
118
|
|
119
|
-
if if_node.if?
|
120
|
-
if_node.
|
121
|
-
|
122
|
-
if_node.if_branch.
|
119
|
+
if if_node.if?
|
120
|
+
if_node.if_branch.arguments.any?
|
121
|
+
else
|
122
|
+
if_node.if_branch.arguments.none?
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
126
|
def range(node)
|
127
|
-
buffer = node.source_range.source_buffer
|
128
127
|
map_node = node.receiver.send_node
|
129
|
-
begin_pos = map_node.loc.selector.begin_pos
|
130
|
-
end_pos = node.source_range.end_pos
|
131
128
|
|
132
|
-
|
129
|
+
map_node.loc.selector.join(node.source_range.end)
|
133
130
|
end
|
134
131
|
end
|
135
132
|
end
|