rubocop 1.39.0 → 1.44.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/config/default.yml +149 -11
- data/exe/rubocop +1 -1
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/comment_config.rb +5 -0
- data/lib/rubocop/config.rb +39 -15
- data/lib/rubocop/config_loader.rb +26 -20
- data/lib/rubocop/config_loader_resolver.rb +6 -2
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/badge.rb +9 -4
- data/lib/rubocop/cop/base.rb +84 -74
- data/lib/rubocop/cop/commissioner.rb +8 -3
- data/lib/rubocop/cop/cop.rb +29 -29
- data/lib/rubocop/cop/corrector.rb +30 -10
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +22 -6
- data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +1 -6
- data/lib/rubocop/cop/gemspec/dependency_version.rb +16 -18
- data/lib/rubocop/cop/gemspec/development_dependencies.rb +107 -0
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +11 -3
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/block_end_newline.rb +7 -1
- data/lib/rubocop/cop/layout/class_structure.rb +32 -11
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +2 -6
- data/lib/rubocop/cop/layout/comment_indentation.rb +3 -1
- data/lib/rubocop/cop/layout/empty_lines.rb +2 -0
- data/lib/rubocop/cop/layout/extra_spacing.rb +10 -6
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +38 -2
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +49 -2
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +61 -2
- data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +52 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +6 -9
- data/lib/rubocop/cop/layout/indentation_style.rb +7 -2
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +5 -0
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +11 -5
- data/lib/rubocop/cop/layout/line_length.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +51 -2
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +49 -2
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +53 -2
- data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +58 -2
- data/lib/rubocop/cop/layout/redundant_line_break.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +0 -2
- data/lib/rubocop/cop/layout/trailing_empty_lines.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +11 -4
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +4 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
- data/lib/rubocop/cop/lint/constant_resolution.rb +4 -0
- data/lib/rubocop/cop/lint/debugger.rb +3 -1
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +62 -112
- data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
- data/lib/rubocop/cop/lint/duplicate_branch.rb +0 -2
- data/lib/rubocop/cop/lint/duplicate_methods.rb +19 -8
- data/lib/rubocop/cop/lint/else_layout.rb +2 -6
- data/lib/rubocop/cop/lint/empty_block.rb +1 -5
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +11 -7
- data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +15 -17
- data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -5
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +19 -0
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +15 -3
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +11 -1
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +6 -0
- data/lib/rubocop/cop/lint/require_parentheses.rb +3 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +10 -12
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -4
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +4 -3
- data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -1
- data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -3
- data/lib/rubocop/cop/lint/useless_rescue.rb +85 -0
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +14 -4
- data/lib/rubocop/cop/lint/void.rb +25 -16
- data/lib/rubocop/cop/metrics/block_length.rb +9 -4
- data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +10 -5
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +9 -4
- data/lib/rubocop/cop/metrics/module_length.rb +10 -5
- data/lib/rubocop/cop/metrics/parameter_lists.rb +27 -0
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +3 -6
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +6 -3
- data/lib/rubocop/cop/mixin/alignment.rb +2 -2
- data/lib/rubocop/cop/mixin/allowed_identifiers.rb +2 -2
- data/lib/rubocop/cop/mixin/annotation_comment.rb +13 -6
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +21 -9
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +11 -7
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +59 -6
- data/lib/rubocop/cop/mixin/line_length_help.rb +11 -2
- data/lib/rubocop/cop/mixin/method_complexity.rb +5 -3
- data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +5 -3
- data/lib/rubocop/cop/mixin/percent_array.rb +3 -5
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/require_library.rb +2 -0
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -3
- data/lib/rubocop/cop/mixin/statement_modifier.rb +16 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +5 -1
- data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +2 -0
- data/lib/rubocop/cop/naming/inclusive_language.rb +4 -1
- data/lib/rubocop/cop/registry.rb +63 -43
- data/lib/rubocop/cop/security/compound_hash.rb +2 -1
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +18 -10
- data/lib/rubocop/cop/style/alias.rb +9 -1
- data/lib/rubocop/cop/style/array_intersect.rb +111 -0
- data/lib/rubocop/cop/style/block_comments.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +8 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +2 -9
- data/lib/rubocop/cop/style/comparable_clamp.rb +125 -0
- data/lib/rubocop/cop/style/concat_array_literals.rb +86 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +0 -6
- data/lib/rubocop/cop/style/documentation.rb +11 -5
- data/lib/rubocop/cop/style/guard_clause.rb +44 -9
- data/lib/rubocop/cop/style/hash_each_methods.rb +13 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +11 -7
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +15 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +4 -4
- data/lib/rubocop/cop/style/infinite_loop.rb +2 -5
- data/lib/rubocop/cop/style/inverse_methods.rb +2 -0
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +114 -0
- data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -1
- data/lib/rubocop/cop/style/map_to_set.rb +61 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +23 -14
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/method_def_parentheses.rb +11 -4
- data/lib/rubocop/cop/style/min_max_comparison.rb +83 -0
- data/lib/rubocop/cop/style/missing_else.rb +13 -1
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +0 -4
- data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -5
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/one_line_conditional.rb +3 -6
- data/lib/rubocop/cop/style/operator_method_call.rb +15 -1
- data/lib/rubocop/cop/style/parallel_assignment.rb +3 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +3 -0
- data/lib/rubocop/cop/style/redundant_conditional.rb +0 -4
- data/lib/rubocop/cop/style/redundant_constant_base.rb +85 -0
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +45 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
- 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 +6 -3
- data/lib/rubocop/cop/style/require_order.rb +135 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +35 -6
- data/lib/rubocop/cop/style/select_by_regexp.rb +13 -5
- data/lib/rubocop/cop/style/self_assignment.rb +2 -2
- data/lib/rubocop/cop/style/semicolon.rb +26 -3
- data/lib/rubocop/cop/style/signal_exception.rb +8 -6
- data/lib/rubocop/cop/style/string_hash_keys.rb +4 -1
- data/lib/rubocop/cop/style/string_literals.rb +1 -5
- data/lib/rubocop/cop/style/symbol_proc.rb +2 -4
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -4
- data/lib/rubocop/cop/style/word_array.rb +41 -0
- data/lib/rubocop/cop/style/yoda_expression.rb +81 -0
- data/lib/rubocop/cop/style/zero_length_predicate.rb +31 -14
- data/lib/rubocop/cop/team.rb +30 -30
- data/lib/rubocop/cop/util.rb +32 -5
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable_table.rb +3 -1
- data/lib/rubocop/cop/variable_force.rb +18 -30
- data/lib/rubocop/cops_documentation_generator.rb +33 -11
- data/lib/rubocop/directive_comment.rb +1 -1
- data/lib/rubocop/file_patterns.rb +43 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter.rb +4 -1
- data/lib/rubocop/options.rb +8 -0
- data/lib/rubocop/path_util.rb +50 -22
- data/lib/rubocop/result_cache.rb +2 -2
- data/lib/rubocop/rspec/cop_helper.rb +4 -1
- data/lib/rubocop/rspec/expect_offense.rb +6 -4
- data/lib/rubocop/rspec/support.rb +2 -2
- data/lib/rubocop/runner.rb +10 -3
- data/lib/rubocop/server/cache.rb +3 -1
- data/lib/rubocop/server/core.rb +1 -1
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/target_ruby.rb +1 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +23 -6
- metadata +23 -9
@@ -50,6 +50,11 @@ module RuboCop
|
|
50
50
|
# foo && foo.bar { |e| e.something }
|
51
51
|
# foo && foo.bar(param) { |e| e.something }
|
52
52
|
#
|
53
|
+
# foo ? foo.bar : nil
|
54
|
+
# foo.nil? ? nil : foo.bar
|
55
|
+
# !foo.nil? ? foo.bar : nil
|
56
|
+
# !foo ? nil : foo.bar
|
57
|
+
#
|
53
58
|
# # good
|
54
59
|
# foo&.bar
|
55
60
|
# foo&.bar&.baz
|
@@ -105,6 +110,17 @@ module RuboCop
|
|
105
110
|
}
|
106
111
|
PATTERN
|
107
112
|
|
113
|
+
# @!method ternary_safe_navigation_candidate(node)
|
114
|
+
def_node_matcher :ternary_safe_navigation_candidate, <<~PATTERN
|
115
|
+
{
|
116
|
+
(if (send $_ {:nil? :!}) nil $_)
|
117
|
+
|
118
|
+
(if (send (send $_ :nil?) :!) $_ nil)
|
119
|
+
|
120
|
+
(if $_ $_ nil)
|
121
|
+
}
|
122
|
+
PATTERN
|
123
|
+
|
108
124
|
# @!method not_nil_check?(node)
|
109
125
|
def_node_matcher :not_nil_check?, '(send (send $_ :nil?) :!)'
|
110
126
|
|
@@ -118,9 +134,11 @@ module RuboCop
|
|
118
134
|
check_node(node)
|
119
135
|
end
|
120
136
|
|
137
|
+
private
|
138
|
+
|
121
139
|
def check_node(node)
|
122
140
|
checked_variable, receiver, method_chain, method = extract_parts(node)
|
123
|
-
return
|
141
|
+
return if receiver != checked_variable || receiver.nil?
|
124
142
|
return if use_var_only_in_unless_modifier?(node, checked_variable)
|
125
143
|
return if chain_length(method_chain, method) > max_chain_length
|
126
144
|
return if unsafe_method_used?(method_chain, method)
|
@@ -133,10 +151,8 @@ module RuboCop
|
|
133
151
|
node.if_type? && node.unless? && !method_called?(variable)
|
134
152
|
end
|
135
153
|
|
136
|
-
private
|
137
|
-
|
138
154
|
def autocorrect(corrector, node)
|
139
|
-
body = node
|
155
|
+
body = extract_body(node)
|
140
156
|
method_call = method_call(node)
|
141
157
|
|
142
158
|
corrector.remove(begin_range(node, body))
|
@@ -147,6 +163,14 @@ module RuboCop
|
|
147
163
|
add_safe_nav_to_all_methods_in_chain(corrector, method_call, body)
|
148
164
|
end
|
149
165
|
|
166
|
+
def extract_body(node)
|
167
|
+
if node.if_type? && node.ternary?
|
168
|
+
node.branches.find { |branch| !branch.nil_type? }
|
169
|
+
else
|
170
|
+
node.node_parts[1]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
150
174
|
def handle_comments(corrector, node, method_call)
|
151
175
|
comments = comments(node)
|
152
176
|
return if comments.empty?
|
@@ -174,7 +198,7 @@ module RuboCop
|
|
174
198
|
end
|
175
199
|
|
176
200
|
def allowed_if_condition?(node)
|
177
|
-
node.else? || node.elsif?
|
201
|
+
node.else? || node.elsif?
|
178
202
|
end
|
179
203
|
|
180
204
|
def method_call(node)
|
@@ -192,7 +216,12 @@ module RuboCop
|
|
192
216
|
end
|
193
217
|
|
194
218
|
def extract_parts_from_if(node)
|
195
|
-
variable, receiver =
|
219
|
+
variable, receiver =
|
220
|
+
if node.ternary?
|
221
|
+
ternary_safe_navigation_candidate(node)
|
222
|
+
else
|
223
|
+
modifier_if_safe_navigation_candidate(node)
|
224
|
+
end
|
196
225
|
|
197
226
|
checked_variable, matching_receiver, method = extract_common_parts(receiver, variable)
|
198
227
|
|
@@ -49,7 +49,8 @@ module RuboCop
|
|
49
49
|
MSG = 'Prefer `%<replacement>s` to `%<original_method>s` with a regexp match.'
|
50
50
|
RESTRICT_ON_SEND = %i[select find_all reject].freeze
|
51
51
|
REPLACEMENTS = { select: 'grep', find_all: 'grep', reject: 'grep_v' }.freeze
|
52
|
-
|
52
|
+
OPPOSITE_REPLACEMENTS = { select: 'grep_v', find_all: 'grep_v', reject: 'grep' }.freeze
|
53
|
+
REGEXP_METHODS = %i[match? =~ !~].to_set.freeze
|
53
54
|
|
54
55
|
# @!method regexp_match?(node)
|
55
56
|
def_node_matcher :regexp_match?, <<~PATTERN
|
@@ -85,13 +86,15 @@ module RuboCop
|
|
85
86
|
|
86
87
|
def on_send(node)
|
87
88
|
return unless (block_node = node.block_node)
|
88
|
-
return if block_node.body
|
89
|
+
return if block_node.body&.begin_type?
|
89
90
|
return if receiver_allowed?(block_node.receiver)
|
90
91
|
return unless (regexp_method_send_node = extract_send_node(block_node))
|
91
92
|
return if match_predicate_without_receiver?(regexp_method_send_node)
|
92
93
|
|
94
|
+
opposite = opposite?(regexp_method_send_node)
|
93
95
|
regexp = find_regexp(regexp_method_send_node, block_node)
|
94
|
-
|
96
|
+
|
97
|
+
register_offense(node, block_node, regexp, opposite)
|
95
98
|
end
|
96
99
|
|
97
100
|
private
|
@@ -102,8 +105,9 @@ module RuboCop
|
|
102
105
|
node.hash_type? || creates_hash?(node) || env_const?(node)
|
103
106
|
end
|
104
107
|
|
105
|
-
def register_offense(node, block_node, regexp)
|
106
|
-
|
108
|
+
def register_offense(node, block_node, regexp, opposite)
|
109
|
+
method_name = node.method_name.to_sym
|
110
|
+
replacement = opposite ? OPPOSITE_REPLACEMENTS[method_name] : REPLACEMENTS[method_name]
|
107
111
|
message = format(MSG, replacement: replacement, original_method: node.method_name)
|
108
112
|
|
109
113
|
add_offense(block_node, message: message) do |corrector|
|
@@ -124,6 +128,10 @@ module RuboCop
|
|
124
128
|
regexp_method_send_node
|
125
129
|
end
|
126
130
|
|
131
|
+
def opposite?(regexp_method_send_node)
|
132
|
+
regexp_method_send_node.send_type? && regexp_method_send_node.method?(:!~)
|
133
|
+
end
|
134
|
+
|
127
135
|
def find_regexp(node, block)
|
128
136
|
return node.child_nodes.first if node.match_with_lvasgn_type?
|
129
137
|
|
@@ -42,7 +42,7 @@ module RuboCop
|
|
42
42
|
|
43
43
|
if rhs.send_type?
|
44
44
|
check_send_node(node, rhs, var_name, var_type)
|
45
|
-
elsif
|
45
|
+
elsif rhs.operator_keyword?
|
46
46
|
check_boolean_node(node, rhs, var_name, var_type)
|
47
47
|
end
|
48
48
|
end
|
@@ -76,7 +76,7 @@ module RuboCop
|
|
76
76
|
|
77
77
|
if rhs.send_type?
|
78
78
|
autocorrect_send_node(corrector, node, rhs)
|
79
|
-
elsif
|
79
|
+
elsif rhs.operator_keyword?
|
80
80
|
autocorrect_boolean_node(corrector, node, rhs)
|
81
81
|
end
|
82
82
|
end
|
@@ -37,13 +37,14 @@ module RuboCop
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def on_new_investigation
|
40
|
-
return if processed_source.blank?
|
40
|
+
return if processed_source.blank? || !processed_source.raw_source.include?(';')
|
41
41
|
|
42
42
|
check_for_line_terminator_or_opener
|
43
43
|
end
|
44
44
|
|
45
45
|
def on_begin(node)
|
46
46
|
return if cop_config['AllowAsExpressionSeparator']
|
47
|
+
return unless node.source.include?(';')
|
47
48
|
|
48
49
|
exprs = node.children
|
49
50
|
|
@@ -71,8 +72,10 @@ module RuboCop
|
|
71
72
|
|
72
73
|
def each_semicolon
|
73
74
|
tokens_for_lines.each do |line, tokens|
|
74
|
-
|
75
|
-
|
75
|
+
semicolon_pos = semicolon_position(tokens)
|
76
|
+
after_expr_pos = semicolon_pos == -1 ? -2 : semicolon_pos
|
77
|
+
|
78
|
+
yield line, tokens[semicolon_pos].column, tokens[after_expr_pos] if semicolon_pos
|
76
79
|
end
|
77
80
|
end
|
78
81
|
|
@@ -80,6 +83,26 @@ module RuboCop
|
|
80
83
|
processed_source.tokens.group_by(&:line)
|
81
84
|
end
|
82
85
|
|
86
|
+
def semicolon_position(tokens)
|
87
|
+
if tokens.last.semicolon?
|
88
|
+
-1
|
89
|
+
elsif tokens.first.semicolon?
|
90
|
+
0
|
91
|
+
elsif exist_semicolon_before_right_curly_brace?(tokens)
|
92
|
+
-3
|
93
|
+
elsif exist_semicolon_after_left_curly_brace?(tokens)
|
94
|
+
2
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def exist_semicolon_before_right_curly_brace?(tokens)
|
99
|
+
tokens[-2]&.right_curly_brace? && tokens[-3]&.semicolon?
|
100
|
+
end
|
101
|
+
|
102
|
+
def exist_semicolon_after_left_curly_brace?(tokens)
|
103
|
+
tokens[1]&.left_curly_brace? && tokens[2]&.semicolon?
|
104
|
+
end
|
105
|
+
|
83
106
|
def register_semicolon(line, column, after_expression, token_before_semicolon = nil)
|
84
107
|
range = source_range(processed_source.buffer, line, column)
|
85
108
|
|
@@ -119,11 +119,6 @@ module RuboCop
|
|
119
119
|
# @!method custom_fail_methods(node)
|
120
120
|
def_node_search :custom_fail_methods, '{(def :fail ...) (defs _ :fail ...)}'
|
121
121
|
|
122
|
-
def on_new_investigation
|
123
|
-
ast = processed_source.ast
|
124
|
-
@custom_fail_defined = ast && custom_fail_methods(ast).any?
|
125
|
-
end
|
126
|
-
|
127
122
|
def on_rescue(node)
|
128
123
|
return unless style == :semantic
|
129
124
|
|
@@ -141,7 +136,7 @@ module RuboCop
|
|
141
136
|
when :semantic
|
142
137
|
check_send(:raise, node) unless ignored_node?(node)
|
143
138
|
when :only_raise
|
144
|
-
return if
|
139
|
+
return if custom_fail_defined?
|
145
140
|
|
146
141
|
check_send(:fail, node)
|
147
142
|
when :only_fail
|
@@ -151,6 +146,13 @@ module RuboCop
|
|
151
146
|
|
152
147
|
private
|
153
148
|
|
149
|
+
def custom_fail_defined?
|
150
|
+
return @custom_fail_defined if defined?(@custom_fail_defined)
|
151
|
+
|
152
|
+
ast = processed_source.ast
|
153
|
+
@custom_fail_defined = ast && custom_fail_methods(ast).any?
|
154
|
+
end
|
155
|
+
|
154
156
|
def message(method_name)
|
155
157
|
case style
|
156
158
|
when :semantic
|
@@ -41,10 +41,13 @@ module RuboCop
|
|
41
41
|
|
42
42
|
def on_pair(node)
|
43
43
|
return unless string_hash_key?(node)
|
44
|
+
|
45
|
+
key_content = node.key.str_content
|
46
|
+
return unless key_content.valid_encoding?
|
44
47
|
return if receive_environments_method?(node)
|
45
48
|
|
46
49
|
add_offense(node.key) do |corrector|
|
47
|
-
symbol_content =
|
50
|
+
symbol_content = key_content.to_sym.inspect
|
48
51
|
|
49
52
|
corrector.replace(node.key, symbol_content)
|
50
53
|
end
|
@@ -95,11 +95,7 @@ module RuboCop
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def offense?(node)
|
98
|
-
|
99
|
-
# for this cop.
|
100
|
-
return false if inside_interpolation?(node)
|
101
|
-
|
102
|
-
wrong_quotes?(node)
|
98
|
+
wrong_quotes?(node) && !inside_interpolation?(node)
|
103
99
|
end
|
104
100
|
|
105
101
|
def consistent_multiline?
|
@@ -7,7 +7,7 @@ module RuboCop
|
|
7
7
|
#
|
8
8
|
# If you prefer a style that allows block for method with arguments,
|
9
9
|
# please set `true` to `AllowMethodsWithArguments`.
|
10
|
-
#
|
10
|
+
# `define_method?` methods are allowed by default.
|
11
11
|
# These are customizable with `AllowedMethods` option.
|
12
12
|
#
|
13
13
|
# @safety
|
@@ -72,12 +72,10 @@ module RuboCop
|
|
72
72
|
# # some comment
|
73
73
|
# end
|
74
74
|
#
|
75
|
-
# @example AllowedMethods: [
|
75
|
+
# @example AllowedMethods: [define_method] (default)
|
76
76
|
# # good
|
77
|
-
# respond_to { |foo| foo.bar }
|
78
77
|
# define_method(:foo) { |foo| foo.bar }
|
79
78
|
#
|
80
|
-
#
|
81
79
|
# @example AllowedPatterns: [] (default)
|
82
80
|
# # bad
|
83
81
|
# something.map { |s| s.upcase }
|
@@ -88,6 +88,10 @@ module RuboCop
|
|
88
88
|
include TrailingComma
|
89
89
|
extend AutoCorrector
|
90
90
|
|
91
|
+
def self.autocorrect_incompatible_with
|
92
|
+
[Layout::HeredocArgumentClosingParenthesis]
|
93
|
+
end
|
94
|
+
|
91
95
|
def on_send(node)
|
92
96
|
return unless node.arguments? && node.parenthesized?
|
93
97
|
|
@@ -96,10 +100,6 @@ module RuboCop
|
|
96
100
|
node.source_range.end_pos)
|
97
101
|
end
|
98
102
|
alias on_csend on_send
|
99
|
-
|
100
|
-
def self.autocorrect_incompatible_with
|
101
|
-
[Layout::HeredocArgumentClosingParenthesis]
|
102
|
-
end
|
103
103
|
end
|
104
104
|
end
|
105
105
|
end
|
@@ -27,6 +27,25 @@ module RuboCop
|
|
27
27
|
# # bad (contains spaces)
|
28
28
|
# %w[foo\ bar baz\ quux]
|
29
29
|
#
|
30
|
+
# # bad
|
31
|
+
# [
|
32
|
+
# ['one', 'One'],
|
33
|
+
# ['two', 'Two']
|
34
|
+
# ]
|
35
|
+
#
|
36
|
+
# # good
|
37
|
+
# [
|
38
|
+
# %w[one One],
|
39
|
+
# %w[two Two]
|
40
|
+
# ]
|
41
|
+
#
|
42
|
+
# # good (2d array containing spaces)
|
43
|
+
# [
|
44
|
+
# ['one', 'One'],
|
45
|
+
# ['two', 'Two'],
|
46
|
+
# ['forty two', 'Forty Two']
|
47
|
+
# ]
|
48
|
+
#
|
30
49
|
# @example EnforcedStyle: brackets
|
31
50
|
# # good
|
32
51
|
# ['foo', 'bar', 'baz']
|
@@ -36,6 +55,19 @@ module RuboCop
|
|
36
55
|
#
|
37
56
|
# # good (contains spaces)
|
38
57
|
# ['foo bar', 'baz quux']
|
58
|
+
#
|
59
|
+
# # good
|
60
|
+
# [
|
61
|
+
# ['one', 'One'],
|
62
|
+
# ['two', 'Two']
|
63
|
+
# ]
|
64
|
+
#
|
65
|
+
# # bad
|
66
|
+
# [
|
67
|
+
# %w[one One],
|
68
|
+
# %w[two Two]
|
69
|
+
# ]
|
70
|
+
#
|
39
71
|
class WordArray < Base
|
40
72
|
include ArrayMinSize
|
41
73
|
include ArraySyntax
|
@@ -53,6 +85,7 @@ module RuboCop
|
|
53
85
|
def on_array(node)
|
54
86
|
if bracketed_array_of?(:str, node)
|
55
87
|
return if complex_content?(node.values)
|
88
|
+
return if within_2d_array_of_complex_content?(node)
|
56
89
|
|
57
90
|
check_bracketed_array(node, 'w')
|
58
91
|
elsif node.percent_literal?(:string)
|
@@ -62,6 +95,14 @@ module RuboCop
|
|
62
95
|
|
63
96
|
private
|
64
97
|
|
98
|
+
def within_2d_array_of_complex_content?(node)
|
99
|
+
return false unless (parent = node.parent)
|
100
|
+
|
101
|
+
parent.array_type? &&
|
102
|
+
parent.values.all?(&:array_type?) &&
|
103
|
+
parent.values.any? { |subarray| complex_content?(subarray.values) }
|
104
|
+
end
|
105
|
+
|
65
106
|
def complex_content?(strings, complex_regex: word_regex)
|
66
107
|
strings.any? do |s|
|
67
108
|
next unless s.str_content
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Forbids Yoda expressions, i.e. binary operations (using `*`, `+`, `&`, `|`,
|
7
|
+
# and `^` operators) where the order of expression is reversed, eg. `1 + x`.
|
8
|
+
# This cop complements `Style/YodaCondition` cop, which has a similar purpose.
|
9
|
+
#
|
10
|
+
# This cop is disabled by default to respect user intentions such as:
|
11
|
+
#
|
12
|
+
# [source,ruby]
|
13
|
+
# ----
|
14
|
+
# config.server_port = 9000 + ENV["TEST_ENV_NUMBER"].to_i
|
15
|
+
# ----
|
16
|
+
#
|
17
|
+
# @safety
|
18
|
+
# This cop is unsafe because binary operators can be defined
|
19
|
+
# differently on different classes, and are not guaranteed to
|
20
|
+
# have the same result if reversed.
|
21
|
+
#
|
22
|
+
# @example SupportedOperators: ['*', '+', '&'']
|
23
|
+
# # bad
|
24
|
+
# 1 + x
|
25
|
+
# 10 * y
|
26
|
+
# 1 & z
|
27
|
+
#
|
28
|
+
# # good
|
29
|
+
# 60 * 24
|
30
|
+
# x + 1
|
31
|
+
# y * 10
|
32
|
+
# z & 1
|
33
|
+
#
|
34
|
+
# # good
|
35
|
+
# 1 | x
|
36
|
+
#
|
37
|
+
class YodaExpression < Base
|
38
|
+
extend AutoCorrector
|
39
|
+
|
40
|
+
MSG = 'Non-literal operand (`%<source>s`) should be first.'
|
41
|
+
|
42
|
+
RESTRICT_ON_SEND = %i[* + & | ^].freeze
|
43
|
+
|
44
|
+
def on_new_investigation
|
45
|
+
@offended_nodes = nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def on_send(node)
|
49
|
+
return unless supported_operators.include?(node.method_name.to_s)
|
50
|
+
|
51
|
+
lhs = node.receiver
|
52
|
+
rhs = node.first_argument
|
53
|
+
return if !lhs.numeric_type? || rhs.numeric_type?
|
54
|
+
|
55
|
+
return if offended_ancestor?(node)
|
56
|
+
|
57
|
+
message = format(MSG, source: rhs.source)
|
58
|
+
add_offense(node, message: message) do |corrector|
|
59
|
+
corrector.swap(lhs, rhs)
|
60
|
+
end
|
61
|
+
|
62
|
+
offended_nodes.add(node)
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def supported_operators
|
68
|
+
Array(cop_config['SupportedOperators'])
|
69
|
+
end
|
70
|
+
|
71
|
+
def offended_ancestor?(node)
|
72
|
+
node.each_ancestor(:send).any? { |ancestor| @offended_nodes&.include?(ancestor) }
|
73
|
+
end
|
74
|
+
|
75
|
+
def offended_nodes
|
76
|
+
@offended_nodes ||= Set.new.compare_by_identity
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -34,43 +34,55 @@ module RuboCop
|
|
34
34
|
class ZeroLengthPredicate < Base
|
35
35
|
extend AutoCorrector
|
36
36
|
|
37
|
-
ZERO_MSG = 'Use `empty?` instead of `%<
|
38
|
-
NONZERO_MSG = 'Use `!empty?` instead of `%<
|
37
|
+
ZERO_MSG = 'Use `empty?` instead of `%<current>s`.'
|
38
|
+
NONZERO_MSG = 'Use `!empty?` instead of `%<current>s`.'
|
39
39
|
|
40
40
|
RESTRICT_ON_SEND = %i[size length].freeze
|
41
41
|
|
42
42
|
def on_send(node)
|
43
43
|
check_zero_length_predicate(node)
|
44
|
-
|
44
|
+
check_zero_length_comparison(node)
|
45
|
+
check_nonzero_length_comparison(node)
|
45
46
|
end
|
46
47
|
|
47
48
|
private
|
48
49
|
|
49
50
|
def check_zero_length_predicate(node)
|
50
|
-
|
51
|
-
return unless zero_length_predicate
|
51
|
+
return unless (length_method = zero_length_predicate(node.parent))
|
52
52
|
|
53
|
-
|
53
|
+
offense = node.loc.selector.join(node.parent.source_range.end)
|
54
|
+
message = format(ZERO_MSG, current: "#{length_method}.zero?")
|
55
|
+
|
56
|
+
add_offense(offense, message: message) do |corrector|
|
57
|
+
corrector.replace(offense, 'empty?')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def check_zero_length_comparison(node)
|
62
|
+
zero_length_comparison = zero_length_comparison(node.parent)
|
63
|
+
return unless zero_length_comparison
|
64
|
+
|
65
|
+
lhs, opr, rhs = zero_length_comparison
|
54
66
|
|
55
67
|
return if non_polymorphic_collection?(node.parent)
|
56
68
|
|
57
69
|
add_offense(
|
58
|
-
node.parent, message: format(ZERO_MSG,
|
70
|
+
node.parent, message: format(ZERO_MSG, current: "#{lhs} #{opr} #{rhs}")
|
59
71
|
) do |corrector|
|
60
72
|
corrector.replace(node.parent, replacement(node.parent))
|
61
73
|
end
|
62
74
|
end
|
63
75
|
|
64
|
-
def
|
65
|
-
|
66
|
-
return unless
|
76
|
+
def check_nonzero_length_comparison(node)
|
77
|
+
nonzero_length_comparison = nonzero_length_comparison(node.parent)
|
78
|
+
return unless nonzero_length_comparison
|
67
79
|
|
68
|
-
lhs, opr, rhs =
|
80
|
+
lhs, opr, rhs = nonzero_length_comparison
|
69
81
|
|
70
82
|
return if non_polymorphic_collection?(node.parent)
|
71
83
|
|
72
84
|
add_offense(
|
73
|
-
node.parent, message: format(NONZERO_MSG,
|
85
|
+
node.parent, message: format(NONZERO_MSG, current: "#{lhs} #{opr} #{rhs}")
|
74
86
|
) do |corrector|
|
75
87
|
corrector.replace(node.parent, replacement(node.parent))
|
76
88
|
end
|
@@ -78,14 +90,19 @@ module RuboCop
|
|
78
90
|
|
79
91
|
# @!method zero_length_predicate(node)
|
80
92
|
def_node_matcher :zero_length_predicate, <<~PATTERN
|
93
|
+
(send (send (...) ${:length :size}) :zero?)
|
94
|
+
PATTERN
|
95
|
+
|
96
|
+
# @!method zero_length_comparison(node)
|
97
|
+
def_node_matcher :zero_length_comparison, <<~PATTERN
|
81
98
|
{(send (send (...) ${:length :size}) $:== (int $0))
|
82
99
|
(send (int $0) $:== (send (...) ${:length :size}))
|
83
100
|
(send (send (...) ${:length :size}) $:< (int $1))
|
84
101
|
(send (int $1) $:> (send (...) ${:length :size}))}
|
85
102
|
PATTERN
|
86
103
|
|
87
|
-
# @!method
|
88
|
-
def_node_matcher :
|
104
|
+
# @!method nonzero_length_comparison(node)
|
105
|
+
def_node_matcher :nonzero_length_comparison, <<~PATTERN
|
89
106
|
{(send (send (...) ${:length :size}) ${:> :!=} (int $0))
|
90
107
|
(send (int $0) ${:< :!=} (send (...) ${:length :size}))}
|
91
108
|
PATTERN
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -10,20 +10,6 @@ module RuboCop
|
|
10
10
|
# first the ones needed for autocorrection (if any), then the rest
|
11
11
|
# (unless autocorrections happened).
|
12
12
|
class Team
|
13
|
-
attr_reader :errors, :warnings, :updated_source_file, :cops
|
14
|
-
|
15
|
-
alias updated_source_file? updated_source_file
|
16
|
-
|
17
|
-
def initialize(cops, config = nil, options = {})
|
18
|
-
@cops = cops
|
19
|
-
@config = config
|
20
|
-
@options = options
|
21
|
-
reset
|
22
|
-
@ready = true
|
23
|
-
|
24
|
-
validate_config
|
25
|
-
end
|
26
|
-
|
27
13
|
# @return [Team]
|
28
14
|
def self.new(cop_or_classes, config, options = {})
|
29
15
|
# Support v0 api:
|
@@ -38,7 +24,7 @@ module RuboCop
|
|
38
24
|
new(cops, config, options)
|
39
25
|
end
|
40
26
|
|
41
|
-
# @return [Array<Cop::
|
27
|
+
# @return [Array<Cop::Base>]
|
42
28
|
def self.mobilize_cops(cop_classes, config, options = {})
|
43
29
|
cop_classes = Registry.new(cop_classes.to_a, options) unless cop_classes.is_a?(Registry)
|
44
30
|
|
@@ -47,6 +33,35 @@ module RuboCop
|
|
47
33
|
end
|
48
34
|
end
|
49
35
|
|
36
|
+
# @return [Array<Force>] needed for the given cops
|
37
|
+
def self.forces_for(cops)
|
38
|
+
needed = Hash.new { |h, k| h[k] = [] }
|
39
|
+
cops.each do |cop|
|
40
|
+
forces = cop.class.joining_forces
|
41
|
+
if forces.is_a?(Array)
|
42
|
+
forces.each { |force| needed[force] << cop }
|
43
|
+
elsif forces
|
44
|
+
needed[forces] << cop
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
needed.map { |force_class, joining_cops| force_class.new(joining_cops) }
|
49
|
+
end
|
50
|
+
|
51
|
+
attr_reader :errors, :warnings, :updated_source_file, :cops
|
52
|
+
|
53
|
+
alias updated_source_file? updated_source_file
|
54
|
+
|
55
|
+
def initialize(cops, config = nil, options = {})
|
56
|
+
@cops = cops
|
57
|
+
@config = config
|
58
|
+
@options = options
|
59
|
+
reset
|
60
|
+
@ready = true
|
61
|
+
|
62
|
+
validate_config
|
63
|
+
end
|
64
|
+
|
50
65
|
def autocorrect?
|
51
66
|
@options[:autocorrect]
|
52
67
|
end
|
@@ -94,21 +109,6 @@ module RuboCop
|
|
94
109
|
@forces ||= self.class.forces_for(cops)
|
95
110
|
end
|
96
111
|
|
97
|
-
# @return [Array<Force>] needed for the given cops
|
98
|
-
def self.forces_for(cops)
|
99
|
-
needed = Hash.new { |h, k| h[k] = [] }
|
100
|
-
cops.each do |cop|
|
101
|
-
forces = cop.class.joining_forces
|
102
|
-
if forces.is_a?(Array)
|
103
|
-
forces.each { |force| needed[force] << cop }
|
104
|
-
elsif forces
|
105
|
-
needed[forces] << cop
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
needed.map { |force_class, joining_cops| force_class.new(joining_cops) }
|
110
|
-
end
|
111
|
-
|
112
112
|
def external_dependency_checksum
|
113
113
|
keys = cops.map(&:external_dependency_checksum).compact
|
114
114
|
Digest::SHA1.hexdigest(keys.join)
|