rubocop 1.77.0 → 1.80.2
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 -3
- data/config/default.yml +36 -20
- data/exe/rubocop +1 -8
- data/lib/rubocop/cli.rb +17 -1
- data/lib/rubocop/config_loader.rb +1 -38
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +6 -3
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
- data/lib/rubocop/cop/internal_affairs/example_description.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_type_group.rb +3 -2
- data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +101 -0
- data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +8 -29
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -0
- data/lib/rubocop/cop/layout/space_around_keyword.rb +6 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +8 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +25 -4
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
- data/lib/rubocop/cop/lint/literal_as_condition.rb +15 -1
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -2
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +1 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +101 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +4 -4
- data/lib/rubocop/cop/lint/require_range_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/rescue_type.rb +1 -1
- data/lib/rubocop/cop/lint/self_assignment.rb +5 -4
- data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +1 -0
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +121 -0
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
- data/lib/rubocop/cop/naming/method_name.rb +127 -13
- data/lib/rubocop/cop/naming/predicate_method.rb +30 -4
- data/lib/rubocop/cop/security/eval.rb +2 -1
- data/lib/rubocop/cop/security/open.rb +1 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -1
- data/lib/rubocop/cop/style/accessor_grouping.rb +13 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +11 -17
- data/lib/rubocop/cop/style/array_intersect.rb +98 -34
- data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
- data/lib/rubocop/cop/style/dig_chain.rb +1 -1
- data/lib/rubocop/cop/style/exponential_notation.rb +1 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +8 -9
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +1 -1
- data/lib/rubocop/cop/style/it_assignment.rb +69 -12
- data/lib/rubocop/cop/style/it_block_parameter.rb +3 -1
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -3
- data/lib/rubocop/cop/style/map_to_set.rb +1 -3
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +16 -0
- data/lib/rubocop/cop/style/parallel_assignment.rb +32 -20
- data/lib/rubocop/cop/style/redundant_begin.rb +34 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +1 -1
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -9
- data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +1 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +28 -11
- data/lib/rubocop/cop/style/safe_navigation.rb +20 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +7 -4
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +30 -1
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +17 -13
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +25 -8
- data/lib/rubocop/cops_documentation_generator.rb +1 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +18 -5
- data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
- data/lib/rubocop/formatter/pacman_formatter.rb +1 -0
- data/lib/rubocop/lsp/routes.rb +35 -6
- data/lib/rubocop/pending_cops_reporter.rb +56 -0
- data/lib/rubocop/result_cache.rb +14 -12
- data/lib/rubocop/runner.rb +6 -4
- data/lib/rubocop/server/cache.rb +4 -2
- data/lib/rubocop/server/client_command/base.rb +10 -0
- data/lib/rubocop/server/client_command/exec.rb +2 -1
- data/lib/rubocop/server/client_command/start.rb +11 -1
- data/lib/rubocop/target_finder.rb +9 -9
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +3 -0
- metadata +9 -6
@@ -44,10 +44,10 @@ module RuboCop
|
|
44
44
|
class HashConversion < Base
|
45
45
|
extend AutoCorrector
|
46
46
|
|
47
|
-
MSG_TO_H = 'Prefer ary.to_h to Hash[ary]
|
48
|
-
MSG_LITERAL_MULTI_ARG = 'Prefer literal hash to Hash[arg1, arg2, ...]
|
49
|
-
MSG_LITERAL_HASH_ARG = 'Prefer literal hash to Hash[key: value, ...]
|
50
|
-
MSG_SPLAT = 'Prefer array_of_pairs.to_h to Hash[*array]
|
47
|
+
MSG_TO_H = 'Prefer `ary.to_h` to `Hash[ary]`.'
|
48
|
+
MSG_LITERAL_MULTI_ARG = 'Prefer literal hash to `Hash[arg1, arg2, ...]`.'
|
49
|
+
MSG_LITERAL_HASH_ARG = 'Prefer literal hash to `Hash[key: value, ...]`.'
|
50
|
+
MSG_SPLAT = 'Prefer `array_of_pairs.to_h` to `Hash[*array]`.'
|
51
51
|
RESTRICT_ON_SEND = %i[[]].freeze
|
52
52
|
|
53
53
|
# @!method hash_from_array?(node)
|
@@ -64,11 +64,11 @@ module RuboCop
|
|
64
64
|
# Hash[a1, a2, a3, a4] => {a1 => a2, a3 => a4}
|
65
65
|
# ...but don't suggest correction if there is odd number of them (it is a bug)
|
66
66
|
node.arguments.one? ? single_argument(node) : multi_argument(node)
|
67
|
+
ignore_node(node)
|
67
68
|
end
|
68
69
|
|
69
70
|
private
|
70
71
|
|
71
|
-
# rubocop:disable Metrics/MethodLength
|
72
72
|
def single_argument(node)
|
73
73
|
first_argument = node.first_argument
|
74
74
|
if first_argument.hash_type?
|
@@ -83,11 +83,8 @@ module RuboCop
|
|
83
83
|
replacement = "(#{replacement})" if requires_parens?(first_argument)
|
84
84
|
corrector.replace(node, "#{replacement}.to_h")
|
85
85
|
end
|
86
|
-
|
87
|
-
ignore_node(node)
|
88
86
|
end
|
89
87
|
end
|
90
|
-
# rubocop:enable Metrics/MethodLength
|
91
88
|
|
92
89
|
def use_zip_method_without_argument?(first_argument)
|
93
90
|
return false unless first_argument&.send_type?
|
@@ -131,7 +128,9 @@ module RuboCop
|
|
131
128
|
corrector.replace(node, args_to_hash(node.arguments))
|
132
129
|
|
133
130
|
parent = node.parent
|
134
|
-
|
131
|
+
if parent&.send_type? && !parent.method?(:to_h) && !parent.parenthesized?
|
132
|
+
add_parentheses(parent, corrector)
|
133
|
+
end
|
135
134
|
end
|
136
135
|
end
|
137
136
|
end
|
@@ -68,7 +68,7 @@ module RuboCop
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def autocorrect(corrector, node)
|
71
|
-
if node.
|
71
|
+
if node.post_condition_loop?
|
72
72
|
replace_begin_end_with_modifier(corrector, node)
|
73
73
|
elsif node.modifier_form?
|
74
74
|
replace_source(corrector, node.source_range, modifier_replacement(node))
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
#
|
6
|
+
# Checks for usages of not (`not` or `!`) called on a method
|
7
7
|
# when an inverse of that method can be used instead.
|
8
8
|
#
|
9
9
|
# Methods that can be inverted by a not (`not` or `!`) should be defined
|
@@ -3,33 +3,90 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for
|
6
|
+
# Checks for local variables and method parameters named `it`,
|
7
7
|
# where `it` can refer to the first anonymous parameter as of Ruby 3.4.
|
8
|
+
# Use a meaningful variable name instead.
|
8
9
|
#
|
9
|
-
# Although Ruby allows reassigning `it` in these cases, it could
|
10
|
+
# NOTE: Although Ruby allows reassigning `it` in these cases, it could
|
10
11
|
# cause confusion if `it` is used as a block parameter elsewhere.
|
11
|
-
# For consistency, this also applies to numblocks and blocks with
|
12
|
-
# parameters, even though `it` cannot be used in those cases.
|
13
12
|
#
|
14
13
|
# @example
|
15
14
|
# # bad
|
16
|
-
#
|
17
|
-
# foo { |bar| it = bar }
|
18
|
-
# foo { it = _2 }
|
15
|
+
# it = 5
|
19
16
|
#
|
20
|
-
# # good
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
17
|
+
# # good
|
18
|
+
# var = 5
|
19
|
+
#
|
20
|
+
# # bad
|
21
|
+
# def foo(it)
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# def foo(arg)
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# # bad
|
29
|
+
# def foo(it = 5)
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # good
|
33
|
+
# def foo(arg = 5)
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# # bad
|
37
|
+
# def foo(*it)
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# # good
|
41
|
+
# def foo(*args)
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# # bad
|
45
|
+
# def foo(it:)
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# # good
|
49
|
+
# def foo(arg:)
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# # bad
|
53
|
+
# def foo(it: 5)
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# # good
|
57
|
+
# def foo(arg: 5)
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# # bad
|
61
|
+
# def foo(**it)
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# # good
|
65
|
+
# def foo(**kwargs)
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# # bad
|
69
|
+
# def foo(&it)
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
# # good
|
73
|
+
# def foo(&block)
|
74
|
+
# end
|
24
75
|
class ItAssignment < Base
|
25
76
|
MSG = '`it` is the default block parameter; consider another name.'
|
26
77
|
|
27
78
|
def on_lvasgn(node)
|
28
79
|
return unless node.name == :it
|
29
|
-
return unless node.each_ancestor(:any_block).any?
|
30
80
|
|
31
81
|
add_offense(node.loc.name)
|
32
82
|
end
|
83
|
+
alias on_arg on_lvasgn
|
84
|
+
alias on_optarg on_lvasgn
|
85
|
+
alias on_restarg on_lvasgn
|
86
|
+
alias on_blockarg on_lvasgn
|
87
|
+
alias on_kwarg on_lvasgn
|
88
|
+
alias on_kwoptarg on_lvasgn
|
89
|
+
alias on_kwrestarg on_lvasgn
|
33
90
|
end
|
34
91
|
end
|
35
92
|
end
|
@@ -109,7 +109,9 @@ module RuboCop
|
|
109
109
|
private
|
110
110
|
|
111
111
|
def find_block_variables(node, block_argument_name)
|
112
|
-
node.
|
112
|
+
return [] unless node.body
|
113
|
+
|
114
|
+
node.body.each_descendant(:lvar).select do |descendant|
|
113
115
|
descendant.source == block_argument_name
|
114
116
|
end
|
115
117
|
end
|
@@ -56,12 +56,10 @@ module RuboCop
|
|
56
56
|
|
57
57
|
def on_send(node)
|
58
58
|
return unless (to_h_node, map_node = map_to_h(node))
|
59
|
+
return if to_h_node.block_literal?
|
59
60
|
|
60
61
|
message = format(MSG, method: map_node.loc.selector.source, dot: to_h_node.loc.dot.source)
|
61
62
|
add_offense(map_node.loc.selector, message: message) do |corrector|
|
62
|
-
# If the `to_h` call already has a block, do not autocorrect.
|
63
|
-
next if to_h_node.block_literal?
|
64
|
-
|
65
63
|
autocorrect(corrector, to_h_node, map_node)
|
66
64
|
end
|
67
65
|
end
|
@@ -40,12 +40,10 @@ module RuboCop
|
|
40
40
|
|
41
41
|
def on_send(node)
|
42
42
|
return unless (to_set_node, map_node = map_to_set?(node))
|
43
|
+
return if to_set_node.block_literal?
|
43
44
|
|
44
45
|
message = format(MSG, method: map_node.loc.selector.source)
|
45
46
|
add_offense(map_node.loc.selector, message: message) do |corrector|
|
46
|
-
# If the `to_set` call already has a block, do not autocorrect.
|
47
|
-
next if to_set_node.block_literal?
|
48
|
-
|
49
47
|
autocorrect(corrector, to_set_node, map_node)
|
50
48
|
end
|
51
49
|
end
|
@@ -222,11 +222,9 @@ module RuboCop
|
|
222
222
|
end
|
223
223
|
|
224
224
|
def unary_literal?(node)
|
225
|
-
|
226
|
-
return node.source.match?(/\A[+-]/) if node.complex_type?
|
225
|
+
return true if node.numeric_type? && node.sign?
|
227
226
|
|
228
|
-
|
229
|
-
(node.parent&.send_type? && node.parent.unary_operation?)
|
227
|
+
node.parent&.send_type? && node.parent.unary_operation?
|
230
228
|
end
|
231
229
|
|
232
230
|
def assigned_before?(node, target)
|
@@ -132,6 +132,22 @@ module RuboCop
|
|
132
132
|
# bar :baz
|
133
133
|
# end
|
134
134
|
#
|
135
|
+
# @example AllowedMethods: ["puts", "print"]
|
136
|
+
#
|
137
|
+
# # good
|
138
|
+
# puts "Hello world"
|
139
|
+
# print "Hello world"
|
140
|
+
# # still enforces parentheses on other methods
|
141
|
+
# array.delete(e)
|
142
|
+
#
|
143
|
+
# @example AllowedPatterns: ["^assert"]
|
144
|
+
#
|
145
|
+
# # good
|
146
|
+
# assert_equal 'test', x
|
147
|
+
# assert_match(/foo/, bar)
|
148
|
+
# # still enforces parentheses on other methods
|
149
|
+
# array.delete(e)
|
150
|
+
#
|
135
151
|
# @example AllowParenthesesInMultilineCall: false (default)
|
136
152
|
#
|
137
153
|
# # bad
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'tsort'
|
4
|
-
|
5
3
|
module RuboCop
|
6
4
|
module Cop
|
7
5
|
module Style
|
@@ -29,6 +27,8 @@ module RuboCop
|
|
29
27
|
MSG = 'Do not use parallel assignment.'
|
30
28
|
|
31
29
|
def on_masgn(node) # rubocop:disable Metrics/AbcSize
|
30
|
+
return if part_of_ignored_node?(node)
|
31
|
+
|
32
32
|
rhs = node.rhs
|
33
33
|
rhs = rhs.body if rhs.rescue_type?
|
34
34
|
rhs_elements = Array(rhs).compact # edge case for one constant
|
@@ -41,6 +41,7 @@ module RuboCop
|
|
41
41
|
add_offense(range) do |corrector|
|
42
42
|
autocorrect(corrector, node, rhs)
|
43
43
|
end
|
44
|
+
ignore_node(node)
|
44
45
|
end
|
45
46
|
|
46
47
|
private
|
@@ -91,15 +92,9 @@ module RuboCop
|
|
91
92
|
def find_valid_order(left_elements, right_elements)
|
92
93
|
# arrange left_elements in an order such that no corresponding right
|
93
94
|
# element refers to a left element earlier in the sequence
|
94
|
-
# this can be done using an algorithm called a "topological sort"
|
95
|
-
# fortunately for us, Ruby's stdlib contains an implementation
|
96
95
|
assignments = left_elements.zip(right_elements)
|
97
96
|
|
98
|
-
|
99
|
-
AssignmentSorter.new(assignments).tsort
|
100
|
-
rescue TSort::Cyclic
|
101
|
-
nil
|
102
|
-
end
|
97
|
+
AssignmentSorter.new(assignments).tsort
|
103
98
|
end
|
104
99
|
|
105
100
|
# Converts (send nil :something) nodes to (send (:self) :something).
|
@@ -114,10 +109,9 @@ module RuboCop
|
|
114
109
|
# @!method implicit_self_getter?(node)
|
115
110
|
def_node_matcher :implicit_self_getter?, '(send nil? $_)'
|
116
111
|
|
117
|
-
#
|
118
|
-
#
|
112
|
+
# Topologically sorts the assignments with Kahn's algorithm.
|
113
|
+
# https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm
|
119
114
|
class AssignmentSorter
|
120
|
-
include TSort
|
121
115
|
extend RuboCop::NodePattern::Macros
|
122
116
|
|
123
117
|
# @!method var_name(node)
|
@@ -133,21 +127,39 @@ module RuboCop
|
|
133
127
|
@assignments = assignments
|
134
128
|
end
|
135
129
|
|
136
|
-
def
|
137
|
-
@assignments.
|
130
|
+
def tsort
|
131
|
+
dependencies = @assignments.to_h do |assignment|
|
132
|
+
[assignment, dependencies_for_assignment(assignment)]
|
133
|
+
end
|
134
|
+
result = []
|
135
|
+
|
136
|
+
while (matched_node, = dependencies.find { |_node, edges| edges.empty? })
|
137
|
+
dependencies.delete(matched_node)
|
138
|
+
result.push(matched_node)
|
139
|
+
|
140
|
+
dependencies.each do |node, edges|
|
141
|
+
dependencies[node].delete(matched_node) if edges.include?(matched_node)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
# Cyclic dependency
|
145
|
+
return nil if dependencies.any?
|
146
|
+
|
147
|
+
result
|
138
148
|
end
|
139
149
|
|
140
|
-
|
141
|
-
|
142
|
-
|
150
|
+
# Returns all the assignments which must come after `assignment`
|
151
|
+
# (due to dependencies on the previous value of the assigned var)
|
152
|
+
def dependencies_for_assignment(assignment)
|
143
153
|
my_lhs, _my_rhs = *assignment
|
144
154
|
|
145
|
-
@assignments.
|
146
|
-
|
155
|
+
@assignments.filter_map do |other|
|
156
|
+
# Exclude self, there are no dependencies in cases such as `a, b = a, b`.
|
157
|
+
next if other == assignment
|
147
158
|
|
159
|
+
_other_lhs, other_rhs = *other
|
148
160
|
next unless dependency?(my_lhs, other_rhs)
|
149
161
|
|
150
|
-
|
162
|
+
other
|
151
163
|
end
|
152
164
|
end
|
153
165
|
|
@@ -85,6 +85,29 @@ module RuboCop
|
|
85
85
|
end
|
86
86
|
alias on_defs on_def
|
87
87
|
|
88
|
+
def on_if(node)
|
89
|
+
return if node.modifier_form?
|
90
|
+
|
91
|
+
inspect_branches(node)
|
92
|
+
end
|
93
|
+
|
94
|
+
def on_case(node)
|
95
|
+
inspect_branches(node)
|
96
|
+
end
|
97
|
+
alias on_case_match on_case
|
98
|
+
|
99
|
+
def on_while(node)
|
100
|
+
return if node.modifier_form?
|
101
|
+
|
102
|
+
body = node.body
|
103
|
+
|
104
|
+
return unless body&.kwbegin_type?
|
105
|
+
return if body.rescue_node || body.ensure_node
|
106
|
+
|
107
|
+
register_offense(body)
|
108
|
+
end
|
109
|
+
alias on_until on_while
|
110
|
+
|
88
111
|
def on_block(node)
|
89
112
|
return if target_ruby_version < 2.5
|
90
113
|
return if node.send_node.lambda_literal?
|
@@ -180,6 +203,8 @@ module RuboCop
|
|
180
203
|
end
|
181
204
|
|
182
205
|
def begin_block_has_multiline_statements?(node)
|
206
|
+
return false unless node.parent
|
207
|
+
|
183
208
|
node.children.count >= 2
|
184
209
|
end
|
185
210
|
|
@@ -199,6 +224,15 @@ module RuboCop
|
|
199
224
|
def valid_begin_assignment?(node)
|
200
225
|
node.parent&.assignment? && !node.children.one?
|
201
226
|
end
|
227
|
+
|
228
|
+
def inspect_branches(node)
|
229
|
+
node.branches.each do |branch|
|
230
|
+
next unless branch&.kwbegin_type?
|
231
|
+
next if branch.rescue_node || branch.ensure_node
|
232
|
+
|
233
|
+
register_offense(branch)
|
234
|
+
end
|
235
|
+
end
|
202
236
|
end
|
203
237
|
end
|
204
238
|
end
|
@@ -247,7 +247,7 @@ module RuboCop
|
|
247
247
|
"#{if_branch.receiver.source} #{if_branch.method_name} (#{argument_source}"
|
248
248
|
elsif if_branch.true_type?
|
249
249
|
condition = if_branch.parent.condition
|
250
|
-
return condition.source if condition.arguments.empty?
|
250
|
+
return condition.source if condition.arguments.empty? || condition.parenthesized?
|
251
251
|
|
252
252
|
wrap_arguments_with_parens(condition)
|
253
253
|
else
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
49
49
|
(block
|
50
50
|
$(call _ :fetch _)
|
51
51
|
(args)
|
52
|
-
${nil?
|
52
|
+
${nil? basic_literal? const_type?})
|
53
53
|
PATTERN
|
54
54
|
|
55
55
|
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
@@ -71,14 +71,6 @@ module RuboCop
|
|
71
71
|
|
72
72
|
private
|
73
73
|
|
74
|
-
def basic_literal?(node)
|
75
|
-
node&.basic_literal?
|
76
|
-
end
|
77
|
-
|
78
|
-
def const_type?(node)
|
79
|
-
node&.const_type?
|
80
|
-
end
|
81
|
-
|
82
74
|
def should_not_check?(send, body)
|
83
75
|
(body&.const_type? && !check_for_constant?) ||
|
84
76
|
(body&.str_type? && !check_for_string?) ||
|
@@ -24,9 +24,6 @@ module RuboCop
|
|
24
24
|
(send `{(send _recv _msg) str array hash const #variable?} :[] ...)
|
25
25
|
PATTERN
|
26
26
|
|
27
|
-
# @!method method_node_and_args(node)
|
28
|
-
def_node_matcher :method_node_and_args, '$(call _recv _msg $...)'
|
29
|
-
|
30
27
|
# @!method rescue?(node)
|
31
28
|
def_node_matcher :rescue?, '{^resbody ^^resbody}'
|
32
29
|
|
@@ -149,7 +146,7 @@ module RuboCop
|
|
149
146
|
return offense(begin_node, message)
|
150
147
|
end
|
151
148
|
|
152
|
-
check_send(begin_node, node) if node
|
149
|
+
check_send(begin_node, node) if call_node?(node)
|
153
150
|
end
|
154
151
|
|
155
152
|
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
@@ -169,6 +166,7 @@ module RuboCop
|
|
169
166
|
end
|
170
167
|
return 'an interpolated expression' if interpolation?(begin_node)
|
171
168
|
return 'a method argument' if argument_of_parenthesized_method_call?(begin_node, node)
|
169
|
+
return 'a one-line rescue' if oneline_rescue_parentheses_required?(begin_node, node)
|
172
170
|
|
173
171
|
return if begin_node.chained?
|
174
172
|
|
@@ -200,6 +198,14 @@ module RuboCop
|
|
200
198
|
parent.call_type? && parent.parenthesized? && parent.receiver != begin_node
|
201
199
|
end
|
202
200
|
|
201
|
+
def oneline_rescue_parentheses_required?(begin_node, node)
|
202
|
+
return false unless node.rescue_type?
|
203
|
+
return false unless (parent = begin_node.parent)
|
204
|
+
return false if parent.if_type? && parent.ternary?
|
205
|
+
|
206
|
+
!parent.type?(:call, :array, :pair)
|
207
|
+
end
|
208
|
+
|
203
209
|
def method_call_parentheses_required?(node)
|
204
210
|
return false unless node.call_type?
|
205
211
|
|
@@ -210,10 +216,16 @@ module RuboCop
|
|
210
216
|
!!config.for_enabled_cop('Style/ParenthesesAroundCondition')['AllowInMultilineConditions']
|
211
217
|
end
|
212
218
|
|
219
|
+
def call_node?(node)
|
220
|
+
node.call_type? || (node.any_block_type? && node.braces? && !node.lambda_or_proc?)
|
221
|
+
end
|
222
|
+
|
213
223
|
def check_send(begin_node, node)
|
224
|
+
node = node.send_node if node.any_block_type?
|
225
|
+
|
214
226
|
return check_unary(begin_node, node) if node.unary_operation?
|
215
227
|
|
216
|
-
return unless method_call_with_redundant_parentheses?(node)
|
228
|
+
return unless method_call_with_redundant_parentheses?(begin_node, node)
|
217
229
|
return if call_chain_starts_with_int?(begin_node, node) ||
|
218
230
|
do_end_block_in_method_chain?(begin_node, node)
|
219
231
|
|
@@ -224,8 +236,7 @@ module RuboCop
|
|
224
236
|
return if begin_node.chained?
|
225
237
|
|
226
238
|
node = node.children.first while suspect_unary?(node)
|
227
|
-
|
228
|
-
return if node.send_type? && !method_call_with_redundant_parentheses?(node)
|
239
|
+
return unless method_call_with_redundant_parentheses?(begin_node, node)
|
229
240
|
|
230
241
|
offense(begin_node, 'a unary operation')
|
231
242
|
end
|
@@ -287,13 +298,19 @@ module RuboCop
|
|
287
298
|
end
|
288
299
|
end
|
289
300
|
|
290
|
-
def method_call_with_redundant_parentheses?(node)
|
291
|
-
return false unless node.
|
301
|
+
def method_call_with_redundant_parentheses?(begin_node, node)
|
302
|
+
return false unless node.type?(:call, :super, :yield, :defined?)
|
292
303
|
return false if node.prefix_not?
|
304
|
+
return true if singular_parenthesized_parent?(begin_node)
|
305
|
+
|
306
|
+
node.arguments.empty? || parentheses?(node) || square_brackets?(node)
|
307
|
+
end
|
293
308
|
|
294
|
-
|
309
|
+
def singular_parenthesized_parent?(begin_node)
|
310
|
+
return true unless begin_node.parent
|
311
|
+
return false if begin_node.parent.type?(:splat, :kwsplat)
|
295
312
|
|
296
|
-
|
313
|
+
parentheses?(begin_node) && begin_node.parent.children.one?
|
297
314
|
end
|
298
315
|
|
299
316
|
def only_begin_arg?(args)
|
@@ -142,6 +142,7 @@ module RuboCop
|
|
142
142
|
# @!method strip_begin(node)
|
143
143
|
def_node_matcher :strip_begin, '{ (begin $!begin) $!(begin) }'
|
144
144
|
|
145
|
+
# rubocop:disable Metrics/AbcSize
|
145
146
|
def on_if(node)
|
146
147
|
return if allowed_if_condition?(node)
|
147
148
|
|
@@ -155,9 +156,11 @@ module RuboCop
|
|
155
156
|
removal_ranges = [begin_range(node, body), end_range(node, body)]
|
156
157
|
|
157
158
|
report_offense(node, method_chain, method_call, *removal_ranges) do |corrector|
|
159
|
+
corrector.replace(receiver, checked_variable.source) if checked_variable.csend_type?
|
158
160
|
corrector.insert_before(method_call.loc.dot, '&') unless method_call.safe_navigation?
|
159
161
|
end
|
160
162
|
end
|
163
|
+
# rubocop:enable Metrics/AbcSize
|
161
164
|
|
162
165
|
def on_and(node) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
163
166
|
collect_and_clauses(node).each do |(lhs, lhs_operator_range), (rhs, _rhs_operator_range)|
|
@@ -259,6 +262,14 @@ module RuboCop
|
|
259
262
|
end
|
260
263
|
|
261
264
|
def dotless_operator_call?(method_call)
|
265
|
+
return true if dotless_operator_method?(method_call)
|
266
|
+
|
267
|
+
method_call = method_call.parent while method_call.parent.send_type?
|
268
|
+
|
269
|
+
dotless_operator_method?(method_call)
|
270
|
+
end
|
271
|
+
|
272
|
+
def dotless_operator_method?(method_call)
|
262
273
|
return false if method_call.loc.dot
|
263
274
|
|
264
275
|
method_call.method?(:[]) || method_call.method?(:[]=) || method_call.operator_method?
|
@@ -333,8 +344,16 @@ module RuboCop
|
|
333
344
|
|
334
345
|
def matching_call_nodes?(left, right)
|
335
346
|
return false unless left && right.respond_to?(:call_type?)
|
347
|
+
return false unless left.call_type? && right.call_type?
|
348
|
+
|
349
|
+
# Compare receiver and method name, but ignore the difference between
|
350
|
+
# safe navigation method call (`&.`) and dot method call (`.`).
|
351
|
+
left_receiver, left_method, *left_args = left.children
|
352
|
+
right_receiver, right_method, *right_args = right.children
|
336
353
|
|
337
|
-
|
354
|
+
left_method == right_method &&
|
355
|
+
matching_nodes?(left_receiver, right_receiver) &&
|
356
|
+
left_args == right_args
|
338
357
|
end
|
339
358
|
|
340
359
|
def chain_length(method_chain, method)
|
@@ -65,7 +65,7 @@ module RuboCop
|
|
65
65
|
return false if target_ruby_version < 3.0
|
66
66
|
return false if disallow_endless_method_style?
|
67
67
|
return false unless body_node
|
68
|
-
return false if body_node.parent.assignment_method? ||
|
68
|
+
return false if body_node.basic_conditional? || body_node.parent.assignment_method? ||
|
69
69
|
NOT_SUPPORTED_ENDLESS_METHOD_BODY_TYPES.include?(body_node.type)
|
70
70
|
|
71
71
|
!body_node.type?(:begin, :kwbegin)
|
@@ -86,10 +86,10 @@ module RuboCop
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def correct_to_endless(corrector, node)
|
89
|
-
|
89
|
+
receiver = "#{node.receiver.source}." if node.receiver
|
90
90
|
arguments = node.arguments.any? ? node.arguments.source : '()'
|
91
91
|
body_source = method_body_source(node.body)
|
92
|
-
replacement = "def #{
|
92
|
+
replacement = "def #{receiver}#{node.method_name}#{arguments} = #{body_source}"
|
93
93
|
|
94
94
|
corrector.replace(node, replacement)
|
95
95
|
end
|
@@ -130,7 +130,10 @@ module RuboCop
|
|
130
130
|
end
|
131
131
|
|
132
132
|
def require_parentheses?(method_body)
|
133
|
-
|
133
|
+
return false unless method_body.send_type?
|
134
|
+
return false if method_body.arithmetic_operation?
|
135
|
+
|
136
|
+
!method_body.arguments.empty? && !method_body.comparison_method?
|
134
137
|
end
|
135
138
|
|
136
139
|
def disallow_endless_method_style?
|