rubocop 1.60.2 → 1.62.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/assets/output.css.erb +159 -0
- data/assets/output.html.erb +1 -160
- data/config/default.yml +41 -12
- data/lib/rubocop/cli/command/auto_generate_config.rb +12 -3
- data/lib/rubocop/cli/command/lsp.rb +2 -2
- data/lib/rubocop/cli.rb +6 -1
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_finder.rb +12 -2
- data/lib/rubocop/config_validator.rb +14 -5
- data/lib/rubocop/cop/autocorrect_logic.rb +6 -1
- data/lib/rubocop/cop/base.rb +17 -8
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +5 -13
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +5 -1
- data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +122 -28
- data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +14 -7
- data/lib/rubocop/cop/layout/end_alignment.rb +3 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +11 -3
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +14 -9
- data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -0
- data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
- data/lib/rubocop/cop/lint/script_permission.rb +3 -3
- data/lib/rubocop/cop/lint/syntax.rb +1 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +7 -2
- data/lib/rubocop/cop/lint/useless_times.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +6 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_name.rb +2 -2
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +29 -8
- data/lib/rubocop/cop/style/case_like_if.rb +1 -1
- data/lib/rubocop/cop/style/class_vars.rb +3 -3
- data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +4 -5
- data/lib/rubocop/cop/style/for.rb +2 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +1 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +6 -2
- data/lib/rubocop/cop/style/inverse_methods.rb +8 -8
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +10 -5
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +5 -8
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +10 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +4 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
- data/lib/rubocop/cop/style/object_then.rb +5 -3
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -3
- data/lib/rubocop/cop/style/raise_args.rb +4 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +2 -2
- data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +4 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +17 -6
- data/lib/rubocop/cop/style/redundant_return.rb +6 -0
- data/lib/rubocop/cop/style/sample.rb +1 -3
- data/lib/rubocop/cop/utils/regexp_ranges.rb +1 -1
- data/lib/rubocop/cops_documentation_generator.rb +4 -2
- data/lib/rubocop/directive_comment.rb +10 -8
- data/lib/rubocop/formatter/html_formatter.rb +30 -10
- data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
- data/lib/rubocop/lsp/logger.rb +1 -1
- data/lib/rubocop/lsp/routes.rb +1 -1
- data/lib/rubocop/lsp/runtime.rb +1 -1
- data/lib/rubocop/lsp/server.rb +5 -2
- data/lib/rubocop/lsp/severity.rb +1 -1
- data/lib/rubocop/lsp.rb +29 -0
- data/lib/rubocop/magic_comment.rb +1 -1
- data/lib/rubocop/options.rb +11 -0
- data/lib/rubocop/path_util.rb +6 -2
- data/lib/rubocop/rspec/cop_helper.rb +8 -2
- data/lib/rubocop/rspec/expect_offense.rb +8 -8
- data/lib/rubocop/rspec/shared_contexts.rb +36 -17
- data/lib/rubocop/rspec/support.rb +2 -1
- data/lib/rubocop/runner.rb +9 -2
- data/lib/rubocop/target_finder.rb +84 -78
- data/lib/rubocop/target_ruby.rb +82 -80
- data/lib/rubocop/version.rb +18 -3
- metadata +9 -6
@@ -5,7 +5,8 @@ module RuboCop
|
|
5
5
|
module Lint
|
6
6
|
# Checks for redundant safe navigation calls.
|
7
7
|
# Use cases where a constant, named in camel case for classes and modules is `nil` are rare,
|
8
|
-
# and an offense is not detected when the receiver is a
|
8
|
+
# and an offense is not detected when the receiver is a constant. The detection also applies
|
9
|
+
# to literal receivers, except for `nil`.
|
9
10
|
#
|
10
11
|
# For all receivers, the `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`,
|
11
12
|
# and `equal?` methods are checked by default.
|
@@ -76,10 +77,9 @@ module RuboCop
|
|
76
77
|
#
|
77
78
|
class RedundantSafeNavigation < Base
|
78
79
|
include AllowedMethods
|
79
|
-
include RangeHelp
|
80
80
|
extend AutoCorrector
|
81
81
|
|
82
|
-
MSG = 'Redundant safe navigation detected.'
|
82
|
+
MSG = 'Redundant safe navigation detected, use `.` instead.'
|
83
83
|
MSG_LITERAL = 'Redundant safe navigation with default literal detected.'
|
84
84
|
|
85
85
|
NIL_SPECIFIC_METHODS = (nil.methods - Object.new.methods).to_set.freeze
|
@@ -105,24 +105,23 @@ module RuboCop
|
|
105
105
|
|
106
106
|
# rubocop:disable Metrics/AbcSize
|
107
107
|
def on_csend(node)
|
108
|
-
unless
|
108
|
+
unless assume_receiver_instance_exists?(node.receiver)
|
109
109
|
return unless check?(node) && allowed_method?(node.method_name)
|
110
110
|
return if respond_to_nil_specific_method?(node)
|
111
111
|
end
|
112
112
|
|
113
|
-
range =
|
114
|
-
add_offense(range) { |corrector| corrector.replace(
|
113
|
+
range = node.loc.dot
|
114
|
+
add_offense(range) { |corrector| corrector.replace(range, '.') }
|
115
115
|
end
|
116
116
|
|
117
117
|
def on_or(node)
|
118
118
|
conversion_with_default?(node) do |send_node|
|
119
|
-
range =
|
119
|
+
range = send_node.loc.dot.begin.join(node.source_range.end)
|
120
120
|
|
121
121
|
add_offense(range, message: MSG_LITERAL) do |corrector|
|
122
122
|
corrector.replace(send_node.loc.dot, '.')
|
123
123
|
|
124
|
-
range_with_default =
|
125
|
-
node.source_range.end.end_pos)
|
124
|
+
range_with_default = node.lhs.source_range.end.begin.join(node.source_range.end)
|
126
125
|
corrector.remove(range_with_default)
|
127
126
|
end
|
128
127
|
end
|
@@ -131,6 +130,12 @@ module RuboCop
|
|
131
130
|
|
132
131
|
private
|
133
132
|
|
133
|
+
def assume_receiver_instance_exists?(receiver)
|
134
|
+
return true if receiver.const_type? && !receiver.source.match?(SNAKE_CASE)
|
135
|
+
|
136
|
+
receiver.literal? && !receiver.nil_type?
|
137
|
+
end
|
138
|
+
|
134
139
|
def check?(node)
|
135
140
|
parent = node.parent
|
136
141
|
return false unless parent
|
@@ -59,9 +59,7 @@ module RuboCop
|
|
59
59
|
|
60
60
|
def autocorrect(corrector, node)
|
61
61
|
rescued, _, _body = *node
|
62
|
-
range =
|
63
|
-
node.loc.keyword.end_pos,
|
64
|
-
rescued.source_range.end_pos)
|
62
|
+
range = node.loc.keyword.end.join(rescued.source_range.end)
|
65
63
|
|
66
64
|
corrector.replace(range, correction(*rescued))
|
67
65
|
end
|
@@ -46,14 +46,14 @@ module RuboCop
|
|
46
46
|
message = format_message_from(processed_source)
|
47
47
|
|
48
48
|
add_offense(comment, message: message) do
|
49
|
-
autocorrect
|
49
|
+
autocorrect if autocorrect_requested?
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
53
|
private
|
54
54
|
|
55
|
-
def autocorrect
|
56
|
-
FileUtils.chmod('+x',
|
55
|
+
def autocorrect
|
56
|
+
FileUtils.chmod('+x', processed_source.file_path)
|
57
57
|
end
|
58
58
|
|
59
59
|
def executable?(processed_source)
|
@@ -51,8 +51,13 @@ module RuboCop
|
|
51
51
|
enum_conversion_call?(node) do |method_node, arguments|
|
52
52
|
next if method_node.call_type? &&
|
53
53
|
!method_node.method?(:__method__) && !method_node.method?(:__callee__)
|
54
|
-
|
55
|
-
|
54
|
+
|
55
|
+
valid = if method_name?(method_node, def_node.method_name)
|
56
|
+
arguments_match?(arguments, def_node)
|
57
|
+
else
|
58
|
+
def_node.arguments.empty?
|
59
|
+
end
|
60
|
+
return if valid
|
56
61
|
|
57
62
|
add_offense(node)
|
58
63
|
end
|
@@ -100,7 +100,12 @@ module RuboCop
|
|
100
100
|
expressions = *node
|
101
101
|
expressions.pop unless in_void_context?(node)
|
102
102
|
expressions.each do |expr|
|
103
|
-
check_void_op(expr)
|
103
|
+
check_void_op(expr) do
|
104
|
+
block_node = node.each_ancestor(:block).first
|
105
|
+
|
106
|
+
block_node&.method?(:each)
|
107
|
+
end
|
108
|
+
|
104
109
|
check_expression(expr)
|
105
110
|
end
|
106
111
|
end
|
@@ -189,7 +189,7 @@ module RuboCop
|
|
189
189
|
case node.type
|
190
190
|
when :casgn then _scope, _lhs, rhs = *node
|
191
191
|
when :op_asgn then _lhs, _op, rhs = *node
|
192
|
-
when :send
|
192
|
+
when :send, :csend then rhs = node.last_argument
|
193
193
|
else _lhs, rhs = *node
|
194
194
|
end
|
195
195
|
rhs
|
@@ -99,7 +99,7 @@ module RuboCop
|
|
99
99
|
!(method_name.start_with?(prefix) && # cheap check to avoid allocating Regexp
|
100
100
|
method_name.match?(/^#{prefix}[^0-9]/)) ||
|
101
101
|
method_name == expected_name(method_name, prefix) ||
|
102
|
-
method_name.end_with?('=') ||
|
102
|
+
method_name.end_with?('=') ||
|
103
103
|
allowed_method?(method_name)
|
104
104
|
end
|
105
105
|
|
@@ -109,7 +109,7 @@ module RuboCop
|
|
109
109
|
else
|
110
110
|
method_name.dup
|
111
111
|
end
|
112
|
-
new_name << '?' unless method_name.end_with?('?')
|
112
|
+
new_name << '?' unless method_name.end_with?('?')
|
113
113
|
new_name
|
114
114
|
end
|
115
115
|
|
data/lib/rubocop/cop/registry.rb
CHANGED
@@ -300,7 +300,7 @@ module RuboCop
|
|
300
300
|
unless given_badge.match?(real_badge)
|
301
301
|
path = PathUtil.smart_path(source_path)
|
302
302
|
warn "#{path}: #{given_badge} has the wrong namespace - " \
|
303
|
-
"
|
303
|
+
"replace it with #{given_badge.with_department(real_badge.department)}"
|
304
304
|
end
|
305
305
|
|
306
306
|
real_badge.to_s
|
@@ -8,6 +8,12 @@ module RuboCop
|
|
8
8
|
# This cop identifies places where `do_something(*args, &block)`
|
9
9
|
# can be replaced by `do_something(...)`.
|
10
10
|
#
|
11
|
+
# In Ruby 3.1, anonymous block forwarding has been added.
|
12
|
+
#
|
13
|
+
# This cop identifies places where `do_something(&block)` can be replaced
|
14
|
+
# by `do_something(&)`; if desired, this functionality can be disabled
|
15
|
+
# by setting `UseAnonymousForwarding: false`.
|
16
|
+
#
|
11
17
|
# In Ruby 3.2, anonymous args/kwargs forwarding has been added.
|
12
18
|
#
|
13
19
|
# This cop also identifies places where `use_args(*args)`/`use_kwargs(**kwargs)` can be
|
@@ -41,22 +47,25 @@ module RuboCop
|
|
41
47
|
#
|
42
48
|
# @example UseAnonymousForwarding: true (default, only relevant for Ruby >= 3.2)
|
43
49
|
# # bad
|
44
|
-
# def foo(*args, **kwargs)
|
50
|
+
# def foo(*args, **kwargs, &block)
|
45
51
|
# args_only(*args)
|
46
52
|
# kwargs_only(**kwargs)
|
53
|
+
# block_only(&block)
|
47
54
|
# end
|
48
55
|
#
|
49
56
|
# # good
|
50
|
-
# def foo(*,
|
57
|
+
# def foo(*, **, &)
|
51
58
|
# args_only(*)
|
52
59
|
# kwargs_only(**)
|
60
|
+
# block_only(&)
|
53
61
|
# end
|
54
62
|
#
|
55
63
|
# @example UseAnonymousForwarding: false (only relevant for Ruby >= 3.2)
|
56
64
|
# # good
|
57
|
-
# def foo(*args, **kwargs)
|
65
|
+
# def foo(*args, **kwargs, &block)
|
58
66
|
# args_only(*args)
|
59
67
|
# kwargs_only(**kwargs)
|
68
|
+
# block_only(&block)
|
60
69
|
# end
|
61
70
|
#
|
62
71
|
# @example AllowOnlyRestArgument: true (default, only relevant for Ruby < 3.2)
|
@@ -179,9 +188,12 @@ module RuboCop
|
|
179
188
|
|
180
189
|
send_classifications.each do |send_node, _c, forward_rest, forward_kwrest, forward_block_arg| # rubocop:disable Layout/LineLength
|
181
190
|
if !forward_rest && !forward_kwrest
|
182
|
-
|
183
|
-
|
184
|
-
|
191
|
+
# Prevents `anonymous block parameter is also used within block (SyntaxError)` occurs
|
192
|
+
# in Ruby 3.3.0.
|
193
|
+
if outside_block?(forward_block_arg)
|
194
|
+
register_forward_block_arg_offense(!forward_rest, node.arguments, block_arg)
|
195
|
+
register_forward_block_arg_offense(!forward_rest, send_node, forward_block_arg)
|
196
|
+
end
|
185
197
|
registered_block_arg_offense = true
|
186
198
|
break
|
187
199
|
else
|
@@ -196,12 +208,13 @@ module RuboCop
|
|
196
208
|
end
|
197
209
|
# rubocop:enable Metrics/MethodLength
|
198
210
|
|
211
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
199
212
|
def add_post_ruby_32_offenses(def_node, send_classifications, forwardable_args)
|
200
213
|
return unless use_anonymous_forwarding?
|
201
214
|
|
202
|
-
rest_arg, kwrest_arg,
|
215
|
+
rest_arg, kwrest_arg, block_arg = *forwardable_args
|
203
216
|
|
204
|
-
send_classifications.each do |send_node, _c, forward_rest, forward_kwrest,
|
217
|
+
send_classifications.each do |send_node, _c, forward_rest, forward_kwrest, forward_block_arg| # rubocop:disable Layout/LineLength
|
205
218
|
if outside_block?(forward_rest)
|
206
219
|
register_forward_args_offense(def_node.arguments, rest_arg)
|
207
220
|
register_forward_args_offense(send_node, forward_rest)
|
@@ -211,8 +224,16 @@ module RuboCop
|
|
211
224
|
register_forward_kwargs_offense(!forward_rest, def_node.arguments, kwrest_arg)
|
212
225
|
register_forward_kwargs_offense(!forward_rest, send_node, forward_kwrest)
|
213
226
|
end
|
227
|
+
|
228
|
+
# Prevents `anonymous block parameter is also used within block (SyntaxError)` occurs
|
229
|
+
# in Ruby 3.3.0.
|
230
|
+
if outside_block?(forward_block_arg)
|
231
|
+
register_forward_block_arg_offense(!forward_rest, def_node.arguments, block_arg)
|
232
|
+
register_forward_block_arg_offense(!forward_rest, send_node, forward_block_arg)
|
233
|
+
end
|
214
234
|
end
|
215
235
|
end
|
236
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
216
237
|
|
217
238
|
def non_splat_or_block_pass_lvar_references(body)
|
218
239
|
body.each_descendant(:lvar, :lvasgn).filter_map do |lvar|
|
@@ -54,9 +54,9 @@ module RuboCop
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def on_send(node)
|
57
|
-
|
58
|
-
|
59
|
-
)
|
57
|
+
return unless (first_argument = node.first_argument)
|
58
|
+
|
59
|
+
add_offense(first_argument, message: format(MSG, class_var: first_argument.source))
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative '../../directive_comment'
|
4
|
+
|
3
5
|
module RuboCop
|
4
6
|
module Cop
|
5
7
|
module Style
|
@@ -49,8 +51,9 @@ module RuboCop
|
|
49
51
|
KEYWORDS = %w[begin class def end module].freeze
|
50
52
|
KEYWORD_REGEXES = KEYWORDS.map { |w| /^\s*#{w}\s/ }.freeze
|
51
53
|
|
52
|
-
ALLOWED_COMMENTS = %w[:nodoc: :yields:
|
53
|
-
ALLOWED_COMMENT_REGEXES = ALLOWED_COMMENTS.map { |c| /#\s*#{c}/ }
|
54
|
+
ALLOWED_COMMENTS = %w[:nodoc: :yields:].freeze
|
55
|
+
ALLOWED_COMMENT_REGEXES = (ALLOWED_COMMENTS.map { |c| /#\s*#{c}/ } +
|
56
|
+
[DirectiveComment::DIRECTIVE_COMMENT_REGEXP]).freeze
|
54
57
|
|
55
58
|
REGEXP = /(?<keyword>\S+).*#/.freeze
|
56
59
|
|
@@ -115,8 +115,8 @@ module RuboCop
|
|
115
115
|
end
|
116
116
|
|
117
117
|
# Check for `if` and `case` statements where each branch is used for
|
118
|
-
#
|
119
|
-
# condition can be used instead.
|
118
|
+
# both the assignment and comparison of the same variable
|
119
|
+
# when using the return of the condition can be used instead.
|
120
120
|
#
|
121
121
|
# @example EnforcedStyle: assign_to_condition (default)
|
122
122
|
# # bad
|
@@ -460,9 +460,8 @@ module RuboCop
|
|
460
460
|
|
461
461
|
def assignment(node)
|
462
462
|
*_, condition = *node
|
463
|
-
|
464
|
-
|
465
|
-
condition.source_range.begin_pos)
|
463
|
+
|
464
|
+
node.source_range.begin.join(condition.source_range.begin)
|
466
465
|
end
|
467
466
|
|
468
467
|
def correct_if_branches(corrector, cop, node)
|
@@ -40,7 +40,7 @@ module RuboCop
|
|
40
40
|
|
41
41
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
42
42
|
UNUSED_BLOCK_ARG_MSG = "#{MSG.chop} and remove the unused `%<unused_code>s` block argument."
|
43
|
-
ARRAY_CONVERTER_METHODS = %i[assoc flatten rassoc sort sort_by to_a].freeze
|
43
|
+
ARRAY_CONVERTER_METHODS = %i[assoc chunk flatten rassoc sort sort_by to_a].freeze
|
44
44
|
|
45
45
|
# @!method kv_each(node)
|
46
46
|
def_node_matcher :kv_each, <<~PATTERN
|
@@ -195,6 +195,7 @@ module RuboCop
|
|
195
195
|
acceptable_19_syntax_symbol?(pair.key.source)
|
196
196
|
end
|
197
197
|
|
198
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
198
199
|
def acceptable_19_syntax_symbol?(sym_name)
|
199
200
|
sym_name.delete_prefix!(':')
|
200
201
|
|
@@ -209,9 +210,12 @@ module RuboCop
|
|
209
210
|
# Most hash keys can be matched against a simple regex.
|
210
211
|
return true if /\A[_a-z]\w*[?!]?\z/i.match?(sym_name)
|
211
212
|
|
212
|
-
|
213
|
-
|
213
|
+
return false if target_ruby_version <= 2.1
|
214
|
+
|
215
|
+
(sym_name.start_with?("'") && sym_name.end_with?("'")) ||
|
216
|
+
(sym_name.start_with?('"') && sym_name.end_with?('"'))
|
214
217
|
end
|
218
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
215
219
|
|
216
220
|
def check(pairs, delim, msg)
|
217
221
|
pairs.each do |pair|
|
@@ -76,9 +76,9 @@ module RuboCop
|
|
76
76
|
PATTERN
|
77
77
|
|
78
78
|
def on_send(node)
|
79
|
-
inverse_candidate?(node) do |
|
79
|
+
inverse_candidate?(node) do |method_call, lhs, method, rhs|
|
80
80
|
return unless inverse_methods.key?(method)
|
81
|
-
return if negated?(node)
|
81
|
+
return if negated?(node) || relational_comparison_with_safe_navigation?(method_call)
|
82
82
|
return if part_of_ignored_node?(node)
|
83
83
|
return if possible_class_hierarchy_check?(lhs, rhs, method)
|
84
84
|
|
@@ -155,16 +155,16 @@ module RuboCop
|
|
155
155
|
node.parent.respond_to?(:method?) && node.parent.method?(:!)
|
156
156
|
end
|
157
157
|
|
158
|
+
def relational_comparison_with_safe_navigation?(node)
|
159
|
+
node.csend_type? && CLASS_COMPARISON_METHODS.include?(node.method_name)
|
160
|
+
end
|
161
|
+
|
158
162
|
def not_to_receiver(node, method_call)
|
159
|
-
|
160
|
-
node.loc.selector.begin_pos,
|
161
|
-
method_call.source_range.begin_pos)
|
163
|
+
node.loc.selector.begin.join(method_call.source_range.begin)
|
162
164
|
end
|
163
165
|
|
164
166
|
def end_parentheses(node, method_call)
|
165
|
-
|
166
|
-
method_call.source_range.end_pos,
|
167
|
-
node.source_range.end_pos)
|
167
|
+
method_call.source_range.end.join(node.source_range.end)
|
168
168
|
end
|
169
169
|
|
170
170
|
# When comparing classes, `!(Integer < Numeric)` is not the same as
|
@@ -32,12 +32,14 @@ module RuboCop
|
|
32
32
|
# foo unless x != y
|
33
33
|
# foo unless x >= 10
|
34
34
|
# foo unless x.even?
|
35
|
+
# foo unless odd?
|
35
36
|
#
|
36
37
|
# # good
|
37
38
|
# foo if bar
|
38
39
|
# foo if x == y
|
39
40
|
# foo if x < 10
|
40
41
|
# foo if x.odd?
|
42
|
+
# foo if even?
|
41
43
|
#
|
42
44
|
# # bad (complex condition)
|
43
45
|
# foo unless x != y || x.even?
|
@@ -99,12 +101,15 @@ module RuboCop
|
|
99
101
|
end
|
100
102
|
end
|
101
103
|
|
102
|
-
def preferred_send_condition(node)
|
103
|
-
receiver_source = node.receiver
|
104
|
+
def preferred_send_condition(node) # rubocop:disable Metrics/CyclomaticComplexity
|
105
|
+
receiver_source = node.receiver&.source
|
104
106
|
return receiver_source if node.method?(:!)
|
105
107
|
|
108
|
+
# receiver may be implicit (self)
|
109
|
+
dotted_receiver_source = receiver_source ? "#{receiver_source}." : ''
|
110
|
+
|
106
111
|
inverse_method_name = inverse_methods[node.method_name]
|
107
|
-
return "#{
|
112
|
+
return "#{dotted_receiver_source}#{inverse_method_name}" unless node.arguments?
|
108
113
|
|
109
114
|
argument_list = node.arguments.map(&:source).join(', ')
|
110
115
|
if node.operator_method?
|
@@ -112,10 +117,10 @@ module RuboCop
|
|
112
117
|
end
|
113
118
|
|
114
119
|
if node.parenthesized?
|
115
|
-
return "#{
|
120
|
+
return "#{dotted_receiver_source}#{inverse_method_name}(#{argument_list})"
|
116
121
|
end
|
117
122
|
|
118
|
-
"#{
|
123
|
+
"#{dotted_receiver_source}#{inverse_method_name} #{argument_list}"
|
119
124
|
end
|
120
125
|
|
121
126
|
def preferred_logical_condition(node)
|
@@ -116,20 +116,17 @@ module RuboCop
|
|
116
116
|
def truthy_branch_for_guard?(node)
|
117
117
|
if_node = node.left_sibling
|
118
118
|
|
119
|
-
if if_node.if?
|
120
|
-
if_node.
|
121
|
-
|
122
|
-
if_node.if_branch.
|
119
|
+
if if_node.if?
|
120
|
+
if_node.if_branch.arguments.any?
|
121
|
+
else
|
122
|
+
if_node.if_branch.arguments.none?
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
126
|
def range(node)
|
127
|
-
buffer = node.source_range.source_buffer
|
128
127
|
map_node = node.receiver.send_node
|
129
|
-
begin_pos = map_node.loc.selector.begin_pos
|
130
|
-
end_pos = node.source_range.end_pos
|
131
128
|
|
132
|
-
|
129
|
+
map_node.loc.selector.join(node.source_range.end)
|
133
130
|
end
|
134
131
|
end
|
135
132
|
end
|
@@ -132,7 +132,7 @@ module RuboCop
|
|
132
132
|
call_in_match_pattern?(node) ||
|
133
133
|
hash_literal_in_arguments?(node) ||
|
134
134
|
node.descendants.any? do |n|
|
135
|
-
n.forwarded_args_type? || n.block_type? ||
|
135
|
+
n.forwarded_args_type? || n.block_type? || n.numblock_type? ||
|
136
136
|
ambiguous_literal?(n) || logical_operator?(n)
|
137
137
|
end
|
138
138
|
end
|
@@ -38,6 +38,7 @@ module RuboCop
|
|
38
38
|
|
39
39
|
private
|
40
40
|
|
41
|
+
# rubocop:disable Metrics/AbcSize
|
41
42
|
def autocorrect(corrector, node, begin_of_arguments)
|
42
43
|
arguments = node.arguments
|
43
44
|
joined_arguments = arguments.map(&:source).join(', ')
|
@@ -49,9 +50,17 @@ module RuboCop
|
|
49
50
|
corrector.remove(range_by_whole_lines(arguments.loc.end, include_final_newline: true))
|
50
51
|
end
|
51
52
|
|
52
|
-
|
53
|
+
arguments_range = arguments_range(node)
|
54
|
+
# If the method name isn't on the same line as def, move it directly after def
|
55
|
+
if arguments_range.first_line != opening_line(node)
|
56
|
+
corrector.remove(node.loc.name)
|
57
|
+
corrector.insert_after(node.loc.keyword, " #{node.loc.name.source}")
|
58
|
+
end
|
59
|
+
|
60
|
+
corrector.remove(arguments_range)
|
53
61
|
corrector.insert_after(begin_of_arguments, joined_arguments)
|
54
62
|
end
|
63
|
+
# rubocop:enable Metrics/AbcSize
|
55
64
|
|
56
65
|
def last_line_source_of_arguments(arguments)
|
57
66
|
processed_source[arguments.last_line - 1].strip
|
@@ -47,7 +47,11 @@ module RuboCop
|
|
47
47
|
message = enforce_single_line_ternary_operator?(node) ? MSG_SINGLE_LINE : MSG_IF
|
48
48
|
|
49
49
|
add_offense(node, message: message) do |corrector|
|
50
|
+
next if part_of_ignored_node?(node)
|
51
|
+
|
50
52
|
autocorrect(corrector, node)
|
53
|
+
|
54
|
+
ignore_node(node)
|
51
55
|
end
|
52
56
|
end
|
53
57
|
|
@@ -46,15 +46,17 @@ module RuboCop
|
|
46
46
|
private
|
47
47
|
|
48
48
|
def check_method_node(node)
|
49
|
-
return unless preferred_method(node)
|
49
|
+
return unless preferred_method?(node)
|
50
50
|
|
51
51
|
message = message(node)
|
52
52
|
add_offense(node.loc.selector, message: message) do |corrector|
|
53
|
-
|
53
|
+
prefer = style == :then && node.receiver.nil? ? 'self.then' : style
|
54
|
+
|
55
|
+
corrector.replace(node.loc.selector, prefer)
|
54
56
|
end
|
55
57
|
end
|
56
58
|
|
57
|
-
def preferred_method(node)
|
59
|
+
def preferred_method?(node)
|
58
60
|
case style
|
59
61
|
when :then
|
60
62
|
node.method?(:yield_self)
|
@@ -289,9 +289,7 @@ module RuboCop
|
|
289
289
|
private
|
290
290
|
|
291
291
|
def modifier_range(node)
|
292
|
-
|
293
|
-
node.loc.keyword.begin_pos,
|
294
|
-
node.source_range.end_pos)
|
292
|
+
node.loc.keyword.join(node.source_range.end)
|
295
293
|
end
|
296
294
|
end
|
297
295
|
end
|
@@ -16,6 +16,9 @@ module RuboCop
|
|
16
16
|
# The exploded style has an `AllowedCompactTypes` configuration
|
17
17
|
# option that takes an Array of exception name Strings.
|
18
18
|
#
|
19
|
+
# @safety
|
20
|
+
# This cop is unsafe because `raise Foo` calls `Foo.exception`, not `Foo.new`.
|
21
|
+
#
|
19
22
|
# @example EnforcedStyle: exploded (default)
|
20
23
|
# # bad
|
21
24
|
# raise StandardError.new('message')
|
@@ -77,7 +80,7 @@ module RuboCop
|
|
77
80
|
|
78
81
|
def correction_exploded_to_compact(node)
|
79
82
|
exception_node, *message_nodes = *node.arguments
|
80
|
-
return
|
83
|
+
return if message_nodes.size > 1
|
81
84
|
|
82
85
|
argument = message_nodes.first.source
|
83
86
|
exception_class = exception_node.receiver&.source || exception_node.source
|
@@ -81,14 +81,14 @@ module RuboCop
|
|
81
81
|
redundant_argument = redundant_arg_for_method(node.method_name.to_s)
|
82
82
|
return false if redundant_argument.nil?
|
83
83
|
|
84
|
-
node.first_argument == redundant_argument
|
84
|
+
node.first_argument.source.sub(/\A'/, '"').sub(/'\z/, '"') == redundant_argument
|
85
85
|
end
|
86
86
|
|
87
87
|
def redundant_arg_for_method(method_name)
|
88
88
|
arg = cop_config['Methods'].fetch(method_name) { return }
|
89
89
|
|
90
90
|
@mem ||= {}
|
91
|
-
@mem[method_name] ||=
|
91
|
+
@mem[method_name] ||= arg.inspect
|
92
92
|
end
|
93
93
|
|
94
94
|
def argument_range(node)
|