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
@@ -36,7 +36,6 @@ module RuboCop
|
|
36
36
|
# raise 'exception' if something
|
37
37
|
# ok
|
38
38
|
class GuardClause < Cop
|
39
|
-
include IfNode
|
40
39
|
include MinBodyLength
|
41
40
|
include OnMethodDef
|
42
41
|
|
@@ -48,7 +47,7 @@ module RuboCop
|
|
48
47
|
|
49
48
|
if body.if_type?
|
50
49
|
check_ending_if(body)
|
51
|
-
elsif body.begin_type?
|
50
|
+
elsif body.begin_type? && body.children.last.if_type?
|
52
51
|
check_ending_if(body.children.last)
|
53
52
|
end
|
54
53
|
end
|
@@ -56,39 +55,34 @@ module RuboCop
|
|
56
55
|
def on_if(node)
|
57
56
|
return if accepted_form?(node) || !contains_guard_clause?(node)
|
58
57
|
|
59
|
-
add_offense(node, :keyword
|
58
|
+
add_offense(node, :keyword)
|
60
59
|
end
|
61
60
|
|
62
61
|
private
|
63
62
|
|
64
63
|
def check_ending_if(node)
|
65
|
-
return if
|
66
|
-
accepted_form?(node, true) ||
|
67
|
-
!min_body_length?(node)
|
64
|
+
return if accepted_form?(node, true) || !min_body_length?(node)
|
68
65
|
|
69
|
-
add_offense(node, :keyword
|
66
|
+
add_offense(node, :keyword)
|
70
67
|
end
|
71
68
|
|
72
69
|
def accepted_form?(node, ending = false)
|
73
|
-
|
74
|
-
|
75
|
-
ignored_node?(node, ending) || condition.multiline?
|
70
|
+
accepted_if?(node, ending) || node.condition.multiline?
|
76
71
|
end
|
77
72
|
|
78
|
-
def
|
79
|
-
return true if
|
73
|
+
def accepted_if?(node, ending)
|
74
|
+
return true if node.modifier_form? || node.ternary?
|
80
75
|
|
81
76
|
if ending
|
82
|
-
|
77
|
+
node.else?
|
83
78
|
else
|
84
|
-
!
|
79
|
+
!node.else? || node.elsif?
|
85
80
|
end
|
86
81
|
end
|
87
82
|
|
88
83
|
def contains_guard_clause?(node)
|
89
|
-
|
90
|
-
|
91
|
-
guard_clause?(body) || guard_clause?(else_body)
|
84
|
+
node.if_branch && node.if_branch.guard_clause? ||
|
85
|
+
node.else_branch && node.else_branch.guard_clause?
|
92
86
|
end
|
93
87
|
end
|
94
88
|
end
|
@@ -69,43 +69,31 @@ module RuboCop
|
|
69
69
|
MSG_NO_MIXED_KEYS = "Don't mix styles in the same hash.".freeze
|
70
70
|
MSG_HASH_ROCKETS = 'Use hash rockets syntax.'.freeze
|
71
71
|
|
72
|
-
def initialize(*)
|
73
|
-
@force_hash_rockets = false
|
74
|
-
super
|
75
|
-
end
|
76
|
-
|
77
72
|
def on_hash(node)
|
78
|
-
if
|
79
|
-
|
80
|
-
|
81
|
-
end
|
73
|
+
return if node.pairs.empty?
|
74
|
+
|
75
|
+
@force_hash_rockets = force_hash_rockets?(node.pairs)
|
82
76
|
|
83
77
|
if style == :hash_rockets || @force_hash_rockets
|
84
|
-
hash_rockets_check(node)
|
78
|
+
hash_rockets_check(node.pairs)
|
85
79
|
elsif style == :ruby19_no_mixed_keys
|
86
|
-
ruby19_no_mixed_keys_check(node)
|
80
|
+
ruby19_no_mixed_keys_check(node.pairs)
|
87
81
|
elsif style == :no_mixed_keys
|
88
|
-
no_mixed_keys_check(node)
|
82
|
+
no_mixed_keys_check(node.pairs)
|
89
83
|
else
|
90
|
-
ruby19_check(node)
|
84
|
+
ruby19_check(node.pairs)
|
91
85
|
end
|
92
86
|
end
|
93
87
|
|
94
|
-
def ruby19_check(
|
95
|
-
pairs = *node
|
96
|
-
|
88
|
+
def ruby19_check(pairs)
|
97
89
|
check(pairs, '=>', MSG_19) if sym_indices?(pairs)
|
98
90
|
end
|
99
91
|
|
100
|
-
def hash_rockets_check(
|
101
|
-
pairs = *node
|
102
|
-
|
92
|
+
def hash_rockets_check(pairs)
|
103
93
|
check(pairs, ':', MSG_HASH_ROCKETS)
|
104
94
|
end
|
105
95
|
|
106
|
-
def ruby19_no_mixed_keys_check(
|
107
|
-
pairs = *node
|
108
|
-
|
96
|
+
def ruby19_no_mixed_keys_check(pairs)
|
109
97
|
if @force_hash_rockets
|
110
98
|
check(pairs, ':', MSG_HASH_ROCKETS)
|
111
99
|
elsif sym_indices?(pairs)
|
@@ -115,14 +103,11 @@ module RuboCop
|
|
115
103
|
end
|
116
104
|
end
|
117
105
|
|
118
|
-
def no_mixed_keys_check(
|
119
|
-
pairs = *node
|
120
|
-
|
106
|
+
def no_mixed_keys_check(pairs)
|
121
107
|
if !sym_indices?(pairs)
|
122
108
|
check(pairs, ':', MSG_NO_MIXED_KEYS)
|
123
109
|
else
|
124
|
-
|
125
|
-
check(pairs, delim, MSG_NO_MIXED_KEYS)
|
110
|
+
check(pairs, pairs.first.inverse_delimiter, MSG_NO_MIXED_KEYS)
|
126
111
|
end
|
127
112
|
end
|
128
113
|
|
@@ -149,22 +134,14 @@ module RuboCop
|
|
149
134
|
|
150
135
|
private
|
151
136
|
|
152
|
-
def symbol_value?(pair)
|
153
|
-
_key, value = *pair
|
154
|
-
|
155
|
-
value.sym_type?
|
156
|
-
end
|
157
|
-
|
158
137
|
def sym_indices?(pairs)
|
159
138
|
pairs.all? { |p| word_symbol_pair?(p) }
|
160
139
|
end
|
161
140
|
|
162
141
|
def word_symbol_pair?(pair)
|
163
|
-
|
142
|
+
return false unless pair.key.sym_type?
|
164
143
|
|
165
|
-
|
166
|
-
|
167
|
-
acceptable_19_syntax_symbol?(key.source)
|
144
|
+
acceptable_19_syntax_symbol?(pair.key.source)
|
168
145
|
end
|
169
146
|
|
170
147
|
def acceptable_19_syntax_symbol?(sym_name)
|
@@ -186,7 +163,7 @@ module RuboCop
|
|
186
163
|
|
187
164
|
def check(pairs, delim, msg)
|
188
165
|
pairs.each do |pair|
|
189
|
-
if pair.
|
166
|
+
if pair.delimiter == delim
|
190
167
|
add_offense(pair,
|
191
168
|
pair.source_range.begin.join(pair.loc.operator),
|
192
169
|
msg) do
|
@@ -212,20 +189,25 @@ module RuboCop
|
|
212
189
|
key = node.children.first.source_range
|
213
190
|
op = node.loc.operator
|
214
191
|
|
215
|
-
corrector.insert_after(key,
|
192
|
+
corrector.insert_after(key, node.inverse_delimiter(true))
|
216
193
|
corrector.insert_before(key, ':')
|
217
194
|
corrector.remove(range_with_surrounding_space(op))
|
218
195
|
end
|
219
196
|
|
220
197
|
def autocorrect_no_mixed_keys(corrector, node)
|
221
|
-
|
222
|
-
|
223
|
-
if op.is?(':')
|
198
|
+
if node.colon?
|
224
199
|
autocorrect_hash_rockets(corrector, node)
|
225
200
|
else
|
226
201
|
autocorrect_ruby19(corrector, node)
|
227
202
|
end
|
228
203
|
end
|
204
|
+
|
205
|
+
def force_hash_rockets?(pairs)
|
206
|
+
@force_hash_rockets ||= begin
|
207
|
+
cop_config['UseHashRocketsWithSymbolValues'] &&
|
208
|
+
pairs.map(&:value).any?(&:sym_type?)
|
209
|
+
end
|
210
|
+
end
|
229
211
|
end
|
230
212
|
end
|
231
213
|
end
|
@@ -3,8 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# This cop checks for identical lines at the
|
7
|
-
# conditional statement.
|
6
|
+
# This cop checks for identical lines at the beginning or end of
|
7
|
+
# each branch of a conditional statement.
|
8
8
|
#
|
9
9
|
# @example
|
10
10
|
# @bad
|
@@ -23,40 +23,58 @@ module RuboCop
|
|
23
23
|
# do_y
|
24
24
|
# end
|
25
25
|
# do_z
|
26
|
+
#
|
27
|
+
# @bad
|
28
|
+
# if condition
|
29
|
+
# do_z
|
30
|
+
# do_x
|
31
|
+
# else
|
32
|
+
# do_z
|
33
|
+
# do_y
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# @good
|
37
|
+
# do_z
|
38
|
+
# if condition
|
39
|
+
# do_x
|
40
|
+
# else
|
41
|
+
# do_y
|
42
|
+
# end
|
26
43
|
class IdenticalConditionalBranches < Cop
|
27
|
-
include IfNode
|
28
|
-
|
29
44
|
MSG = 'Move `%s` out of the conditional.'.freeze
|
30
45
|
|
31
46
|
def on_if(node)
|
32
|
-
return if elsif?
|
33
|
-
|
34
|
-
branches = expand_elses(else_branch).unshift(if_branch)
|
47
|
+
return if node.elsif?
|
48
|
+
|
49
|
+
branches = expand_elses(node.else_branch).unshift(node.if_branch)
|
35
50
|
|
36
51
|
# return if any branch is empty. An empty branch can be an `if`
|
37
52
|
# without an `else`, or a branch that contains only comments.
|
38
53
|
return if branches.any?(&:nil?)
|
39
54
|
|
40
|
-
|
55
|
+
check_branches(branches)
|
41
56
|
end
|
42
57
|
|
43
58
|
def on_case(node)
|
44
|
-
return unless node.
|
45
|
-
_condition, *when_branches, else_branch = *node
|
46
|
-
return unless else_branch # empty else
|
47
|
-
when_branches = expand_when_branches(when_branches)
|
59
|
+
return unless node.else? && node.else_branch
|
48
60
|
|
49
|
-
|
61
|
+
check_branches(node.when_branches.map(&:body).push(node.else_branch))
|
50
62
|
end
|
51
63
|
|
52
64
|
private
|
53
65
|
|
54
|
-
def
|
55
|
-
|
66
|
+
def check_branches(branches)
|
67
|
+
tails = branches.compact.map { |branch| tail(branch) }
|
68
|
+
check_expressions(tails)
|
69
|
+
heads = branches.compact.map { |branch| head(branch) }
|
70
|
+
check_expressions(heads)
|
71
|
+
end
|
72
|
+
|
73
|
+
def check_expressions(expressions)
|
74
|
+
return unless expressions.size > 1 && expressions.uniq.one?
|
56
75
|
|
57
|
-
|
58
|
-
|
59
|
-
add_offense(branch, :expression, format(MSG, branch.source))
|
76
|
+
expressions.each do |expression|
|
77
|
+
add_offense(expression, :expression, format(MSG, expression.source))
|
60
78
|
end
|
61
79
|
end
|
62
80
|
|
@@ -73,18 +91,12 @@ module RuboCop
|
|
73
91
|
end
|
74
92
|
end
|
75
93
|
|
76
|
-
|
77
|
-
|
78
|
-
def expand_when_branches(when_branches)
|
79
|
-
when_branches.map { |branch| branch.children[1] }
|
94
|
+
def tail(node)
|
95
|
+
node.begin_type? ? node.children.last : node
|
80
96
|
end
|
81
97
|
|
82
|
-
def
|
83
|
-
|
84
|
-
node.children.last
|
85
|
-
else
|
86
|
-
node
|
87
|
-
end
|
98
|
+
def head(node)
|
99
|
+
node.begin_type? ? node.children.first : node
|
88
100
|
end
|
89
101
|
end
|
90
102
|
end
|
@@ -28,19 +28,16 @@ module RuboCop
|
|
28
28
|
# end
|
29
29
|
# end
|
30
30
|
class IfInsideElse < Cop
|
31
|
-
include IfNode
|
32
|
-
|
33
31
|
MSG = 'Convert `if` nested inside `else` to `elsif`.'.freeze
|
34
32
|
|
35
33
|
def on_if(node)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
return unless else_branch.
|
41
|
-
return if node.loc.keyword.is?('unless')
|
34
|
+
return if node.ternary? || node.unless?
|
35
|
+
|
36
|
+
else_branch = node.else_branch
|
37
|
+
|
38
|
+
return unless else_branch && else_branch.if_type? && else_branch.if?
|
42
39
|
|
43
|
-
add_offense(else_branch, :keyword
|
40
|
+
add_offense(else_branch, :keyword)
|
44
41
|
end
|
45
42
|
end
|
46
43
|
end
|
@@ -7,37 +7,36 @@ module RuboCop
|
|
7
7
|
# if written as a modifier if/unless.
|
8
8
|
# The maximum line length is configurable.
|
9
9
|
class IfUnlessModifier < Cop
|
10
|
-
include IfNode
|
11
10
|
include StatementModifier
|
12
11
|
|
12
|
+
MSG = 'Favor modifier `%s` usage when having a single-line body. ' \
|
13
|
+
'Another good alternative is the usage of control flow ' \
|
14
|
+
'`&&`/`||`.'.freeze
|
15
|
+
|
13
16
|
ASSIGNMENT_TYPES = [:lvasgn, :casgn, :cvasgn,
|
14
17
|
:gvasgn, :ivasgn, :masgn].freeze
|
15
18
|
|
16
19
|
def on_if(node)
|
17
20
|
return unless eligible_node?(node)
|
18
21
|
|
19
|
-
add_offense(node, :keyword,
|
22
|
+
add_offense(node, :keyword, format(MSG, node.keyword))
|
20
23
|
end
|
21
24
|
|
22
25
|
private
|
23
26
|
|
24
27
|
def autocorrect(node)
|
25
|
-
|
28
|
+
lambda do |corrector|
|
29
|
+
corrector.replace(node.source_range, to_modifier_form(node))
|
30
|
+
end
|
26
31
|
end
|
27
32
|
|
28
33
|
def eligible_node?(node)
|
29
34
|
!non_eligible_if?(node) && !node.chained? &&
|
30
|
-
!nested_conditional?
|
35
|
+
!node.nested_conditional? && single_line_as_modifier?(node)
|
31
36
|
end
|
32
37
|
|
33
38
|
def non_eligible_if?(node)
|
34
|
-
ternary?
|
35
|
-
elsif?(node) || if_else?(node)
|
36
|
-
end
|
37
|
-
|
38
|
-
def message(keyword)
|
39
|
-
"Favor modifier `#{keyword}` usage when having a single-line body." \
|
40
|
-
' Another good alternative is the usage of control flow `&&`/`||`.'
|
39
|
+
node.ternary? || node.modifier_form? || node.elsif? || node.else?
|
41
40
|
end
|
42
41
|
|
43
42
|
def parenthesize?(node)
|
@@ -60,21 +59,13 @@ module RuboCop
|
|
60
59
|
source =~ /\s*\(\s*$/
|
61
60
|
end
|
62
61
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
def oneline(node)
|
69
|
-
cond, body, _else = if_node_parts(node)
|
70
|
-
|
71
|
-
expr = "#{body.source} #{node.loc.keyword.source} " + cond.source
|
72
|
-
if (comment_after = first_line_comment(node))
|
73
|
-
expr << ' ' << comment_after
|
74
|
-
end
|
75
|
-
expr = "(#{expr})" if parenthesize?(node)
|
62
|
+
def to_modifier_form(node)
|
63
|
+
expression = [node.body.source,
|
64
|
+
node.keyword,
|
65
|
+
node.condition.source,
|
66
|
+
first_line_comment(node)].compact.join(' ')
|
76
67
|
|
77
|
-
|
68
|
+
parenthesize?(node) ? "(#{expression})" : expression
|
78
69
|
end
|
79
70
|
|
80
71
|
def first_line_comment(node)
|
@@ -25,18 +25,12 @@ module RuboCop
|
|
25
25
|
class IfUnlessModifierOfIfUnless < Cop
|
26
26
|
include StatementModifier
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
def message(keyword)
|
31
|
-
format(MESSAGE, keyword)
|
32
|
-
end
|
28
|
+
MSG = 'Avoid modifier `%s` after another conditional.'.freeze
|
33
29
|
|
34
30
|
def on_if(node)
|
35
|
-
return unless
|
36
|
-
_cond, body, _else = if_node_parts(node)
|
37
|
-
return unless body.if_type?
|
31
|
+
return unless node.modifier_form? && node.body.if_type?
|
38
32
|
|
39
|
-
add_offense(node, :keyword,
|
33
|
+
add_offense(node, :keyword, format(MSG, node.keyword))
|
40
34
|
end
|
41
35
|
end
|
42
36
|
end
|
@@ -63,7 +63,7 @@ module RuboCop
|
|
63
63
|
return if ignored_node?(array_node)
|
64
64
|
|
65
65
|
left_bracket = array_node.loc.begin
|
66
|
-
first_elem = array_node.
|
66
|
+
first_elem = array_node.values.first
|
67
67
|
if first_elem
|
68
68
|
return if first_elem.source_range.line == left_bracket.line
|
69
69
|
check_first(first_elem, left_bracket, left_parenthesis, 0)
|
@@ -12,12 +12,11 @@ module RuboCop
|
|
12
12
|
# puts 'hello'
|
13
13
|
# end
|
14
14
|
# end
|
15
|
-
class IndentationWidth < Cop
|
15
|
+
class IndentationWidth < Cop
|
16
16
|
include EndKeywordAlignment
|
17
17
|
include AutocorrectAlignment
|
18
18
|
include OnMethodDef
|
19
19
|
include CheckAssignment
|
20
|
-
include IfNode
|
21
20
|
include AccessModifierNode
|
22
21
|
|
23
22
|
SPECIAL_MODIFIERS = %w(private protected).freeze
|
@@ -67,18 +66,6 @@ module RuboCop
|
|
67
66
|
check_members(node.loc.keyword, members)
|
68
67
|
end
|
69
68
|
|
70
|
-
def check_members(base, members)
|
71
|
-
check_indentation(base, members.first)
|
72
|
-
|
73
|
-
return unless members.any? && members.first.begin_type?
|
74
|
-
return unless indentation_consistency_style == 'rails'
|
75
|
-
|
76
|
-
each_member(members) do |member, previous_modifier|
|
77
|
-
check_indentation(previous_modifier, member,
|
78
|
-
indentation_consistency_style)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
69
|
def on_send(node)
|
83
70
|
super
|
84
71
|
return unless modifier_and_def_on_same_line?(node)
|
@@ -87,7 +74,7 @@ module RuboCop
|
|
87
74
|
*_, body = *args.first
|
88
75
|
|
89
76
|
def_end_config = config.for_cop('Lint/DefEndAlignment')
|
90
|
-
style = def_end_config['
|
77
|
+
style = def_end_config['EnforcedStyleAlignWith'] || 'start_of_line'
|
91
78
|
base = style == 'def' ? args.first : node
|
92
79
|
|
93
80
|
check_indentation(base.source_range, body)
|
@@ -99,67 +86,49 @@ module RuboCop
|
|
99
86
|
end
|
100
87
|
|
101
88
|
def on_for(node)
|
102
|
-
|
103
|
-
check_indentation(node.loc.keyword, body)
|
89
|
+
check_indentation(node.loc.keyword, node.body)
|
104
90
|
end
|
105
91
|
|
106
92
|
def on_while(node, base = node)
|
107
93
|
return if ignored_node?(node)
|
108
94
|
|
109
|
-
|
110
|
-
return unless node.loc.keyword.begin_pos ==
|
111
|
-
node.source_range.begin_pos
|
95
|
+
return unless node.single_line_condition?
|
112
96
|
|
113
|
-
check_indentation(base.loc, body)
|
97
|
+
check_indentation(base.loc, node.body)
|
114
98
|
end
|
115
99
|
|
116
100
|
alias on_until on_while
|
117
101
|
|
118
|
-
def on_case(
|
119
|
-
|
120
|
-
|
121
|
-
branches.compact.each do |b|
|
122
|
-
if b.when_type?
|
123
|
-
# TODO: Revert to the original expression once the fix in Rubinius
|
124
|
-
# is released.
|
125
|
-
#
|
126
|
-
# Originally this expression was:
|
127
|
-
#
|
128
|
-
# *_conditions, body = *b
|
129
|
-
#
|
130
|
-
# However it fails on Rubinius 2.2.9 due to its bug:
|
131
|
-
#
|
132
|
-
# RuntimeError:
|
133
|
-
# can't modify frozen instance of Array
|
134
|
-
# # kernel/common/array.rb:988:in `pop'
|
135
|
-
# # ./lib/rubocop/cop/style/indentation_width.rb:99:in `on_case'
|
136
|
-
#
|
137
|
-
# It seems to be fixed on the current master (0a92c3c).
|
138
|
-
body = b.children.last
|
139
|
-
|
140
|
-
# Check "when" body against "when" keyword indentation.
|
141
|
-
check_indentation(b.loc.keyword, body)
|
142
|
-
latest_when = b
|
143
|
-
else
|
144
|
-
# Since it's not easy to get the position of the "else" keyword,
|
145
|
-
# we check "else" body against latest "when" keyword indentation.
|
146
|
-
check_indentation(latest_when.loc.keyword, b)
|
147
|
-
end
|
102
|
+
def on_case(case_node)
|
103
|
+
case_node.each_when do |when_node|
|
104
|
+
check_indentation(when_node.loc.keyword, when_node.body)
|
148
105
|
end
|
106
|
+
|
107
|
+
check_indentation(case_node.when_branches.last.loc.keyword,
|
108
|
+
case_node.else_branch)
|
149
109
|
end
|
150
110
|
|
151
111
|
def on_if(node, base = node)
|
152
|
-
return if ignored_node?(node)
|
153
|
-
return if ternary?
|
154
|
-
return if modifier_if?(node)
|
155
|
-
|
156
|
-
_condition, body, else_clause = if_node_parts(node)
|
112
|
+
return if ignored_node?(node) || !node.body
|
113
|
+
return if node.ternary? || node.modifier_form?
|
157
114
|
|
158
|
-
check_if(node, body,
|
115
|
+
check_if(node, node.body, node.else_branch, base.loc)
|
159
116
|
end
|
160
117
|
|
161
118
|
private
|
162
119
|
|
120
|
+
def check_members(base, members)
|
121
|
+
check_indentation(base, members.first)
|
122
|
+
|
123
|
+
return unless members.any? && members.first.begin_type?
|
124
|
+
return unless indentation_consistency_style == 'rails'
|
125
|
+
|
126
|
+
each_member(members) do |member, previous_modifier|
|
127
|
+
check_indentation(previous_modifier, member,
|
128
|
+
indentation_consistency_style)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
163
132
|
def each_member(members)
|
164
133
|
previous_modifier = nil
|
165
134
|
members.first.children.each do |member|
|
@@ -188,7 +157,7 @@ module RuboCop
|
|
188
157
|
return unless rhs
|
189
158
|
|
190
159
|
end_config = config.for_cop('Lint/EndAlignment')
|
191
|
-
style = end_config['
|
160
|
+
style = end_config['EnforcedStyleAlignWith'] || 'keyword'
|
192
161
|
base = variable_alignment?(node.loc, rhs, style.to_sym) ? node : rhs
|
193
162
|
|
194
163
|
case rhs.type
|
@@ -201,14 +170,14 @@ module RuboCop
|
|
201
170
|
end
|
202
171
|
|
203
172
|
def check_if(node, body, else_clause, base_loc)
|
204
|
-
return if ternary?
|
173
|
+
return if node.ternary?
|
205
174
|
|
206
175
|
check_indentation(base_loc, body)
|
207
176
|
return unless else_clause
|
208
177
|
|
209
178
|
# If the else clause is an elsif, it will get its own on_if call so
|
210
179
|
# we don't need to process it here.
|
211
|
-
return if elsif?
|
180
|
+
return if else_clause.if_type? && else_clause.elsif?
|
212
181
|
|
213
182
|
check_indentation(node.loc.else, else_clause)
|
214
183
|
end
|