rubocop 1.36.0 → 1.40.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 +78 -12
- data/exe/rubocop +1 -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/cli/command/suggest_extensions.rb +8 -1
- data/lib/rubocop/comment_config.rb +41 -1
- data/lib/rubocop/config.rb +5 -4
- data/lib/rubocop/config_loader.rb +5 -5
- data/lib/rubocop/config_loader_resolver.rb +1 -1
- data/lib/rubocop/cop/base.rb +2 -9
- data/lib/rubocop/cop/commissioner.rb +3 -1
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +22 -6
- data/lib/rubocop/cop/generator.rb +1 -2
- data/lib/rubocop/cop/internal_affairs/create_empty_file.rb +37 -0
- data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +111 -0
- data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
- data/lib/rubocop/cop/internal_affairs.rb +3 -0
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +29 -8
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
- data/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb +3 -0
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +30 -3
- data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +34 -0
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +6 -2
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -2
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
- data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
- data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +28 -9
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
- data/lib/rubocop/cop/lint/empty_block.rb +1 -5
- data/lib/rubocop/cop/lint/empty_class.rb +3 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +21 -9
- data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
- 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/parentheses_as_grouped_expression.rb +5 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +36 -4
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +38 -10
- data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +18 -8
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -4
- data/lib/rubocop/cop/lint/shadowed_exception.rb +0 -10
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +7 -3
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- 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/lint/void.rb +6 -6
- data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
- data/lib/rubocop/cop/metrics/block_length.rb +9 -4
- data/lib/rubocop/cop/metrics/class_length.rb +9 -4
- data/lib/rubocop/cop/metrics/method_length.rb +9 -4
- data/lib/rubocop/cop/metrics/module_length.rb +9 -4
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +5 -2
- 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 +30 -8
- data/lib/rubocop/cop/mixin/range_help.rb +23 -0
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +15 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +10 -8
- data/lib/rubocop/cop/mixin/visibility_help.rb +40 -5
- data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
- data/lib/rubocop/cop/registry.rb +32 -14
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +5 -7
- data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
- data/lib/rubocop/cop/style/array_intersect.rb +111 -0
- data/lib/rubocop/cop/style/block_delimiters.rb +2 -2
- data/lib/rubocop/cop/style/character_literal.rb +1 -1
- data/lib/rubocop/cop/style/class_equality_comparison.rb +8 -6
- data/lib/rubocop/cop/style/collection_compact.rb +12 -3
- 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/guard_clause.rb +90 -22
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +32 -10
- data/lib/rubocop/cop/style/hash_except.rb +4 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +25 -2
- data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +13 -2
- data/lib/rubocop/cop/style/module_function.rb +28 -6
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
- data/lib/rubocop/cop/style/object_then.rb +3 -0
- data/lib/rubocop/cop/style/operator_method_call.rb +53 -0
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +3 -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_constant_base.rb +72 -0
- data/lib/rubocop/cop/style/redundant_each.rb +116 -0
- 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_regexp_escape.rb +12 -3
- data/lib/rubocop/cop/style/redundant_return.rb +7 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +181 -0
- data/lib/rubocop/cop/style/require_order.rb +88 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +35 -6
- data/lib/rubocop/cop/style/select_by_regexp.rb +8 -4
- data/lib/rubocop/cop/style/static_class.rb +32 -1
- data/lib/rubocop/cop/style/string_literals.rb +1 -5
- data/lib/rubocop/cop/style/symbol_array.rb +2 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +3 -5
- data/lib/rubocop/cop/style/word_array.rb +2 -0
- data/lib/rubocop/cop/team.rb +4 -5
- data/lib/rubocop/cop/util.rb +2 -2
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable_table.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +20 -29
- data/lib/rubocop/cops_documentation_generator.rb +2 -1
- data/lib/rubocop/ext/processed_source.rb +2 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +25 -8
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +8 -5
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +6 -3
- data/lib/rubocop/formatter.rb +3 -1
- data/lib/rubocop/optimized_patterns.rb +38 -0
- data/lib/rubocop/options.rb +28 -16
- data/lib/rubocop/path_util.rb +14 -2
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/rspec/cop_helper.rb +24 -1
- data/lib/rubocop/rspec/shared_contexts.rb +14 -1
- data/lib/rubocop/rspec/support.rb +2 -2
- data/lib/rubocop/runner.rb +15 -11
- 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 +19 -2
- data/lib/rubocop/server/socket_reader.rb +5 -1
- data/lib/rubocop/server.rb +1 -1
- data/lib/rubocop/target_ruby.rb +1 -1
- data/lib/rubocop/version.rb +8 -3
- data/lib/rubocop.rb +18 -6
- metadata +18 -5
@@ -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
|
data/lib/rubocop/cop/registry.rb
CHANGED
@@ -72,27 +72,27 @@ module RuboCop
|
|
72
72
|
#
|
73
73
|
# @example gives back a correctly qualified cop name
|
74
74
|
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
# qualified_cop_name('Layout/EndOfLine') # => 'Layout/EndOfLine'
|
75
|
+
# registry = RuboCop::Cop::Registry
|
76
|
+
# registry.qualified_cop_name('Layout/EndOfLine', '') # => 'Layout/EndOfLine'
|
78
77
|
#
|
79
78
|
# @example fixes incorrect namespaces
|
80
79
|
#
|
81
|
-
#
|
82
|
-
#
|
80
|
+
# registry = RuboCop::Cop::Registry
|
81
|
+
# registry.qualified_cop_name('Lint/EndOfLine', '') # => 'Layout/EndOfLine'
|
83
82
|
#
|
84
83
|
# @example namespaces bare cop identifiers
|
85
84
|
#
|
86
|
-
#
|
87
|
-
#
|
85
|
+
# registry = RuboCop::Cop::Registry
|
86
|
+
# registry.qualified_cop_name('EndOfLine', '') # => 'Layout/EndOfLine'
|
88
87
|
#
|
89
88
|
# @example passes back unrecognized cop names
|
90
89
|
#
|
91
|
-
#
|
92
|
-
#
|
90
|
+
# registry = RuboCop::Cop::Registry
|
91
|
+
# registry.qualified_cop_name('NotACop', '') # => 'NotACop'
|
93
92
|
#
|
94
93
|
# @param name [String] Cop name extracted from config
|
95
94
|
# @param path [String, nil] Path of file that `name` was extracted from
|
95
|
+
# @param warn [Boolean] Print a warning if no department given for `name`
|
96
96
|
#
|
97
97
|
# @raise [AmbiguousCopName]
|
98
98
|
# if a bare identifier with two possible namespaces is provided
|
@@ -149,16 +149,22 @@ module RuboCop
|
|
149
149
|
@registry.size
|
150
150
|
end
|
151
151
|
|
152
|
-
def enabled(config
|
153
|
-
select { |cop|
|
152
|
+
def enabled(config)
|
153
|
+
select { |cop| enabled?(cop, config) }
|
154
154
|
end
|
155
155
|
|
156
|
-
def
|
156
|
+
def disabled(config)
|
157
|
+
reject { |cop| enabled?(cop, config) }
|
158
|
+
end
|
159
|
+
|
160
|
+
def enabled?(cop, config)
|
161
|
+
return true if options[:only]&.include?(cop.cop_name)
|
162
|
+
|
157
163
|
cfg = config.for_cop(cop)
|
158
164
|
|
159
165
|
cop_enabled = cfg.fetch('Enabled') == true || enabled_pending_cop?(cfg, config)
|
160
166
|
|
161
|
-
if
|
167
|
+
if options.fetch(:safe, false)
|
162
168
|
cop_enabled && cfg.fetch('Safe', true)
|
163
169
|
else
|
164
170
|
cop_enabled
|
@@ -176,8 +182,12 @@ module RuboCop
|
|
176
182
|
cops.map(&:cop_name)
|
177
183
|
end
|
178
184
|
|
185
|
+
def cops_for_department(department)
|
186
|
+
cops.select { |cop| cop.department == department.to_sym }
|
187
|
+
end
|
188
|
+
|
179
189
|
def names_for_department(department)
|
180
|
-
|
190
|
+
cops_for_department(department).map(&:cop_name)
|
181
191
|
end
|
182
192
|
|
183
193
|
def ==(other)
|
@@ -205,6 +215,14 @@ module RuboCop
|
|
205
215
|
to_h[cop_name].first
|
206
216
|
end
|
207
217
|
|
218
|
+
# When a cop name is given returns a single-element array with the cop class.
|
219
|
+
# When a department name is given returns an array with all the cop classes
|
220
|
+
# for that department.
|
221
|
+
def find_cops_by_directive(directive)
|
222
|
+
cop = find_by_cop_name(directive)
|
223
|
+
cop ? [cop] : cops_for_department(directive)
|
224
|
+
end
|
225
|
+
|
208
226
|
def freeze
|
209
227
|
clear_enrollment_queue
|
210
228
|
unqualified_cop_names # build cache
|
@@ -85,6 +85,8 @@ module RuboCop
|
|
85
85
|
|
86
86
|
RESTRICT_ON_SEND = %i[private protected public module_function].freeze
|
87
87
|
|
88
|
+
ALLOWED_NODE_TYPES = %i[pair block].freeze
|
89
|
+
|
88
90
|
# @!method access_modifier_with_symbol?(node)
|
89
91
|
def_node_matcher :access_modifier_with_symbol?, <<~PATTERN
|
90
92
|
(send nil? {:private :protected :public :module_function} (sym _))
|
@@ -92,7 +94,7 @@ module RuboCop
|
|
92
94
|
|
93
95
|
def on_send(node)
|
94
96
|
return unless node.access_modifier?
|
95
|
-
return if node.parent&.
|
97
|
+
return if ALLOWED_NODE_TYPES.include?(node.parent&.type)
|
96
98
|
return if allow_modifiers_on_symbols?(node)
|
97
99
|
|
98
100
|
if offense?(node)
|
@@ -183,6 +185,7 @@ module RuboCop
|
|
183
185
|
end
|
184
186
|
|
185
187
|
def insert_def(corrector, node, source)
|
188
|
+
source = [*processed_source.ast_with_comments[node].map(&:text), source].join("\n")
|
186
189
|
argument_less_modifier_node = find_argument_less_modifier_node(node)
|
187
190
|
if argument_less_modifier_node
|
188
191
|
corrector.insert_after(argument_less_modifier_node, "\n\n#{source}")
|
@@ -199,12 +202,7 @@ module RuboCop
|
|
199
202
|
end
|
200
203
|
|
201
204
|
def remove_node(corrector, node)
|
202
|
-
corrector.remove(
|
203
|
-
range_by_whole_lines(
|
204
|
-
node.location.expression,
|
205
|
-
include_final_newline: true
|
206
|
-
)
|
207
|
-
)
|
205
|
+
corrector.remove(range_with_comments_and_lines(node))
|
208
206
|
end
|
209
207
|
end
|
210
208
|
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
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# In Ruby 3.1, `Array#intersect?` has been added.
|
7
|
+
#
|
8
|
+
# This cop identifies places where `(array1 & array2).any?`
|
9
|
+
# can be replaced by `array1.intersect?(array2)`.
|
10
|
+
#
|
11
|
+
# The `array1.intersect?(array2)` method is faster than
|
12
|
+
# `(array1 & array2).any?` and is more readable.
|
13
|
+
#
|
14
|
+
# @safety
|
15
|
+
# This cop cannot guarantee that array1 and array2 are
|
16
|
+
# actually arrays while method `intersect?` is for arrays only.
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# # bad
|
20
|
+
# (array1 & array2).any?
|
21
|
+
# (array1 & array2).empty?
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# array1.intersect?(array2)
|
25
|
+
# !array1.intersect?(array2)
|
26
|
+
#
|
27
|
+
# @example AllCops:ActiveSupportExtensionsEnabled: false (default)
|
28
|
+
# # good
|
29
|
+
# (array1 & array2).present?
|
30
|
+
# (array1 & array2).blank?
|
31
|
+
#
|
32
|
+
# @example AllCops:ActiveSupportExtensionsEnabled: true
|
33
|
+
# # bad
|
34
|
+
# (array1 & array2).present?
|
35
|
+
# (array1 & array2).blank?
|
36
|
+
#
|
37
|
+
# # good
|
38
|
+
# array1.intersect?(array2)
|
39
|
+
# !array1.intersect?(array2)
|
40
|
+
class ArrayIntersect < Base
|
41
|
+
extend AutoCorrector
|
42
|
+
extend TargetRubyVersion
|
43
|
+
|
44
|
+
minimum_target_ruby_version 3.1
|
45
|
+
|
46
|
+
# @!method regular_bad_intersection_check?(node)
|
47
|
+
def_node_matcher :regular_bad_intersection_check?, <<~PATTERN
|
48
|
+
(send
|
49
|
+
(begin
|
50
|
+
(send $(...) :& $(...))
|
51
|
+
) ${:any? :empty?}
|
52
|
+
)
|
53
|
+
PATTERN
|
54
|
+
|
55
|
+
# @!method active_support_bad_intersection_check?(node)
|
56
|
+
def_node_matcher :active_support_bad_intersection_check?, <<~PATTERN
|
57
|
+
(send
|
58
|
+
(begin
|
59
|
+
(send $(...) :& $(...))
|
60
|
+
) ${:present? :any? :blank? :empty?}
|
61
|
+
)
|
62
|
+
PATTERN
|
63
|
+
|
64
|
+
MSG = 'Use `%<negated>s%<receiver>s.intersect?(%<argument>s)` ' \
|
65
|
+
'instead of `(%<receiver>s & %<argument>s).%<method_name>s`.'
|
66
|
+
STRAIGHT_METHODS = %i[present? any?].freeze
|
67
|
+
NEGATED_METHODS = %i[blank? empty?].freeze
|
68
|
+
RESTRICT_ON_SEND = (STRAIGHT_METHODS + NEGATED_METHODS).freeze
|
69
|
+
|
70
|
+
def on_send(node)
|
71
|
+
return unless (receiver, argument, method_name = bad_intersection_check?(node))
|
72
|
+
|
73
|
+
message = message(receiver.source, argument.source, method_name)
|
74
|
+
|
75
|
+
add_offense(node, message: message) do |corrector|
|
76
|
+
if straight?(method_name)
|
77
|
+
corrector.replace(node, "#{receiver.source}.intersect?(#{argument.source})")
|
78
|
+
else
|
79
|
+
corrector.replace(node, "!#{receiver.source}.intersect?(#{argument.source})")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def bad_intersection_check?(node)
|
87
|
+
if active_support_extensions_enabled?
|
88
|
+
active_support_bad_intersection_check?(node)
|
89
|
+
else
|
90
|
+
regular_bad_intersection_check?(node)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def straight?(method_name)
|
95
|
+
STRAIGHT_METHODS.include?(method_name.to_sym)
|
96
|
+
end
|
97
|
+
|
98
|
+
def message(receiver, argument, method_name)
|
99
|
+
negated = straight?(method_name) ? '' : '!'
|
100
|
+
format(
|
101
|
+
MSG,
|
102
|
+
negated: negated,
|
103
|
+
receiver: receiver,
|
104
|
+
argument: argument,
|
105
|
+
method_name: method_name
|
106
|
+
)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -157,7 +157,7 @@ module RuboCop
|
|
157
157
|
# process(something)
|
158
158
|
# }
|
159
159
|
#
|
160
|
-
# @example AllowedPatterns: [
|
160
|
+
# @example AllowedPatterns: ['map']
|
161
161
|
#
|
162
162
|
# # good
|
163
163
|
# things.map { |thing|
|
@@ -425,7 +425,7 @@ module RuboCop
|
|
425
425
|
if node.parent.begin_type?
|
426
426
|
return_value_used?(node.parent)
|
427
427
|
else
|
428
|
-
node.parent.assignment? || node.parent.
|
428
|
+
node.parent.assignment? || node.parent.call_type?
|
429
429
|
end
|
430
430
|
end
|
431
431
|
|
@@ -29,7 +29,7 @@ module RuboCop
|
|
29
29
|
|
30
30
|
def offense?(node)
|
31
31
|
# we don't register an offense for things like ?\C-\M-d
|
32
|
-
node.
|
32
|
+
node.character_literal? && node.source.size.between?(2, 3)
|
33
33
|
end
|
34
34
|
|
35
35
|
def autocorrect(corrector, node)
|
@@ -48,7 +48,7 @@ module RuboCop
|
|
48
48
|
# var.class.eql?(Date)
|
49
49
|
# var.class.name == 'Date'
|
50
50
|
#
|
51
|
-
# @example AllowedPatterns: [
|
51
|
+
# @example AllowedPatterns: ['eq']
|
52
52
|
# # good
|
53
53
|
# var.instance_of?(Date)
|
54
54
|
# var.class.equal?(Date)
|
@@ -97,12 +97,14 @@ module RuboCop
|
|
97
97
|
if node.children.first.method?(:name)
|
98
98
|
return class_node.receiver.source if class_node.receiver
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
100
|
+
if class_node.str_type?
|
101
|
+
value = class_node.source.delete('"').delete("'")
|
102
|
+
value.prepend('::') if class_node.each_ancestor(:class, :module).any?
|
103
|
+
return value
|
104
|
+
end
|
105
105
|
end
|
106
|
+
|
107
|
+
class_node.source
|
106
108
|
end
|
107
109
|
|
108
110
|
def offense_range(receiver_node, node)
|
@@ -8,7 +8,9 @@ module RuboCop
|
|
8
8
|
#
|
9
9
|
# @safety
|
10
10
|
# It is unsafe by default because false positives may occur in the
|
11
|
-
# `nil` check of block arguments to the receiver object.
|
11
|
+
# `nil` check of block arguments to the receiver object. Additionally,
|
12
|
+
# we can't know the type of the receiver object for sure, which may
|
13
|
+
# result in false positives as well.
|
12
14
|
#
|
13
15
|
# For example, `[[1, 2], [3, nil]].reject { |first, second| second.nil? }`
|
14
16
|
# and `[[1, 2], [3, nil]].compact` are not compatible. This will work fine
|
@@ -36,8 +38,8 @@ module RuboCop
|
|
36
38
|
extend AutoCorrector
|
37
39
|
|
38
40
|
MSG = 'Use `%<good>s` instead of `%<bad>s`.'
|
39
|
-
|
40
41
|
RESTRICT_ON_SEND = %i[reject reject! select select!].freeze
|
42
|
+
TO_ENUM_METHODS = %i[to_enum lazy].freeze
|
41
43
|
|
42
44
|
# @!method reject_method_with_block_pass?(node)
|
43
45
|
def_node_matcher :reject_method_with_block_pass?, <<~PATTERN
|
@@ -69,6 +71,7 @@ module RuboCop
|
|
69
71
|
|
70
72
|
def on_send(node)
|
71
73
|
return unless (range = offense_range(node))
|
74
|
+
return if target_ruby_version <= 3.0 && to_enum_method?(node)
|
72
75
|
|
73
76
|
good = good_method_name(node)
|
74
77
|
message = format(MSG, good: good, bad: range.source)
|
@@ -94,6 +97,12 @@ module RuboCop
|
|
94
97
|
end
|
95
98
|
end
|
96
99
|
|
100
|
+
def to_enum_method?(node)
|
101
|
+
return false unless node.receiver.send_type?
|
102
|
+
|
103
|
+
TO_ENUM_METHODS.include?(node.receiver.method_name)
|
104
|
+
end
|
105
|
+
|
97
106
|
def good_method_name(node)
|
98
107
|
if node.bang_method?
|
99
108
|
'compact!'
|
@@ -103,7 +112,7 @@ module RuboCop
|
|
103
112
|
end
|
104
113
|
|
105
114
|
def range(begin_pos_node, end_pos_node)
|
106
|
-
range_between(begin_pos_node.loc.selector.begin_pos, end_pos_node.loc.
|
115
|
+
range_between(begin_pos_node.loc.selector.begin_pos, end_pos_node.loc.expression.end_pos)
|
107
116
|
end
|
108
117
|
end
|
109
118
|
end
|
@@ -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|
|
@@ -10,6 +10,9 @@ module RuboCop
|
|
10
10
|
# one of `return`, `break`, `next`, `raise`, or `fail` is used
|
11
11
|
# in the body of the conditional expression.
|
12
12
|
#
|
13
|
+
# NOTE: Autocorrect works in most cases except with if-else statements
|
14
|
+
# that contain logical operators such as `foo || raise('exception')`
|
15
|
+
#
|
13
16
|
# @example
|
14
17
|
# # bad
|
15
18
|
# def test
|
@@ -90,6 +93,8 @@ module RuboCop
|
|
90
93
|
# end
|
91
94
|
#
|
92
95
|
class GuardClause < Base
|
96
|
+
extend AutoCorrector
|
97
|
+
include RangeHelp
|
93
98
|
include MinBodyLength
|
94
99
|
include StatementModifier
|
95
100
|
|
@@ -101,40 +106,49 @@ module RuboCop
|
|
101
106
|
|
102
107
|
return unless body
|
103
108
|
|
104
|
-
|
105
|
-
check_ending_if(body)
|
106
|
-
elsif body.begin_type?
|
107
|
-
final_expression = body.children.last
|
108
|
-
check_ending_if(final_expression) if final_expression&.if_type?
|
109
|
-
end
|
109
|
+
check_ending_body(body)
|
110
110
|
end
|
111
111
|
alias on_defs on_def
|
112
112
|
|
113
113
|
def on_if(node)
|
114
114
|
return if accepted_form?(node)
|
115
115
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
116
|
+
if (guard_clause = node.if_branch&.guard_clause?)
|
117
|
+
kw = node.loc.keyword.source
|
118
|
+
guard = :if
|
119
|
+
elsif (guard_clause = node.else_branch&.guard_clause?)
|
120
|
+
kw = node.inverse_keyword
|
121
|
+
guard = :else
|
122
|
+
else
|
123
|
+
return
|
124
|
+
end
|
120
125
|
|
121
|
-
|
122
|
-
node.loc.keyword.source
|
123
|
-
else
|
124
|
-
node.inverse_keyword
|
125
|
-
end
|
126
|
+
guard = nil if and_or_guard_clause?(guard_clause)
|
126
127
|
|
127
|
-
register_offense(node, guard_clause_source(guard_clause), kw)
|
128
|
+
register_offense(node, guard_clause_source(guard_clause), kw, guard)
|
128
129
|
end
|
129
130
|
|
130
131
|
private
|
131
132
|
|
133
|
+
def check_ending_body(body)
|
134
|
+
return if body.nil?
|
135
|
+
|
136
|
+
if body.if_type?
|
137
|
+
check_ending_if(body)
|
138
|
+
elsif body.begin_type?
|
139
|
+
final_expression = body.children.last
|
140
|
+
check_ending_if(final_expression) if final_expression&.if_type?
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
132
144
|
def check_ending_if(node)
|
133
145
|
return if accepted_form?(node, ending: true) || !min_body_length?(node)
|
134
146
|
return if allowed_consecutive_conditionals? &&
|
135
147
|
consecutive_conditionals?(node.parent, node)
|
136
148
|
|
137
149
|
register_offense(node, 'return', node.inverse_keyword)
|
150
|
+
|
151
|
+
check_ending_body(node.if_branch)
|
138
152
|
end
|
139
153
|
|
140
154
|
def consecutive_conditionals?(parent, node)
|
@@ -145,28 +159,78 @@ module RuboCop
|
|
145
159
|
end
|
146
160
|
end
|
147
161
|
|
148
|
-
def register_offense(node, scope_exiting_keyword, conditional_keyword)
|
162
|
+
def register_offense(node, scope_exiting_keyword, conditional_keyword, guard = nil)
|
149
163
|
condition, = node.node_parts
|
150
164
|
example = [scope_exiting_keyword, conditional_keyword, condition.source].join(' ')
|
151
165
|
if too_long_for_single_line?(node, example)
|
152
166
|
return if trivial?(node)
|
153
167
|
|
154
168
|
example = "#{conditional_keyword} #{condition.source}; #{scope_exiting_keyword}; end"
|
169
|
+
replacement = <<~RUBY.chomp
|
170
|
+
#{conditional_keyword} #{condition.source}
|
171
|
+
#{scope_exiting_keyword}
|
172
|
+
end
|
173
|
+
RUBY
|
174
|
+
end
|
175
|
+
|
176
|
+
add_offense(node.loc.keyword, message: format(MSG, example: example)) do |corrector|
|
177
|
+
next if node.else? && guard.nil?
|
178
|
+
|
179
|
+
autocorrect(corrector, node, condition, replacement || example, guard)
|
155
180
|
end
|
181
|
+
end
|
182
|
+
|
183
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
184
|
+
def autocorrect(corrector, node, condition, replacement, guard)
|
185
|
+
corrector.replace(node.loc.keyword.join(condition.loc.expression), replacement)
|
186
|
+
|
187
|
+
if_branch = node.if_branch
|
188
|
+
else_branch = node.else_branch
|
156
189
|
|
157
|
-
|
190
|
+
if if_branch&.send_type? && if_branch.last_argument&.heredoc?
|
191
|
+
autocorrect_heredoc_argument(corrector, node, if_branch, else_branch, guard)
|
192
|
+
elsif else_branch&.send_type? && else_branch.last_argument&.heredoc?
|
193
|
+
autocorrect_heredoc_argument(corrector, node, else_branch, if_branch, guard)
|
194
|
+
else
|
195
|
+
corrector.remove(node.loc.end)
|
196
|
+
return unless node.else?
|
197
|
+
|
198
|
+
corrector.remove(node.loc.else)
|
199
|
+
corrector.remove(branch_to_remove(node, guard))
|
200
|
+
end
|
158
201
|
end
|
202
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
159
203
|
|
160
|
-
def
|
161
|
-
|
204
|
+
def autocorrect_heredoc_argument(corrector, node, heredoc_branch, leave_branch, guard)
|
205
|
+
remove_whole_lines(corrector, leave_branch.source_range)
|
206
|
+
remove_whole_lines(corrector, node.loc.else)
|
207
|
+
remove_whole_lines(corrector, node.loc.end)
|
208
|
+
remove_whole_lines(corrector, branch_to_remove(node, guard).source_range)
|
209
|
+
corrector.insert_after(
|
210
|
+
heredoc_branch.last_argument.loc.heredoc_end, "\n#{leave_branch.source}"
|
211
|
+
)
|
212
|
+
end
|
162
213
|
|
163
|
-
|
214
|
+
def branch_to_remove(node, guard)
|
215
|
+
case guard
|
216
|
+
when :if then node.if_branch
|
217
|
+
when :else then node.else_branch
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def guard_clause_source(guard_clause)
|
222
|
+
if and_or_guard_clause?(guard_clause)
|
164
223
|
guard_clause.parent.source
|
165
224
|
else
|
166
225
|
guard_clause.source
|
167
226
|
end
|
168
227
|
end
|
169
228
|
|
229
|
+
def and_or_guard_clause?(guard_clause)
|
230
|
+
parent = guard_clause.parent
|
231
|
+
parent.and_type? || parent.or_type?
|
232
|
+
end
|
233
|
+
|
170
234
|
def too_long_for_single_line?(node, example)
|
171
235
|
max = max_line_length
|
172
236
|
max && node.source_range.column + example.length > max
|
@@ -181,7 +245,7 @@ module RuboCop
|
|
181
245
|
end
|
182
246
|
|
183
247
|
def accepted_if?(node, ending)
|
184
|
-
return true if node.modifier_form? || node.ternary?
|
248
|
+
return true if node.modifier_form? || node.ternary? || node.elsif_conditional?
|
185
249
|
|
186
250
|
if ending
|
187
251
|
node.else?
|
@@ -190,6 +254,10 @@ module RuboCop
|
|
190
254
|
end
|
191
255
|
end
|
192
256
|
|
257
|
+
def remove_whole_lines(corrector, range)
|
258
|
+
corrector.remove(range_by_whole_lines(range, include_final_newline: true))
|
259
|
+
end
|
260
|
+
|
193
261
|
def allowed_consecutive_conditionals?
|
194
262
|
cop_config.fetch('AllowConsecutiveConditionals', false)
|
195
263
|
end
|