rubocop 1.36.0 → 1.37.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 +21 -1
- data/lib/rubocop/arguments_env.rb +17 -0
- data/lib/rubocop/arguments_file.rb +17 -0
- data/lib/rubocop/cli/command/execute_runner.rb +7 -7
- data/lib/rubocop/cop/generator.rb +1 -2
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +28 -3
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +11 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
- data/lib/rubocop/cop/lint/empty_class.rb +3 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +19 -7
- data/lib/rubocop/cop/lint/nested_method_definition.rb +50 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +12 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +29 -9
- data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -2
- data/lib/rubocop/cop/lint/shadowed_exception.rb +0 -10
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +3 -0
- data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
- data/lib/rubocop/cop/lint/unused_method_argument.rb +4 -0
- data/lib/rubocop/cop/mixin/comments_help.rb +12 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +6 -3
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +6 -5
- data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +21 -1
- data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
- data/lib/rubocop/cop/style/block_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
- data/lib/rubocop/cop/style/collection_compact.rb +6 -1
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +4 -0
- data/lib/rubocop/cop/style/format_string_token.rb +1 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +13 -2
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +39 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +5 -2
- data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +8 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +173 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
- data/lib/rubocop/cop/style/static_class.rb +32 -1
- data/lib/rubocop/cop/style/symbol_array.rb +2 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +2 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +8 -2
- data/lib/rubocop/options.rb +13 -13
- data/lib/rubocop/rspec/shared_contexts.rb +13 -1
- data/lib/rubocop/server/cache.rb +5 -1
- data/lib/rubocop/server/cli.rb +9 -2
- data/lib/rubocop/server/client_command/exec.rb +5 -0
- data/lib/rubocop/server/core.rb +2 -1
- data/lib/rubocop/server/socket_reader.rb +5 -1
- data/lib/rubocop/server.rb +1 -1
- data/lib/rubocop/version.rb +8 -3
- data/lib/rubocop.rb +3 -0
- metadata +10 -5
@@ -209,7 +209,12 @@ module RuboCop
|
|
209
209
|
|
210
210
|
add_offense(location, message: message(cop_names)) do |corrector|
|
211
211
|
range = comment_range_with_surrounding_space(location, comment.loc.expression)
|
212
|
-
|
212
|
+
|
213
|
+
if leave_free_comment?(comment, range)
|
214
|
+
corrector.replace(range, ' # ')
|
215
|
+
else
|
216
|
+
corrector.remove(range)
|
217
|
+
end
|
213
218
|
end
|
214
219
|
end
|
215
220
|
|
@@ -227,6 +232,12 @@ module RuboCop
|
|
227
232
|
end
|
228
233
|
end
|
229
234
|
|
235
|
+
def leave_free_comment?(comment, range)
|
236
|
+
free_comment = comment.text.gsub(range.source.strip, '')
|
237
|
+
|
238
|
+
!free_comment.empty? && !free_comment.start_with?('#')
|
239
|
+
end
|
240
|
+
|
230
241
|
def cop_range(comment, cop)
|
231
242
|
cop = remove_department_marker(cop)
|
232
243
|
matching_range(comment.loc.expression, cop) ||
|
@@ -41,6 +41,7 @@ module RuboCop
|
|
41
41
|
return unless (receiver = node.receiver)
|
42
42
|
return unless receiver.receiver&.const_type? && receiver.receiver.short_name == :Dir
|
43
43
|
return unless GLOB_METHODS.include?(receiver.method_name)
|
44
|
+
return if multiple_argument?(receiver)
|
44
45
|
|
45
46
|
selector = node.loc.selector
|
46
47
|
|
@@ -49,6 +50,12 @@ module RuboCop
|
|
49
50
|
corrector.remove(node.loc.dot)
|
50
51
|
end
|
51
52
|
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def multiple_argument?(glob_method)
|
57
|
+
glob_method.arguments.count >= 2 || glob_method.first_argument&.splat_type?
|
58
|
+
end
|
52
59
|
end
|
53
60
|
end
|
54
61
|
end
|
@@ -6,13 +6,22 @@ module RuboCop
|
|
6
6
|
# Checks for unnecessary `require` statement.
|
7
7
|
#
|
8
8
|
# The following features are unnecessary `require` statement because
|
9
|
-
# they are already loaded.
|
9
|
+
# they are already loaded. e.g. Ruby 2.2:
|
10
10
|
#
|
11
11
|
# ruby -ve 'p $LOADED_FEATURES.reject { |feature| %r|/| =~ feature }'
|
12
12
|
# ruby 2.2.8p477 (2017-09-14 revision 59906) [x86_64-darwin13]
|
13
13
|
# ["enumerator.so", "rational.so", "complex.so", "thread.rb"]
|
14
14
|
#
|
15
|
-
#
|
15
|
+
# Below are the features that each `TargetRubyVersion` targets.
|
16
|
+
#
|
17
|
+
# * 2.0+ ... `enumerator`
|
18
|
+
# * 2.1+ ... `thread`
|
19
|
+
# * 2.2+ ... Add `rational` and `complex` above
|
20
|
+
# * 2.5+ ... Add `pp` above
|
21
|
+
# * 2.7+ ... Add `ruby2_keywords` above
|
22
|
+
# * 3.1+ ... Add `fiber` above
|
23
|
+
#
|
24
|
+
# This cop target those features.
|
16
25
|
#
|
17
26
|
# @example
|
18
27
|
# # bad
|
@@ -24,21 +33,19 @@ module RuboCop
|
|
24
33
|
class RedundantRequireStatement < Base
|
25
34
|
include RangeHelp
|
26
35
|
extend AutoCorrector
|
27
|
-
extend TargetRubyVersion
|
28
|
-
|
29
|
-
minimum_target_ruby_version 2.2
|
30
36
|
|
31
37
|
MSG = 'Remove unnecessary `require` statement.'
|
32
38
|
RESTRICT_ON_SEND = %i[require].freeze
|
39
|
+
RUBY_22_LOADED_FEATURES = %w[rational complex].freeze
|
33
40
|
|
34
|
-
# @!method
|
35
|
-
def_node_matcher :
|
41
|
+
# @!method redundant_require_statement?(node)
|
42
|
+
def_node_matcher :redundant_require_statement?, <<~PATTERN
|
36
43
|
(send nil? :require
|
37
|
-
(str
|
44
|
+
(str #redundant_feature?))
|
38
45
|
PATTERN
|
39
46
|
|
40
47
|
def on_send(node)
|
41
|
-
return unless
|
48
|
+
return unless redundant_require_statement?(node)
|
42
49
|
|
43
50
|
add_offense(node) do |corrector|
|
44
51
|
range = range_with_surrounding_space(node.loc.expression, side: :right)
|
@@ -46,6 +53,19 @@ module RuboCop
|
|
46
53
|
corrector.remove(range)
|
47
54
|
end
|
48
55
|
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
60
|
+
def redundant_feature?(feature_name)
|
61
|
+
feature_name == 'enumerator' ||
|
62
|
+
(target_ruby_version >= 2.1 && feature_name == 'thread') ||
|
63
|
+
(target_ruby_version >= 2.2 && RUBY_22_LOADED_FEATURES.include?(feature_name)) ||
|
64
|
+
(target_ruby_version >= 2.5 && feature_name == 'pp') ||
|
65
|
+
(target_ruby_version >= 2.7 && feature_name == 'ruby2_keywords') ||
|
66
|
+
(target_ruby_version >= 3.1 && feature_name == 'fiber')
|
67
|
+
end
|
68
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
49
69
|
end
|
50
70
|
end
|
51
71
|
end
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
46
46
|
private
|
47
47
|
|
48
48
|
def check_ternary(ternary, node)
|
49
|
-
return
|
49
|
+
return if node.method?(:[]) || !ternary.condition.operator_keyword?
|
50
50
|
|
51
51
|
range = range_between(node.source_range.begin_pos, ternary.condition.source_range.end_pos)
|
52
52
|
|
@@ -31,6 +31,7 @@ module RuboCop
|
|
31
31
|
minimum_target_ruby_version 2.3
|
32
32
|
|
33
33
|
MSG = 'Do not chain ordinary method call after safe navigation operator.'
|
34
|
+
PLUS_MINUS_METHODS = %i[+@ -@].freeze
|
34
35
|
|
35
36
|
# @!method bad_method?(node)
|
36
37
|
def_node_matcher :bad_method?, <<~PATTERN
|
@@ -42,7 +43,7 @@ module RuboCop
|
|
42
43
|
|
43
44
|
def on_send(node)
|
44
45
|
bad_method?(node) do |safe_nav, method|
|
45
|
-
return if nil_methods.include?(method)
|
46
|
+
return if nil_methods.include?(method) || PLUS_MINUS_METHODS.include?(node.method_name)
|
46
47
|
|
47
48
|
method_chain = method_chain(node)
|
48
49
|
location =
|
@@ -71,7 +72,7 @@ module RuboCop
|
|
71
72
|
else
|
72
73
|
offense_range.source.dup
|
73
74
|
end
|
74
|
-
source.prepend('.') unless
|
75
|
+
source.prepend('.') unless source.start_with?('.')
|
75
76
|
source.prepend('&')
|
76
77
|
end
|
77
78
|
|
@@ -155,16 +155,6 @@ module RuboCop
|
|
155
155
|
end
|
156
156
|
end
|
157
157
|
|
158
|
-
# @param [RuboCop::AST::Node] rescue_group is a node of array_type
|
159
|
-
def rescued_exceptions(rescue_group)
|
160
|
-
klasses = *rescue_group
|
161
|
-
klasses.map do |klass|
|
162
|
-
next unless klass.const_type?
|
163
|
-
|
164
|
-
klass.source
|
165
|
-
end.compact
|
166
|
-
end
|
167
|
-
|
168
158
|
def find_shadowing_rescue(rescues)
|
169
159
|
rescued_groups = rescued_groups_for(rescues)
|
170
160
|
rescued_groups.zip(rescues).each do |group, res|
|
@@ -12,9 +12,12 @@ module RuboCop
|
|
12
12
|
# because `Ractor` should not access outer variables.
|
13
13
|
# eg. following style is encouraged:
|
14
14
|
#
|
15
|
+
# [source,ruby]
|
16
|
+
# ----
|
15
17
|
# worker_id, pipe = env
|
16
18
|
# Ractor.new(worker_id, pipe) do |worker_id, pipe|
|
17
19
|
# end
|
20
|
+
# ----
|
18
21
|
#
|
19
22
|
# @example
|
20
23
|
#
|
@@ -79,7 +79,7 @@ module RuboCop
|
|
79
79
|
# # bad
|
80
80
|
# 2.times { raise ArgumentError }
|
81
81
|
#
|
82
|
-
# @example AllowedPatterns: [
|
82
|
+
# @example AllowedPatterns: ['(exactly|at_least|at_most)\(\d+\)\.times'] (default)
|
83
83
|
#
|
84
84
|
# # good
|
85
85
|
# exactly(2).times { raise StandardError }
|
@@ -22,6 +22,18 @@ module RuboCop
|
|
22
22
|
processed_source.each_comment_in_lines(start_line...end_line)
|
23
23
|
end
|
24
24
|
|
25
|
+
def comments_contain_disables?(node, cop_name)
|
26
|
+
disabled_ranges = processed_source.disabled_line_ranges[cop_name]
|
27
|
+
|
28
|
+
return unless disabled_ranges
|
29
|
+
|
30
|
+
node_range = node.source_range.line...find_end_line(node)
|
31
|
+
|
32
|
+
disabled_ranges.any? do |disable_range|
|
33
|
+
disable_range.cover?(node_range) || node_range.cover?(disable_range)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
25
37
|
private
|
26
38
|
|
27
39
|
def end_position_for(node)
|
@@ -96,11 +96,14 @@ module RuboCop
|
|
96
96
|
end
|
97
97
|
|
98
98
|
def without_parentheses_call_expr_follows?(ancestor)
|
99
|
+
return false unless ancestor.respond_to?(:parenthesized?) && !ancestor.parenthesized?
|
100
|
+
|
99
101
|
right_sibling = ancestor.right_sibling
|
100
|
-
right_sibling ||= ancestor.each_ancestor.find
|
101
|
-
|
102
|
+
right_sibling ||= ancestor.each_ancestor.find do |node|
|
103
|
+
node.assignment? || node.send_type?
|
104
|
+
end&.right_sibling
|
102
105
|
|
103
|
-
|
106
|
+
!!right_sibling
|
104
107
|
end
|
105
108
|
|
106
109
|
def breakdown_value_types_of_hash(hash_node)
|
@@ -11,7 +11,9 @@ module RuboCop
|
|
11
11
|
private
|
12
12
|
|
13
13
|
def rescue_modifier?(node)
|
14
|
-
|
14
|
+
return false unless node.respond_to?(:resbody_type?)
|
15
|
+
|
16
|
+
node.resbody_type? && @modifier_locations.include?(node.loc.keyword)
|
15
17
|
end
|
16
18
|
|
17
19
|
# @deprecated Use ResbodyNode#exceptions instead
|
@@ -13,7 +13,7 @@ module RuboCop
|
|
13
13
|
|
14
14
|
private
|
15
15
|
|
16
|
-
def side_space_range(range:, side:)
|
16
|
+
def side_space_range(range:, side:, include_newlines: false)
|
17
17
|
buffer = processed_source.buffer
|
18
18
|
src = buffer.source
|
19
19
|
|
@@ -21,11 +21,11 @@ module RuboCop
|
|
21
21
|
end_pos = range.end_pos
|
22
22
|
if side == :left
|
23
23
|
end_pos = begin_pos
|
24
|
-
begin_pos = reposition(src, begin_pos, -1)
|
24
|
+
begin_pos = reposition(src, begin_pos, -1, include_newlines: include_newlines)
|
25
25
|
end
|
26
26
|
if side == :right
|
27
27
|
begin_pos = end_pos
|
28
|
-
end_pos = reposition(src, end_pos, 1)
|
28
|
+
end_pos = reposition(src, end_pos, 1, include_newlines: include_newlines)
|
29
29
|
end
|
30
30
|
Parser::Source::Range.new(buffer, begin_pos, end_pos)
|
31
31
|
end
|
@@ -75,9 +75,10 @@ module RuboCop
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
def reposition(src, pos, step)
|
78
|
+
def reposition(src, pos, step, include_newlines: false)
|
79
79
|
offset = step == -1 ? -1 : 0
|
80
|
-
pos += step while SINGLE_SPACE_REGEXP.match?(src[pos + offset])
|
80
|
+
pos += step while SINGLE_SPACE_REGEXP.match?(src[pos + offset]) ||
|
81
|
+
(include_newlines && src[pos + offset] == "\n")
|
81
82
|
pos.negative? ? 0 : pos
|
82
83
|
end
|
83
84
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Naming
|
6
|
-
#
|
6
|
+
# Recommends the use of inclusive language instead of problematic terms.
|
7
7
|
# The cop can check the following locations for offenses:
|
8
8
|
# - identifiers
|
9
9
|
# - constants
|
@@ -183,6 +183,7 @@ module RuboCop
|
|
183
183
|
end
|
184
184
|
|
185
185
|
def insert_def(corrector, node, source)
|
186
|
+
source = [*processed_source.ast_with_comments[node].map(&:text), source].join("\n")
|
186
187
|
argument_less_modifier_node = find_argument_less_modifier_node(node)
|
187
188
|
if argument_less_modifier_node
|
188
189
|
corrector.insert_after(argument_less_modifier_node, "\n\n#{source}")
|
@@ -201,11 +202,30 @@ module RuboCop
|
|
201
202
|
def remove_node(corrector, node)
|
202
203
|
corrector.remove(
|
203
204
|
range_by_whole_lines(
|
204
|
-
node
|
205
|
+
range_with_comments(node),
|
205
206
|
include_final_newline: true
|
206
207
|
)
|
207
208
|
)
|
208
209
|
end
|
210
|
+
|
211
|
+
def range_with_comments(node)
|
212
|
+
ranges = [
|
213
|
+
node,
|
214
|
+
*processed_source.ast_with_comments[node]
|
215
|
+
].map do |element|
|
216
|
+
element.location.expression
|
217
|
+
end
|
218
|
+
ranges.reduce do |result, range|
|
219
|
+
add_range(result, range)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def add_range(range1, range2)
|
224
|
+
range1.with(
|
225
|
+
begin_pos: [range1.begin_pos, range2.begin_pos].min,
|
226
|
+
end_pos: [range1.end_pos, range2.end_pos].max
|
227
|
+
)
|
228
|
+
end
|
209
229
|
end
|
210
230
|
end
|
211
231
|
end
|
@@ -135,12 +135,16 @@ module RuboCop
|
|
135
135
|
end
|
136
136
|
|
137
137
|
def separate_accessors(node)
|
138
|
-
node.arguments.
|
139
|
-
|
138
|
+
node.arguments.flat_map do |arg|
|
139
|
+
lines = [
|
140
|
+
*processed_source.ast_with_comments[arg].map(&:text),
|
140
141
|
"#{node.method_name} #{arg.source}"
|
142
|
+
]
|
143
|
+
if arg == node.arguments.first
|
144
|
+
lines
|
141
145
|
else
|
142
146
|
indent = ' ' * node.loc.column
|
143
|
-
"#{indent}#{
|
147
|
+
lines.map { |line| "#{indent}#{line}" }
|
144
148
|
end
|
145
149
|
end.join("\n")
|
146
150
|
end
|
@@ -36,8 +36,8 @@ module RuboCop
|
|
36
36
|
extend AutoCorrector
|
37
37
|
|
38
38
|
MSG = 'Use `%<good>s` instead of `%<bad>s`.'
|
39
|
-
|
40
39
|
RESTRICT_ON_SEND = %i[reject reject! select select!].freeze
|
40
|
+
TO_ENUM_METHODS = %i[to_enum lazy].freeze
|
41
41
|
|
42
42
|
# @!method reject_method_with_block_pass?(node)
|
43
43
|
def_node_matcher :reject_method_with_block_pass?, <<~PATTERN
|
@@ -69,6 +69,7 @@ module RuboCop
|
|
69
69
|
|
70
70
|
def on_send(node)
|
71
71
|
return unless (range = offense_range(node))
|
72
|
+
return if target_ruby_version <= 3.0 && to_enum_method?(node)
|
72
73
|
|
73
74
|
good = good_method_name(node)
|
74
75
|
message = format(MSG, good: good, bad: range.source)
|
@@ -94,6 +95,10 @@ module RuboCop
|
|
94
95
|
end
|
95
96
|
end
|
96
97
|
|
98
|
+
def to_enum_method?(node)
|
99
|
+
TO_ENUM_METHODS.include?(node.children.first.method_name)
|
100
|
+
end
|
101
|
+
|
97
102
|
def good_method_name(node)
|
98
103
|
if node.bang_method?
|
99
104
|
'compact!'
|
@@ -52,7 +52,7 @@ module RuboCop
|
|
52
52
|
MSG_EXPANDED = 'Put the `end` of empty method definitions on the next line.'
|
53
53
|
|
54
54
|
def on_def(node)
|
55
|
-
return if node.body ||
|
55
|
+
return if node.body || processed_source.contains_comment?(node.source_range)
|
56
56
|
return if correct_style?(node)
|
57
57
|
|
58
58
|
add_offense(node) do |corrector|
|
@@ -28,7 +28,7 @@ module RuboCop
|
|
28
28
|
# * always - forces use of the 3.1 syntax (e.g. {foo:})
|
29
29
|
# * never - forces use of explicit hash literal value
|
30
30
|
# * either - accepts both shorthand and explicit use of hash literal value
|
31
|
-
# * consistent - like "
|
31
|
+
# * consistent - like "either", but will avoid mixing styles in a single hash
|
32
32
|
#
|
33
33
|
# @example EnforcedStyle: ruby19 (default)
|
34
34
|
# # bad
|
@@ -20,8 +20,8 @@ module RuboCop
|
|
20
20
|
return if require_parentheses_for_hash_value_omission?(node)
|
21
21
|
return if syntax_like_method_call?(node)
|
22
22
|
return if super_call_without_arguments?(node)
|
23
|
-
return if allowed_camel_case_method_call?(node)
|
24
23
|
return if legitimate_call_with_parentheses?(node)
|
24
|
+
return if allowed_camel_case_method_call?(node)
|
25
25
|
return if allowed_string_interpolation_method_call?(node)
|
26
26
|
|
27
27
|
add_offense(offense_range(node), message: OMIT_MSG) do |corrector|
|
@@ -97,7 +97,8 @@ module RuboCop
|
|
97
97
|
call_in_optional_arguments?(node) ||
|
98
98
|
call_in_single_line_inheritance?(node) ||
|
99
99
|
allowed_multiline_call_with_parentheses?(node) ||
|
100
|
-
allowed_chained_call_with_parentheses?(node)
|
100
|
+
allowed_chained_call_with_parentheses?(node) ||
|
101
|
+
assignment_in_condition?(node)
|
101
102
|
end
|
102
103
|
|
103
104
|
def call_in_literals?(node)
|
@@ -202,6 +203,16 @@ module RuboCop
|
|
202
203
|
def inside_string_interpolation?(node)
|
203
204
|
node.ancestors.drop_while { |a| !a.begin_type? }.any?(&:dstr_type?)
|
204
205
|
end
|
206
|
+
|
207
|
+
def assignment_in_condition?(node)
|
208
|
+
parent = node.parent
|
209
|
+
return false unless parent
|
210
|
+
|
211
|
+
grandparent = parent.parent
|
212
|
+
return false unless grandparent
|
213
|
+
|
214
|
+
parent.assignment? && (grandparent.conditional? || grandparent.when_type?)
|
215
|
+
end
|
205
216
|
end
|
206
217
|
# rubocop:enable Metrics/ModuleLength, Metrics/CyclomaticComplexity
|
207
218
|
end
|
@@ -49,7 +49,8 @@ module RuboCop
|
|
49
49
|
def on_if(node)
|
50
50
|
return unless if_else?(node)
|
51
51
|
|
52
|
-
condition = node.condition
|
52
|
+
condition = unwrap_begin_nodes(node.condition)
|
53
|
+
|
53
54
|
return if double_negation?(condition) || !negated_condition?(condition)
|
54
55
|
|
55
56
|
type = node.ternary? ? 'ternary' : 'if-else'
|
@@ -71,6 +72,11 @@ module RuboCop
|
|
71
72
|
!node.elsif? && else_branch && (!else_branch.if_type? || !else_branch.elsif?)
|
72
73
|
end
|
73
74
|
|
75
|
+
def unwrap_begin_nodes(node)
|
76
|
+
node = node.children.first while node.begin_type? || node.kwbegin_type?
|
77
|
+
node
|
78
|
+
end
|
79
|
+
|
74
80
|
def negated_condition?(node)
|
75
81
|
node.send_type? &&
|
76
82
|
(node.negation_method? || NEGATED_EQUALITY_METHODS.include?(node.method_name))
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for redundant dot before operator method call.
|
7
|
+
# The target operator methods are `|`, `^`, `&`, `<=>`, `==`, `===`, `=~`, `>`, `>=`, `<`,
|
8
|
+
# `<=`, `<<`, `>>`, `+`, `-`, `*`, `/`, `%`, `**`, `~`, `!`, `!=`, and `!~`.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
# foo.+ bar
|
14
|
+
# foo.& bar
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# foo + bar
|
18
|
+
# foo & bar
|
19
|
+
#
|
20
|
+
class OperatorMethodCall < Base
|
21
|
+
extend AutoCorrector
|
22
|
+
|
23
|
+
MSG = 'Redundant dot detected.'
|
24
|
+
RESTRICT_ON_SEND = %i[| ^ & <=> == === =~ > >= < <= << >> + - * / % ** ~ ! != !~].freeze
|
25
|
+
|
26
|
+
def on_send(node)
|
27
|
+
return unless (dot = node.loc.dot)
|
28
|
+
|
29
|
+
_lhs, _op, rhs = *node
|
30
|
+
return if rhs.children.first
|
31
|
+
|
32
|
+
add_offense(dot) do |corrector|
|
33
|
+
corrector.replace(dot, ' ')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -145,11 +145,14 @@ module RuboCop
|
|
145
145
|
|
146
146
|
return false unless if_branch && else_branch
|
147
147
|
|
148
|
-
if_branch
|
149
|
-
else_branch.send_type? && else_branch.arguments.count == 1 &&
|
148
|
+
single_argument_method?(if_branch) && single_argument_method?(else_branch) &&
|
150
149
|
same_method?(if_branch, else_branch)
|
151
150
|
end
|
152
151
|
|
152
|
+
def single_argument_method?(node)
|
153
|
+
node.send_type? && !node.method?(:[]) && node.arguments.one?
|
154
|
+
end
|
155
|
+
|
153
156
|
def same_method?(if_branch, else_branch)
|
154
157
|
if_branch.method?(else_branch.method_name) && if_branch.receiver == else_branch.receiver
|
155
158
|
end
|
@@ -140,7 +140,9 @@ module RuboCop
|
|
140
140
|
end
|
141
141
|
|
142
142
|
def allow_comments?(node)
|
143
|
-
cop_config['AllowComments']
|
143
|
+
return false unless cop_config['AllowComments']
|
144
|
+
|
145
|
+
contains_comments?(node) && !comments_contain_disables?(node, name)
|
144
146
|
end
|
145
147
|
|
146
148
|
def same_args?(super_node, args)
|
@@ -74,7 +74,7 @@ module RuboCop
|
|
74
74
|
|
75
75
|
non_redundant =
|
76
76
|
whitespace_in_free_space_mode?(node, class_elem) ||
|
77
|
-
backslash_b?(class_elem) ||
|
77
|
+
backslash_b?(class_elem) || backslash_zero?(class_elem) ||
|
78
78
|
requires_escape_outside_char_class?(class_elem)
|
79
79
|
|
80
80
|
!non_redundant
|
@@ -104,6 +104,13 @@ module RuboCop
|
|
104
104
|
elem == '\b'
|
105
105
|
end
|
106
106
|
|
107
|
+
def backslash_zero?(elem)
|
108
|
+
# See https://github.com/rubocop/rubocop/issues/11067 for details - in short "\0" != "0" -
|
109
|
+
# the former means an Unicode code point `"\u0000"`, the latter a number character `"0"`.
|
110
|
+
# Similarly "\032" means "\u001A". Other numbers starting with "\0" can also be mentioned.
|
111
|
+
elem == '\0'
|
112
|
+
end
|
113
|
+
|
107
114
|
def requires_escape_outside_char_class?(elem)
|
108
115
|
REQUIRES_ESCAPE_OUTSIDE_CHAR_CLASS_CHARS.include?(elem)
|
109
116
|
end
|