rubocop 1.30.0 → 1.31.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -2
- data/config/default.yml +41 -8
- data/config/obsoletion.yml +2 -0
- data/exe/rubocop +15 -7
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
- data/lib/rubocop/cli/command/suggest_extensions.rb +3 -3
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_loader.rb +1 -0
- data/lib/rubocop/config_validator.rb +9 -5
- data/lib/rubocop/cop/base.rb +4 -0
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
- data/lib/rubocop/cop/bundler/gem_filename.rb +4 -4
- data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -2
- data/lib/rubocop/cop/corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +3 -3
- data/lib/rubocop/cop/correctors/unused_arg_corrector.rb +1 -1
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +31 -16
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -1
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
- data/lib/rubocop/cop/gemspec/require_mfa.rb +20 -20
- data/lib/rubocop/cop/generator.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -5
- data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +25 -4
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +4 -4
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +9 -9
- data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +9 -9
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +27 -27
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +17 -11
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +49 -10
- data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +68 -0
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +120 -0
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +10 -10
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +5 -3
- data/lib/rubocop/cop/layout/trailing_empty_lines.rb +7 -7
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +51 -0
- data/lib/rubocop/cop/lint/interpolation_check.rb +1 -1
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +121 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +3 -3
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +5 -5
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -1
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +2 -2
- data/lib/rubocop/cop/lint/struct_new_override.rb +2 -2
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +44 -0
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +36 -12
- data/lib/rubocop/cop/mixin/range_help.rb +7 -3
- data/lib/rubocop/cop/naming/accessor_method_name.rb +3 -1
- data/lib/rubocop/cop/naming/variable_number.rb +17 -17
- data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
- data/lib/rubocop/cop/style/and_or.rb +8 -8
- data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +4 -2
- data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +1 -0
- data/lib/rubocop/cop/style/empty_else.rb +10 -10
- data/lib/rubocop/cop/style/empty_method.rb +16 -1
- data/lib/rubocop/cop/style/encoding.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/fetch_env_var.rb +9 -2
- data/lib/rubocop/cop/style/format_string_token.rb +48 -17
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +8 -6
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -1
- data/lib/rubocop/cop/style/hash_except.rb +88 -8
- data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
- data/lib/rubocop/cop/style/implicit_runtime_error.rb +2 -2
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
- data/lib/rubocop/cop/style/line_end_concatenation.rb +1 -1
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/missing_else.rb +24 -24
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -2
- data/lib/rubocop/cop/style/multiline_if_then.rb +1 -1
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -3
- data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +1 -3
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +19 -7
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/not.rb +1 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +1 -1
- data/lib/rubocop/cop/style/redundant_return.rb +1 -1
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/rescue_standard_error.rb +10 -10
- data/lib/rubocop/cop/style/safe_navigation.rb +3 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
- data/lib/rubocop/cop/style/string_concatenation.rb +5 -6
- data/lib/rubocop/cop/style/struct_inheritance.rb +2 -2
- data/lib/rubocop/cop/style/swap_values.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
- data/lib/rubocop/cop/style/unpack_first.rb +1 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cops_documentation_generator.rb +18 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +8 -5
- data/lib/rubocop/formatter/formatter_set.rb +20 -19
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +15 -2
- data/lib/rubocop/formatter/html_formatter.rb +0 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +2 -0
- data/lib/rubocop/formatter/simple_text_formatter.rb +6 -9
- data/lib/rubocop/formatter.rb +31 -0
- data/lib/rubocop/options.rb +25 -2
- data/lib/rubocop/rake_task.rb +30 -9
- data/lib/rubocop/runner.rb +2 -2
- data/lib/rubocop/server/cache.rb +109 -0
- data/lib/rubocop/server/cli.rb +104 -0
- data/lib/rubocop/server/client_command/base.rb +44 -0
- data/lib/rubocop/server/client_command/exec.rb +59 -0
- data/lib/rubocop/server/client_command/restart.rb +25 -0
- data/lib/rubocop/server/client_command/start.rb +43 -0
- data/lib/rubocop/server/client_command/status.rb +28 -0
- data/lib/rubocop/server/client_command/stop.rb +31 -0
- data/lib/rubocop/server/client_command.rb +26 -0
- data/lib/rubocop/server/core.rb +79 -0
- data/lib/rubocop/server/errors.rb +23 -0
- data/lib/rubocop/server/helper.rb +34 -0
- data/lib/rubocop/server/server_command/base.rb +50 -0
- data/lib/rubocop/server/server_command/exec.rb +34 -0
- data/lib/rubocop/server/server_command/stop.rb +24 -0
- data/lib/rubocop/server/server_command.rb +21 -0
- data/lib/rubocop/server/socket_reader.rb +65 -0
- data/lib/rubocop/server.rb +53 -0
- data/lib/rubocop/version.rb +15 -8
- data/lib/rubocop.rb +7 -26
- metadata +27 -4
- data/lib/rubocop/cop/gemspec/date_assignment.rb +0 -49
@@ -184,6 +184,8 @@ module RuboCop
|
|
184
184
|
end
|
185
185
|
end
|
186
186
|
|
187
|
+
alias on_numblock on_block
|
188
|
+
|
187
189
|
private
|
188
190
|
|
189
191
|
def autocorrect(corrector, node)
|
@@ -281,7 +283,7 @@ module RuboCop
|
|
281
283
|
def move_comment_before_block(corrector, comment, block_node, closing_brace)
|
282
284
|
range = block_node.chained? ? end_of_chain(block_node.parent).source_range : closing_brace
|
283
285
|
comment_range = range_between(range.end_pos, comment.loc.expression.end_pos)
|
284
|
-
corrector.remove(range_with_surrounding_space(
|
286
|
+
corrector.remove(range_with_surrounding_space(comment_range, side: :right))
|
285
287
|
corrector.insert_after(range, "\n")
|
286
288
|
|
287
289
|
corrector.insert_before(block_node, "#{comment.text}\n")
|
@@ -300,7 +302,7 @@ module RuboCop
|
|
300
302
|
|
301
303
|
def get_blocks(node, &block)
|
302
304
|
case node.type
|
303
|
-
when :block
|
305
|
+
when :block, :numblock
|
304
306
|
yield node
|
305
307
|
when :send
|
306
308
|
get_blocks(node.receiver, &block) if node.receiver
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
66
66
|
|
67
67
|
def register_offense(comment, matched_keyword)
|
68
68
|
add_offense(comment, message: format(MSG, keyword: matched_keyword)) do |corrector|
|
69
|
-
range = range_with_surrounding_space(
|
69
|
+
range = range_with_surrounding_space(comment.loc.expression, newlines: false)
|
70
70
|
corrector.remove(range)
|
71
71
|
|
72
72
|
unless matched_keyword == 'end'
|
@@ -6,20 +6,20 @@ module RuboCop
|
|
6
6
|
# Checks for empty else-clauses, possibly including comments and/or an
|
7
7
|
# explicit `nil` depending on the EnforcedStyle.
|
8
8
|
#
|
9
|
-
# @example EnforcedStyle:
|
10
|
-
# # warn
|
9
|
+
# @example EnforcedStyle: both (default)
|
10
|
+
# # warn on empty else and else with nil in it
|
11
11
|
#
|
12
12
|
# # bad
|
13
13
|
# if condition
|
14
14
|
# statement
|
15
15
|
# else
|
16
|
+
# nil
|
16
17
|
# end
|
17
18
|
#
|
18
|
-
# #
|
19
|
+
# # bad
|
19
20
|
# if condition
|
20
21
|
# statement
|
21
22
|
# else
|
22
|
-
# nil
|
23
23
|
# end
|
24
24
|
#
|
25
25
|
# # good
|
@@ -34,20 +34,20 @@ module RuboCop
|
|
34
34
|
# statement
|
35
35
|
# end
|
36
36
|
#
|
37
|
-
# @example EnforcedStyle:
|
38
|
-
# # warn on else
|
37
|
+
# @example EnforcedStyle: empty
|
38
|
+
# # warn only on empty else
|
39
39
|
#
|
40
40
|
# # bad
|
41
41
|
# if condition
|
42
42
|
# statement
|
43
43
|
# else
|
44
|
-
# nil
|
45
44
|
# end
|
46
45
|
#
|
47
46
|
# # good
|
48
47
|
# if condition
|
49
48
|
# statement
|
50
49
|
# else
|
50
|
+
# nil
|
51
51
|
# end
|
52
52
|
#
|
53
53
|
# # good
|
@@ -62,8 +62,8 @@ module RuboCop
|
|
62
62
|
# statement
|
63
63
|
# end
|
64
64
|
#
|
65
|
-
# @example EnforcedStyle:
|
66
|
-
# # warn on
|
65
|
+
# @example EnforcedStyle: nil
|
66
|
+
# # warn on else with nil in it
|
67
67
|
#
|
68
68
|
# # bad
|
69
69
|
# if condition
|
@@ -72,7 +72,7 @@ module RuboCop
|
|
72
72
|
# nil
|
73
73
|
# end
|
74
74
|
#
|
75
|
-
# #
|
75
|
+
# # good
|
76
76
|
# if condition
|
77
77
|
# statement
|
78
78
|
# else
|
@@ -11,6 +11,10 @@ module RuboCop
|
|
11
11
|
# NOTE: A method definition is not considered empty if it contains
|
12
12
|
# comments.
|
13
13
|
#
|
14
|
+
# NOTE: Autocorrection will not be applied for the `compact` style
|
15
|
+
# if the resulting code is longer than the `Max` configuration for
|
16
|
+
# `Layout/LineLength`, but an offense will still be registered.
|
17
|
+
#
|
14
18
|
# @example EnforcedStyle: compact (default)
|
15
19
|
# # bad
|
16
20
|
# def foo(bar)
|
@@ -51,7 +55,12 @@ module RuboCop
|
|
51
55
|
return if node.body || comment_lines?(node)
|
52
56
|
return if correct_style?(node)
|
53
57
|
|
54
|
-
add_offense(node)
|
58
|
+
add_offense(node) do |corrector|
|
59
|
+
correction = corrected(node)
|
60
|
+
next if compact_style? && max_line_length && correction.size > max_line_length
|
61
|
+
|
62
|
+
corrector.replace(node, correction)
|
63
|
+
end
|
55
64
|
end
|
56
65
|
alias on_defs on_def
|
57
66
|
|
@@ -98,6 +107,12 @@ module RuboCop
|
|
98
107
|
def expanded_style?
|
99
108
|
style == :expanded
|
100
109
|
end
|
110
|
+
|
111
|
+
def max_line_length
|
112
|
+
return unless config.for_cop('Layout/LineLength')['Enabled']
|
113
|
+
|
114
|
+
config.for_cop('Layout/LineLength')['Max']
|
115
|
+
end
|
101
116
|
end
|
102
117
|
end
|
103
118
|
end
|
@@ -51,7 +51,7 @@ module RuboCop
|
|
51
51
|
text = comment.without(:encoding)
|
52
52
|
|
53
53
|
if text.blank?
|
54
|
-
corrector.remove(range_with_surrounding_space(range
|
54
|
+
corrector.remove(range_with_surrounding_space(range, side: :right))
|
55
55
|
else
|
56
56
|
corrector.replace(range, text)
|
57
57
|
end
|
@@ -42,7 +42,7 @@ module RuboCop
|
|
42
42
|
include RangeHelp
|
43
43
|
extend AutoCorrector
|
44
44
|
|
45
|
-
MSG = 'Consider using explicit block argument in the '\
|
45
|
+
MSG = 'Consider using explicit block argument in the ' \
|
46
46
|
"surrounding method's signature over `yield`."
|
47
47
|
|
48
48
|
# @!method yielding_block?(node)
|
@@ -112,13 +112,20 @@ module RuboCop
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def used_in_condition?(node, condition)
|
115
|
-
if condition.send_type?
|
116
|
-
return
|
115
|
+
if condition.send_type?
|
116
|
+
return true if condition.assignment_method? && partial_matched?(node, condition)
|
117
|
+
return false if !condition.comparison_method? && !condition.predicate_method?
|
117
118
|
end
|
118
119
|
|
119
120
|
condition.child_nodes.any?(node)
|
120
121
|
end
|
121
122
|
|
123
|
+
# Avoid offending in the following cases:
|
124
|
+
# `ENV['key'] if ENV['key'] = x`
|
125
|
+
def partial_matched?(node, condition)
|
126
|
+
node.child_nodes == node.child_nodes & condition.child_nodes
|
127
|
+
end
|
128
|
+
|
122
129
|
def offensive?(node)
|
123
130
|
!(allowed_var?(node) || allowable_use?(node))
|
124
131
|
end
|
@@ -69,6 +69,7 @@ module RuboCop
|
|
69
69
|
class FormatStringToken < Base
|
70
70
|
include ConfigurableEnforcedStyle
|
71
71
|
include IgnoredMethods
|
72
|
+
extend AutoCorrector
|
72
73
|
|
73
74
|
def on_str(node)
|
74
75
|
return if format_string_token?(node) || use_ignored_method?(node)
|
@@ -77,13 +78,8 @@ module RuboCop
|
|
77
78
|
return if detections.empty?
|
78
79
|
return if allowed_unannotated?(detections)
|
79
80
|
|
80
|
-
detections.each do |
|
81
|
-
|
82
|
-
correct_style_detected
|
83
|
-
else
|
84
|
-
style_detected(detected_style)
|
85
|
-
add_offense(token_range, message: message(detected_style))
|
86
|
-
end
|
81
|
+
detections.each do |detected_sequence, token_range|
|
82
|
+
check_sequence(detected_sequence, token_range)
|
87
83
|
end
|
88
84
|
end
|
89
85
|
|
@@ -106,6 +102,38 @@ module RuboCop
|
|
106
102
|
send_parent && ignored_method?(send_parent.method_name)
|
107
103
|
end
|
108
104
|
|
105
|
+
def check_sequence(detected_sequence, token_range)
|
106
|
+
if detected_sequence.style == style
|
107
|
+
correct_style_detected
|
108
|
+
elsif correctable_sequence?(detected_sequence.type)
|
109
|
+
style_detected(detected_sequence.style)
|
110
|
+
add_offense(token_range, message: message(detected_sequence.style)) do |corrector|
|
111
|
+
autocorrect_sequence(corrector, detected_sequence, token_range)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def correctable_sequence?(detected_type)
|
117
|
+
detected_type == 's' || style == :annotated || style == :unannotated
|
118
|
+
end
|
119
|
+
|
120
|
+
def autocorrect_sequence(corrector, detected_sequence, token_range)
|
121
|
+
return if style == :unannotated
|
122
|
+
|
123
|
+
name = detected_sequence.name
|
124
|
+
return if name.nil?
|
125
|
+
|
126
|
+
flags = detected_sequence.flags
|
127
|
+
width = detected_sequence.width
|
128
|
+
precision = detected_sequence.precision
|
129
|
+
type = detected_sequence.style == :template ? 's' : detected_sequence.type
|
130
|
+
correction = case style
|
131
|
+
when :annotated then "%<#{name}>#{flags}#{width}#{precision}#{type}"
|
132
|
+
when :template then "%#{flags}#{width}#{precision}{#{name}}"
|
133
|
+
end
|
134
|
+
corrector.replace(token_range, correction)
|
135
|
+
end
|
136
|
+
|
109
137
|
def unannotated_format?(node, detected_style)
|
110
138
|
detected_style == :unannotated && !format_string_in_typical_context?(node)
|
111
139
|
end
|
@@ -143,30 +171,33 @@ module RuboCop
|
|
143
171
|
def token_ranges(contents)
|
144
172
|
format_string = RuboCop::Cop::Utils::FormatString.new(contents.source)
|
145
173
|
|
146
|
-
format_string.format_sequences.each do |
|
147
|
-
next if
|
174
|
+
format_string.format_sequences.each do |detected_sequence|
|
175
|
+
next if detected_sequence.percent?
|
148
176
|
|
149
|
-
|
150
|
-
|
177
|
+
token = contents.begin.adjust(begin_pos: detected_sequence.begin_pos,
|
178
|
+
end_pos: detected_sequence.end_pos)
|
151
179
|
|
152
|
-
yield(
|
180
|
+
yield(detected_sequence, token)
|
153
181
|
end
|
154
182
|
end
|
155
183
|
|
156
184
|
def collect_detections(node)
|
157
185
|
detections = []
|
158
|
-
tokens(node) do |
|
159
|
-
unless unannotated_format?(node,
|
160
|
-
detections << [
|
186
|
+
tokens(node) do |detected_sequence, token_range|
|
187
|
+
unless unannotated_format?(node, detected_sequence.style)
|
188
|
+
detections << [detected_sequence, token_range]
|
161
189
|
end
|
162
190
|
end
|
163
191
|
detections
|
164
192
|
end
|
165
193
|
|
166
194
|
def allowed_unannotated?(detections)
|
167
|
-
return false
|
195
|
+
return false unless detections.all? do |detected_sequence,|
|
196
|
+
detected_sequence.style == :unannotated
|
197
|
+
end
|
198
|
+
return true if detections.size <= max_unannotated_placeholders_allowed
|
168
199
|
|
169
|
-
detections.
|
200
|
+
detections.any? { |detected_sequence,| !correctable_sequence?(detected_sequence.type) }
|
170
201
|
end
|
171
202
|
|
172
203
|
def max_unannotated_placeholders_allowed
|
@@ -182,7 +182,7 @@ module RuboCop
|
|
182
182
|
end
|
183
183
|
|
184
184
|
def remove_comment(corrector, node)
|
185
|
-
corrector.remove(range_with_surrounding_space(
|
185
|
+
corrector.remove(range_with_surrounding_space(node.pos, side: :right))
|
186
186
|
end
|
187
187
|
|
188
188
|
def enable_comment(corrector)
|
@@ -110,7 +110,7 @@ module RuboCop
|
|
110
110
|
kw = if guard_clause_in_if
|
111
111
|
node.loc.keyword.source
|
112
112
|
else
|
113
|
-
|
113
|
+
node.inverse_keyword
|
114
114
|
end
|
115
115
|
|
116
116
|
register_offense(node, guard_clause_source(guard_clause), kw)
|
@@ -123,7 +123,7 @@ module RuboCop
|
|
123
123
|
return if allowed_consecutive_conditionals? &&
|
124
124
|
consecutive_conditionals?(node.parent, node)
|
125
125
|
|
126
|
-
register_offense(node, 'return',
|
126
|
+
register_offense(node, 'return', node.inverse_keyword)
|
127
127
|
end
|
128
128
|
|
129
129
|
def consecutive_conditionals?(parent, node)
|
@@ -134,14 +134,12 @@ module RuboCop
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
|
-
def opposite_keyword(node)
|
138
|
-
node.if? ? 'unless' : 'if'
|
139
|
-
end
|
140
|
-
|
141
137
|
def register_offense(node, scope_exiting_keyword, conditional_keyword)
|
142
138
|
condition, = node.node_parts
|
143
139
|
example = [scope_exiting_keyword, conditional_keyword, condition.source].join(' ')
|
144
140
|
if too_long_for_single_line?(node, example)
|
141
|
+
return if trivial?(node)
|
142
|
+
|
145
143
|
example = "#{conditional_keyword} #{condition.source}; #{scope_exiting_keyword}; end"
|
146
144
|
end
|
147
145
|
|
@@ -167,6 +165,10 @@ module RuboCop
|
|
167
165
|
accepted_if?(node, ending) || node.condition.multiline? || node.parent&.assignment?
|
168
166
|
end
|
169
167
|
|
168
|
+
def trivial?(node)
|
169
|
+
node.branches.one? && !node.if_branch.if_type? && !node.if_branch.begin_type?
|
170
|
+
end
|
171
|
+
|
170
172
|
def accepted_if?(node, ending)
|
171
173
|
return true if node.modifier_form? || node.ternary?
|
172
174
|
|
@@ -19,6 +19,9 @@ module RuboCop
|
|
19
19
|
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| k == :bar }
|
20
20
|
# {foo: 1, bar: 2, baz: 3}.select {|k, v| k != :bar }
|
21
21
|
# {foo: 1, bar: 2, baz: 3}.filter {|k, v| k != :bar }
|
22
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[foo bar].include?(k) }
|
23
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[foo bar].include?(k) }
|
24
|
+
# {foo: 1, bar: 2, baz: 3}.filter {|k, v| !%i[foo bar].include?(k) }
|
22
25
|
#
|
23
26
|
# # good
|
24
27
|
# {foo: 1, bar: 2, baz: 3}.except(:bar)
|
@@ -33,15 +36,36 @@ module RuboCop
|
|
33
36
|
MSG = 'Use `%<prefer>s` instead.'
|
34
37
|
RESTRICT_ON_SEND = %i[reject select filter].freeze
|
35
38
|
|
36
|
-
# @!method
|
37
|
-
def_node_matcher :
|
39
|
+
# @!method bad_method_with_poro?(node)
|
40
|
+
def_node_matcher :bad_method_with_poro?, <<~PATTERN
|
38
41
|
(block
|
39
42
|
(send _ _)
|
40
43
|
(args
|
41
44
|
(arg _)
|
42
45
|
(arg _))
|
43
|
-
|
44
|
-
|
46
|
+
{
|
47
|
+
(send
|
48
|
+
_ {:== :!= :eql? :include?} _)
|
49
|
+
(send
|
50
|
+
(send
|
51
|
+
_ {:== :!= :eql? :include?} _) :!)
|
52
|
+
})
|
53
|
+
PATTERN
|
54
|
+
|
55
|
+
# @!method bad_method_with_active_support?(node)
|
56
|
+
def_node_matcher :bad_method_with_active_support?, <<~PATTERN
|
57
|
+
(block
|
58
|
+
(send _ _)
|
59
|
+
(args
|
60
|
+
(arg _)
|
61
|
+
(arg _))
|
62
|
+
{
|
63
|
+
(send
|
64
|
+
_ {:== :!= :eql? :in? :include? :exclude?} _)
|
65
|
+
(send
|
66
|
+
(send
|
67
|
+
_ {:== :!= :eql? :in? :include? :exclude?} _) :!)
|
68
|
+
})
|
45
69
|
PATTERN
|
46
70
|
|
47
71
|
def on_send(node)
|
@@ -52,7 +76,7 @@ module RuboCop
|
|
52
76
|
return if except_key.nil? || !safe_to_register_offense?(block, except_key)
|
53
77
|
|
54
78
|
range = offense_range(node)
|
55
|
-
preferred_method = "except(#{except_key
|
79
|
+
preferred_method = "except(#{except_key_source(except_key)})"
|
56
80
|
|
57
81
|
add_offense(range, message: format(MSG, prefer: preferred_method)) do |corrector|
|
58
82
|
corrector.replace(range, preferred_method)
|
@@ -61,28 +85,84 @@ module RuboCop
|
|
61
85
|
|
62
86
|
private
|
63
87
|
|
88
|
+
def bad_method?(block)
|
89
|
+
if active_support_extensions_enabled?
|
90
|
+
bad_method_with_active_support?(block)
|
91
|
+
else
|
92
|
+
bad_method_with_poro?(block)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
64
96
|
def semantically_except_method?(send, block)
|
65
97
|
body = block.body
|
66
98
|
|
99
|
+
negated = body.method?('!')
|
100
|
+
body = body.receiver if negated
|
101
|
+
|
67
102
|
case send.method_name
|
68
103
|
when :reject
|
69
|
-
body.method?('==') || body.method?('eql?')
|
104
|
+
body.method?('==') || body.method?('eql?') || included?(negated, body)
|
70
105
|
when :select, :filter
|
71
|
-
body.method?('!=')
|
106
|
+
body.method?('!=') || not_included?(negated, body)
|
72
107
|
else
|
73
108
|
false
|
74
109
|
end
|
75
110
|
end
|
76
111
|
|
112
|
+
def included?(negated, body)
|
113
|
+
body.method?('include?') || body.method?('in?') || (negated && body.method?('exclude?'))
|
114
|
+
end
|
115
|
+
|
116
|
+
def not_included?(negated, body)
|
117
|
+
body.method?('exclude?') || (negated && (body.method?('include?') || body.method?('in?')))
|
118
|
+
end
|
119
|
+
|
77
120
|
def safe_to_register_offense?(block, except_key)
|
121
|
+
extracted = extract_body_if_nagated(block.body)
|
122
|
+
if extracted.method?('in?') || extracted.method?('include?') || \
|
123
|
+
extracted.method?('exclude?')
|
124
|
+
return true
|
125
|
+
end
|
78
126
|
return true if block.body.method?('eql?')
|
79
127
|
|
80
128
|
except_key.sym_type? || except_key.str_type?
|
81
129
|
end
|
82
130
|
|
131
|
+
def extract_body_if_nagated(body)
|
132
|
+
return body unless body.method?('!')
|
133
|
+
|
134
|
+
body.receiver
|
135
|
+
end
|
136
|
+
|
137
|
+
def except_key_source(key)
|
138
|
+
if key.array_type?
|
139
|
+
key = if key.percent_literal?
|
140
|
+
key.each_value.map { |v| decorate_source(v) }
|
141
|
+
else
|
142
|
+
key.each_value.map(&:source)
|
143
|
+
end
|
144
|
+
return key.join(', ')
|
145
|
+
end
|
146
|
+
|
147
|
+
key.source
|
148
|
+
end
|
149
|
+
|
150
|
+
def decorate_source(value)
|
151
|
+
return ":\"#{value.source}\"" if value.dsym_type?
|
152
|
+
return "\"#{value.source}\"" if value.dstr_type?
|
153
|
+
return ":#{value.source}" if value.sym_type?
|
154
|
+
|
155
|
+
"'#{value.source}'"
|
156
|
+
end
|
157
|
+
|
83
158
|
def except_key(node)
|
84
159
|
key_argument = node.argument_list.first.source
|
85
|
-
|
160
|
+
body = extract_body_if_nagated(node.body)
|
161
|
+
lhs, _method_name, rhs = *body
|
162
|
+
|
163
|
+
return lhs if body.method?('include?')
|
164
|
+
return lhs if body.method?('exclude?')
|
165
|
+
return rhs if body.method?('in?')
|
86
166
|
return if [lhs, rhs].map(&:source).none?(key_argument)
|
87
167
|
|
88
168
|
[lhs, rhs].find { |operand| operand.source != key_argument }
|
@@ -223,7 +223,7 @@ module RuboCop
|
|
223
223
|
operator = pair_node.loc.operator
|
224
224
|
|
225
225
|
range = key.join(operator)
|
226
|
-
range_with_surrounding_space(range
|
226
|
+
range_with_surrounding_space(range, side: :right)
|
227
227
|
end
|
228
228
|
|
229
229
|
def argument_without_space?(node)
|
@@ -235,7 +235,7 @@ module RuboCop
|
|
235
235
|
|
236
236
|
key_with_hash_rocket = ":#{pair_node.key.source}#{pair_node.inverse_delimiter(true)}"
|
237
237
|
corrector.replace(pair_node.key, key_with_hash_rocket)
|
238
|
-
corrector.remove(range_with_surrounding_space(
|
238
|
+
corrector.remove(range_with_surrounding_space(op))
|
239
239
|
end
|
240
240
|
|
241
241
|
def autocorrect_no_mixed_keys(corrector, pair_node)
|
@@ -15,8 +15,8 @@ module RuboCop
|
|
15
15
|
# # good
|
16
16
|
# raise ArgumentError, 'Error message here'
|
17
17
|
class ImplicitRuntimeError < Base
|
18
|
-
MSG = 'Use `%<method>s` with an explicit exception class and message,' \
|
19
|
-
'
|
18
|
+
MSG = 'Use `%<method>s` with an explicit exception class and message, ' \
|
19
|
+
'rather than just a message.'
|
20
20
|
RESTRICT_ON_SEND = %i[raise fail].freeze
|
21
21
|
|
22
22
|
# @!method implicit_runtime_error_raise_or_fail(node)
|
@@ -65,7 +65,7 @@ module RuboCop
|
|
65
65
|
|
66
66
|
def remove_kwargs(kwarg_nodes, corrector)
|
67
67
|
kwarg_nodes.each do |kwarg|
|
68
|
-
with_space = range_with_surrounding_space(
|
68
|
+
with_space = range_with_surrounding_space(kwarg.source_range)
|
69
69
|
corrector.remove(range_with_surrounding_comma(with_space, :left))
|
70
70
|
end
|
71
71
|
end
|
@@ -70,7 +70,7 @@ module RuboCop
|
|
70
70
|
|
71
71
|
def autocorrect(corrector, operator_range)
|
72
72
|
# Include any trailing whitespace so we don't create a syntax error.
|
73
|
-
operator_range = range_with_surrounding_space(
|
73
|
+
operator_range = range_with_surrounding_space(operator_range,
|
74
74
|
side: :right,
|
75
75
|
newlines: false)
|
76
76
|
one_more_char = operator_range.resize(operator_range.size + 1)
|
@@ -59,7 +59,7 @@ module RuboCop
|
|
59
59
|
def autocorrect(corrector, to_h, map)
|
60
60
|
removal_range = range_between(to_h.loc.dot.begin_pos, to_h.loc.selector.end_pos)
|
61
61
|
|
62
|
-
corrector.remove(range_with_surrounding_space(
|
62
|
+
corrector.remove(range_with_surrounding_space(removal_range, side: :left))
|
63
63
|
corrector.replace(map.loc.selector, 'to_h')
|
64
64
|
end
|
65
65
|
end
|
@@ -25,12 +25,12 @@ module RuboCop
|
|
25
25
|
return if allowed_string_interpolation_method_call?(node)
|
26
26
|
|
27
27
|
add_offense(offense_range(node), message: OMIT_MSG) do |corrector|
|
28
|
-
|
28
|
+
autocorrect(corrector, node)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
# rubocop:enable Metrics/PerceivedComplexity
|
32
32
|
|
33
|
-
def
|
33
|
+
def autocorrect(corrector, node)
|
34
34
|
if parentheses_at_the_end_of_multiline_call?(node)
|
35
35
|
corrector.replace(args_begin(node), ' \\')
|
36
36
|
else
|