rubocop 1.60.2 → 1.62.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +41 -12
- data/lib/rubocop/cli/command/lsp.rb +2 -2
- data/lib/rubocop/cli.rb +6 -1
- data/lib/rubocop/config.rb +4 -0
- 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 +17 -8
- 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/layout/space_inside_hash_literal_braces.rb +1 -1
- 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/to_enum_arguments.rb +7 -2
- 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 +17 -6
- 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/magic_comment.rb +1 -1
- data/lib/rubocop/options.rb +11 -0
- data/lib/rubocop/path_util.rb +6 -2
- data/lib/rubocop/rspec/cop_helper.rb +8 -2
- data/lib/rubocop/rspec/expect_offense.rb +1 -1
- data/lib/rubocop/rspec/shared_contexts.rb +36 -17
- data/lib/rubocop/rspec/support.rb +2 -1
- data/lib/rubocop/runner.rb +9 -2
- data/lib/rubocop/target_finder.rb +84 -78
- data/lib/rubocop/target_ruby.rb +82 -80
- data/lib/rubocop/version.rb +18 -3
- metadata +9 -6
data/lib/rubocop/cop/base.rb
CHANGED
@@ -232,6 +232,10 @@ module RuboCop
|
|
232
232
|
@config.target_ruby_version
|
233
233
|
end
|
234
234
|
|
235
|
+
def parser_engine
|
236
|
+
@config.parser_engine
|
237
|
+
end
|
238
|
+
|
235
239
|
def target_rails_version
|
236
240
|
@config.target_rails_version
|
237
241
|
end
|
@@ -254,7 +258,7 @@ module RuboCop
|
|
254
258
|
|
255
259
|
# There should be very limited reasons for a Cop to do it's own parsing
|
256
260
|
def parse(source, path = nil)
|
257
|
-
ProcessedSource.new(source, target_ruby_version, path)
|
261
|
+
ProcessedSource.new(source, target_ruby_version, path, parser_engine: parser_engine)
|
258
262
|
end
|
259
263
|
|
260
264
|
# @api private
|
@@ -305,6 +309,17 @@ module RuboCop
|
|
305
309
|
@current_original = original
|
306
310
|
end
|
307
311
|
|
312
|
+
# @api private
|
313
|
+
def always_autocorrect?
|
314
|
+
# `true` is the same as `'always'` for backward compatibility.
|
315
|
+
['always', true].include?(cop_config.fetch('AutoCorrect', 'always'))
|
316
|
+
end
|
317
|
+
|
318
|
+
# @api private
|
319
|
+
def contextual_autocorrect?
|
320
|
+
cop_config.fetch('AutoCorrect', 'always') == 'contextual'
|
321
|
+
end
|
322
|
+
|
308
323
|
def inspect # :nodoc:
|
309
324
|
"#<#{self.class.name}:#{object_id} @config=#{@config} @options=#{@options}>"
|
310
325
|
end
|
@@ -389,7 +404,7 @@ module RuboCop
|
|
389
404
|
def use_corrector(range, corrector)
|
390
405
|
if autocorrect?
|
391
406
|
attempt_correction(range, corrector)
|
392
|
-
elsif corrector &&
|
407
|
+
elsif corrector && (always_autocorrect? || (contextual_autocorrect? && !LSP.enabled?))
|
393
408
|
:uncorrected
|
394
409
|
else
|
395
410
|
:unsupported
|
@@ -481,12 +496,6 @@ module RuboCop
|
|
481
496
|
range.end_pos + @current_offset
|
482
497
|
)
|
483
498
|
end
|
484
|
-
|
485
|
-
# This experimental feature has been under consideration for a while.
|
486
|
-
# @api private
|
487
|
-
def lsp_mode?
|
488
|
-
ARGV.include?('--lsp')
|
489
|
-
end
|
490
499
|
end
|
491
500
|
end
|
492
501
|
end
|
@@ -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
|
|
@@ -116,7 +116,7 @@ module RuboCop
|
|
116
116
|
|
117
117
|
def incorrect_style_detected(token1, token2,
|
118
118
|
expect_space, is_empty_braces)
|
119
|
-
brace = (token1.
|
119
|
+
brace = (token1.left_brace? ? token1 : token2).pos
|
120
120
|
range = expect_space ? brace : space_range(brace)
|
121
121
|
detected_style = expect_space ? 'no_space' : 'space'
|
122
122
|
|
@@ -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)
|
@@ -51,8 +51,13 @@ module RuboCop
|
|
51
51
|
enum_conversion_call?(node) do |method_node, arguments|
|
52
52
|
next if method_node.call_type? &&
|
53
53
|
!method_node.method?(:__method__) && !method_node.method?(:__callee__)
|
54
|
-
|
55
|
-
|
54
|
+
|
55
|
+
valid = if method_name?(method_node, def_node.method_name)
|
56
|
+
arguments_match?(arguments, def_node)
|
57
|
+
else
|
58
|
+
def_node.arguments.empty?
|
59
|
+
end
|
60
|
+
return if valid
|
56
61
|
|
57
62
|
add_offense(node)
|
58
63
|
end
|
@@ -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|
|