rubocop 1.74.0 → 1.75.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 +32 -6
- data/config/obsoletion.yml +3 -1
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/config.rb +35 -6
- data/lib/rubocop/config_loader.rb +4 -0
- data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
- data/lib/rubocop/config_obsoletion.rb +46 -2
- data/lib/rubocop/config_validator.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
- data/lib/rubocop/cop/layout/block_alignment.rb +1 -0
- data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
- data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -0
- data/lib/rubocop/cop/layout/line_length.rb +5 -1
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +9 -5
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +4 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -0
- data/lib/rubocop/cop/lint/debugger.rb +2 -2
- data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
- data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
- data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +8 -1
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +2 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +1 -0
- data/lib/rubocop/cop/lint/unreachable_loop.rb +5 -5
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -0
- data/lib/rubocop/cop/lint/void.rb +1 -0
- data/lib/rubocop/cop/metrics/block_length.rb +1 -0
- data/lib/rubocop/cop/metrics/method_length.rb +1 -0
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
- data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
- data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -0
- data/lib/rubocop/cop/naming/method_name.rb +64 -8
- data/lib/rubocop/cop/naming/variable_name.rb +6 -19
- data/lib/rubocop/cop/registry.rb +9 -6
- data/lib/rubocop/cop/style/array_intersect.rb +39 -28
- data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
- data/lib/rubocop/cop/style/collection_methods.rb +1 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +1 -0
- data/lib/rubocop/cop/style/for.rb +1 -0
- data/lib/rubocop/cop/style/guard_clause.rb +2 -1
- data/lib/rubocop/cop/style/hash_each_methods.rb +3 -2
- data/lib/rubocop/cop/style/hash_fetch_chain.rb +105 -0
- data/lib/rubocop/cop/style/if_inside_else.rb +10 -13
- data/lib/rubocop/cop/style/inverse_methods.rb +1 -0
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
- data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
- data/lib/rubocop/cop/style/it_block_parameter.rb +100 -0
- data/lib/rubocop/cop/style/lambda.rb +1 -0
- data/lib/rubocop/cop/style/map_into_array.rb +1 -0
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +1 -0
- data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -0
- data/lib/rubocop/cop/style/next.rb +44 -0
- data/lib/rubocop/cop/style/object_then.rb +1 -0
- data/lib/rubocop/cop/style/proc.rb +1 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -0
- data/lib/rubocop/cop/style/redundant_format.rb +10 -3
- data/lib/rubocop/cop/style/redundant_parentheses.rb +2 -1
- data/lib/rubocop/cop/style/redundant_self.rb +1 -0
- data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
- data/lib/rubocop/cop/style/select_by_regexp.rb +4 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +3 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +41 -100
- data/lib/rubocop/cop/style/symbol_proc.rb +2 -0
- data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -0
- data/lib/rubocop/cop/variable_force/scope.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +1 -6
- data/lib/rubocop/cop/variable_force.rb +1 -1
- data/lib/rubocop/lsp/runtime.rb +4 -4
- data/lib/rubocop/lsp/stdin_runner.rb +3 -1
- data/lib/rubocop/rspec/cop_helper.rb +4 -1
- data/lib/rubocop/rspec/shared_contexts.rb +20 -0
- data/lib/rubocop/rspec/support.rb +2 -0
- data/lib/rubocop/runner.rb +5 -1
- data/lib/rubocop/target_ruby.rb +1 -1
- data/lib/rubocop/version.rb +14 -7
- data/lib/rubocop.rb +4 -0
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +20 -2
- metadata +10 -6
@@ -74,6 +74,7 @@ module RuboCop
|
|
74
74
|
check_unused_block_args(node, key, value)
|
75
75
|
end
|
76
76
|
alias on_numblock on_block
|
77
|
+
alias on_itblock on_block
|
77
78
|
|
78
79
|
# rubocop:disable Metrics/AbcSize
|
79
80
|
def check_unused_block_args(node, key, value)
|
@@ -128,8 +129,8 @@ module RuboCop
|
|
128
129
|
lvar_sources = node.body.each_descendant(:lvar).map(&:source)
|
129
130
|
|
130
131
|
if block_arg.mlhs_type?
|
131
|
-
block_arg.each_descendant(:arg, :restarg).all? do |
|
132
|
-
lvar_sources.none?(
|
132
|
+
block_arg.each_descendant(:arg, :restarg).all? do |descendant|
|
133
|
+
lvar_sources.none?(descendant.source.delete_prefix('*'))
|
133
134
|
end
|
134
135
|
else
|
135
136
|
lvar_sources.none?(block_arg.source.delete_prefix('*'))
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Use `Hash#dig` instead of chaining potentially null `fetch` calls.
|
7
|
+
#
|
8
|
+
# When `fetch(identifier, nil)` calls are chained on a hash, the expectation
|
9
|
+
# is that each step in the chain returns either `nil` or another hash,
|
10
|
+
# and in both cases, these can be simplified with a single call to `dig` with
|
11
|
+
# multiple arguments.
|
12
|
+
#
|
13
|
+
# If the 2nd parameter is `{}` or `Hash.new`, an offense will also be registered,
|
14
|
+
# as long as the final call in the chain is a nil value. If a non-nil value is given,
|
15
|
+
# the chain will not be registered as an offense, as the default value cannot be safely
|
16
|
+
# given with `dig`.
|
17
|
+
#
|
18
|
+
# NOTE: See `Style/DigChain` for replacing chains of `dig` calls with
|
19
|
+
# a single method call.
|
20
|
+
#
|
21
|
+
# @safety
|
22
|
+
# This cop is unsafe because it cannot be guaranteed that the receiver
|
23
|
+
# is a `Hash` or that `fetch` or `dig` have the expected standard implementation.
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# # bad
|
27
|
+
# hash.fetch('foo', nil)&.fetch('bar', nil)
|
28
|
+
#
|
29
|
+
# # bad
|
30
|
+
# # earlier members of the chain can return `{}` as long as the final `fetch`
|
31
|
+
# # has `nil` as a default value
|
32
|
+
# hash.fetch('foo', {}).fetch('bar', nil)
|
33
|
+
#
|
34
|
+
# # good
|
35
|
+
# hash.dig('foo', 'bar')
|
36
|
+
#
|
37
|
+
# # ok - not handled by the cop since the final `fetch` value is non-nil
|
38
|
+
# hash.fetch('foo', {}).fetch('bar', {})
|
39
|
+
#
|
40
|
+
class HashFetchChain < Base
|
41
|
+
extend AutoCorrector
|
42
|
+
extend TargetRubyVersion
|
43
|
+
include IgnoredNode
|
44
|
+
|
45
|
+
MSG = 'Use `%<replacement>s` instead.'
|
46
|
+
RESTRICT_ON_SEND = %i[fetch].freeze
|
47
|
+
|
48
|
+
minimum_target_ruby_version 2.3
|
49
|
+
|
50
|
+
# @!method diggable?(node)
|
51
|
+
def_node_matcher :diggable?, <<~PATTERN
|
52
|
+
(call _ :fetch $_arg {nil (hash) (send (const {nil? cbase} :Hash) :new)})
|
53
|
+
PATTERN
|
54
|
+
|
55
|
+
def on_send(node)
|
56
|
+
return if ignored_node?(node)
|
57
|
+
return if last_fetch_non_nil?(node)
|
58
|
+
|
59
|
+
last_replaceable_node, arguments = inspect_chain(node)
|
60
|
+
return unless last_replaceable_node
|
61
|
+
return unless arguments.size > 1
|
62
|
+
|
63
|
+
range = last_replaceable_node.selector.join(node.loc.end)
|
64
|
+
replacement = replacement(arguments)
|
65
|
+
message = format(MSG, replacement: replacement)
|
66
|
+
|
67
|
+
add_offense(range, message: message) do |corrector|
|
68
|
+
corrector.replace(range, replacement)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
alias on_csend on_send
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def last_fetch_non_nil?(node)
|
76
|
+
# When chaining `fetch` methods, `fetch(x, {})` is acceptable within
|
77
|
+
# the chain, as long as the last method in the chain has a `nil`
|
78
|
+
# default value.
|
79
|
+
|
80
|
+
return false unless node.method?(:fetch)
|
81
|
+
|
82
|
+
!node.last_argument&.nil_type?
|
83
|
+
end
|
84
|
+
|
85
|
+
def inspect_chain(node)
|
86
|
+
arguments = []
|
87
|
+
|
88
|
+
while (arg = diggable?(node))
|
89
|
+
arguments.unshift(arg)
|
90
|
+
ignore_node(node)
|
91
|
+
last_replaceable_node = node
|
92
|
+
node = node.receiver
|
93
|
+
end
|
94
|
+
|
95
|
+
[last_replaceable_node, arguments]
|
96
|
+
end
|
97
|
+
|
98
|
+
def replacement(arguments)
|
99
|
+
values = arguments.map(&:source).join(', ')
|
100
|
+
"dig(#{values})"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -97,34 +97,31 @@ module RuboCop
|
|
97
97
|
else
|
98
98
|
correct_to_elsif_from_if_inside_else_form(corrector, node, node.condition)
|
99
99
|
end
|
100
|
-
|
101
|
-
corrector.remove(range_by_whole_lines(find_end_range(node), include_final_newline: true))
|
102
|
-
return unless (if_branch = node.if_branch)
|
103
|
-
|
104
|
-
range = range_by_whole_lines(if_branch.source_range, include_final_newline: true)
|
105
|
-
corrector.remove(range)
|
106
100
|
end
|
107
101
|
|
108
102
|
def correct_to_elsif_from_modifier_form(corrector, node)
|
109
|
-
corrector.replace(node.parent.loc.else,
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
103
|
+
corrector.replace(node.parent.loc.else, "elsif #{node.condition.source}")
|
104
|
+
|
105
|
+
condition_range = range_between(
|
106
|
+
node.if_branch.source_range.end_pos, node.condition.source_range.end_pos
|
107
|
+
)
|
108
|
+
corrector.remove(condition_range)
|
114
109
|
end
|
115
110
|
|
116
|
-
def correct_to_elsif_from_if_inside_else_form(corrector, node, condition)
|
111
|
+
def correct_to_elsif_from_if_inside_else_form(corrector, node, condition) # rubocop:disable Metrics/AbcSize
|
117
112
|
corrector.replace(node.parent.loc.else, "elsif #{condition.source}")
|
118
113
|
|
119
114
|
if_condition_range = if_condition_range(node, condition)
|
120
115
|
|
121
116
|
if (if_branch = node.if_branch)
|
122
|
-
corrector.replace(if_condition_range, if_branch.source)
|
117
|
+
corrector.replace(if_condition_range, range_with_comments(if_branch).source)
|
118
|
+
corrector.remove(range_with_comments_and_lines(if_branch))
|
123
119
|
else
|
124
120
|
corrector.remove(range_by_whole_lines(if_condition_range, include_final_newline: true))
|
125
121
|
end
|
126
122
|
|
127
123
|
corrector.remove(condition)
|
124
|
+
corrector.remove(range_by_whole_lines(find_end_range(node), include_final_newline: true))
|
128
125
|
end
|
129
126
|
|
130
127
|
def then?(node)
|
@@ -89,8 +89,8 @@ module RuboCop
|
|
89
89
|
|
90
90
|
def inheritance_check?(node)
|
91
91
|
argument = node.first_argument
|
92
|
-
node.method?(:<) &&
|
93
|
-
|
92
|
+
node.method?(:<) && argument.const_type? &&
|
93
|
+
argument.short_name.to_s.upcase != argument.short_name.to_s
|
94
94
|
end
|
95
95
|
|
96
96
|
def preferred_condition(node)
|
@@ -32,7 +32,7 @@ module RuboCop
|
|
32
32
|
|
33
33
|
# To try to avoid doing two regex checks on every string,
|
34
34
|
# shortcut out if the string does not look like an IP address
|
35
|
-
return false unless
|
35
|
+
return false unless potential_ip?(contents)
|
36
36
|
|
37
37
|
::Resolv::IPv4::Regex.match?(contents) || ::Resolv::IPv6::Regex.match?(contents)
|
38
38
|
end
|
@@ -52,7 +52,7 @@ module RuboCop
|
|
52
52
|
Array(allowed_addresses).map(&:downcase)
|
53
53
|
end
|
54
54
|
|
55
|
-
def
|
55
|
+
def potential_ip?(str)
|
56
56
|
# If the string is too long, it can't be an IP
|
57
57
|
return false if too_long?(str)
|
58
58
|
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for blocks with one argument where `it` block parameter can be used.
|
7
|
+
#
|
8
|
+
# It provides three `EnforcedStyle` options:
|
9
|
+
#
|
10
|
+
# 1. `allow_named_parameter` (default) ... Detects only numbered block parameters.
|
11
|
+
# 2. `always` ... Always uses the `it` block parameter.
|
12
|
+
# 3. `disallow` ... Disallows the `it` block parameter.
|
13
|
+
#
|
14
|
+
# A single numbered parameter is detected when `allow_named_parameter` or `always`.
|
15
|
+
#
|
16
|
+
# @example EnforcedStyle: allow_named_parameter (default)
|
17
|
+
# # bad
|
18
|
+
# block { do_something(_1) }
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# block { do_something(it) }
|
22
|
+
# block { |named_param| do_something(named_param) }
|
23
|
+
#
|
24
|
+
# @example EnforcedStyle: always
|
25
|
+
# # bad
|
26
|
+
# block { do_something(_1) }
|
27
|
+
# block { |named_param| do_something(named_param) }
|
28
|
+
#
|
29
|
+
# # good
|
30
|
+
# block { do_something(it) }
|
31
|
+
#
|
32
|
+
# @example EnforcedStyle: disallow
|
33
|
+
# # bad
|
34
|
+
# block { do_something(it) }
|
35
|
+
#
|
36
|
+
# # good
|
37
|
+
# block { do_something(_1) }
|
38
|
+
# block { |named_param| do_something(named_param) }
|
39
|
+
#
|
40
|
+
class ItBlockParameter < Base
|
41
|
+
include ConfigurableEnforcedStyle
|
42
|
+
extend TargetRubyVersion
|
43
|
+
extend AutoCorrector
|
44
|
+
|
45
|
+
MSG_USE_IT_BLOCK_PARAMETER = 'Use `it` block parameter.'
|
46
|
+
MSG_AVOID_IT_BLOCK_PARAMETER = 'Avoid using `it` block parameter.'
|
47
|
+
|
48
|
+
minimum_target_ruby_version 3.4
|
49
|
+
|
50
|
+
def on_block(node)
|
51
|
+
return unless style == :always
|
52
|
+
return unless node.arguments.one?
|
53
|
+
|
54
|
+
# `restarg`, `kwrestarg`, `blockarg` nodes can return early.
|
55
|
+
return unless node.first_argument.arg_type?
|
56
|
+
|
57
|
+
variables = find_block_variables(node, node.first_argument.source)
|
58
|
+
|
59
|
+
variables.each do |variable|
|
60
|
+
add_offense(variable, message: MSG_USE_IT_BLOCK_PARAMETER) do |corrector|
|
61
|
+
corrector.remove(node.arguments)
|
62
|
+
corrector.replace(variable, 'it')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def on_numblock(node)
|
68
|
+
return if style == :disallow
|
69
|
+
return unless node.children[1] == 1
|
70
|
+
|
71
|
+
variables = find_block_variables(node, '_1')
|
72
|
+
|
73
|
+
variables.each do |variable|
|
74
|
+
add_offense(variable, message: MSG_USE_IT_BLOCK_PARAMETER) do |corrector|
|
75
|
+
corrector.replace(variable, 'it')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def on_itblock(node)
|
81
|
+
return unless style == :disallow
|
82
|
+
|
83
|
+
variables = find_block_variables(node, 'it')
|
84
|
+
|
85
|
+
variables.each do |variable|
|
86
|
+
add_offense(variable, message: MSG_AVOID_IT_BLOCK_PARAMETER)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def find_block_variables(node, block_argument_name)
|
93
|
+
node.each_descendant(:lvar).select do |descendant|
|
94
|
+
descendant.source == block_argument_name
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -46,6 +46,38 @@ module RuboCop
|
|
46
46
|
# next unless a == 1
|
47
47
|
# puts a
|
48
48
|
# end
|
49
|
+
#
|
50
|
+
# @example AllowConsecutiveConditionals: false (default)
|
51
|
+
# # bad
|
52
|
+
# [1, 2].each do |a|
|
53
|
+
# if a == 1
|
54
|
+
# puts a
|
55
|
+
# end
|
56
|
+
# if a == 2
|
57
|
+
# puts a
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# # good
|
62
|
+
# [1, 2].each do |a|
|
63
|
+
# if a == 1
|
64
|
+
# puts a
|
65
|
+
# end
|
66
|
+
# next unless a == 2
|
67
|
+
# puts a
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# @example AllowConsecutiveConditionals: true
|
71
|
+
# # good
|
72
|
+
# [1, 2].each do |a|
|
73
|
+
# if a == 1
|
74
|
+
# puts a
|
75
|
+
# end
|
76
|
+
# if a == 2
|
77
|
+
# puts a
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
#
|
49
81
|
class Next < Base
|
50
82
|
include ConfigurableEnforcedStyle
|
51
83
|
include MinBodyLength
|
@@ -72,6 +104,7 @@ module RuboCop
|
|
72
104
|
end
|
73
105
|
|
74
106
|
alias on_numblock on_block
|
107
|
+
alias on_itblock on_block
|
75
108
|
|
76
109
|
def on_while(node)
|
77
110
|
check(node)
|
@@ -86,6 +119,9 @@ module RuboCop
|
|
86
119
|
|
87
120
|
offending_node = offense_node(node.body)
|
88
121
|
|
122
|
+
return if allowed_consecutive_conditionals? &&
|
123
|
+
consecutive_conditionals?(offending_node)
|
124
|
+
|
89
125
|
add_offense(offense_location(offending_node)) do |corrector|
|
90
126
|
if offending_node.modifier_form?
|
91
127
|
autocorrect_modifier(corrector, offending_node)
|
@@ -227,6 +263,14 @@ module RuboCop
|
|
227
263
|
|
228
264
|
corrector.remove_leading(buffer.line_range(lineno), adjustment) if adjustment.positive?
|
229
265
|
end
|
266
|
+
|
267
|
+
def consecutive_conditionals?(if_node)
|
268
|
+
if_node.parent&.begin_type? && if_node.left_sibling&.if_type?
|
269
|
+
end
|
270
|
+
|
271
|
+
def allowed_consecutive_conditionals?
|
272
|
+
cop_config.fetch('AllowConsecutiveConditionals', false)
|
273
|
+
end
|
230
274
|
end
|
231
275
|
end
|
232
276
|
end
|
@@ -5,8 +5,8 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Checks for calls to `Kernel#format` or `Kernel#sprintf` that are redundant.
|
7
7
|
#
|
8
|
-
# Calling `format` with only a single string argument is redundant,
|
9
|
-
# replaced by the string itself.
|
8
|
+
# Calling `format` with only a single string or constant argument is redundant,
|
9
|
+
# as it can be replaced by the string or constant itself.
|
10
10
|
#
|
11
11
|
# Also looks for `format` calls where the arguments are literals that can be
|
12
12
|
# inlined into a string easily. This applies to the `%s`, `%d`, `%i`, `%u`, and
|
@@ -38,6 +38,13 @@ module RuboCop
|
|
38
38
|
# 'the quick brown fox jumps over the lazy dog.'
|
39
39
|
#
|
40
40
|
# # bad
|
41
|
+
# format(MESSAGE)
|
42
|
+
# sprintf(MESSAGE)
|
43
|
+
#
|
44
|
+
# # good
|
45
|
+
# MESSAGE
|
46
|
+
#
|
47
|
+
# # bad
|
41
48
|
# format('%s %s', 'foo', 'bar')
|
42
49
|
# sprintf('%s %s', 'foo', 'bar')
|
43
50
|
#
|
@@ -54,7 +61,7 @@ module RuboCop
|
|
54
61
|
|
55
62
|
# @!method format_without_additional_args?(node)
|
56
63
|
def_node_matcher :format_without_additional_args?, <<~PATTERN
|
57
|
-
(send {(const {nil? cbase} :Kernel) nil?} %RESTRICT_ON_SEND ${str dstr})
|
64
|
+
(send {(const {nil? cbase} :Kernel) nil?} %RESTRICT_ON_SEND ${str dstr const})
|
58
65
|
PATTERN
|
59
66
|
|
60
67
|
# @!method rational_number?(node)
|
@@ -17,7 +17,7 @@ module RuboCop
|
|
17
17
|
include Parentheses
|
18
18
|
extend AutoCorrector
|
19
19
|
|
20
|
-
ALLOWED_NODE_TYPES = %i[
|
20
|
+
ALLOWED_NODE_TYPES = %i[or send splat kwsplat].freeze
|
21
21
|
|
22
22
|
# @!method square_brackets?(node)
|
23
23
|
def_node_matcher :square_brackets?, <<~PATTERN
|
@@ -162,6 +162,7 @@ module RuboCop
|
|
162
162
|
return if node.semantic_operator? && begin_node.parent
|
163
163
|
return if node.multiline? && allow_in_multiline_conditions?
|
164
164
|
return if ALLOWED_NODE_TYPES.include?(begin_node.parent&.type)
|
165
|
+
return if !node.and_type? && begin_node.parent&.and_type?
|
165
166
|
return if begin_node.parent&.if_type? && begin_node.parent.ternary?
|
166
167
|
|
167
168
|
'a logical expression'
|
@@ -21,6 +21,7 @@ module RuboCop
|
|
21
21
|
|
22
22
|
MSG_BLOCK = 'Use `sort` instead of `sort_by { |%<var>s| %<var>s }`.'
|
23
23
|
MSG_NUMBLOCK = 'Use `sort` instead of `sort_by { _1 }`.'
|
24
|
+
MSG_ITBLOCK = 'Use `sort` instead of `sort_by { it }`.'
|
24
25
|
|
25
26
|
def on_block(node)
|
26
27
|
redundant_sort_by_block(node) do |send, var_name|
|
@@ -36,7 +37,17 @@ module RuboCop
|
|
36
37
|
redundant_sort_by_numblock(node) do |send|
|
37
38
|
range = sort_by_range(send, node)
|
38
39
|
|
39
|
-
add_offense(range, message:
|
40
|
+
add_offense(range, message: MSG_NUMBLOCK) do |corrector|
|
41
|
+
corrector.replace(range, 'sort')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def on_itblock(node)
|
47
|
+
redundant_sort_by_itblock(node) do |send|
|
48
|
+
range = sort_by_range(send, node)
|
49
|
+
|
50
|
+
add_offense(range, message: MSG_ITBLOCK) do |corrector|
|
40
51
|
corrector.replace(range, 'sort')
|
41
52
|
end
|
42
53
|
end
|
@@ -54,6 +65,11 @@ module RuboCop
|
|
54
65
|
(numblock $(call _ :sort_by) 1 (lvar :_1))
|
55
66
|
PATTERN
|
56
67
|
|
68
|
+
# @!method redundant_sort_by_itblock(node)
|
69
|
+
def_node_matcher :redundant_sort_by_itblock, <<~PATTERN
|
70
|
+
(itblock $(call _ :sort_by) _ (lvar :it))
|
71
|
+
PATTERN
|
72
|
+
|
57
73
|
def sort_by_range(send, node)
|
58
74
|
range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
|
59
75
|
end
|
@@ -59,6 +59,7 @@ module RuboCop
|
|
59
59
|
{
|
60
60
|
(block call (args (arg $_)) ${(send _ %REGEXP_METHODS _) match-with-lvasgn})
|
61
61
|
(numblock call $1 ${(send _ %REGEXP_METHODS _) match-with-lvasgn})
|
62
|
+
(itblock call $_ ${(send _ %REGEXP_METHODS _) match-with-lvasgn})
|
62
63
|
}
|
63
64
|
PATTERN
|
64
65
|
|
@@ -137,6 +138,7 @@ module RuboCop
|
|
137
138
|
return unless (block_arg_name, regexp_method_send_node = regexp_match?(block_node))
|
138
139
|
|
139
140
|
block_arg_name = :"_#{block_arg_name}" if block_node.numblock_type?
|
141
|
+
|
140
142
|
return unless calls_lvar?(regexp_method_send_node, block_arg_name)
|
141
143
|
|
142
144
|
regexp_method_send_node
|
@@ -150,7 +152,8 @@ module RuboCop
|
|
150
152
|
return node.child_nodes.first if node.match_with_lvasgn_type?
|
151
153
|
|
152
154
|
if node.receiver.lvar_type? &&
|
153
|
-
(block.
|
155
|
+
(block.type?(:numblock, :itblock) ||
|
156
|
+
node.receiver.source == block.first_argument.source)
|
154
157
|
node.first_argument
|
155
158
|
elsif node.first_argument.lvar_type?
|
156
159
|
node.receiver
|
@@ -56,11 +56,13 @@ module RuboCop
|
|
56
56
|
end
|
57
57
|
# rubocop:enable Metrics/AbcSize
|
58
58
|
alias on_numblock on_block
|
59
|
+
alias on_itblock on_block
|
59
60
|
|
60
61
|
private
|
61
62
|
|
62
63
|
def do_line(node)
|
63
|
-
if node.
|
64
|
+
if node.type?(:numblock, :itblock) ||
|
65
|
+
node.arguments.children.empty? || node.send_node.lambda_literal?
|
64
66
|
node.loc.begin
|
65
67
|
else
|
66
68
|
node.arguments
|