rubocop 1.92.1 → 1.92.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/lib/rubocop/config.rb +0 -4
- data/lib/rubocop/config_obsoletion.rb +9 -0
- data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +2 -8
- data/lib/rubocop/cop/layout/extra_spacing.rb +17 -6
- data/lib/rubocop/cop/layout/line_length.rb +23 -5
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +31 -4
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +12 -0
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_range_literal.rb +29 -11
- data/lib/rubocop/cop/lint/interpolation_check.rb +20 -17
- data/lib/rubocop/cop/lint/nested_percent_literal.rb +3 -0
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +22 -1
- data/lib/rubocop/cop/lint/percent_string_array.rb +75 -9
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +27 -8
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +11 -4
- data/lib/rubocop/cop/mixin/comments_help.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +17 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +14 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
- data/lib/rubocop/cop/style/and_or.rb +33 -10
- data/lib/rubocop/cop/style/case_equality.rb +14 -3
- data/lib/rubocop/cop/style/class_and_module_children.rb +4 -3
- data/lib/rubocop/cop/style/endless_method.rb +34 -6
- data/lib/rubocop/cop/style/float_division.rb +16 -1
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -1
- data/lib/rubocop/cop/style/hash_lookup_method.rb +10 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -0
- data/lib/rubocop/cop/style/method_def_parentheses.rb +9 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +7 -0
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +18 -0
- data/lib/rubocop/cop/style/quoted_symbols.rb +5 -7
- data/lib/rubocop/cop/style/raise_args.rb +66 -7
- data/lib/rubocop/cop/style/reduce_to_hash.rb +32 -34
- data/lib/rubocop/cop/style/redundant_begin.rb +24 -2
- data/lib/rubocop/cop/style/redundant_exception.rb +13 -9
- data/lib/rubocop/cop/style/redundant_self.rb +9 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +21 -0
- data/lib/rubocop/cop/style/string_concatenation.rb +12 -1
- data/lib/rubocop/plugin/configuration_integrator.rb +24 -3
- data/lib/rubocop/runner.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +2 -2
|
@@ -146,8 +146,8 @@ module RuboCop
|
|
|
146
146
|
comment = directive_comment(line_range)
|
|
147
147
|
next if skip_directive?(comment)
|
|
148
148
|
|
|
149
|
-
|
|
150
|
-
redundant = find_redundant_directive(cop, comment, line_range,
|
|
149
|
+
following_ranges = line_ranges[(line_range_index + 1)..]
|
|
150
|
+
redundant = find_redundant_directive(cop, comment, line_range, following_ranges)
|
|
151
151
|
yield comment, redundant if redundant
|
|
152
152
|
end
|
|
153
153
|
end
|
|
@@ -191,14 +191,33 @@ module RuboCop
|
|
|
191
191
|
directive.push? || directive.pop? || directive.next?
|
|
192
192
|
end
|
|
193
193
|
|
|
194
|
-
def find_redundant_directive(cop, comment, line_range,
|
|
195
|
-
if all_disabled?(comment)
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
194
|
+
def find_redundant_directive(cop, comment, line_range, following_ranges)
|
|
195
|
+
return find_redundant_all(line_range, following_ranges.first) if all_disabled?(comment)
|
|
196
|
+
|
|
197
|
+
range = line_range_through_repeated_disables(cop, line_range, following_ranges)
|
|
198
|
+
if department_disabled?(cop, comment)
|
|
199
|
+
find_redundant_department(cop, range)
|
|
199
200
|
else
|
|
200
|
-
find_redundant_cop(cop,
|
|
201
|
+
find_redundant_cop(cop, range)
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def line_range_through_repeated_disables(cop, line_range, following_ranges)
|
|
206
|
+
last_range = line_range
|
|
207
|
+
following_ranges.each do |range|
|
|
208
|
+
break unless followed_ranges?(last_range, range) && repeated_disable?(cop, range)
|
|
209
|
+
|
|
210
|
+
last_range = range
|
|
201
211
|
end
|
|
212
|
+
|
|
213
|
+
line_range.begin..last_range.end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def repeated_disable?(cop, range)
|
|
217
|
+
comment = directive_comment(range)
|
|
218
|
+
return false if comment.nil? || skip_directive?(comment)
|
|
219
|
+
|
|
220
|
+
!all_disabled?(comment) && !department_disabled?(cop, comment)
|
|
202
221
|
end
|
|
203
222
|
|
|
204
223
|
# rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
@@ -118,10 +118,7 @@ module RuboCop
|
|
|
118
118
|
def redundant_splat_expansion(node)
|
|
119
119
|
literal_expansion(node) do |expanded_item|
|
|
120
120
|
if expanded_item.send_type?
|
|
121
|
-
return
|
|
122
|
-
|
|
123
|
-
grandparent = node.parent.parent
|
|
124
|
-
return if grandparent && !ASSIGNMENT_TYPES.include?(grandparent.type)
|
|
121
|
+
return unless redundant_array_new_splat?(node, expanded_item)
|
|
125
122
|
# An empty array/percent literal (`*[]`, `*%w()`, ...) expands to nothing, so
|
|
126
123
|
# removing the splat would produce invalid or semantically different code.
|
|
127
124
|
elsif expanded_item.array_type? && expanded_item.children.empty?
|
|
@@ -132,6 +129,16 @@ module RuboCop
|
|
|
132
129
|
end
|
|
133
130
|
end
|
|
134
131
|
|
|
132
|
+
# A splatted `Array.new` passed as a method argument provides the arguments,
|
|
133
|
+
# so the splat is only redundant directly inside an array.
|
|
134
|
+
def redundant_array_new_splat?(node, array_new_node)
|
|
135
|
+
return false unless node.parent.array_type?
|
|
136
|
+
return false if array_new_inside_array_literal?(array_new_node)
|
|
137
|
+
|
|
138
|
+
grandparent = node.parent.parent
|
|
139
|
+
!grandparent || ASSIGNMENT_TYPES.include?(grandparent.type)
|
|
140
|
+
end
|
|
141
|
+
|
|
135
142
|
def array_new_inside_array_literal?(array_new_node)
|
|
136
143
|
return false unless array_new?(array_new_node)
|
|
137
144
|
|
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
|
66
66
|
# the line at which the parent node ends.
|
|
67
67
|
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
68
68
|
def find_end_line(node)
|
|
69
|
-
if node.if_type?
|
|
69
|
+
if node.if_type? && !node.modifier_form?
|
|
70
70
|
if node.else?
|
|
71
71
|
node.loc.else.line
|
|
72
72
|
elsif node.ternary?
|
|
@@ -55,10 +55,17 @@ module RuboCop
|
|
|
55
55
|
# Common functionality for checking alignment of hash values.
|
|
56
56
|
module ValueAlignment
|
|
57
57
|
def checkable_layout?(node)
|
|
58
|
-
!node.pairs_on_same_line? && !node.mixed_delimiters? && alignable_values?(node)
|
|
58
|
+
!node.pairs_on_same_line? && !node.mixed_delimiters? && alignable_values?(node) &&
|
|
59
|
+
!pair_after_kwsplat_on_same_line?(node)
|
|
59
60
|
end
|
|
60
61
|
|
|
62
|
+
# With several enforced styles, deltas are computed even for a hash this style
|
|
63
|
+
# can't check. A pair that doesn't begin its line can't be moved without
|
|
64
|
+
# deleting whatever precedes it, so it's left alone.
|
|
61
65
|
def deltas(first_pair, current_pair)
|
|
66
|
+
return {} unless current_pair.equal?(first_pair) ||
|
|
67
|
+
Util.begins_its_line?(current_pair.source_range)
|
|
68
|
+
|
|
62
69
|
key_delta = key_delta(first_pair, current_pair)
|
|
63
70
|
shift = separator_shift(current_pair, key_delta)
|
|
64
71
|
separator_delta = separator_delta(first_pair, current_pair, shift)
|
|
@@ -79,6 +86,15 @@ module RuboCop
|
|
|
79
86
|
pair.value && pair.key.last_line != pair.value.first_line
|
|
80
87
|
end
|
|
81
88
|
|
|
89
|
+
def pair_after_kwsplat_on_same_line?(node)
|
|
90
|
+
first_pair = node.pairs.first
|
|
91
|
+
|
|
92
|
+
node.children.each_cons(2).any? do |previous, current|
|
|
93
|
+
current.pair_type? && !current.equal?(first_pair) &&
|
|
94
|
+
previous.last_line == current.first_line
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
82
98
|
def separator_shift(current_pair, key_delta)
|
|
83
99
|
current_pair.key.multiline? ? 0 : key_delta
|
|
84
100
|
end
|
|
@@ -7,6 +7,8 @@ module RuboCop
|
|
|
7
7
|
include LineLengthHelp
|
|
8
8
|
include AllowedPattern
|
|
9
9
|
|
|
10
|
+
SPACE_INSIDE_PARENS_STYLES = %w[space compact].freeze
|
|
11
|
+
|
|
10
12
|
private
|
|
11
13
|
|
|
12
14
|
def single_line_as_modifier?(node)
|
|
@@ -42,7 +44,10 @@ module RuboCop
|
|
|
42
44
|
def modifier_fits_on_single_line?(node)
|
|
43
45
|
return true unless max_line_length
|
|
44
46
|
|
|
45
|
-
line_length(line_in_modifier_form(node))
|
|
47
|
+
length = line_length(line_in_modifier_form(node))
|
|
48
|
+
length += 2 if parenthesize?(node) && space_inside_parens?
|
|
49
|
+
|
|
50
|
+
length <= max_line_length
|
|
46
51
|
end
|
|
47
52
|
|
|
48
53
|
def line_in_modifier_form(node)
|
|
@@ -52,6 +57,14 @@ module RuboCop
|
|
|
52
57
|
"#{code_before}#{to_modifier_form(node)}#{code_after(node)}"
|
|
53
58
|
end
|
|
54
59
|
|
|
60
|
+
def space_inside_parens?
|
|
61
|
+
return false unless config.cop_enabled?('Layout/SpaceInsideParens')
|
|
62
|
+
|
|
63
|
+
style = config.for_cop('Layout/SpaceInsideParens')['EnforcedStyle']
|
|
64
|
+
|
|
65
|
+
SPACE_INSIDE_PARENS_STYLES.include?(style)
|
|
66
|
+
end
|
|
67
|
+
|
|
55
68
|
# Whether an existing line is acceptable to `Layout/LineLength`,
|
|
56
69
|
# exemptions (the cop disabled at that line, an allowed pattern, an
|
|
57
70
|
# allowed cop directive, an allowed URI) included. Only for judging
|
|
@@ -163,7 +163,7 @@ module RuboCop
|
|
|
163
163
|
|
|
164
164
|
def put_comma(items, kind)
|
|
165
165
|
last_item = items.last
|
|
166
|
-
return if last_item.
|
|
166
|
+
return if last_item.type?(:block_pass, :forwarded_args)
|
|
167
167
|
|
|
168
168
|
range = autocorrect_range(last_item)
|
|
169
169
|
msg = format(MSG, command: 'Put a', unit: format(kind, article: 'a multiline'))
|
|
@@ -72,13 +72,7 @@ module RuboCop
|
|
|
72
72
|
|
|
73
73
|
message = message(node)
|
|
74
74
|
add_offense(node.loc.operator, message: message) do |corrector|
|
|
75
|
-
node.each_child_node
|
|
76
|
-
if expr.call_type?
|
|
77
|
-
correct_send(expr, corrector)
|
|
78
|
-
elsif expr.type?(:return, :next, :break, :yield) || expr.assignment?
|
|
79
|
-
correct_other(expr, corrector)
|
|
80
|
-
end
|
|
81
|
-
end
|
|
75
|
+
node.each_child_node { |expr| correct_operand(expr, corrector) }
|
|
82
76
|
|
|
83
77
|
corrector.replace(node.loc.operator, node.alternate_operator)
|
|
84
78
|
|
|
@@ -86,6 +80,22 @@ module RuboCop
|
|
|
86
80
|
end
|
|
87
81
|
end
|
|
88
82
|
|
|
83
|
+
def correct_operand(expr, corrector)
|
|
84
|
+
expr = expr.send_node if expr.any_block_type?
|
|
85
|
+
|
|
86
|
+
if expr.type?(:call, :super)
|
|
87
|
+
correct_send(expr, corrector)
|
|
88
|
+
elsif wrap_in_parentheses?(expr)
|
|
89
|
+
correct_other(expr, corrector)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# These bind looser than `&&` and `||`, or can't be their operands at all.
|
|
94
|
+
def wrap_in_parentheses?(node)
|
|
95
|
+
node.type?(:return, :next, :break, :yield, :any_match_pattern, :range, :defined?) ||
|
|
96
|
+
node.assignment? || (node.if_type? && node.ternary?)
|
|
97
|
+
end
|
|
98
|
+
|
|
89
99
|
def on_conditionals(node)
|
|
90
100
|
node.condition.each_node(*AST::Node::OPERATOR_KEYWORDS) do |operator|
|
|
91
101
|
process_logical_operator(operator)
|
|
@@ -101,6 +111,7 @@ module RuboCop
|
|
|
101
111
|
return correct_setter(node, corrector) if node.setter_method?
|
|
102
112
|
return correct_other(node, corrector) if node.comparison_method?
|
|
103
113
|
|
|
114
|
+
correct_block_receiver(node, corrector)
|
|
104
115
|
return unless correctable_send?(node)
|
|
105
116
|
|
|
106
117
|
whitespace_before_arg_range = whitespace_before_arg(node)
|
|
@@ -120,7 +131,8 @@ module RuboCop
|
|
|
120
131
|
# however, 'not x' also parses as (send x :!)
|
|
121
132
|
def correct_not(node, receiver, corrector)
|
|
122
133
|
if node.prefix_bang?
|
|
123
|
-
|
|
134
|
+
receiver = receiver.send_node if receiver.any_block_type?
|
|
135
|
+
return unless receiver.type?(:call, :super)
|
|
124
136
|
|
|
125
137
|
correct_send(receiver, corrector)
|
|
126
138
|
elsif node.prefix_not?
|
|
@@ -145,12 +157,23 @@ module RuboCop
|
|
|
145
157
|
end
|
|
146
158
|
end
|
|
147
159
|
|
|
160
|
+
# A method chained onto a `do` block, as in `bar baz do ... end.qux`,
|
|
161
|
+
# still needs parentheses around the arguments of the call that takes the block.
|
|
162
|
+
def correct_block_receiver(node, corrector)
|
|
163
|
+
receiver = node.receiver
|
|
164
|
+
receiver = receiver.receiver while receiver&.call_type?
|
|
165
|
+
correct_operand(receiver, corrector) if receiver&.any_block_type?
|
|
166
|
+
end
|
|
167
|
+
|
|
148
168
|
def correctable_send?(node)
|
|
149
|
-
|
|
169
|
+
# Operator syntax such as `a + b` or `a[b]` already binds tighter than `&&` and `||`.
|
|
170
|
+
return false if node.operator_method? && !node.loc.dot
|
|
171
|
+
|
|
172
|
+
!node.parenthesized? && node.arguments?
|
|
150
173
|
end
|
|
151
174
|
|
|
152
175
|
def whitespace_before_arg(node)
|
|
153
|
-
begin_paren = node.
|
|
176
|
+
begin_paren = node.selector.end_pos
|
|
154
177
|
end_paren = begin_paren
|
|
155
178
|
# Increment position of parenthesis, unless message is a predicate
|
|
156
179
|
# method followed by a non-whitespace char (e.g. is_a?String).
|
|
@@ -7,7 +7,7 @@ module RuboCop
|
|
|
7
7
|
# The `===` operator has different behavior depending on the
|
|
8
8
|
# receiver and its use outside of `case`/`when` is confusing.
|
|
9
9
|
# Prefer more explicit alternatives like `is_a?`, `include?`,
|
|
10
|
-
# or `match?`.
|
|
10
|
+
# `cover?`, or `match?`.
|
|
11
11
|
#
|
|
12
12
|
# If `AllowOnConstant` option is enabled, the cop will ignore violations when the receiver of
|
|
13
13
|
# the case equality operator is a constant.
|
|
@@ -22,9 +22,11 @@ module RuboCop
|
|
|
22
22
|
# @example
|
|
23
23
|
# # bad
|
|
24
24
|
# (1..100) === 7
|
|
25
|
+
# ('a'..'z') === char
|
|
25
26
|
#
|
|
26
27
|
# # good
|
|
27
28
|
# (1..100).include?(7)
|
|
29
|
+
# ('a'..'z').cover?(char)
|
|
28
30
|
#
|
|
29
31
|
# @example AllowOnConstant: false (default)
|
|
30
32
|
# # bad
|
|
@@ -90,9 +92,18 @@ module RuboCop
|
|
|
90
92
|
end
|
|
91
93
|
|
|
92
94
|
def begin_replacement(lhs, rhs)
|
|
93
|
-
|
|
95
|
+
range = lhs.children.first
|
|
96
|
+
return unless range&.range_type?
|
|
94
97
|
|
|
95
|
-
|
|
98
|
+
method = cover_semantics?(range) ? 'cover?' : 'include?'
|
|
99
|
+
|
|
100
|
+
"#{lhs.source}.#{method}(#{rhs.source})"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# `Range#===` behaves like `Range#cover?` since Ruby 2.7 (since Ruby 2.6 for ranges
|
|
104
|
+
# that aren't string ranges), and `Range#include?` only matches that for numeric ranges.
|
|
105
|
+
def cover_semantics?(range)
|
|
106
|
+
target_ruby_version >= 2.7 && !range.children.compact.all?(&:numeric_type?)
|
|
96
107
|
end
|
|
97
108
|
|
|
98
109
|
def const_replacement(lhs, rhs)
|
|
@@ -65,10 +65,11 @@ module RuboCop
|
|
|
65
65
|
NESTED_MSG = 'Use nested module/class definitions instead of compact style.'
|
|
66
66
|
COMPACT_MSG = 'Use compact module/class definition instead of nested style.'
|
|
67
67
|
|
|
68
|
-
# `Style/StructInheritance`
|
|
69
|
-
# the same pass, which the compacted `class` keyword would
|
|
68
|
+
# `Style/StructInheritance` and `Style/DataInheritance` turn a class definition into
|
|
69
|
+
# a constant assignment in the same pass, which the compacted `class` keyword would
|
|
70
|
+
# then precede.
|
|
70
71
|
def self.autocorrect_incompatible_with
|
|
71
|
-
[Style::StructInheritance]
|
|
72
|
+
[Style::DataInheritance, Style::StructInheritance]
|
|
72
73
|
end
|
|
73
74
|
|
|
74
75
|
def on_class(node)
|
|
@@ -151,8 +151,17 @@ module RuboCop
|
|
|
151
151
|
# which an endless definition cannot hold.
|
|
152
152
|
# `Style/RaiseArgs` would drop the parentheses of a `raise` that becomes
|
|
153
153
|
# the body in the same pass, which a method passed as an argument needs.
|
|
154
|
+
# `Style/IfUnlessModifier` and `Style/WhileUntilModifier` would turn the body into
|
|
155
|
+
# a modifier form, which then applies to the whole endless definition.
|
|
154
156
|
def self.autocorrect_incompatible_with
|
|
155
|
-
[
|
|
157
|
+
[
|
|
158
|
+
Style::GuardClause,
|
|
159
|
+
Style::IfUnlessModifier,
|
|
160
|
+
Style::MethodCallWithArgsParentheses,
|
|
161
|
+
Style::MethodDefParentheses,
|
|
162
|
+
Style::RaiseArgs,
|
|
163
|
+
Style::WhileUntilModifier
|
|
164
|
+
]
|
|
156
165
|
end
|
|
157
166
|
|
|
158
167
|
def on_def(node)
|
|
@@ -189,9 +198,7 @@ module RuboCop
|
|
|
189
198
|
add_offense(node, message: MSG_MULTI_LINE) do |corrector|
|
|
190
199
|
correct_to_multiline(corrector, node)
|
|
191
200
|
end
|
|
192
|
-
elsif
|
|
193
|
-
return if too_long_when_made_endless?(node)
|
|
194
|
-
|
|
201
|
+
elsif convertible_to_endless?(node) && single_line_when_made_endless?(node)
|
|
195
202
|
add_offense(node, message: MSG_REQUIRE_SINGLE) do |corrector|
|
|
196
203
|
correct_to_endless(corrector, node)
|
|
197
204
|
end
|
|
@@ -199,14 +206,18 @@ module RuboCop
|
|
|
199
206
|
end
|
|
200
207
|
|
|
201
208
|
def handle_require_always_style(node)
|
|
202
|
-
return
|
|
203
|
-
return if too_long_when_made_endless?(node)
|
|
209
|
+
return unless convertible_to_endless?(node)
|
|
204
210
|
|
|
205
211
|
add_offense(node, message: MSG_REQUIRE_ALWAYS) do |corrector|
|
|
206
212
|
correct_to_endless(corrector, node)
|
|
207
213
|
end
|
|
208
214
|
end
|
|
209
215
|
|
|
216
|
+
def convertible_to_endless?(node)
|
|
217
|
+
!node.endless? && can_be_made_endless?(node) &&
|
|
218
|
+
!too_long_when_made_endless?(node) && !ambiguous_when_made_endless?(node)
|
|
219
|
+
end
|
|
220
|
+
|
|
210
221
|
def handle_disallow_style(node)
|
|
211
222
|
return unless node.endless?
|
|
212
223
|
|
|
@@ -297,6 +308,23 @@ module RuboCop
|
|
|
297
308
|
!endless_replacement(node).include?("\n")
|
|
298
309
|
end
|
|
299
310
|
|
|
311
|
+
def ambiguous_when_made_endless?(node)
|
|
312
|
+
(operation = ambiguous_operation(node)) && ambiguous_enclosing_operation?(operation)
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# @!method ambiguous_operation(node)
|
|
316
|
+
def_node_matcher :ambiguous_operation, <<~PATTERN
|
|
317
|
+
^${
|
|
318
|
+
(if _ <any_def _>)
|
|
319
|
+
({and or} any_def _)
|
|
320
|
+
({while until} _ any_def)
|
|
321
|
+
}
|
|
322
|
+
PATTERN
|
|
323
|
+
|
|
324
|
+
def ambiguous_enclosing_operation?(operation)
|
|
325
|
+
operation.operator_keyword? || operation.modifier_form?
|
|
326
|
+
end
|
|
327
|
+
|
|
300
328
|
def too_long_when_made_endless?(node)
|
|
301
329
|
return false unless config.cop_enabled?('Layout/LineLength')
|
|
302
330
|
|
|
@@ -146,11 +146,26 @@ module RuboCop
|
|
|
146
146
|
end
|
|
147
147
|
|
|
148
148
|
def comment_before_to_f?(node)
|
|
149
|
+
return true if comment_around_fdiv_operator?(node)
|
|
150
|
+
|
|
149
151
|
operands_losing_to_f(node).any? do |operand|
|
|
150
152
|
next false unless to_f_method?(operand)
|
|
151
153
|
|
|
152
154
|
range = operand.receiver.source_range.end.join(operand.loc.selector.begin)
|
|
153
|
-
|
|
155
|
+
comment_in_range?(range)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def comment_around_fdiv_operator?(node)
|
|
160
|
+
return false unless style == :fdiv
|
|
161
|
+
|
|
162
|
+
range = node.receiver.source_range.end.join(node.first_argument.source_range.begin)
|
|
163
|
+
comment_in_range?(range)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def comment_in_range?(range)
|
|
167
|
+
processed_source.each_comment_in_lines(range.line..range.last_line).any? do |comment|
|
|
168
|
+
range.contains?(comment.source_range)
|
|
154
169
|
end
|
|
155
170
|
end
|
|
156
171
|
|
|
@@ -90,9 +90,19 @@ module RuboCop
|
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
def exempt_from_brackets?(node)
|
|
93
|
+
return true if forwarded_or_splatted?(node.first_argument)
|
|
94
|
+
|
|
93
95
|
comment_before_dot?(node) || env_fetch_preferred?(node.receiver)
|
|
94
96
|
end
|
|
95
97
|
|
|
98
|
+
def forwarded_or_splatted?(argument)
|
|
99
|
+
if argument.hash_type? && !argument.braces?
|
|
100
|
+
argument.children.any? { |child| child.type?(:kwsplat, :forwarded_kwrestarg) }
|
|
101
|
+
else
|
|
102
|
+
argument.type?(:forwarded_args, :forwarded_restarg, :splat, :block_pass)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
96
106
|
def comment_before_dot?(node)
|
|
97
107
|
processed_source.contains_comment?(node.receiver.source_range.end.join(node.loc.dot))
|
|
98
108
|
end
|
|
@@ -169,12 +169,20 @@ module RuboCop
|
|
|
169
169
|
location = node.arguments.source_range
|
|
170
170
|
|
|
171
171
|
add_offense(location, message: MSG_MISSING) do |corrector|
|
|
172
|
-
|
|
172
|
+
corrector.replace(range_before_arguments(node), '(')
|
|
173
|
+
corrector.insert_after(location, ')')
|
|
173
174
|
|
|
174
175
|
unexpected_style_detected 'require_no_parentheses'
|
|
175
176
|
end
|
|
176
177
|
end
|
|
177
178
|
|
|
179
|
+
def range_before_arguments(node)
|
|
180
|
+
range = node.loc.name.end.join(node.arguments.source_range.begin)
|
|
181
|
+
last_line_break = range.source.rindex("\n")
|
|
182
|
+
|
|
183
|
+
last_line_break ? range.resize(last_line_break) : range
|
|
184
|
+
end
|
|
185
|
+
|
|
178
186
|
def unwanted_parentheses(args)
|
|
179
187
|
add_offense(args, message: MSG_PRESENT) do |corrector|
|
|
180
188
|
# offense is registered on args node when parentheses are unwanted
|
|
@@ -99,7 +99,10 @@ module RuboCop
|
|
|
99
99
|
|
|
100
100
|
message = format(MSG, prefer: replacement, current: node.source)
|
|
101
101
|
add_offense(node, message: message) do |corrector|
|
|
102
|
+
next if inside_corrected_predicate?(node)
|
|
103
|
+
|
|
102
104
|
corrector.replace(node, replacement)
|
|
105
|
+
ignore_node(node)
|
|
103
106
|
end
|
|
104
107
|
end
|
|
105
108
|
|
|
@@ -115,6 +118,10 @@ module RuboCop
|
|
|
115
118
|
BitwisePredicate.support_target_ruby_version?(target_ruby_version)
|
|
116
119
|
end
|
|
117
120
|
|
|
121
|
+
def inside_corrected_predicate?(node)
|
|
122
|
+
node.each_ancestor(:send).any? { |ancestor| ignored_node?(ancestor) }
|
|
123
|
+
end
|
|
124
|
+
|
|
118
125
|
def check(node)
|
|
119
126
|
numeric, operator =
|
|
120
127
|
if style == :predicate
|
|
@@ -84,6 +84,7 @@ module RuboCop
|
|
|
84
84
|
return if require_parentheses?(node, first_child)
|
|
85
85
|
return if semicolon_separated_expressions?(first_child, rest_children)
|
|
86
86
|
return if modifier_op?(first_child) || first_child.masgn_type?
|
|
87
|
+
return if command_call_assignment?(first_child)
|
|
87
88
|
return if parens_allowed?(cond)
|
|
88
89
|
|
|
89
90
|
message = message(cond)
|
|
@@ -115,6 +116,23 @@ module RuboCop
|
|
|
115
116
|
node.basic_conditional? && node.modifier_form?
|
|
116
117
|
end
|
|
117
118
|
|
|
119
|
+
def command_call_assignment?(node)
|
|
120
|
+
return false if !node.assignment? && !setter_method?(node)
|
|
121
|
+
|
|
122
|
+
value = node.children.last
|
|
123
|
+
value = value.body if value.rescue_type?
|
|
124
|
+
|
|
125
|
+
command_call_assignment?(value) || command_call?(value)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def command_call?(node)
|
|
129
|
+
node = node.send_node if node.any_block_type?
|
|
130
|
+
return false if !node.type?(:call, :super, :yield) || !node.arguments?
|
|
131
|
+
return false if node.parenthesized? || node.operator_method? || node.setter_method?
|
|
132
|
+
|
|
133
|
+
!node.method?(:[])
|
|
134
|
+
end
|
|
135
|
+
|
|
118
136
|
def message(node)
|
|
119
137
|
kw = node.parent.keyword
|
|
120
138
|
article = kw == 'while' ? 'a' : 'an'
|
|
@@ -86,14 +86,12 @@ module RuboCop
|
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
def correct_quotes(str)
|
|
89
|
-
correction = if style == :single_quotes
|
|
90
|
-
to_string_literal(str)
|
|
91
|
-
else
|
|
92
|
-
str.gsub("\\'", "'").inspect
|
|
93
|
-
end
|
|
94
|
-
|
|
95
89
|
# The conversion process doubles escaped slashes, so they have to be reverted
|
|
96
|
-
|
|
90
|
+
if style == :single_quotes
|
|
91
|
+
to_string_literal(str).gsub('\\\\', '\\').gsub('\"', '"')
|
|
92
|
+
else
|
|
93
|
+
str.gsub("\\'", "'").inspect.gsub('\\\\', '\\')
|
|
94
|
+
end
|
|
97
95
|
end
|
|
98
96
|
|
|
99
97
|
def style
|