rubocop 0.46.0 → 0.47.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +77 -2
- data/config/default.yml +151 -74
- data/config/disabled.yml +9 -0
- data/config/enabled.yml +49 -9
- data/lib/rubocop.rb +36 -8
- data/lib/rubocop/ast/builder.rb +59 -0
- data/lib/rubocop/ast/node.rb +607 -0
- data/lib/rubocop/ast/node/array_node.rb +45 -0
- data/lib/rubocop/ast/node/case_node.rb +63 -0
- data/lib/rubocop/ast/node/for_node.rb +53 -0
- data/lib/rubocop/ast/node/hash_node.rb +102 -0
- data/lib/rubocop/ast/node/if_node.rb +136 -0
- data/lib/rubocop/ast/node/keyword_splat_node.rb +45 -0
- data/lib/rubocop/ast/node/mixin/conditional_node.rb +45 -0
- data/lib/rubocop/ast/node/mixin/hash_element_node.rb +125 -0
- data/lib/rubocop/ast/node/mixin/modifier_node.rb +17 -0
- data/lib/rubocop/ast/node/pair_node.rb +64 -0
- data/lib/rubocop/ast/node/until_node.rb +43 -0
- data/lib/rubocop/ast/node/when_node.rb +61 -0
- data/lib/rubocop/ast/node/while_node.rb +43 -0
- data/lib/rubocop/ast/sexp.rb +16 -0
- data/lib/rubocop/{ast_node → ast}/traversal.rb +1 -1
- data/lib/rubocop/cli.rb +18 -14
- data/lib/rubocop/comment_config.rb +1 -3
- data/lib/rubocop/config.rb +93 -35
- data/lib/rubocop/config_loader.rb +1 -1
- data/lib/rubocop/cop/badge.rb +73 -0
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
- data/lib/rubocop/cop/bundler/ordered_gems.rb +43 -3
- data/lib/rubocop/cop/commissioner.rb +17 -6
- data/lib/rubocop/cop/cop.rb +25 -112
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +9 -4
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +7 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +18 -4
- data/lib/rubocop/cop/lint/block_alignment.rb +40 -9
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +14 -0
- data/lib/rubocop/cop/lint/condition_position.rb +14 -16
- data/lib/rubocop/cop/lint/debugger.rb +28 -0
- data/lib/rubocop/cop/lint/def_end_alignment.rb +21 -1
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +13 -1
- data/lib/rubocop/cop/lint/duplicate_case_condition.rb +26 -22
- data/lib/rubocop/cop/lint/duplicate_methods.rb +15 -1
- data/lib/rubocop/cop/lint/duplicated_key.rb +16 -8
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +9 -0
- data/lib/rubocop/cop/lint/else_layout.rb +26 -29
- data/lib/rubocop/cop/lint/empty_ensure.rb +38 -0
- data/lib/rubocop/cop/lint/empty_expression.rb +11 -1
- data/lib/rubocop/cop/lint/empty_interpolation.rb +8 -0
- data/lib/rubocop/cop/lint/empty_when.rb +14 -16
- data/lib/rubocop/cop/lint/end_alignment.rb +48 -28
- data/lib/rubocop/cop/lint/end_in_method.rb +23 -0
- data/lib/rubocop/cop/lint/ensure_return.rb +21 -0
- data/lib/rubocop/cop/lint/float_out_of_range.rb +5 -0
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +29 -4
- data/lib/rubocop/cop/lint/handle_exceptions.rb +40 -0
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +7 -2
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +11 -2
- data/lib/rubocop/cop/lint/invalid_character_literal.rb +3 -0
- data/lib/rubocop/cop/lint/literal_in_condition.rb +34 -36
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +8 -0
- data/lib/rubocop/cop/lint/loop.rb +36 -0
- data/lib/rubocop/cop/lint/multiple_compare.rb +46 -0
- data/lib/rubocop/cop/lint/nested_method_definition.rb +22 -0
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +5 -0
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +8 -0
- data/lib/rubocop/cop/lint/percent_string_array.rb +27 -13
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +14 -4
- data/lib/rubocop/cop/lint/rand_one.rb +7 -3
- data/lib/rubocop/cop/lint/require_parentheses.rb +20 -19
- data/lib/rubocop/cop/lint/rescue_exception.rb +20 -0
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +66 -0
- data/lib/rubocop/cop/lint/shadowed_exception.rb +6 -1
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +24 -0
- data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +8 -0
- data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +24 -0
- data/lib/rubocop/cop/lint/unified_integer.rb +5 -0
- data/lib/rubocop/cop/lint/unneeded_disable.rb +2 -2
- data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +5 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +17 -0
- data/lib/rubocop/cop/lint/unused_block_argument.rb +2 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +28 -1
- data/lib/rubocop/cop/lint/useless_assignment.rb +18 -0
- data/lib/rubocop/cop/lint/useless_comparison.rb +3 -1
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +16 -1
- data/lib/rubocop/cop/lint/useless_setter_call.rb +16 -4
- data/lib/rubocop/cop/lint/void.rb +52 -0
- data/lib/rubocop/cop/message_annotator.rb +102 -0
- data/lib/rubocop/cop/metrics/block_length.rb +6 -0
- data/lib/rubocop/cop/metrics/block_nesting.rb +17 -5
- data/lib/rubocop/cop/metrics/line_length.rb +11 -4
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -2
- data/lib/rubocop/cop/mixin/array_syntax.rb +2 -11
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +12 -5
- data/lib/rubocop/cop/mixin/configurable_formatting.rb +48 -0
- data/lib/rubocop/cop/mixin/configurable_max.rb +3 -3
- data/lib/rubocop/cop/mixin/configurable_naming.rb +5 -33
- data/lib/rubocop/cop/mixin/configurable_numbering.rb +6 -47
- data/lib/rubocop/cop/mixin/documentation_comment.rb +7 -1
- data/lib/rubocop/cop/mixin/duplication.rb +46 -0
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +2 -2
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +14 -11
- data/lib/rubocop/cop/mixin/hash_alignment.rb +114 -0
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -3
- data/lib/rubocop/cop/mixin/negative_conditional.rb +21 -7
- data/lib/rubocop/cop/mixin/on_method_def.rb +14 -0
- data/lib/rubocop/cop/mixin/on_normal_if_unless.rb +1 -24
- data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -13
- data/lib/rubocop/cop/mixin/target_ruby_version.rb +16 -0
- data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -3
- data/lib/rubocop/cop/offense.rb +1 -1
- data/lib/rubocop/cop/performance/case_when_splat.rb +56 -59
- data/lib/rubocop/cop/performance/detect.rb +2 -2
- data/lib/rubocop/cop/performance/flat_map.rb +3 -3
- data/lib/rubocop/cop/performance/redundant_merge.rb +3 -6
- data/lib/rubocop/cop/performance/regexp_match.rb +201 -0
- data/lib/rubocop/cop/rails/delegate.rb +2 -2
- data/lib/rubocop/cop/rails/delegate_allow_blank.rb +10 -19
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +12 -40
- data/lib/rubocop/cop/rails/file_path.rb +80 -0
- data/lib/rubocop/cop/rails/find_each.rb +5 -14
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +30 -24
- data/lib/rubocop/cop/rails/not_null_column.rb +23 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +217 -0
- data/lib/rubocop/cop/rails/safe_navigation.rb +4 -2
- data/lib/rubocop/cop/rails/skips_model_validations.rb +46 -0
- data/lib/rubocop/cop/rails/time_zone.rb +1 -1
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +7 -5
- data/lib/rubocop/cop/registry.rb +170 -0
- data/lib/rubocop/cop/{lint → security}/eval.rb +7 -1
- data/lib/rubocop/cop/security/marshal_load.rb +33 -0
- data/lib/rubocop/cop/security/yaml_load.rb +37 -0
- data/lib/rubocop/cop/style/align_hash.rb +138 -169
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +10 -15
- data/lib/rubocop/cop/style/case_indentation.rb +36 -27
- data/lib/rubocop/cop/style/conditional_assignment.rb +64 -47
- data/lib/rubocop/cop/style/each_with_object.rb +4 -1
- data/lib/rubocop/cop/style/else_alignment.rb +14 -20
- data/lib/rubocop/cop/style/empty_case_condition.rb +16 -25
- data/lib/rubocop/cop/style/empty_else.rb +20 -22
- data/lib/rubocop/cop/style/empty_literal.rb +4 -4
- data/lib/rubocop/cop/style/empty_method.rb +12 -6
- data/lib/rubocop/cop/style/encoding.rb +1 -1
- data/lib/rubocop/cop/style/file_name.rb +24 -4
- data/lib/rubocop/cop/style/first_method_argument_line_break.rb +1 -1
- data/lib/rubocop/cop/style/format_string.rb +17 -48
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +40 -11
- data/lib/rubocop/cop/style/guard_clause.rb +11 -17
- data/lib/rubocop/cop/style/hash_syntax.rb +24 -42
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +40 -28
- data/lib/rubocop/cop/style/if_inside_else.rb +6 -9
- data/lib/rubocop/cop/style/if_unless_modifier.rb +16 -25
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +3 -9
- data/lib/rubocop/cop/style/indent_array.rb +1 -1
- data/lib/rubocop/cop/style/indentation_width.rb +29 -60
- data/lib/rubocop/cop/style/infinite_loop.rb +21 -22
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +86 -0
- data/lib/rubocop/cop/style/{method_call_parentheses.rb → method_call_without_args_parentheses.rb} +8 -1
- data/lib/rubocop/cop/style/missing_else.rb +40 -14
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +5 -15
- data/lib/rubocop/cop/style/multiline_if_then.rb +14 -8
- data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +3 -3
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -5
- data/lib/rubocop/cop/style/mutable_constant.rb +3 -2
- data/lib/rubocop/cop/style/negated_if.rb +3 -19
- data/lib/rubocop/cop/style/negated_while.rb +2 -17
- data/lib/rubocop/cop/style/nested_modifier.rb +16 -43
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -5
- data/lib/rubocop/cop/style/next.rb +23 -21
- data/lib/rubocop/cop/style/non_nil_check.rb +2 -3
- data/lib/rubocop/cop/style/not.rb +1 -3
- data/lib/rubocop/cop/style/numeric_literals.rb +2 -2
- data/lib/rubocop/cop/style/one_line_conditional.rb +12 -22
- data/lib/rubocop/cop/style/option_hash.rb +4 -15
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -3
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -12
- data/lib/rubocop/cop/style/percent_q_literals.rb +15 -12
- data/lib/rubocop/cop/style/redundant_freeze.rb +3 -2
- data/lib/rubocop/cop/style/redundant_parentheses.rb +27 -4
- data/lib/rubocop/cop/style/redundant_return.rb +4 -8
- data/lib/rubocop/cop/style/safe_navigation.rb +13 -6
- data/lib/rubocop/cop/style/space_after_colon.rb +2 -4
- data/lib/rubocop/cop/style/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/style/space_around_operators.rb +15 -13
- data/lib/rubocop/cop/style/string_methods.rb +1 -3
- data/lib/rubocop/cop/style/symbol_array.rb +1 -5
- data/lib/rubocop/cop/style/ternary_parentheses.rb +5 -6
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +2 -5
- data/lib/rubocop/cop/style/trailing_comma_in_literal.rb +1 -1
- data/lib/rubocop/cop/style/unless_else.rb +1 -5
- data/lib/rubocop/cop/style/when_then.rb +4 -2
- data/lib/rubocop/cop/style/while_until_do.rb +9 -13
- data/lib/rubocop/cop/style/while_until_modifier.rb +12 -11
- data/lib/rubocop/cop/style/word_array.rb +5 -9
- data/lib/rubocop/cop/team.rb +16 -15
- data/lib/rubocop/cop/util.rb +13 -3
- data/lib/rubocop/formatter/clang_style_formatter.rb +2 -2
- data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -1
- data/lib/rubocop/magic_comment.rb +196 -0
- data/lib/rubocop/options.rb +5 -4
- data/lib/rubocop/processed_source.rb +1 -1
- data/lib/rubocop/rspec/cop_helper.rb +9 -0
- data/lib/rubocop/rspec/shared_examples.rb +1 -1
- data/lib/rubocop/runner.rb +7 -2
- data/lib/rubocop/version.rb +1 -1
- metadata +41 -14
- data/lib/rubocop/ast_node.rb +0 -624
- data/lib/rubocop/ast_node/builder.rb +0 -30
- data/lib/rubocop/ast_node/sexp.rb +0 -13
- data/lib/rubocop/cop/mixin/hash_node.rb +0 -14
- data/lib/rubocop/cop/mixin/if_node.rb +0 -42
@@ -11,25 +11,24 @@ module RuboCop
|
|
11
11
|
MSG = '%s curly braces around a hash parameter.'.freeze
|
12
12
|
|
13
13
|
def on_send(node)
|
14
|
+
return if node.asgn_method_call?
|
15
|
+
|
14
16
|
_receiver, method_name, *args = *node
|
15
17
|
|
16
|
-
# Discard attr writer methods.
|
17
|
-
return if node.asgn_method_call?
|
18
|
-
# Discard operator methods.
|
19
18
|
return if operator?(method_name)
|
19
|
+
return if args.empty?
|
20
20
|
|
21
|
-
|
22
|
-
arg = args.last
|
21
|
+
return unless args.last.hash_type? && !args.last.pairs.empty?
|
23
22
|
|
24
|
-
check(
|
23
|
+
check(args.last, args)
|
25
24
|
end
|
26
25
|
|
27
26
|
private
|
28
27
|
|
29
28
|
def check(arg, args)
|
30
|
-
if style == :braces && !braces?
|
29
|
+
if style == :braces && !arg.braces?
|
31
30
|
add_offense(arg.parent, arg.source_range, format(MSG, 'Missing'))
|
32
|
-
elsif style == :no_braces && braces?
|
31
|
+
elsif style == :no_braces && arg.braces?
|
33
32
|
add_offense(arg.parent, arg.source_range,
|
34
33
|
format(MSG, 'Redundant'))
|
35
34
|
elsif style == :context_dependent
|
@@ -38,8 +37,8 @@ module RuboCop
|
|
38
37
|
end
|
39
38
|
|
40
39
|
def check_context_dependent(arg, args)
|
41
|
-
braces_around_second_from_end = args.
|
42
|
-
if braces?
|
40
|
+
braces_around_second_from_end = args.size > 1 && args[-2].hash_type?
|
41
|
+
if arg.braces?
|
43
42
|
unless braces_around_second_from_end
|
44
43
|
add_offense(arg.parent, arg.source_range,
|
45
44
|
format(MSG, 'Redundant'))
|
@@ -57,7 +56,7 @@ module RuboCop
|
|
57
56
|
_receiver, _method_name, *args = *send_node
|
58
57
|
node = args.last
|
59
58
|
lambda do |corrector|
|
60
|
-
if braces?
|
59
|
+
if node.braces?
|
61
60
|
remove_braces_with_whitespace(corrector, node)
|
62
61
|
else
|
63
62
|
add_braces(corrector, node)
|
@@ -100,10 +99,6 @@ module RuboCop
|
|
100
99
|
corrector.insert_after(node.source_range, '}')
|
101
100
|
end
|
102
101
|
|
103
|
-
def non_empty_hash?(arg)
|
104
|
-
arg && arg.hash_type? && !arg.children.empty?
|
105
|
-
end
|
106
|
-
|
107
102
|
def braces?(arg)
|
108
103
|
arg.loc.begin
|
109
104
|
end
|
@@ -11,39 +11,41 @@ module RuboCop
|
|
11
11
|
include AutocorrectAlignment
|
12
12
|
include ConfigurableEnforcedStyle
|
13
13
|
|
14
|
-
|
15
|
-
_condition, *whens, _else = *case_node
|
16
|
-
|
17
|
-
base = style
|
18
|
-
indent = cop_config['IndentOneStep']
|
19
|
-
base_column = base_column(case_node, base)
|
14
|
+
MSG = 'Indent `when` %s `%s`.'.freeze
|
20
15
|
|
21
|
-
|
22
|
-
|
16
|
+
def on_case(case_node)
|
17
|
+
case_node.each_when do |when_node|
|
18
|
+
check_when(when_node)
|
23
19
|
end
|
24
20
|
end
|
25
21
|
|
26
22
|
private
|
27
23
|
|
28
|
-
def check_when(when_node
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
if
|
24
|
+
def check_when(when_node)
|
25
|
+
when_column = when_node.loc.keyword.column
|
26
|
+
base_column = base_column(when_node.parent, style)
|
27
|
+
|
28
|
+
if when_column == base_column + indentation_width
|
33
29
|
correct_style_detected
|
34
30
|
else
|
35
|
-
incorrect_style(when_node
|
31
|
+
incorrect_style(when_node)
|
36
32
|
end
|
37
33
|
end
|
38
34
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
35
|
+
def indent_one_step?
|
36
|
+
cop_config['IndentOneStep']
|
37
|
+
end
|
38
|
+
|
39
|
+
def indentation_width
|
40
|
+
indent_one_step? ? configured_indentation_width : 0
|
41
|
+
end
|
42
|
+
|
43
|
+
def incorrect_style(when_node)
|
44
|
+
when_column = when_node.loc.keyword.column
|
45
|
+
base_column = base_column(when_node.parent, alternative_style)
|
46
|
+
|
47
|
+
add_offense(when_node, :keyword, message(style)) do
|
48
|
+
if when_column == base_column
|
47
49
|
opposite_style_detected
|
48
50
|
else
|
49
51
|
unrecognized_style_detected
|
@@ -51,8 +53,10 @@ module RuboCop
|
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
54
|
-
def
|
55
|
-
'
|
56
|
+
def message(base)
|
57
|
+
depth = indent_one_step? ? 'one step more than' : 'as deep as'
|
58
|
+
|
59
|
+
format(MSG, depth, base)
|
56
60
|
end
|
57
61
|
|
58
62
|
def base_column(case_node, base)
|
@@ -64,9 +68,12 @@ module RuboCop
|
|
64
68
|
|
65
69
|
def autocorrect(node)
|
66
70
|
whitespace = whitespace_range(node)
|
71
|
+
|
67
72
|
return false unless whitespace.source.strip.empty?
|
68
73
|
|
69
|
-
|
74
|
+
lambda do |corrector|
|
75
|
+
corrector.replace(whitespace, replacement(node))
|
76
|
+
end
|
70
77
|
end
|
71
78
|
|
72
79
|
def whitespace_range(node)
|
@@ -78,9 +85,11 @@ module RuboCop
|
|
78
85
|
|
79
86
|
def replacement(node)
|
80
87
|
case_node = node.each_ancestor(:case).first
|
81
|
-
base_type = cop_config[
|
88
|
+
base_type = cop_config[style_parameter_name] == 'end' ? :end : :case
|
89
|
+
|
82
90
|
column = base_column(case_node, base_type)
|
83
|
-
column +=
|
91
|
+
column += indentation_width
|
92
|
+
|
84
93
|
' ' * column
|
85
94
|
end
|
86
95
|
end
|
@@ -8,7 +8,7 @@ module RuboCop
|
|
8
8
|
module ConditionalAssignmentHelper
|
9
9
|
EQUAL = '='.freeze
|
10
10
|
END_ALIGNMENT = 'Lint/EndAlignment'.freeze
|
11
|
-
ALIGN_WITH = '
|
11
|
+
ALIGN_WITH = 'EnforcedStyleAlignWith'.freeze
|
12
12
|
KEYWORD = 'keyword'.freeze
|
13
13
|
|
14
14
|
# `elsif` branches show up in the `node` as an `else`. We need
|
@@ -92,6 +92,12 @@ module RuboCop
|
|
92
92
|
method_name.to_s.end_with?(EQUAL) &&
|
93
93
|
![:!=, :==, :===, :>=, :<=].include?(method_name)
|
94
94
|
end
|
95
|
+
|
96
|
+
def assignment_rhs_exist?(node)
|
97
|
+
parent = node.parent
|
98
|
+
return true unless parent
|
99
|
+
!(parent.mlhs_type? || parent.resbody_type?)
|
100
|
+
end
|
95
101
|
end
|
96
102
|
|
97
103
|
# Check for `if` and `case` statements where each branch is used for
|
@@ -190,7 +196,6 @@ module RuboCop
|
|
190
196
|
# bar = 2
|
191
197
|
# end
|
192
198
|
class ConditionalAssignment < Cop
|
193
|
-
include IfNode
|
194
199
|
include ConditionalAssignmentHelper
|
195
200
|
include ConfigurableEnforcedStyle
|
196
201
|
include IgnoredNode
|
@@ -201,10 +206,8 @@ module RuboCop
|
|
201
206
|
'Assign variables inside of conditionals'.freeze
|
202
207
|
VARIABLE_ASSIGNMENT_TYPES =
|
203
208
|
[:casgn, :cvasgn, :gvasgn, :ivasgn, :lvasgn].freeze
|
204
|
-
ASSIGNMENT_TYPES =
|
205
|
-
|
206
|
-
IF = 'if'.freeze
|
207
|
-
UNLESS = 'unless'.freeze
|
209
|
+
ASSIGNMENT_TYPES = VARIABLE_ASSIGNMENT_TYPES +
|
210
|
+
[:and_asgn, :or_asgn, :op_asgn, :masgn].freeze
|
208
211
|
LINE_LENGTH = 'Metrics/LineLength'.freeze
|
209
212
|
INDENTATION_WIDTH = 'Style/IndentationWidth'.freeze
|
210
213
|
ENABLED = 'Enabled'.freeze
|
@@ -218,6 +221,7 @@ module RuboCop
|
|
218
221
|
define_method "on_#{type}" do |node|
|
219
222
|
return if part_of_ignored_node?(node)
|
220
223
|
return unless style == :assign_inside_condition
|
224
|
+
return unless assignment_rhs_exist?(node)
|
221
225
|
|
222
226
|
check_assignment_to_condition(node)
|
223
227
|
end
|
@@ -226,53 +230,56 @@ module RuboCop
|
|
226
230
|
def on_send(node)
|
227
231
|
return unless assignment_type?(node)
|
228
232
|
return unless style == :assign_inside_condition
|
233
|
+
return unless assignment_rhs_exist?(node)
|
229
234
|
|
230
235
|
check_assignment_to_condition(node)
|
231
236
|
end
|
232
237
|
|
233
|
-
def check_assignment_to_condition(node)
|
234
|
-
ignore_node(node)
|
235
|
-
|
236
|
-
assignment = assignment_node(node)
|
237
|
-
return unless condition?(assignment)
|
238
|
-
|
239
|
-
_condition, *branches, else_branch = *assignment
|
240
|
-
return unless else_branch # empty else
|
241
|
-
return if single_line_conditions_only? &&
|
242
|
-
[*branches, else_branch].any?(&:begin_type?)
|
243
|
-
|
244
|
-
add_offense(node, :expression, ASSIGN_TO_CONDITION_MSG)
|
245
|
-
end
|
246
|
-
|
247
238
|
def on_if(node)
|
248
239
|
return unless style == :assign_to_condition
|
249
|
-
return if elsif?
|
250
|
-
|
251
|
-
if ternary?(node) || node.loc.keyword.is?('if')
|
252
|
-
_condition, if_branch, else_branch = *node
|
253
|
-
else
|
254
|
-
_condition, else_branch, if_branch = *node
|
255
|
-
end
|
240
|
+
return if node.elsif?
|
256
241
|
|
242
|
+
else_branch = node.else_branch
|
257
243
|
elsif_branches, else_branch = expand_elses(else_branch)
|
258
|
-
return unless else_branch # empty else
|
259
244
|
|
260
|
-
|
245
|
+
return unless else_branch
|
246
|
+
|
247
|
+
branches = [node.if_branch, *elsif_branches, else_branch]
|
261
248
|
|
262
249
|
check_node(node, branches)
|
263
250
|
end
|
264
251
|
|
265
252
|
def on_case(node)
|
266
253
|
return unless style == :assign_to_condition
|
267
|
-
|
268
|
-
return unless else_branch # empty else
|
254
|
+
return unless node.else_branch
|
269
255
|
|
270
|
-
when_branches = expand_when_branches(when_branches)
|
271
|
-
branches = [*when_branches, else_branch]
|
256
|
+
when_branches = expand_when_branches(node.when_branches)
|
257
|
+
branches = [*when_branches, node.else_branch]
|
272
258
|
|
273
259
|
check_node(node, branches)
|
274
260
|
end
|
275
261
|
|
262
|
+
private
|
263
|
+
|
264
|
+
def check_assignment_to_condition(node)
|
265
|
+
ignore_node(node)
|
266
|
+
|
267
|
+
assignment = assignment_node(node)
|
268
|
+
return unless condition?(assignment)
|
269
|
+
return if allowed_ternary?(assignment)
|
270
|
+
|
271
|
+
_condition, *branches, else_branch = *assignment
|
272
|
+
return unless else_branch # empty else
|
273
|
+
return if single_line_conditions_only? &&
|
274
|
+
[*branches, else_branch].any?(&:begin_type?)
|
275
|
+
|
276
|
+
add_offense(node, :expression, ASSIGN_TO_CONDITION_MSG)
|
277
|
+
end
|
278
|
+
|
279
|
+
def allowed_ternary?(assignment)
|
280
|
+
assignment.if_type? && assignment.ternary? && !include_ternary?
|
281
|
+
end
|
282
|
+
|
276
283
|
def autocorrect(node)
|
277
284
|
if assignment_type?(node)
|
278
285
|
move_assignment_inside_condition(node)
|
@@ -281,8 +288,6 @@ module RuboCop
|
|
281
288
|
end
|
282
289
|
end
|
283
290
|
|
284
|
-
private
|
285
|
-
|
286
291
|
def assignment_node(node)
|
287
292
|
*_variable, assignment = *node
|
288
293
|
|
@@ -298,20 +303,21 @@ module RuboCop
|
|
298
303
|
end
|
299
304
|
|
300
305
|
def move_assignment_outside_condition(node)
|
301
|
-
if
|
306
|
+
if node.case_type?
|
307
|
+
CaseCorrector.correct(self, node)
|
308
|
+
elsif node.ternary?
|
302
309
|
TernaryCorrector.correct(node)
|
303
|
-
elsif node.
|
310
|
+
elsif node.if?
|
304
311
|
IfCorrector.correct(self, node)
|
305
|
-
elsif node.
|
312
|
+
elsif node.unless?
|
306
313
|
UnlessCorrector.correct(self, node)
|
307
|
-
else
|
308
|
-
CaseCorrector.correct(self, node)
|
309
314
|
end
|
310
315
|
end
|
311
316
|
|
312
317
|
def move_assignment_inside_condition(node)
|
313
318
|
*_assignment, condition = *node
|
314
|
-
|
319
|
+
|
320
|
+
if ternary_condition?(condition)
|
315
321
|
TernaryCorrector.move_assignment_inside_condition(node)
|
316
322
|
elsif condition.case_type?
|
317
323
|
CaseCorrector.move_assignment_inside_condition(node)
|
@@ -320,6 +326,10 @@ module RuboCop
|
|
320
326
|
end
|
321
327
|
end
|
322
328
|
|
329
|
+
def ternary_condition?(node)
|
330
|
+
[node, node.children.first].any? { |n| n.if_type? && n.ternary? }
|
331
|
+
end
|
332
|
+
|
323
333
|
def lhs_all_match?(branches)
|
324
334
|
first_lhs = lhs(branches.first)
|
325
335
|
branches.all? { |branch| lhs(branch) == first_lhs }
|
@@ -327,8 +337,8 @@ module RuboCop
|
|
327
337
|
|
328
338
|
def assignment_types_match?(*nodes)
|
329
339
|
return unless assignment_type?(nodes.first)
|
330
|
-
|
331
|
-
nodes.
|
340
|
+
|
341
|
+
nodes.map(&:type).uniq.one?
|
332
342
|
end
|
333
343
|
|
334
344
|
# The shovel operator `<<` does not have its own type. It is a `send`
|
@@ -337,15 +347,15 @@ module RuboCop
|
|
337
347
|
return true if ASSIGNMENT_TYPES.include?(branch.type)
|
338
348
|
|
339
349
|
if branch.send_type?
|
340
|
-
|
341
|
-
|
342
|
-
return true if method.to_s.end_with?(EQUAL)
|
350
|
+
return true if METHODS.include?(branch.method_name) ||
|
351
|
+
branch.method_name.to_s.end_with?(EQUAL)
|
343
352
|
end
|
344
353
|
|
345
354
|
false
|
346
355
|
end
|
347
356
|
|
348
357
|
def check_node(node, branches)
|
358
|
+
return if allowed_ternary?(node)
|
349
359
|
return unless allowed_statements?(branches)
|
350
360
|
return if single_line_conditions_only? && branches.any?(&:begin_type?)
|
351
361
|
return if correction_exceeds_line_limit?(node, branches)
|
@@ -400,7 +410,10 @@ module RuboCop
|
|
400
410
|
end
|
401
411
|
|
402
412
|
def longest_rhs(branches)
|
403
|
-
branches.
|
413
|
+
line_lengths = branches.flat_map do |branch|
|
414
|
+
branch.children.last.source.split("\n").map(&:length)
|
415
|
+
end
|
416
|
+
line_lengths.max
|
404
417
|
end
|
405
418
|
|
406
419
|
def line_length_cop_enabled?
|
@@ -418,6 +431,10 @@ module RuboCop
|
|
418
431
|
def single_line_conditions_only?
|
419
432
|
cop_config[SINGLE_LINE_CONDITIONS_ONLY]
|
420
433
|
end
|
434
|
+
|
435
|
+
def include_ternary?
|
436
|
+
cop_config['IncludeTernaryExpressions']
|
437
|
+
end
|
421
438
|
end
|
422
439
|
|
423
440
|
# Helper module to provide common methods to ConditionalAssignment
|
@@ -40,11 +40,14 @@ module RuboCop
|
|
40
40
|
|
41
41
|
def autocorrect(node)
|
42
42
|
lambda do |corrector|
|
43
|
-
method, args,
|
43
|
+
method, args, body = *node
|
44
44
|
corrector.replace(method.loc.selector, 'each_with_object')
|
45
45
|
first_arg, second_arg = *args
|
46
46
|
corrector.replace(first_arg.loc.expression, second_arg.source)
|
47
47
|
corrector.replace(second_arg.loc.expression, first_arg.source)
|
48
|
+
|
49
|
+
return_value = return_value(body)
|
50
|
+
corrector.remove(return_value.loc.expression)
|
48
51
|
end
|
49
52
|
end
|
50
53
|
|
@@ -11,34 +11,31 @@ module RuboCop
|
|
11
11
|
include EndKeywordAlignment
|
12
12
|
include AutocorrectAlignment
|
13
13
|
include CheckAssignment
|
14
|
-
include IfNode
|
15
14
|
|
16
15
|
MSG = 'Align `%s` with `%s`.'.freeze
|
17
16
|
|
18
17
|
def on_if(node, base = nil)
|
19
18
|
return if ignored_node?(node)
|
20
|
-
return unless
|
19
|
+
return unless node.else? && begins_its_line?(node.loc.else)
|
21
20
|
|
22
|
-
|
23
|
-
return unless begins_its_line?(else_range)
|
24
|
-
|
25
|
-
check_alignment(base_range(node, base), else_range)
|
21
|
+
check_alignment(base_range(node, base), node.loc.else)
|
26
22
|
|
27
|
-
|
23
|
+
else_branch = node.else_branch
|
28
24
|
|
29
|
-
return unless
|
25
|
+
return unless else_branch && else_branch.if_type? &&
|
26
|
+
else_branch.elsif?
|
30
27
|
|
31
28
|
# If the `else` part is actually an `elsif`, we check the `elsif`
|
32
29
|
# node in case it contains an `else` within, because that `else`
|
33
30
|
# should have the same alignment (base).
|
34
|
-
on_if(
|
31
|
+
on_if(else_branch, base)
|
35
32
|
# The `elsif` node will get an `on_if` call from the framework later,
|
36
33
|
# but we're done here, so we set it to ignored.
|
37
|
-
ignore_node(
|
34
|
+
ignore_node(else_branch)
|
38
35
|
end
|
39
36
|
|
40
37
|
def on_rescue(node)
|
41
|
-
return unless
|
38
|
+
return unless node.loc.respond_to?(:else) && node.loc.else
|
42
39
|
|
43
40
|
parent = node.parent
|
44
41
|
parent = parent.parent if parent.ensure_type?
|
@@ -51,9 +48,9 @@ module RuboCop
|
|
51
48
|
end
|
52
49
|
|
53
50
|
def on_case(node)
|
54
|
-
|
55
|
-
|
56
|
-
check_alignment(
|
51
|
+
return unless node.else?
|
52
|
+
|
53
|
+
check_alignment(node.when_branches.last.loc.keyword, node.loc.else)
|
57
54
|
end
|
58
55
|
|
59
56
|
private
|
@@ -62,11 +59,8 @@ module RuboCop
|
|
62
59
|
if base
|
63
60
|
base.source_range
|
64
61
|
else
|
65
|
-
|
66
|
-
|
67
|
-
base = base.parent
|
68
|
-
end
|
69
|
-
base.loc.keyword
|
62
|
+
lineage = [node, *node.each_ancestor(:if)]
|
63
|
+
lineage.find { |parent| parent.if? || parent.unless? }.loc.keyword
|
70
64
|
end
|
71
65
|
end
|
72
66
|
|
@@ -87,7 +81,7 @@ module RuboCop
|
|
87
81
|
return unless rhs
|
88
82
|
|
89
83
|
end_config = config.for_cop('Lint/EndAlignment')
|
90
|
-
style = end_config['
|
84
|
+
style = end_config['EnforcedStyleAlignWith'] || 'keyword'
|
91
85
|
base = variable_alignment?(node.loc, rhs, style.to_sym) ? node : rhs
|
92
86
|
|
93
87
|
return unless rhs.if_type?
|