rubocop 1.18.1 → 1.22.3
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 +116 -23
- data/lib/rubocop/cli.rb +18 -0
- data/lib/rubocop/config.rb +5 -0
- data/lib/rubocop/config_loader.rb +5 -3
- data/lib/rubocop/config_loader_resolver.rb +22 -7
- data/lib/rubocop/config_validator.rb +27 -6
- data/lib/rubocop/cop/base.rb +3 -3
- data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
- data/lib/rubocop/cop/bundler/gem_filename.rb +103 -0
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +45 -21
- data/lib/rubocop/cop/bundler/ordered_gems.rb +3 -12
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +11 -10
- data/lib/rubocop/cop/correctors/require_library_corrector.rb +23 -0
- data/lib/rubocop/cop/documentation.rb +1 -1
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +3 -12
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +31 -24
- data/lib/rubocop/cop/generator.rb +14 -8
- data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +34 -0
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +60 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +71 -0
- data/lib/rubocop/cop/internal_affairs.rb +3 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/assignment_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
- data/lib/rubocop/cop/layout/class_structure.rb +7 -2
- data/lib/rubocop/cop/layout/dot_position.rb +34 -5
- data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +9 -0
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +7 -4
- data/lib/rubocop/cop/layout/end_alignment.rb +9 -2
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +22 -18
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +0 -7
- data/lib/rubocop/cop/layout/indentation_style.rb +2 -2
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/leading_comment_space.rb +2 -2
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +36 -17
- data/lib/rubocop/cop/layout/line_length.rb +9 -7
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -3
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +3 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -0
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +23 -10
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +15 -4
- data/lib/rubocop/cop/layout/space_after_not.rb +1 -0
- data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_operators.rb +12 -1
- data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -0
- data/lib/rubocop/cop/layout/space_before_comment.rb +2 -2
- data/lib/rubocop/cop/layout/space_inside_parens.rb +78 -32
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +24 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +111 -0
- data/lib/rubocop/cop/lint/ambiguous_range.rb +105 -0
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +5 -2
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +7 -5
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +18 -5
- data/lib/rubocop/cop/lint/boolean_symbol.rb +5 -0
- data/lib/rubocop/cop/lint/debugger.rb +2 -4
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
- data/lib/rubocop/cop/lint/deprecated_constants.rb +3 -2
- data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +24 -1
- data/lib/rubocop/cop/lint/duplicate_branch.rb +2 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +8 -5
- data/lib/rubocop/cop/lint/else_layout.rb +10 -6
- data/lib/rubocop/cop/lint/empty_in_pattern.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +12 -3
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +67 -0
- data/lib/rubocop/cop/lint/interpolation_check.rb +5 -0
- data/lib/rubocop/cop/lint/loop.rb +4 -3
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +5 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +12 -1
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +4 -2
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -0
- data/lib/rubocop/cop/lint/percent_string_array.rb +10 -0
- data/lib/rubocop/cop/lint/raise_exception.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +5 -4
- data/lib/rubocop/cop/lint/require_relative_self_path.rb +50 -0
- data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -1
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
- data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/triple_quotes.rb +1 -1
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +8 -3
- data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -3
- data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -2
- data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
- data/lib/rubocop/cop/lint/useless_times.rb +5 -4
- data/lib/rubocop/cop/metrics/abc_size.rb +6 -0
- data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/mixin/annotation_comment.rb +57 -34
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
- data/lib/rubocop/cop/mixin/code_length.rb +1 -1
- data/lib/rubocop/cop/mixin/documentation_comment.rb +5 -2
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -2
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +23 -1
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +9 -4
- data/lib/rubocop/cop/mixin/heredoc.rb +5 -0
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +9 -1
- data/lib/rubocop/cop/mixin/percent_array.rb +18 -7
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +9 -1
- data/lib/rubocop/cop/mixin/require_library.rb +59 -0
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +2 -2
- data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
- data/lib/rubocop/cop/mixin/string_literals_help.rb +5 -1
- data/lib/rubocop/cop/mixin/trailing_body.rb +1 -1
- data/lib/rubocop/cop/naming/ascii_identifiers.rb +0 -3
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +1 -1
- data/lib/rubocop/cop/naming/inclusive_language.rb +27 -10
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +5 -4
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +7 -0
- data/lib/rubocop/cop/security/io_methods.rb +49 -0
- data/lib/rubocop/cop/security/json_load.rb +8 -7
- data/lib/rubocop/cop/security/open.rb +4 -0
- data/lib/rubocop/cop/security/yaml_load.rb +4 -0
- data/lib/rubocop/cop/style/accessor_grouping.rb +2 -2
- data/lib/rubocop/cop/style/and_or.rb +5 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +13 -2
- data/lib/rubocop/cop/style/array_coercion.rb +21 -3
- data/lib/rubocop/cop/style/ascii_comments.rb +0 -3
- data/lib/rubocop/cop/style/block_delimiters.rb +50 -2
- data/lib/rubocop/cop/style/case_equality.rb +6 -9
- data/lib/rubocop/cop/style/case_like_if.rb +5 -0
- data/lib/rubocop/cop/style/class_and_module_children.rb +9 -0
- data/lib/rubocop/cop/style/collection_compact.rb +7 -5
- data/lib/rubocop/cop/style/collection_methods.rb +8 -6
- data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
- data/lib/rubocop/cop/style/comment_annotation.rb +55 -25
- data/lib/rubocop/cop/style/commented_keyword.rb +9 -3
- data/lib/rubocop/cop/style/conditional_assignment.rb +19 -5
- data/lib/rubocop/cop/style/date_time.rb +5 -0
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
- data/lib/rubocop/cop/style/documentation.rb +23 -8
- data/lib/rubocop/cop/style/double_cop_disable_directive.rb +1 -7
- data/lib/rubocop/cop/style/double_negation.rb +27 -6
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/encoding.rb +26 -15
- data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +46 -11
- data/lib/rubocop/cop/style/float_division.rb +10 -2
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +14 -3
- data/lib/rubocop/cop/style/global_std_stream.rb +4 -0
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +11 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +5 -0
- data/lib/rubocop/cop/style/hash_except.rb +4 -3
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -9
- data/lib/rubocop/cop/style/hash_transform_values.rb +4 -6
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +32 -5
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +18 -4
- data/lib/rubocop/cop/style/infinite_loop.rb +4 -3
- data/lib/rubocop/cop/style/inverse_methods.rb +9 -2
- data/lib/rubocop/cop/style/lambda_call.rb +1 -1
- data/lib/rubocop/cop/style/line_end_concatenation.rb +14 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -6
- data/lib/rubocop/cop/style/method_def_parentheses.rb +10 -1
- data/lib/rubocop/cop/style/missing_else.rb +7 -0
- data/lib/rubocop/cop/style/module_function.rb +8 -9
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +1 -1
- data/lib/rubocop/cop/style/mutable_constant.rb +79 -14
- data/lib/rubocop/cop/style/negated_if.rb +1 -1
- data/lib/rubocop/cop/style/negated_unless.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +2 -2
- data/lib/rubocop/cop/style/not.rb +2 -2
- data/lib/rubocop/cop/style/numbered_parameters.rb +46 -0
- data/lib/rubocop/cop/style/numbered_parameters_limit.rb +50 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +7 -8
- data/lib/rubocop/cop/style/numeric_predicate.rb +5 -0
- data/lib/rubocop/cop/style/optional_arguments.rb +4 -0
- data/lib/rubocop/cop/style/optional_boolean_parameter.rb +14 -4
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
- data/lib/rubocop/cop/style/percent_q_literals.rb +2 -2
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -4
- data/lib/rubocop/cop/style/quoted_symbols.rb +10 -6
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +19 -9
- data/lib/rubocop/cop/style/redundant_begin.rb +25 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +2 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +4 -0
- data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +12 -3
- data/lib/rubocop/cop/style/redundant_freeze.rb +4 -4
- data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -3
- data/lib/rubocop/cop/style/redundant_self.rb +10 -0
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +4 -3
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +83 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +53 -20
- data/lib/rubocop/cop/style/regexp_literal.rb +3 -3
- data/lib/rubocop/cop/style/return_nil.rb +2 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +13 -2
- data/lib/rubocop/cop/style/select_by_regexp.rb +139 -0
- data/lib/rubocop/cop/style/semicolon.rb +32 -24
- data/lib/rubocop/cop/style/single_argument_dig.rb +5 -0
- data/lib/rubocop/cop/style/single_line_block_params.rb +3 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +25 -15
- data/lib/rubocop/cop/style/slicing_with_range.rb +13 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -0
- data/lib/rubocop/cop/style/special_global_vars.rb +25 -0
- data/lib/rubocop/cop/style/static_class.rb +5 -5
- data/lib/rubocop/cop/style/string_chars.rb +4 -2
- data/lib/rubocop/cop/style/string_concatenation.rb +5 -1
- data/lib/rubocop/cop/style/string_hash_keys.rb +4 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +4 -0
- data/lib/rubocop/cop/style/swap_values.rb +4 -2
- data/lib/rubocop/cop/style/symbol_array.rb +3 -3
- data/lib/rubocop/cop/style/symbol_proc.rb +26 -0
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +19 -0
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +23 -5
- data/lib/rubocop/cop/style/yoda_condition.rb +24 -7
- data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -0
- data/lib/rubocop/cop/util.rb +22 -6
- data/lib/rubocop/cops_documentation_generator.rb +17 -5
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -1
- data/lib/rubocop/magic_comment.rb +44 -15
- data/lib/rubocop/options.rb +127 -113
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/result_cache.rb +3 -3
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +6 -2
- data/lib/rubocop/rspec/parallel_formatter.rb +90 -0
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/runner.rb +2 -3
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +14 -2
- metadata +21 -5
@@ -65,9 +65,8 @@ module RuboCop
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def allowed_percent_q?(node)
|
68
|
-
node.source.start_with?(PERCENT_Q) && acceptable_q?(node) ||
|
69
|
-
node.source.start_with?(PERCENT_CAPITAL_Q) &&
|
70
|
-
acceptable_capital_q?(node)
|
68
|
+
(node.source.start_with?(PERCENT_Q) && acceptable_q?(node)) ||
|
69
|
+
(node.source.start_with?(PERCENT_CAPITAL_Q) && acceptable_capital_q?(node))
|
71
70
|
end
|
72
71
|
|
73
72
|
def message(node)
|
@@ -100,6 +100,10 @@ module RuboCop
|
|
100
100
|
add_lhs_to_local_variables_scopes(rhs, lhs)
|
101
101
|
end
|
102
102
|
|
103
|
+
def on_in_pattern(node)
|
104
|
+
add_match_var_scopes(node)
|
105
|
+
end
|
106
|
+
|
103
107
|
def on_send(node)
|
104
108
|
return unless node.self_receiver? && regular_method_call?(node)
|
105
109
|
return if node.parent&.mlhs_type?
|
@@ -185,6 +189,12 @@ module RuboCop
|
|
185
189
|
add_lhs_to_local_variables_scopes(rhs, child.to_a.first)
|
186
190
|
end
|
187
191
|
end
|
192
|
+
|
193
|
+
def add_match_var_scopes(in_pattern_node)
|
194
|
+
in_pattern_node.each_descendant(:match_var) do |match_var_node|
|
195
|
+
@local_variables_scopes[in_pattern_node] << match_var_node.children.first
|
196
|
+
end
|
197
|
+
end
|
188
198
|
end
|
189
199
|
end
|
190
200
|
end
|
@@ -6,9 +6,10 @@ module RuboCop
|
|
6
6
|
# This cop checks for places where redundant assignments are made for in place
|
7
7
|
# modification methods.
|
8
8
|
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
9
|
+
# @safety
|
10
|
+
# This cop is unsafe, because it can produce false positives for
|
11
|
+
# user defined methods having one of the expected names, but not modifying
|
12
|
+
# its receiver in place.
|
12
13
|
#
|
13
14
|
# @example
|
14
15
|
# # bad
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop checks for places where conditional branch makes redundant self-assignment.
|
7
|
+
#
|
8
|
+
# It only detects local variable because it may replace state of instance variable,
|
9
|
+
# class variable, and global variable that have state across methods with `nil`.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
#
|
13
|
+
# # bad
|
14
|
+
# foo = condition ? bar : foo
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# foo = bar if condition
|
18
|
+
#
|
19
|
+
# # bad
|
20
|
+
# foo = condition ? foo : bar
|
21
|
+
#
|
22
|
+
# # good
|
23
|
+
# foo = bar unless condition
|
24
|
+
#
|
25
|
+
class RedundantSelfAssignmentBranch < Base
|
26
|
+
include RangeHelp
|
27
|
+
extend AutoCorrector
|
28
|
+
|
29
|
+
MSG = 'Remove the self-assignment branch.'
|
30
|
+
|
31
|
+
# @!method bad_method?(node)
|
32
|
+
def_node_matcher :bad_method?, <<~PATTERN
|
33
|
+
(send nil? :bad_method ...)
|
34
|
+
PATTERN
|
35
|
+
|
36
|
+
def on_lvasgn(node)
|
37
|
+
variable, expression = *node
|
38
|
+
return unless use_if_and_else_branch?(expression)
|
39
|
+
|
40
|
+
if_branch = expression.if_branch
|
41
|
+
else_branch = expression.else_branch
|
42
|
+
return if inconvertible_to_modifier?(if_branch, else_branch)
|
43
|
+
|
44
|
+
if self_assign?(variable, if_branch)
|
45
|
+
register_offense(expression, if_branch, else_branch, 'unless')
|
46
|
+
elsif self_assign?(variable, else_branch)
|
47
|
+
register_offense(expression, else_branch, if_branch, 'if')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def use_if_and_else_branch?(expression)
|
54
|
+
return false unless expression&.if_type?
|
55
|
+
|
56
|
+
!expression.ternary? || !expression.else?
|
57
|
+
end
|
58
|
+
|
59
|
+
def inconvertible_to_modifier?(if_branch, else_branch)
|
60
|
+
multiple_statements?(if_branch) || multiple_statements?(else_branch) ||
|
61
|
+
(else_branch.respond_to?(:elsif?) && else_branch.elsif?)
|
62
|
+
end
|
63
|
+
|
64
|
+
def multiple_statements?(branch)
|
65
|
+
branch && branch.children.compact.count > 1
|
66
|
+
end
|
67
|
+
|
68
|
+
def self_assign?(variable, branch)
|
69
|
+
variable.to_s == branch&.source
|
70
|
+
end
|
71
|
+
|
72
|
+
def register_offense(if_node, offense_branch, opposite_branch, keyword)
|
73
|
+
add_offense(offense_branch) do |corrector|
|
74
|
+
assignment_value = opposite_branch ? opposite_branch.source : 'nil'
|
75
|
+
replacement = "#{assignment_value} #{keyword} #{if_node.condition.source}"
|
76
|
+
|
77
|
+
corrector.replace(if_node, replacement)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -12,6 +12,33 @@ module RuboCop
|
|
12
12
|
# `Enumerable#max_by` can replace `Enumerable#sort_by` calls
|
13
13
|
# after which only the first or last element is used.
|
14
14
|
#
|
15
|
+
# @safety
|
16
|
+
# This cop is unsafe, because `sort...last` and `max` may not return the
|
17
|
+
# same element in all cases.
|
18
|
+
#
|
19
|
+
# In an enumerable where there are multiple elements where `a <=> b == 0`,
|
20
|
+
# or where the transformation done by the `sort_by` block has the
|
21
|
+
# same result, `sort.last` and `max` (or `sort_by.last` and `max_by`)
|
22
|
+
# will return different elements. `sort.last` will return the last
|
23
|
+
# element but `max` will return the first element.
|
24
|
+
#
|
25
|
+
# For example:
|
26
|
+
#
|
27
|
+
# [source,ruby]
|
28
|
+
# ----
|
29
|
+
# class MyString < String; end
|
30
|
+
# strings = [MyString.new('test'), 'test']
|
31
|
+
# strings.sort.last.class #=> String
|
32
|
+
# strings.max.class #=> MyString
|
33
|
+
# ----
|
34
|
+
#
|
35
|
+
# [source,ruby]
|
36
|
+
# ----
|
37
|
+
# words = %w(dog horse mouse)
|
38
|
+
# words.sort_by { |word| word.length }.last #=> 'mouse'
|
39
|
+
# words.max_by { |word| word.length } #=> 'horse'
|
40
|
+
# ----
|
41
|
+
#
|
15
42
|
# @example
|
16
43
|
# # bad
|
17
44
|
# [2, 1, 3].sort.first
|
@@ -60,8 +87,8 @@ module RuboCop
|
|
60
87
|
# @!method redundant_sort?(node)
|
61
88
|
def_node_matcher :redundant_sort?, <<~MATCHER
|
62
89
|
{
|
63
|
-
(send $(send _ $:sort
|
64
|
-
(send $(send _ $:sort
|
90
|
+
(send $(send _ $:sort) ${:last :first})
|
91
|
+
(send $(send _ $:sort) ${:[] :at :slice} {(int 0) (int -1)})
|
65
92
|
|
66
93
|
(send $(send _ $:sort_by _) ${:last :first})
|
67
94
|
(send $(send _ $:sort_by _) ${:[] :at :slice} {(int 0) (int -1)})
|
@@ -75,33 +102,39 @@ module RuboCop
|
|
75
102
|
MATCHER
|
76
103
|
|
77
104
|
def on_send(node)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
ancestor = node.parent.parent
|
82
|
-
else
|
83
|
-
return
|
84
|
-
end
|
105
|
+
ancestor, sort_node, sorter, accessor =
|
106
|
+
find_redundant_sort(node.parent, node.parent&.parent)
|
107
|
+
return unless ancestor
|
85
108
|
|
86
|
-
|
109
|
+
register_offense(ancestor, sort_node, sorter, accessor)
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
87
113
|
|
88
|
-
|
89
|
-
|
114
|
+
def find_redundant_sort(*nodes)
|
115
|
+
nodes.each do |node|
|
116
|
+
if (sort_node, sorter, accessor = redundant_sort?(node))
|
117
|
+
return [node, sort_node, sorter, accessor]
|
118
|
+
end
|
90
119
|
end
|
120
|
+
|
121
|
+
nil
|
91
122
|
end
|
92
123
|
|
93
|
-
|
124
|
+
def register_offense(node, sort_node, sorter, accessor)
|
125
|
+
message = message(node, sorter, accessor)
|
94
126
|
|
95
|
-
|
96
|
-
|
97
|
-
|
127
|
+
add_offense(offense_range(sort_node, node), message: message) do |corrector|
|
128
|
+
# Remove accessor, e.g. `first` or `[-1]`.
|
129
|
+
corrector.remove(range_between(accessor_start(node), node.loc.expression.end_pos))
|
98
130
|
|
99
|
-
|
100
|
-
|
131
|
+
# Replace "sort" or "sort_by" with the appropriate min/max method.
|
132
|
+
corrector.replace(sort_node.loc.selector, suggestion(sorter, accessor, arg_value(node)))
|
133
|
+
end
|
101
134
|
end
|
102
135
|
|
103
|
-
def offense_range(sort_node,
|
104
|
-
range_between(sort_node.loc.selector.begin_pos,
|
136
|
+
def offense_range(sort_node, node)
|
137
|
+
range_between(sort_node.loc.selector.begin_pos, node.loc.expression.end_pos)
|
105
138
|
end
|
106
139
|
|
107
140
|
def message(node, sorter, accessor)
|
@@ -107,7 +107,7 @@ module RuboCop
|
|
107
107
|
private
|
108
108
|
|
109
109
|
def allowed_slash_literal?(node)
|
110
|
-
style == :slashes && !contains_disallowed_slash?(node) || allowed_mixed_slash?(node)
|
110
|
+
(style == :slashes && !contains_disallowed_slash?(node)) || allowed_mixed_slash?(node)
|
111
111
|
end
|
112
112
|
|
113
113
|
def allowed_mixed_slash?(node)
|
@@ -115,13 +115,13 @@ module RuboCop
|
|
115
115
|
end
|
116
116
|
|
117
117
|
def allowed_percent_r_literal?(node)
|
118
|
-
style == :slashes && contains_disallowed_slash?(node) ||
|
118
|
+
(style == :slashes && contains_disallowed_slash?(node)) ||
|
119
119
|
style == :percent_r ||
|
120
120
|
allowed_mixed_percent_r?(node) || allowed_omit_parentheses_with_percent_r_literal?(node)
|
121
121
|
end
|
122
122
|
|
123
123
|
def allowed_mixed_percent_r?(node)
|
124
|
-
style == :mixed && node.multiline? || contains_disallowed_slash?(node)
|
124
|
+
(style == :mixed && node.multiline?) || contains_disallowed_slash?(node)
|
125
125
|
end
|
126
126
|
|
127
127
|
def contains_disallowed_slash?(node)
|
@@ -74,7 +74,8 @@ module RuboCop
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def correct_style?(node)
|
77
|
-
style == :return && !return_nil_node?(node) ||
|
77
|
+
(style == :return && !return_nil_node?(node)) ||
|
78
|
+
(style == :return_nil && !return_node?(node))
|
78
79
|
end
|
79
80
|
|
80
81
|
def scoped_node?(node)
|
@@ -10,14 +10,25 @@ module RuboCop
|
|
10
10
|
# need to be changed to use safe navigation. We have limited the cop to
|
11
11
|
# not register an offense for method chains that exceed 2 methods.
|
12
12
|
#
|
13
|
-
#
|
14
|
-
#
|
13
|
+
# The default for `ConvertCodeThatCanStartToReturnNil` is `false`.
|
14
|
+
# When configured to `true`, this will
|
15
15
|
# check for code in the format `!foo.nil? && foo.bar`. As it is written,
|
16
16
|
# the return of this code is limited to `false` and whatever the return
|
17
17
|
# of the method is. If this is converted to safe navigation,
|
18
18
|
# `foo&.bar` can start returning `nil` as well as what the method
|
19
19
|
# returns.
|
20
20
|
#
|
21
|
+
# @safety
|
22
|
+
# Autocorrection is unsafe because if a value is `false`, the resulting
|
23
|
+
# code will have different behaviour or raise an error.
|
24
|
+
#
|
25
|
+
# [source,ruby]
|
26
|
+
# ----
|
27
|
+
# x = false
|
28
|
+
# x && x.foo # return false
|
29
|
+
# x&.foo # raises NoMethodError
|
30
|
+
# ----
|
31
|
+
#
|
21
32
|
# @example
|
22
33
|
# # bad
|
23
34
|
# foo.bar if foo
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop looks for places where an subset of an Enumerable (array,
|
7
|
+
# range, set, etc.; see note below) is calculated based on a `Regexp`
|
8
|
+
# match, and suggests `grep` or `grep_v` instead.
|
9
|
+
#
|
10
|
+
# NOTE: Hashes do not behave as you may expect with `grep`, which
|
11
|
+
# means that `hash.grep` is not equivalent to `hash.select`. Although
|
12
|
+
# RuboCop is limited by static analysis, this cop attempts to avoid
|
13
|
+
# registering an offense when the receiver is a hash (hash literal,
|
14
|
+
# `Hash.new`, `Hash#[]`, or `to_h`/`to_hash`).
|
15
|
+
#
|
16
|
+
# NOTE: `grep` and `grep_v` were optimized when used without a block
|
17
|
+
# in Ruby 3.0, but may be slower in previous versions.
|
18
|
+
# See https://bugs.ruby-lang.org/issues/17030
|
19
|
+
#
|
20
|
+
# @safety
|
21
|
+
# Autocorrection is marked as unsafe because `MatchData` will
|
22
|
+
# not be created by `grep`, but may have previously been relied
|
23
|
+
# upon after the `match?` or `=~` call.
|
24
|
+
#
|
25
|
+
# Additionally, the cop cannot guarantee that the receiver of
|
26
|
+
# `select` or `reject` is actually an array by static analysis,
|
27
|
+
# so the correction may not be actually equivalent.
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# # bad (select or find_all)
|
31
|
+
# array.select { |x| x.match? /regexp/ }
|
32
|
+
# array.select { |x| /regexp/.match?(x) }
|
33
|
+
# array.select { |x| x =~ /regexp/ }
|
34
|
+
# array.select { |x| /regexp/ =~ x }
|
35
|
+
#
|
36
|
+
# # bad (reject)
|
37
|
+
# array.reject { |x| x.match? /regexp/ }
|
38
|
+
# array.reject { |x| /regexp/.match?(x) }
|
39
|
+
# array.reject { |x| x =~ /regexp/ }
|
40
|
+
# array.reject { |x| /regexp/ =~ x }
|
41
|
+
#
|
42
|
+
# # good
|
43
|
+
# array.grep(regexp)
|
44
|
+
# array.grep_v(regexp)
|
45
|
+
class SelectByRegexp < Base
|
46
|
+
extend AutoCorrector
|
47
|
+
include RangeHelp
|
48
|
+
|
49
|
+
MSG = 'Prefer `%<replacement>s` to `%<original_method>s` with a regexp match.'
|
50
|
+
RESTRICT_ON_SEND = %i[select find_all reject].freeze
|
51
|
+
REPLACEMENTS = { select: 'grep', find_all: 'grep', reject: 'grep_v' }.freeze
|
52
|
+
REGEXP_METHODS = %i[match? =~].to_set.freeze
|
53
|
+
|
54
|
+
# @!method regexp_match?(node)
|
55
|
+
def_node_matcher :regexp_match?, <<~PATTERN
|
56
|
+
{
|
57
|
+
(block send (args (arg $_)) ${(send _ %REGEXP_METHODS _) match-with-lvasgn})
|
58
|
+
(numblock send $1 ${(send _ %REGEXP_METHODS _) match-with-lvasgn})
|
59
|
+
}
|
60
|
+
PATTERN
|
61
|
+
|
62
|
+
# Returns true if a node appears to return a hash
|
63
|
+
# @!method creates_hash?(node)
|
64
|
+
def_node_matcher :creates_hash?, <<~PATTERN
|
65
|
+
{
|
66
|
+
(send (const _ :Hash) {:new :[]} ...)
|
67
|
+
(block (send (const _ :Hash) :new ...) ...)
|
68
|
+
(send _ { :to_h :to_hash } ...)
|
69
|
+
}
|
70
|
+
PATTERN
|
71
|
+
|
72
|
+
# @!method calls_lvar?(node, name)
|
73
|
+
def_node_matcher :calls_lvar?, <<~PATTERN
|
74
|
+
{
|
75
|
+
(send (lvar %1) ...)
|
76
|
+
(send ... (lvar %1))
|
77
|
+
(match-with-lvasgn regexp (lvar %1))
|
78
|
+
}
|
79
|
+
PATTERN
|
80
|
+
|
81
|
+
def on_send(node)
|
82
|
+
return unless (block_node = node.block_node)
|
83
|
+
return if block_node.body.begin_type?
|
84
|
+
return if receiver_allowed?(block_node.receiver)
|
85
|
+
return unless (regexp_method_send_node = extract_send_node(block_node))
|
86
|
+
return if match_predicate_without_receiver?(regexp_method_send_node)
|
87
|
+
|
88
|
+
regexp = find_regexp(regexp_method_send_node, block_node)
|
89
|
+
register_offense(node, block_node, regexp)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def receiver_allowed?(node)
|
95
|
+
return false unless node
|
96
|
+
|
97
|
+
node.hash_type? || creates_hash?(node)
|
98
|
+
end
|
99
|
+
|
100
|
+
def register_offense(node, block_node, regexp)
|
101
|
+
replacement = REPLACEMENTS[node.method_name.to_sym]
|
102
|
+
message = format(MSG, replacement: replacement, original_method: node.method_name)
|
103
|
+
|
104
|
+
add_offense(block_node, message: message) do |corrector|
|
105
|
+
# Only correct if it can be determined what the regexp is
|
106
|
+
if regexp
|
107
|
+
range = range_between(node.loc.selector.begin_pos, block_node.loc.end.end_pos)
|
108
|
+
corrector.replace(range, "#{replacement}(#{regexp.source})")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def extract_send_node(block_node)
|
114
|
+
return unless (block_arg_name, regexp_method_send_node = regexp_match?(block_node))
|
115
|
+
|
116
|
+
block_arg_name = :"_#{block_arg_name}" if block_node.numblock_type?
|
117
|
+
return unless calls_lvar?(regexp_method_send_node, block_arg_name)
|
118
|
+
|
119
|
+
regexp_method_send_node
|
120
|
+
end
|
121
|
+
|
122
|
+
def find_regexp(node, block)
|
123
|
+
return node.child_nodes.first if node.match_with_lvasgn_type?
|
124
|
+
|
125
|
+
if node.receiver.lvar_type? &&
|
126
|
+
(block.numblock_type? || node.receiver.source == block.arguments.first.source)
|
127
|
+
node.first_argument
|
128
|
+
elsif node.first_argument.lvar_type?
|
129
|
+
node.receiver
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def match_predicate_without_receiver?(node)
|
134
|
+
node.send_type? && node.method?(:match?) && node.receiver.nil?
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -32,38 +32,29 @@ module RuboCop
|
|
32
32
|
|
33
33
|
MSG = 'Do not use semicolons to terminate expressions.'
|
34
34
|
|
35
|
+
def self.autocorrect_incompatible_with
|
36
|
+
[Style::SingleLineMethods]
|
37
|
+
end
|
38
|
+
|
35
39
|
def on_new_investigation
|
36
40
|
return if processed_source.blank?
|
37
41
|
|
38
|
-
@processed_source = processed_source
|
39
|
-
|
40
42
|
check_for_line_terminator_or_opener
|
41
43
|
end
|
42
44
|
|
43
|
-
def on_begin(node)
|
45
|
+
def on_begin(node)
|
44
46
|
return if cop_config['AllowAsExpressionSeparator']
|
45
47
|
|
46
48
|
exprs = node.children
|
47
49
|
|
48
50
|
return if exprs.size < 2
|
49
51
|
|
50
|
-
|
51
|
-
exprs_lines = exprs.map(&:first_line)
|
52
|
-
lines = exprs_lines.group_by(&:itself)
|
53
|
-
|
54
|
-
lines.each do |line, expr_on_line|
|
52
|
+
expressions_per_line(exprs).each do |line, expr_on_line|
|
55
53
|
# Every line with more than one expression on it is a
|
56
54
|
# potential offense
|
57
55
|
next unless expr_on_line.size > 1
|
58
56
|
|
59
|
-
|
60
|
-
# if the first semicolon on the line is a separator of
|
61
|
-
# expressions. It's just a guess.
|
62
|
-
column = @processed_source[line - 1].index(';')
|
63
|
-
|
64
|
-
next unless column
|
65
|
-
|
66
|
-
convention_on(line, column, false)
|
57
|
+
find_semicolon_positions(line) { |pos| register_semicolon(line, pos, true) }
|
67
58
|
end
|
68
59
|
end
|
69
60
|
|
@@ -71,9 +62,9 @@ module RuboCop
|
|
71
62
|
|
72
63
|
def check_for_line_terminator_or_opener
|
73
64
|
# Make the obvious check first
|
74
|
-
return unless
|
65
|
+
return unless processed_source.raw_source.include?(';')
|
75
66
|
|
76
|
-
each_semicolon { |line, column|
|
67
|
+
each_semicolon { |line, column| register_semicolon(line, column, false) }
|
77
68
|
end
|
78
69
|
|
79
70
|
def each_semicolon
|
@@ -84,15 +75,32 @@ module RuboCop
|
|
84
75
|
end
|
85
76
|
|
86
77
|
def tokens_for_lines
|
87
|
-
|
78
|
+
processed_source.tokens.group_by(&:line)
|
88
79
|
end
|
89
80
|
|
90
|
-
def
|
91
|
-
range = source_range(
|
92
|
-
|
93
|
-
# on the same line
|
81
|
+
def register_semicolon(line, column, after_expression)
|
82
|
+
range = source_range(processed_source.buffer, line, column)
|
83
|
+
|
94
84
|
add_offense(range) do |corrector|
|
95
|
-
|
85
|
+
if after_expression
|
86
|
+
corrector.replace(range, "\n")
|
87
|
+
else
|
88
|
+
corrector.remove(range)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def expressions_per_line(exprs)
|
94
|
+
# create a map matching lines to the number of expressions on them
|
95
|
+
exprs_lines = exprs.map(&:first_line)
|
96
|
+
exprs_lines.group_by(&:itself)
|
97
|
+
end
|
98
|
+
|
99
|
+
def find_semicolon_positions(line)
|
100
|
+
# Scan for all the semicolons on the line
|
101
|
+
semicolons = processed_source[line - 1].enum_for(:scan, ';')
|
102
|
+
semicolons.each do
|
103
|
+
yield Regexp.last_match.begin(0)
|
96
104
|
end
|
97
105
|
end
|
98
106
|
end
|
@@ -6,6 +6,11 @@ module RuboCop
|
|
6
6
|
# Sometimes using dig method ends up with just a single
|
7
7
|
# argument. In such cases, dig should be replaced with [].
|
8
8
|
#
|
9
|
+
# @safety
|
10
|
+
# This cop is unsafe because it cannot be guaranteed that the receiver
|
11
|
+
# is an `Enumerable` or does not have a nonstandard implementation
|
12
|
+
# of `dig`.
|
13
|
+
#
|
9
14
|
# @example
|
10
15
|
# # bad
|
11
16
|
# { key: 'value' }.dig(:key)
|
@@ -109,7 +109,9 @@ module RuboCop
|
|
109
109
|
# we remove any leading underscores before comparing.
|
110
110
|
actual_args_no_underscores = actual_args.map { |arg| arg.to_s.sub(/^_+/, '') }
|
111
111
|
|
112
|
-
|
112
|
+
# Allow the arguments if the names match but not all are given
|
113
|
+
expected_args = target_args(method_name).first(actual_args_no_underscores.size)
|
114
|
+
actual_args_no_underscores == expected_args
|
113
115
|
end
|
114
116
|
end
|
115
117
|
end
|
@@ -36,6 +36,7 @@ module RuboCop
|
|
36
36
|
extend AutoCorrector
|
37
37
|
|
38
38
|
MSG = 'Avoid single-line method definitions.'
|
39
|
+
NOT_SUPPORTED_ENDLESS_METHOD_BODY_TYPES = %i[return break next].freeze
|
39
40
|
|
40
41
|
def on_def(node)
|
41
42
|
return unless node.single_line?
|
@@ -62,29 +63,24 @@ module RuboCop
|
|
62
63
|
|
63
64
|
def correct_to_endless?(body_node)
|
64
65
|
return false if target_ruby_version < 3.0
|
65
|
-
|
66
|
-
endless_method_config = config.for_cop('Style/EndlessMethod')
|
67
|
-
|
68
|
-
return false unless endless_method_config['Enabled']
|
69
|
-
return false if endless_method_config['EnforcedStyle'] == 'disallow'
|
66
|
+
return false if disallow_endless_method_style?
|
70
67
|
return false unless body_node
|
71
|
-
return false if body_node.parent.assignment_method?
|
68
|
+
return false if body_node.parent.assignment_method? ||
|
69
|
+
NOT_SUPPORTED_ENDLESS_METHOD_BODY_TYPES.include?(body_node.type)
|
72
70
|
|
73
71
|
!(body_node.begin_type? || body_node.kwbegin_type?)
|
74
72
|
end
|
75
73
|
|
76
74
|
def correct_to_multiline(corrector, node)
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
75
|
+
if (body = node.body) && body.begin_type? && body.parenthesized_call?
|
76
|
+
break_line_before(corrector, node, body)
|
77
|
+
else
|
78
|
+
each_part(body) do |part|
|
79
|
+
break_line_before(corrector, node, part)
|
80
|
+
end
|
82
81
|
end
|
83
82
|
|
84
|
-
|
85
|
-
range: node.loc.end, node: node, corrector: corrector,
|
86
|
-
indent_steps: 0, configured_width: configured_indentation_width
|
87
|
-
)
|
83
|
+
break_line_before(corrector, node, node.loc.end, indent_steps: 0)
|
88
84
|
|
89
85
|
move_comment(node, corrector)
|
90
86
|
end
|
@@ -98,6 +94,13 @@ module RuboCop
|
|
98
94
|
corrector.replace(node, replacement)
|
99
95
|
end
|
100
96
|
|
97
|
+
def break_line_before(corrector, node, range, indent_steps: 1)
|
98
|
+
LineBreakCorrector.break_line_before(
|
99
|
+
range: range, node: node, corrector: corrector,
|
100
|
+
configured_width: configured_indentation_width, indent_steps: indent_steps
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
101
104
|
def each_part(body)
|
102
105
|
return unless body
|
103
106
|
|
@@ -129,6 +132,13 @@ module RuboCop
|
|
129
132
|
def require_parentheses?(method_body)
|
130
133
|
method_body.send_type? && !method_body.arguments.empty? && !method_body.comparison_method?
|
131
134
|
end
|
135
|
+
|
136
|
+
def disallow_endless_method_style?
|
137
|
+
endless_method_config = config.for_cop('Style/EndlessMethod')
|
138
|
+
return false unless endless_method_config['Enabled']
|
139
|
+
|
140
|
+
endless_method_config['EnforcedStyle'] == 'disallow'
|
141
|
+
end
|
132
142
|
end
|
133
143
|
end
|
134
144
|
end
|
@@ -6,6 +6,19 @@ module RuboCop
|
|
6
6
|
# This cop checks that arrays are sliced with endless ranges instead of
|
7
7
|
# `ary[start..-1]` on Ruby 2.6+.
|
8
8
|
#
|
9
|
+
# @safety
|
10
|
+
# This cop is unsafe because `x..-1` and `x..` are only guaranteed to
|
11
|
+
# be equivalent for `Array#[]`, and the cop cannot determine what class
|
12
|
+
# the receiver is.
|
13
|
+
#
|
14
|
+
# For example:
|
15
|
+
# [source,ruby]
|
16
|
+
# ----
|
17
|
+
# sum = proc { |ary| ary.sum }
|
18
|
+
# sum[-3..-1] # => -6
|
19
|
+
# sum[-3..] # Hangs forever
|
20
|
+
# ----
|
21
|
+
#
|
9
22
|
# @example
|
10
23
|
# # bad
|
11
24
|
# items[1..-1]
|
@@ -38,6 +38,10 @@ module RuboCop
|
|
38
38
|
|
39
39
|
MSG = 'Consider merging nested conditions into outer `%<conditional_type>s` conditions.'
|
40
40
|
|
41
|
+
def self.autocorrect_incompatible_with
|
42
|
+
[Style::NegatedIf, Style::NegatedUnless]
|
43
|
+
end
|
44
|
+
|
41
45
|
def on_if(node)
|
42
46
|
return if node.ternary? || node.else? || node.elsif?
|
43
47
|
|