rubocop 1.67.0 → 1.69.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +81 -6
- data/lib/rubocop/cached_data.rb +12 -4
- data/lib/rubocop/cli/command/execute_runner.rb +1 -1
- data/lib/rubocop/cli/command/version.rb +2 -2
- data/lib/rubocop/cop/autocorrect_logic.rb +22 -2
- data/lib/rubocop/cop/base.rb +1 -1
- data/lib/rubocop/cop/bundler/gem_filename.rb +0 -1
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +0 -1
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -12
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +2 -4
- data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +46 -0
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -2
- data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +1 -2
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +2 -3
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +3 -4
- data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +3 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +7 -7
- data/lib/rubocop/cop/layout/leading_comment_space.rb +44 -1
- data/lib/rubocop/cop/layout/line_length.rb +118 -4
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -3
- data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
- data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -35
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -2
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +16 -17
- data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -5
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +6 -0
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +4 -0
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +4 -0
- data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +11 -12
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -0
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_branch.rb +39 -4
- data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
- data/lib/rubocop/cop/lint/empty_file.rb +0 -2
- data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
- data/lib/rubocop/cop/lint/float_comparison.rb +14 -6
- data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -3
- data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
- data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
- data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +3 -0
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
- data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -5
- data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +8 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +106 -0
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -2
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +12 -7
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
- data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +9 -0
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +5 -1
- data/lib/rubocop/cop/lint/self_assignment.rb +8 -10
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +88 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
- data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
- data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
- data/lib/rubocop/cop/lint/void.rb +3 -2
- data/lib/rubocop/cop/metrics/class_length.rb +7 -7
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +4 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -2
- data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +10 -0
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
- data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
- data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +3 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +5 -9
- data/lib/rubocop/cop/mixin/range_help.rb +0 -1
- data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +6 -7
- data/lib/rubocop/cop/naming/file_name.rb +0 -2
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +11 -12
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -11
- data/lib/rubocop/cop/naming/variable_name.rb +3 -4
- data/lib/rubocop/cop/naming/variable_number.rb +2 -3
- data/lib/rubocop/cop/offense.rb +2 -3
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +53 -24
- data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +79 -0
- data/lib/rubocop/cop/style/array_intersect.rb +5 -4
- data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
- data/lib/rubocop/cop/style/block_delimiters.rb +18 -3
- data/lib/rubocop/cop/style/case_like_if.rb +8 -11
- data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
- data/lib/rubocop/cop/style/commented_keyword.rb +11 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +19 -21
- data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
- data/lib/rubocop/cop/style/dig_chain.rb +90 -0
- data/lib/rubocop/cop/style/endless_method.rb +1 -14
- data/lib/rubocop/cop/style/file_null.rb +73 -0
- data/lib/rubocop/cop/style/file_touch.rb +75 -0
- data/lib/rubocop/cop/style/for.rb +0 -1
- data/lib/rubocop/cop/style/global_vars.rb +1 -3
- data/lib/rubocop/cop/style/guard_clause.rb +15 -2
- data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
- data/lib/rubocop/cop/style/if_inside_else.rb +0 -1
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -2
- data/lib/rubocop/cop/style/if_with_semicolon.rb +14 -5
- data/lib/rubocop/cop/style/inverse_methods.rb +0 -1
- data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
- data/lib/rubocop/cop/style/lambda_call.rb +0 -1
- data/lib/rubocop/cop/style/map_into_array.rb +6 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +7 -11
- data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
- data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
- data/lib/rubocop/cop/style/multiple_comparison.rb +28 -39
- data/lib/rubocop/cop/style/mutable_constant.rb +4 -5
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +6 -4
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
- data/lib/rubocop/cop/style/not.rb +1 -1
- data/lib/rubocop/cop/style/one_line_conditional.rb +25 -4
- data/lib/rubocop/cop/style/operator_method_call.rb +5 -6
- data/lib/rubocop/cop/style/or_assignment.rb +3 -6
- data/lib/rubocop/cop/style/parallel_assignment.rb +8 -13
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +36 -21
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +21 -2
- data/lib/rubocop/cop/style/redundant_parentheses.rb +9 -11
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +1 -0
- data/lib/rubocop/cop/style/redundant_return.rb +2 -2
- data/lib/rubocop/cop/style/redundant_self.rb +7 -14
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +7 -5
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
- data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
- data/lib/rubocop/cop/style/rescue_modifier.rb +2 -3
- data/lib/rubocop/cop/style/safe_navigation.rb +13 -1
- data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
- data/lib/rubocop/cop/style/select_by_regexp.rb +1 -1
- data/lib/rubocop/cop/style/self_assignment.rb +11 -17
- data/lib/rubocop/cop/style/signal_exception.rb +2 -3
- data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +13 -3
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -3
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +0 -1
- data/lib/rubocop/cop/style/swap_values.rb +4 -15
- data/lib/rubocop/cop/style/ternary_parentheses.rb +25 -4
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
- data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
- data/lib/rubocop/cop/variable_force/assignment.rb +18 -3
- data/lib/rubocop/cop/variable_force/branch.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +5 -1
- data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
- data/lib/rubocop/cop/variable_force.rb +4 -10
- data/lib/rubocop/cops_documentation_generator.rb +20 -10
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
- data/lib/rubocop/runner.rb +16 -8
- data/lib/rubocop/target_ruby.rb +1 -1
- data/lib/rubocop/version.rb +27 -8
- data/lib/rubocop.rb +16 -0
- metadata +28 -12
@@ -4,8 +4,8 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
6
|
# Checks for uses of if/then/else/end constructs on a single line.
|
7
|
-
# AlwaysCorrectToMultiline config option can be set to true to
|
8
|
-
# multi-line constructs. When AlwaysCorrectToMultiline is false (default case) the
|
7
|
+
# `AlwaysCorrectToMultiline` config option can be set to true to autocorrect all offenses to
|
8
|
+
# multi-line constructs. When `AlwaysCorrectToMultiline` is false (default case) the
|
9
9
|
# autocorrect will first try converting them to ternary operators.
|
10
10
|
#
|
11
11
|
# @example
|
@@ -30,6 +30,25 @@ module RuboCop
|
|
30
30
|
# else
|
31
31
|
# baz
|
32
32
|
# end
|
33
|
+
#
|
34
|
+
# @example AlwaysCorrectToMultiline: false (default)
|
35
|
+
# # bad
|
36
|
+
# if cond then run else dont end
|
37
|
+
#
|
38
|
+
# # good
|
39
|
+
# cond ? run : dont
|
40
|
+
#
|
41
|
+
# @example AlwaysCorrectToMultiline: true
|
42
|
+
# # bad
|
43
|
+
# if cond then run else dont end
|
44
|
+
#
|
45
|
+
# # good
|
46
|
+
# if cond
|
47
|
+
# run
|
48
|
+
# else
|
49
|
+
# dont
|
50
|
+
# end
|
51
|
+
#
|
33
52
|
class OneLineConditional < Base
|
34
53
|
include Alignment
|
35
54
|
include ConfigurableEnforcedStyle
|
@@ -83,11 +102,13 @@ module RuboCop
|
|
83
102
|
end
|
84
103
|
|
85
104
|
def cannot_replace_to_ternary?(node)
|
86
|
-
node.elsif_conditional?
|
105
|
+
return true if node.elsif_conditional?
|
106
|
+
|
107
|
+
node.else_branch.begin_type? && node.else_branch.children.compact.count >= 2
|
87
108
|
end
|
88
109
|
|
89
110
|
def ternary_replacement(node)
|
90
|
-
condition, if_branch, else_branch = *node
|
111
|
+
condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
91
112
|
|
92
113
|
"#{expr_replacement(condition)} ? " \
|
93
114
|
"#{expr_replacement(if_branch)} : " \
|
@@ -31,10 +31,9 @@ module RuboCop
|
|
31
31
|
return unless (dot = node.loc.dot)
|
32
32
|
return if node.receiver.const_type? || !node.arguments.one?
|
33
33
|
|
34
|
-
|
35
|
-
if
|
36
|
-
|
37
|
-
end
|
34
|
+
return unless (rhs = node.first_argument)
|
35
|
+
return if method_call_with_parenthesized_arg?(rhs)
|
36
|
+
return if invalid_syntax_argument?(rhs)
|
38
37
|
|
39
38
|
add_offense(dot) do |corrector|
|
40
39
|
wrap_in_parentheses_if_chained(corrector, node)
|
@@ -73,7 +72,7 @@ module RuboCop
|
|
73
72
|
end
|
74
73
|
|
75
74
|
def insert_space_after?(node)
|
76
|
-
|
75
|
+
rhs = node.first_argument
|
77
76
|
selector = node.loc.selector
|
78
77
|
|
79
78
|
return true if selector.end_pos == rhs.source_range.begin_pos
|
@@ -82,7 +81,7 @@ module RuboCop
|
|
82
81
|
# For `/` operations, if the RHS starts with a `(` without space,
|
83
82
|
# add one to avoid a syntax error.
|
84
83
|
range = selector.end.join(rhs.source_range.begin)
|
85
|
-
return true if
|
84
|
+
return true if node.method?(:/) && range.source == '('
|
86
85
|
|
87
86
|
false
|
88
87
|
end
|
@@ -78,18 +78,15 @@ module RuboCop
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def take_variable_and_default_from_ternary(node)
|
81
|
-
|
82
|
-
[variable, if_statement.else_branch]
|
81
|
+
[node.name, node.expression.else_branch]
|
83
82
|
end
|
84
83
|
|
85
84
|
def take_variable_and_default_from_unless(node)
|
86
85
|
if node.if_branch
|
87
|
-
|
86
|
+
[node.if_branch.name, node.if_branch.expression]
|
88
87
|
else
|
89
|
-
|
88
|
+
[node.else_branch.name, node.else_branch.expression]
|
90
89
|
end
|
91
|
-
|
92
|
-
[variable, default]
|
93
90
|
end
|
94
91
|
end
|
95
92
|
end
|
@@ -28,28 +28,25 @@ module RuboCop
|
|
28
28
|
|
29
29
|
MSG = 'Do not use parallel assignment.'
|
30
30
|
|
31
|
-
def on_masgn(node)
|
32
|
-
|
33
|
-
lhs_elements = *lhs
|
31
|
+
def on_masgn(node) # rubocop:disable Metrics/AbcSize
|
32
|
+
rhs = node.rhs
|
34
33
|
rhs = rhs.body if rhs.rescue_type?
|
35
34
|
rhs_elements = Array(rhs).compact # edge case for one constant
|
36
35
|
|
37
|
-
return if allowed_lhs?(
|
38
|
-
allowed_masign?(
|
36
|
+
return if allowed_lhs?(node.assignments) || allowed_rhs?(rhs) ||
|
37
|
+
allowed_masign?(node.assignments, rhs_elements)
|
39
38
|
|
40
39
|
range = node.source_range.begin.join(rhs.source_range.end)
|
41
40
|
|
42
41
|
add_offense(range) do |corrector|
|
43
|
-
autocorrect(corrector, node,
|
42
|
+
autocorrect(corrector, node, rhs)
|
44
43
|
end
|
45
44
|
end
|
46
45
|
|
47
46
|
private
|
48
47
|
|
49
|
-
def autocorrect(corrector, node,
|
50
|
-
|
51
|
-
right_elements = Array(rhs).compact
|
52
|
-
order = find_valid_order(left_elements, right_elements)
|
48
|
+
def autocorrect(corrector, node, rhs)
|
49
|
+
order = find_valid_order(node.assignments, Array(rhs).compact)
|
53
50
|
correction = assignment_corrector(node, rhs, order)
|
54
51
|
|
55
52
|
corrector.replace(correction.correction_range, correction.correction)
|
@@ -61,9 +58,7 @@ module RuboCop
|
|
61
58
|
add_self_to_getters(rhs_elements))
|
62
59
|
end
|
63
60
|
|
64
|
-
def allowed_lhs?(
|
65
|
-
elements = *node
|
66
|
-
|
61
|
+
def allowed_lhs?(elements)
|
67
62
|
# Account for edge cases using one variable with a comma
|
68
63
|
# E.g.: `foo, = *bar`
|
69
64
|
elements.one? || elements.any?(&:splat_type?)
|
@@ -5,6 +5,19 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Checks for unnecessary conditional expressions.
|
7
7
|
#
|
8
|
+
# NOTE: Since the intention of the comment cannot be automatically determined,
|
9
|
+
# autocorrection is not applied when a comment is used, as shown below:
|
10
|
+
#
|
11
|
+
# [source,ruby]
|
12
|
+
# -----
|
13
|
+
# if b
|
14
|
+
# # Important note.
|
15
|
+
# b
|
16
|
+
# else
|
17
|
+
# c
|
18
|
+
# end
|
19
|
+
# -----
|
20
|
+
#
|
8
21
|
# @example
|
9
22
|
# # bad
|
10
23
|
# a = b ? b : c
|
@@ -30,6 +43,7 @@ module RuboCop
|
|
30
43
|
# end
|
31
44
|
#
|
32
45
|
class RedundantCondition < Base
|
46
|
+
include CommentsHelp
|
33
47
|
include RangeHelp
|
34
48
|
extend AutoCorrector
|
35
49
|
|
@@ -39,25 +53,15 @@ module RuboCop
|
|
39
53
|
splat block_pass forwarded_restarg forwarded_kwrestarg forwarded_args
|
40
54
|
].freeze
|
41
55
|
|
42
|
-
# rubocop:disable Metrics/AbcSize
|
43
56
|
def on_if(node)
|
44
57
|
return if node.modifier_form? || node.elsif_conditional? || !offense?(node)
|
45
58
|
|
46
59
|
message = message(node)
|
47
60
|
|
48
61
|
add_offense(range_of_offense(node), message: message) do |corrector|
|
49
|
-
|
50
|
-
correct_ternary(corrector, node)
|
51
|
-
elsif redundant_condition?(node)
|
52
|
-
corrector.replace(node, node.if_branch.source)
|
53
|
-
else
|
54
|
-
corrected = make_ternary_form(node)
|
55
|
-
|
56
|
-
corrector.replace(node, corrected)
|
57
|
-
end
|
62
|
+
autocorrect(corrector, node)
|
58
63
|
end
|
59
64
|
end
|
60
|
-
# rubocop:enable Metrics/AbcSize
|
61
65
|
|
62
66
|
private
|
63
67
|
|
@@ -69,6 +73,20 @@ module RuboCop
|
|
69
73
|
end
|
70
74
|
end
|
71
75
|
|
76
|
+
def autocorrect(corrector, node)
|
77
|
+
return if node.each_descendant.any? { |descendant| contains_comments?(descendant) }
|
78
|
+
|
79
|
+
if node.ternary? && !branches_have_method?(node)
|
80
|
+
correct_ternary(corrector, node)
|
81
|
+
elsif redundant_condition?(node)
|
82
|
+
corrector.replace(node, node.if_branch.source)
|
83
|
+
else
|
84
|
+
corrected = make_ternary_form(node)
|
85
|
+
|
86
|
+
corrector.replace(node, corrected)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
72
90
|
def range_of_offense(node)
|
73
91
|
return node.source_range unless node.ternary?
|
74
92
|
return node.source_range if node.ternary? && branches_have_method?(node)
|
@@ -77,8 +95,7 @@ module RuboCop
|
|
77
95
|
end
|
78
96
|
|
79
97
|
def offense?(node)
|
80
|
-
_condition, _if_branch, else_branch = *node
|
81
|
-
|
98
|
+
_condition, _if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
82
99
|
return false if use_if_branch?(else_branch) || use_hash_key_assignment?(else_branch)
|
83
100
|
|
84
101
|
synonymous_condition_and_branch?(node) && !node.elsif? &&
|
@@ -102,7 +119,7 @@ module RuboCop
|
|
102
119
|
end
|
103
120
|
|
104
121
|
def synonymous_condition_and_branch?(node)
|
105
|
-
condition, if_branch, _else_branch = *node
|
122
|
+
condition, if_branch, _else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
106
123
|
# e.g.
|
107
124
|
# if var
|
108
125
|
# var
|
@@ -130,7 +147,7 @@ module RuboCop
|
|
130
147
|
end
|
131
148
|
|
132
149
|
def branches_have_assignment?(node)
|
133
|
-
_condition, if_branch, else_branch = *node
|
150
|
+
_condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
134
151
|
|
135
152
|
return false unless if_branch && else_branch
|
136
153
|
|
@@ -144,12 +161,10 @@ module RuboCop
|
|
144
161
|
end
|
145
162
|
|
146
163
|
def branches_have_method?(node)
|
147
|
-
|
148
|
-
|
149
|
-
return false unless if_branch && else_branch
|
164
|
+
return false unless node.if_branch && node.else_branch
|
150
165
|
|
151
|
-
single_argument_method?(if_branch) && single_argument_method?(else_branch) &&
|
152
|
-
same_method?(if_branch, else_branch)
|
166
|
+
single_argument_method?(node.if_branch) && single_argument_method?(node.else_branch) &&
|
167
|
+
same_method?(node.if_branch, node.else_branch)
|
153
168
|
end
|
154
169
|
|
155
170
|
def single_argument_method?(node)
|
@@ -221,7 +236,7 @@ module RuboCop
|
|
221
236
|
end
|
222
237
|
|
223
238
|
def make_ternary_form(node)
|
224
|
-
_condition, if_branch, else_branch = *node
|
239
|
+
_condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
225
240
|
arithmetic_operation = use_arithmetic_operation?(if_branch)
|
226
241
|
|
227
242
|
ternary_form = [
|
@@ -69,6 +69,8 @@ module RuboCop
|
|
69
69
|
extend AutoCorrector
|
70
70
|
|
71
71
|
MSG = 'Redundant line continuation.'
|
72
|
+
LINE_CONTINUATION = '\\'
|
73
|
+
LINE_CONTINUATION_PATTERN = /(\\\n)/.freeze
|
72
74
|
ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
|
73
75
|
ARGUMENT_TYPES = %i[
|
74
76
|
kFALSE kNIL kSELF kTRUE tCONSTANT tCVAR tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR
|
@@ -79,7 +81,7 @@ module RuboCop
|
|
79
81
|
def on_new_investigation
|
80
82
|
return unless processed_source.ast
|
81
83
|
|
82
|
-
each_match_range(processed_source.ast.source_range,
|
84
|
+
each_match_range(processed_source.ast.source_range, LINE_CONTINUATION_PATTERN) do |range|
|
83
85
|
next if require_line_continuation?(range)
|
84
86
|
next unless redundant_line_continuation?(range)
|
85
87
|
|
@@ -87,6 +89,8 @@ module RuboCop
|
|
87
89
|
corrector.remove_leading(range, 1)
|
88
90
|
end
|
89
91
|
end
|
92
|
+
|
93
|
+
inspect_end_of_ruby_code_line_continuation
|
90
94
|
end
|
91
95
|
|
92
96
|
private
|
@@ -125,10 +129,25 @@ module RuboCop
|
|
125
129
|
return true unless (node = find_node_for_line(range.last_line))
|
126
130
|
return false if argument_newline?(node)
|
127
131
|
|
128
|
-
source = node.
|
132
|
+
source = node.source
|
133
|
+
while (node = node.parent)
|
134
|
+
source = node.source
|
135
|
+
end
|
129
136
|
parse(source.gsub("\\\n", "\n")).valid_syntax?
|
130
137
|
end
|
131
138
|
|
139
|
+
def inspect_end_of_ruby_code_line_continuation
|
140
|
+
last_line = processed_source.lines[processed_source.ast.last_line - 1]
|
141
|
+
return unless last_line.end_with?(LINE_CONTINUATION)
|
142
|
+
|
143
|
+
last_column = last_line.length
|
144
|
+
line_continuation_range = range_between(last_column - 1, last_column)
|
145
|
+
|
146
|
+
add_offense(line_continuation_range) do |corrector|
|
147
|
+
corrector.remove_trailing(line_continuation_range, 1)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
132
151
|
def inside_string_literal?(range, token)
|
133
152
|
ALLOWED_STRING_TOKENS.include?(token.type) && token.pos.overlaps?(range)
|
134
153
|
end
|
@@ -31,9 +31,6 @@ module RuboCop
|
|
31
31
|
# @!method allowed_pin_operator?(node)
|
32
32
|
def_node_matcher :allowed_pin_operator?, '^(pin (begin !{lvar ivar cvar gvar}))'
|
33
33
|
|
34
|
-
# @!method arg_in_call_with_block?(node)
|
35
|
-
def_node_matcher :arg_in_call_with_block?, '^^(block (send _ _ equal?(%0) ...) ...)'
|
36
|
-
|
37
34
|
def on_begin(node)
|
38
35
|
return if !parentheses?(node) || parens_allowed?(node) || ignore_syntax?(node)
|
39
36
|
|
@@ -59,7 +56,6 @@ module RuboCop
|
|
59
56
|
|
60
57
|
def allowed_expression?(node)
|
61
58
|
allowed_ancestor?(node) ||
|
62
|
-
allowed_method_call?(node) ||
|
63
59
|
allowed_multiple_expression?(node) ||
|
64
60
|
allowed_ternary?(node) ||
|
65
61
|
node.parent&.range_type?
|
@@ -70,11 +66,6 @@ module RuboCop
|
|
70
66
|
keyword_ancestor?(node) && parens_required?(node)
|
71
67
|
end
|
72
68
|
|
73
|
-
def allowed_method_call?(node)
|
74
|
-
# Don't flag `method (arg) { }`
|
75
|
-
arg_in_call_with_block?(node) && !parentheses?(node.parent)
|
76
|
-
end
|
77
|
-
|
78
69
|
def allowed_multiple_expression?(node)
|
79
70
|
return false if node.children.one?
|
80
71
|
|
@@ -156,7 +147,7 @@ module RuboCop
|
|
156
147
|
|
157
148
|
return if begin_node.chained?
|
158
149
|
|
159
|
-
if node.
|
150
|
+
if node.operator_keyword?
|
160
151
|
return if node.semantic_operator? && begin_node.parent
|
161
152
|
return if node.multiline? && allow_in_multiline_conditions?
|
162
153
|
return if ALLOWED_NODE_TYPES.include?(begin_node.parent&.type)
|
@@ -185,7 +176,8 @@ module RuboCop
|
|
185
176
|
return check_unary(begin_node, node) if node.unary_operation?
|
186
177
|
|
187
178
|
return unless method_call_with_redundant_parentheses?(node)
|
188
|
-
return if call_chain_starts_with_int?(begin_node, node)
|
179
|
+
return if call_chain_starts_with_int?(begin_node, node) ||
|
180
|
+
do_end_block_in_method_chain?(begin_node, node)
|
189
181
|
|
190
182
|
offense(begin_node, 'a method call')
|
191
183
|
end
|
@@ -285,6 +277,12 @@ module RuboCop
|
|
285
277
|
recv&.int_type? && (parent = begin_node.parent) &&
|
286
278
|
parent.send_type? && (parent.method?(:-@) || parent.method?(:+@))
|
287
279
|
end
|
280
|
+
|
281
|
+
def do_end_block_in_method_chain?(begin_node, node)
|
282
|
+
return false unless (block = node.each_descendant(:block, :numblock).first)
|
283
|
+
|
284
|
+
block.keywords? && begin_node.each_ancestor(:send, :csend).any?
|
285
|
+
end
|
288
286
|
end
|
289
287
|
end
|
290
288
|
end
|
@@ -61,9 +61,9 @@ module RuboCop
|
|
61
61
|
RESTRICT_ON_SEND = %i[define_method define_singleton_method lambda].freeze
|
62
62
|
|
63
63
|
def on_send(node)
|
64
|
-
return unless
|
64
|
+
return unless node.block_literal?
|
65
65
|
|
66
|
-
check_branch(parent.body)
|
66
|
+
check_branch(node.parent.body)
|
67
67
|
end
|
68
68
|
|
69
69
|
def on_def(node)
|
@@ -66,14 +66,12 @@ module RuboCop
|
|
66
66
|
# Assignment of self.x
|
67
67
|
|
68
68
|
def on_or_asgn(node)
|
69
|
-
lhs
|
70
|
-
allow_self(lhs)
|
69
|
+
allow_self(node.lhs)
|
71
70
|
end
|
72
71
|
alias on_and_asgn on_or_asgn
|
73
72
|
|
74
73
|
def on_op_asgn(node)
|
75
|
-
lhs
|
76
|
-
allow_self(lhs)
|
74
|
+
allow_self(node.lhs)
|
77
75
|
end
|
78
76
|
|
79
77
|
# Using self.x to distinguish from local variable x
|
@@ -92,13 +90,11 @@ module RuboCop
|
|
92
90
|
end
|
93
91
|
|
94
92
|
def on_masgn(node)
|
95
|
-
|
96
|
-
add_masgn_lhs_variables(rhs, lhs)
|
93
|
+
add_masgn_lhs_variables(node.rhs, node.lhs)
|
97
94
|
end
|
98
95
|
|
99
96
|
def on_lvasgn(node)
|
100
|
-
|
101
|
-
add_lhs_to_local_variables_scopes(rhs, lhs)
|
97
|
+
add_lhs_to_local_variables_scopes(node.rhs, node.lhs)
|
102
98
|
end
|
103
99
|
|
104
100
|
def on_in_pattern(node)
|
@@ -127,12 +123,10 @@ module RuboCop
|
|
127
123
|
# Allow conditional nodes to use `self` in the condition if that variable
|
128
124
|
# name is used in an `lvasgn` or `masgn` within the `if`.
|
129
125
|
node.child_nodes.each do |child_node|
|
130
|
-
lhs, _rhs = *child_node
|
131
|
-
|
132
126
|
if child_node.lvasgn_type?
|
133
|
-
add_lhs_to_local_variables_scopes(node.condition, lhs)
|
127
|
+
add_lhs_to_local_variables_scopes(node.condition, child_node.lhs)
|
134
128
|
elsif child_node.masgn_type?
|
135
|
-
add_masgn_lhs_variables(node.condition, lhs)
|
129
|
+
add_masgn_lhs_variables(node.condition, child_node.lhs)
|
136
130
|
end
|
137
131
|
end
|
138
132
|
end
|
@@ -182,8 +176,7 @@ module RuboCop
|
|
182
176
|
if node.mlhs_type?
|
183
177
|
on_args(node)
|
184
178
|
else
|
185
|
-
|
186
|
-
@local_variables_scopes[node] << name
|
179
|
+
@local_variables_scopes[node] << node.name
|
187
180
|
end
|
188
181
|
end
|
189
182
|
|
@@ -49,19 +49,21 @@ module RuboCop
|
|
49
49
|
gvasgn: :gvar
|
50
50
|
}.freeze
|
51
51
|
|
52
|
+
# rubocop:disable Metrics/AbcSize
|
52
53
|
def on_lvasgn(node)
|
53
|
-
|
54
|
-
|
55
|
-
return unless receiver
|
54
|
+
return unless (rhs = node.rhs)
|
55
|
+
return unless rhs.send_type? && method_returning_self?(rhs.method_name)
|
56
|
+
return unless (receiver = rhs.receiver)
|
56
57
|
|
57
58
|
receiver_type = ASSIGNMENT_TYPE_TO_RECEIVER_TYPE[node.type]
|
58
|
-
return unless receiver.type == receiver_type && receiver.children.first == lhs
|
59
|
+
return unless receiver.type == receiver_type && receiver.children.first == node.lhs
|
59
60
|
|
60
|
-
message = format(MSG, method_name: method_name)
|
61
|
+
message = format(MSG, method_name: rhs.method_name)
|
61
62
|
add_offense(node.loc.operator, message: message) do |corrector|
|
62
63
|
corrector.replace(node, rhs.source)
|
63
64
|
end
|
64
65
|
end
|
66
|
+
# rubocop:enable Metrics/AbcSize
|
65
67
|
alias on_ivasgn on_lvasgn
|
66
68
|
alias on_cvasgn on_lvasgn
|
67
69
|
alias on_gvasgn on_lvasgn
|
@@ -23,7 +23,6 @@ module RuboCop
|
|
23
23
|
# foo = bar unless condition
|
24
24
|
#
|
25
25
|
class RedundantSelfAssignmentBranch < Base
|
26
|
-
include RangeHelp
|
27
26
|
extend AutoCorrector
|
28
27
|
|
29
28
|
MSG = 'Remove the self-assignment branch.'
|
@@ -34,16 +33,17 @@ module RuboCop
|
|
34
33
|
PATTERN
|
35
34
|
|
36
35
|
def on_lvasgn(node)
|
37
|
-
|
36
|
+
expression = node.expression
|
37
|
+
|
38
38
|
return unless use_if_and_else_branch?(expression)
|
39
39
|
|
40
40
|
if_branch = expression.if_branch
|
41
41
|
else_branch = expression.else_branch
|
42
42
|
return if inconvertible_to_modifier?(if_branch, else_branch)
|
43
43
|
|
44
|
-
if self_assign?(
|
44
|
+
if self_assign?(node.name, if_branch)
|
45
45
|
register_offense(expression, if_branch, else_branch, 'unless')
|
46
|
-
elsif self_assign?(
|
46
|
+
elsif self_assign?(node.name, else_branch)
|
47
47
|
register_offense(expression, else_branch, if_branch, 'if')
|
48
48
|
end
|
49
49
|
end
|
@@ -68,8 +68,7 @@ module RuboCop
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def correct_rescue_block(corrector, node, parenthesized)
|
71
|
-
operation
|
72
|
-
*_, rescue_args = *rescue_modifier
|
71
|
+
operation = node.body
|
73
72
|
|
74
73
|
node_indentation, node_offset = indentation_and_offset(node, parenthesized)
|
75
74
|
|
@@ -78,7 +77,7 @@ module RuboCop
|
|
78
77
|
corrector.insert_after(heredoc_end(operation) || operation, <<~RESCUE_CLAUSE.chop)
|
79
78
|
|
80
79
|
#{node_offset}rescue
|
81
|
-
#{node_indentation}#{
|
80
|
+
#{node_indentation}#{node.resbody_branches.first.body.source}
|
82
81
|
#{node_offset}end
|
83
82
|
RESCUE_CLAUSE
|
84
83
|
end
|
@@ -21,6 +21,11 @@ module RuboCop
|
|
21
21
|
# We have limited the cop to not register an offense for method chains
|
22
22
|
# that exceed this option's value.
|
23
23
|
#
|
24
|
+
# NOTE: This cop will recognize offenses but not autocorrect code when the
|
25
|
+
# right hand side (RHS) of the `&&` statement is an `||` statement
|
26
|
+
# (eg. `foo && (foo.bar? || foo.baz?)`). It can be corrected
|
27
|
+
# manually by removing the `foo &&` and adding `&.` to each `foo` on the RHS.
|
28
|
+
#
|
24
29
|
# @safety
|
25
30
|
# Autocorrection is unsafe because if a value is `false`, the resulting
|
26
31
|
# code will have different behavior or raise an error.
|
@@ -121,6 +126,9 @@ module RuboCop
|
|
121
126
|
}
|
122
127
|
PATTERN
|
123
128
|
|
129
|
+
# @!method and_with_rhs_or?(node)
|
130
|
+
def_node_matcher :and_with_rhs_or?, '(and _ {or (begin or)})'
|
131
|
+
|
124
132
|
# @!method not_nil_check?(node)
|
125
133
|
def_node_matcher :not_nil_check?, '(send (send $_ :nil?) :!)'
|
126
134
|
|
@@ -172,6 +180,10 @@ module RuboCop
|
|
172
180
|
|
173
181
|
def report_offense(node, rhs, rhs_receiver, *removal_ranges, offense_range: node)
|
174
182
|
add_offense(offense_range) do |corrector|
|
183
|
+
# If the RHS is an `or` we cannot safely autocorrect because in order to remove
|
184
|
+
# the non-nil check we need to add safe-navs to all clauses where the receiver is used
|
185
|
+
next if and_with_rhs_or?(node)
|
186
|
+
|
175
187
|
removal_ranges.each { |range| corrector.remove(range) }
|
176
188
|
yield corrector if block_given?
|
177
189
|
|
@@ -300,7 +312,7 @@ module RuboCop
|
|
300
312
|
end
|
301
313
|
|
302
314
|
def chain_length(method_chain, method)
|
303
|
-
method.each_ancestor(:send).inject(0) do |total, ancestor|
|
315
|
+
method.each_ancestor(:send, :csend).inject(0) do |total, ancestor|
|
304
316
|
break total + 1 if ancestor == method_chain
|
305
317
|
|
306
318
|
total + 1
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Enforces safe navigation chains length to not exceed the configured maximum.
|
7
|
+
# The longer the chain is, the harder it becomes to track what on it could be
|
8
|
+
# returning `nil`.
|
9
|
+
#
|
10
|
+
# There is a potential interplay with `Style/SafeNavigation` - if both are enabled
|
11
|
+
# and their settings are "incompatible", one of the cops will complain about what
|
12
|
+
# the other proposes.
|
13
|
+
#
|
14
|
+
# E.g. if `Style/SafeNavigation` is configured with `MaxChainLength: 2` (default)
|
15
|
+
# and this cop is configured with `Max: 1`, then for `foo.bar.baz if foo` the former
|
16
|
+
# will suggest `foo&.bar&.baz`, which is an offense for the latter.
|
17
|
+
#
|
18
|
+
# @example Max: 2 (default)
|
19
|
+
# # bad
|
20
|
+
# user&.address&.zip&.upcase
|
21
|
+
#
|
22
|
+
# # good
|
23
|
+
# user&.address&.zip
|
24
|
+
# user.address.zip if user
|
25
|
+
#
|
26
|
+
class SafeNavigationChainLength < Base
|
27
|
+
MSG = 'Avoid safe navigation chains longer than %<max>d calls.'
|
28
|
+
|
29
|
+
def on_csend(node)
|
30
|
+
safe_navigation_chains = safe_navigation_chains(node)
|
31
|
+
return if safe_navigation_chains.size < max
|
32
|
+
|
33
|
+
add_offense(safe_navigation_chains.last, message: format(MSG, max: max))
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def safe_navigation_chains(node)
|
39
|
+
node.each_ancestor.with_object([]) do |parent, chains|
|
40
|
+
break chains unless parent.csend_type?
|
41
|
+
|
42
|
+
chains << parent
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def max
|
47
|
+
cop_config['Max'] || 2
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|