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
@@ -50,7 +50,7 @@ shared_examples_for 'misaligned' do |prefix, alignment_base, arg, end_kw, name|
|
|
50
50
|
# style. In other cases, it won't match any style at all
|
51
51
|
expect(cop.config_to_allow_offenses).to(
|
52
52
|
eq('Enabled' => false).or(
|
53
|
-
satisfy { |h| other_styles.include?(h['
|
53
|
+
satisfy { |h| other_styles.include?(h['EnforcedStyleAlignWith']) }
|
54
54
|
)
|
55
55
|
)
|
56
56
|
end
|
data/lib/rubocop/runner.rb
CHANGED
@@ -142,7 +142,12 @@ module RuboCop
|
|
142
142
|
|
143
143
|
def autocorrect_unneeded_disables(source, cop)
|
144
144
|
cop.processed_source = source
|
145
|
-
|
145
|
+
|
146
|
+
Cop::Team.new(
|
147
|
+
RuboCop::Cop::Registry.new,
|
148
|
+
nil,
|
149
|
+
@options
|
150
|
+
).autocorrect(source.buffer, [cop])
|
146
151
|
end
|
147
152
|
|
148
153
|
def file_started(file)
|
@@ -268,7 +273,7 @@ module RuboCop
|
|
268
273
|
|
269
274
|
cop_classes.reject! { |c| c.match?(@options[:except]) }
|
270
275
|
|
271
|
-
cop_classes
|
276
|
+
Cop::Registry.new(cop_classes)
|
272
277
|
end
|
273
278
|
end
|
274
279
|
|
data/lib/rubocop/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.47.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2017-01-16 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rainbow
|
@@ -38,7 +38,7 @@ dependencies:
|
|
38
38
|
requirements:
|
39
39
|
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: 2.3.
|
41
|
+
version: 2.3.3.1
|
42
42
|
- - "<"
|
43
43
|
- !ruby/object:Gem::Version
|
44
44
|
version: '3.0'
|
@@ -48,7 +48,7 @@ dependencies:
|
|
48
48
|
requirements:
|
49
49
|
- - ">="
|
50
50
|
- !ruby/object:Gem::Version
|
51
|
-
version: 2.3.
|
51
|
+
version: 2.3.3.1
|
52
52
|
- - "<"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
@@ -134,10 +134,23 @@ files:
|
|
134
134
|
- config/disabled.yml
|
135
135
|
- config/enabled.yml
|
136
136
|
- lib/rubocop.rb
|
137
|
-
- lib/rubocop/
|
138
|
-
- lib/rubocop/
|
139
|
-
- lib/rubocop/
|
140
|
-
- lib/rubocop/
|
137
|
+
- lib/rubocop/ast/builder.rb
|
138
|
+
- lib/rubocop/ast/node.rb
|
139
|
+
- lib/rubocop/ast/node/array_node.rb
|
140
|
+
- lib/rubocop/ast/node/case_node.rb
|
141
|
+
- lib/rubocop/ast/node/for_node.rb
|
142
|
+
- lib/rubocop/ast/node/hash_node.rb
|
143
|
+
- lib/rubocop/ast/node/if_node.rb
|
144
|
+
- lib/rubocop/ast/node/keyword_splat_node.rb
|
145
|
+
- lib/rubocop/ast/node/mixin/conditional_node.rb
|
146
|
+
- lib/rubocop/ast/node/mixin/hash_element_node.rb
|
147
|
+
- lib/rubocop/ast/node/mixin/modifier_node.rb
|
148
|
+
- lib/rubocop/ast/node/pair_node.rb
|
149
|
+
- lib/rubocop/ast/node/until_node.rb
|
150
|
+
- lib/rubocop/ast/node/when_node.rb
|
151
|
+
- lib/rubocop/ast/node/while_node.rb
|
152
|
+
- lib/rubocop/ast/sexp.rb
|
153
|
+
- lib/rubocop/ast/traversal.rb
|
141
154
|
- lib/rubocop/cached_data.rb
|
142
155
|
- lib/rubocop/cli.rb
|
143
156
|
- lib/rubocop/comment_config.rb
|
@@ -146,6 +159,7 @@ files:
|
|
146
159
|
- lib/rubocop/config_loader_resolver.rb
|
147
160
|
- lib/rubocop/config_store.rb
|
148
161
|
- lib/rubocop/cop/autocorrect_logic.rb
|
162
|
+
- lib/rubocop/cop/badge.rb
|
149
163
|
- lib/rubocop/cop/bundler/duplicated_gem.rb
|
150
164
|
- lib/rubocop/cop/bundler/ordered_gems.rb
|
151
165
|
- lib/rubocop/cop/commissioner.rb
|
@@ -174,7 +188,6 @@ files:
|
|
174
188
|
- lib/rubocop/cop/lint/end_alignment.rb
|
175
189
|
- lib/rubocop/cop/lint/end_in_method.rb
|
176
190
|
- lib/rubocop/cop/lint/ensure_return.rb
|
177
|
-
- lib/rubocop/cop/lint/eval.rb
|
178
191
|
- lib/rubocop/cop/lint/float_out_of_range.rb
|
179
192
|
- lib/rubocop/cop/lint/format_parameter_mismatch.rb
|
180
193
|
- lib/rubocop/cop/lint/handle_exceptions.rb
|
@@ -185,6 +198,7 @@ files:
|
|
185
198
|
- lib/rubocop/cop/lint/literal_in_condition.rb
|
186
199
|
- lib/rubocop/cop/lint/literal_in_interpolation.rb
|
187
200
|
- lib/rubocop/cop/lint/loop.rb
|
201
|
+
- lib/rubocop/cop/lint/multiple_compare.rb
|
188
202
|
- lib/rubocop/cop/lint/nested_method_definition.rb
|
189
203
|
- lib/rubocop/cop/lint/next_without_accumulator.rb
|
190
204
|
- lib/rubocop/cop/lint/non_local_exit_from_iterator.rb
|
@@ -194,6 +208,7 @@ files:
|
|
194
208
|
- lib/rubocop/cop/lint/rand_one.rb
|
195
209
|
- lib/rubocop/cop/lint/require_parentheses.rb
|
196
210
|
- lib/rubocop/cop/lint/rescue_exception.rb
|
211
|
+
- lib/rubocop/cop/lint/safe_navigation_chain.rb
|
197
212
|
- lib/rubocop/cop/lint/shadowed_exception.rb
|
198
213
|
- lib/rubocop/cop/lint/shadowing_outer_local_variable.rb
|
199
214
|
- lib/rubocop/cop/lint/string_conversion_in_interpolation.rb
|
@@ -211,6 +226,7 @@ files:
|
|
211
226
|
- lib/rubocop/cop/lint/useless_else_without_rescue.rb
|
212
227
|
- lib/rubocop/cop/lint/useless_setter_call.rb
|
213
228
|
- lib/rubocop/cop/lint/void.rb
|
229
|
+
- lib/rubocop/cop/message_annotator.rb
|
214
230
|
- lib/rubocop/cop/metrics/abc_size.rb
|
215
231
|
- lib/rubocop/cop/metrics/block_length.rb
|
216
232
|
- lib/rubocop/cop/metrics/block_nesting.rb
|
@@ -230,17 +246,18 @@ files:
|
|
230
246
|
- lib/rubocop/cop/mixin/classish_length.rb
|
231
247
|
- lib/rubocop/cop/mixin/code_length.rb
|
232
248
|
- lib/rubocop/cop/mixin/configurable_enforced_style.rb
|
249
|
+
- lib/rubocop/cop/mixin/configurable_formatting.rb
|
233
250
|
- lib/rubocop/cop/mixin/configurable_max.rb
|
234
251
|
- lib/rubocop/cop/mixin/configurable_naming.rb
|
235
252
|
- lib/rubocop/cop/mixin/configurable_numbering.rb
|
236
253
|
- lib/rubocop/cop/mixin/def_node.rb
|
237
254
|
- lib/rubocop/cop/mixin/documentation_comment.rb
|
255
|
+
- lib/rubocop/cop/mixin/duplication.rb
|
238
256
|
- lib/rubocop/cop/mixin/empty_lines_around_body.rb
|
239
257
|
- lib/rubocop/cop/mixin/end_keyword_alignment.rb
|
240
258
|
- lib/rubocop/cop/mixin/first_element_line_break.rb
|
241
259
|
- lib/rubocop/cop/mixin/frozen_string_literal.rb
|
242
|
-
- lib/rubocop/cop/mixin/
|
243
|
-
- lib/rubocop/cop/mixin/if_node.rb
|
260
|
+
- lib/rubocop/cop/mixin/hash_alignment.rb
|
244
261
|
- lib/rubocop/cop/mixin/integer_node.rb
|
245
262
|
- lib/rubocop/cop/mixin/match_range.rb
|
246
263
|
- lib/rubocop/cop/mixin/method_complexity.rb
|
@@ -264,6 +281,7 @@ files:
|
|
264
281
|
- lib/rubocop/cop/mixin/string_help.rb
|
265
282
|
- lib/rubocop/cop/mixin/string_literals_help.rb
|
266
283
|
- lib/rubocop/cop/mixin/surrounding_space.rb
|
284
|
+
- lib/rubocop/cop/mixin/target_ruby_version.rb
|
267
285
|
- lib/rubocop/cop/mixin/too_many_lines.rb
|
268
286
|
- lib/rubocop/cop/mixin/trailing_comma.rb
|
269
287
|
- lib/rubocop/cop/mixin/unused_argument.rb
|
@@ -284,6 +302,7 @@ files:
|
|
284
302
|
- lib/rubocop/cop/performance/redundant_match.rb
|
285
303
|
- lib/rubocop/cop/performance/redundant_merge.rb
|
286
304
|
- lib/rubocop/cop/performance/redundant_sort_by.rb
|
305
|
+
- lib/rubocop/cop/performance/regexp_match.rb
|
287
306
|
- lib/rubocop/cop/performance/reverse_each.rb
|
288
307
|
- lib/rubocop/cop/performance/sample.rb
|
289
308
|
- lib/rubocop/cop/performance/size.rb
|
@@ -297,6 +316,7 @@ files:
|
|
297
316
|
- lib/rubocop/cop/rails/dynamic_find_by.rb
|
298
317
|
- lib/rubocop/cop/rails/enum_uniqueness.rb
|
299
318
|
- lib/rubocop/cop/rails/exit.rb
|
319
|
+
- lib/rubocop/cop/rails/file_path.rb
|
300
320
|
- lib/rubocop/cop/rails/find_by.rb
|
301
321
|
- lib/rubocop/cop/rails/find_each.rb
|
302
322
|
- lib/rubocop/cop/rails/has_and_belongs_to_many.rb
|
@@ -307,13 +327,19 @@ files:
|
|
307
327
|
- lib/rubocop/cop/rails/pluralization_grammar.rb
|
308
328
|
- lib/rubocop/cop/rails/read_write_attribute.rb
|
309
329
|
- lib/rubocop/cop/rails/request_referer.rb
|
330
|
+
- lib/rubocop/cop/rails/reversible_migration.rb
|
310
331
|
- lib/rubocop/cop/rails/safe_navigation.rb
|
311
332
|
- lib/rubocop/cop/rails/save_bang.rb
|
312
333
|
- lib/rubocop/cop/rails/scope_args.rb
|
334
|
+
- lib/rubocop/cop/rails/skips_model_validations.rb
|
313
335
|
- lib/rubocop/cop/rails/time_zone.rb
|
314
336
|
- lib/rubocop/cop/rails/uniq_before_pluck.rb
|
315
337
|
- lib/rubocop/cop/rails/validation.rb
|
338
|
+
- lib/rubocop/cop/registry.rb
|
339
|
+
- lib/rubocop/cop/security/eval.rb
|
316
340
|
- lib/rubocop/cop/security/json_load.rb
|
341
|
+
- lib/rubocop/cop/security/marshal_load.rb
|
342
|
+
- lib/rubocop/cop/security/yaml_load.rb
|
317
343
|
- lib/rubocop/cop/severity.rb
|
318
344
|
- lib/rubocop/cop/style/access_modifier_indentation.rb
|
319
345
|
- lib/rubocop/cop/style/accessor_method_name.rb
|
@@ -405,7 +431,8 @@ files:
|
|
405
431
|
- lib/rubocop/cop/style/lambda_call.rb
|
406
432
|
- lib/rubocop/cop/style/leading_comment_space.rb
|
407
433
|
- lib/rubocop/cop/style/line_end_concatenation.rb
|
408
|
-
- lib/rubocop/cop/style/
|
434
|
+
- lib/rubocop/cop/style/method_call_with_args_parentheses.rb
|
435
|
+
- lib/rubocop/cop/style/method_call_without_args_parentheses.rb
|
409
436
|
- lib/rubocop/cop/style/method_called_on_do_end_block.rb
|
410
437
|
- lib/rubocop/cop/style/method_def_parentheses.rb
|
411
438
|
- lib/rubocop/cop/style/method_missing.rb
|
@@ -545,6 +572,7 @@ files:
|
|
545
572
|
- lib/rubocop/formatter/simple_text_formatter.rb
|
546
573
|
- lib/rubocop/formatter/text_util.rb
|
547
574
|
- lib/rubocop/formatter/worst_offenders_formatter.rb
|
575
|
+
- lib/rubocop/magic_comment.rb
|
548
576
|
- lib/rubocop/name_similarity.rb
|
549
577
|
- lib/rubocop/node_pattern.rb
|
550
578
|
- lib/rubocop/options.rb
|
@@ -585,9 +613,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
585
613
|
version: '0'
|
586
614
|
requirements: []
|
587
615
|
rubyforge_project:
|
588
|
-
rubygems_version: 2.
|
616
|
+
rubygems_version: 2.5.2
|
589
617
|
signing_key:
|
590
618
|
specification_version: 4
|
591
619
|
summary: Automatic Ruby code style checking tool.
|
592
620
|
test_files: []
|
593
|
-
has_rdoc:
|
data/lib/rubocop/ast_node.rb
DELETED
@@ -1,624 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RuboCop
|
4
|
-
# `RuboCop::Node` is a subclass of `Parser::AST::Node`. It provides access to
|
5
|
-
# parent nodes and an object-oriented way to traverse an AST with the power
|
6
|
-
# of `Enumerable`.
|
7
|
-
#
|
8
|
-
# It has predicate methods for every node type, like this:
|
9
|
-
#
|
10
|
-
# @example
|
11
|
-
# node.send_type? # Equivalent to: `node.type == :send`
|
12
|
-
# node.op_asgn_type? # Equivalent to: `node.type == :op_asgn`
|
13
|
-
#
|
14
|
-
# # Non-word characters (other than a-zA-Z0-9_) in type names are omitted.
|
15
|
-
# node.defined_type? # Equivalent to: `node.type == :defined?`
|
16
|
-
#
|
17
|
-
# # Find the first lvar node under the receiver node.
|
18
|
-
# lvar_node = node.each_descendant.find(&:lvar_type?)
|
19
|
-
#
|
20
|
-
class Node < Parser::AST::Node # rubocop:disable Metrics/ClassLength
|
21
|
-
include RuboCop::Sexp
|
22
|
-
|
23
|
-
COMPARISON_OPERATORS = [:!, :==, :===, :!=, :<=, :>=, :>, :<, :<=>].freeze
|
24
|
-
|
25
|
-
TRUTHY_LITERALS = [:str, :dstr, :xstr, :int, :float, :sym, :dsym, :array,
|
26
|
-
:hash, :regexp, :true, :irange, :erange, :complex,
|
27
|
-
:rational, :regopt].freeze
|
28
|
-
FALSEY_LITERALS = [:false, :nil].freeze
|
29
|
-
LITERALS = (TRUTHY_LITERALS + FALSEY_LITERALS).freeze
|
30
|
-
COMPOSITE_LITERALS = [:dstr, :xstr, :dsym, :array, :hash, :irange,
|
31
|
-
:erange, :regexp].freeze
|
32
|
-
BASIC_LITERALS = (LITERALS - COMPOSITE_LITERALS).freeze
|
33
|
-
MUTABLE_LITERALS = [:str, :dstr, :xstr, :array, :hash].freeze
|
34
|
-
IMMUTABLE_LITERALS = (LITERALS - MUTABLE_LITERALS).freeze
|
35
|
-
|
36
|
-
VARIABLES = [:ivar, :gvar, :cvar, :lvar].freeze
|
37
|
-
REFERENCES = [:nth_ref, :back_ref].freeze
|
38
|
-
KEYWORDS = [:alias, :and, :break, :case, :class, :def, :defs, :defined?,
|
39
|
-
:kwbegin, :do, :else, :ensure, :for, :if, :module, :next, :not,
|
40
|
-
:or, :postexe, :redo, :rescue, :retry, :return, :self, :super,
|
41
|
-
:zsuper, :then, :undef, :until, :when, :while, :yield].freeze
|
42
|
-
OPERATOR_KEYWORDS = [:and, :or].freeze
|
43
|
-
SPECIAL_KEYWORDS = %w(__FILE__ __LINE__ __ENCODING__).freeze
|
44
|
-
|
45
|
-
# def_matcher can be used to define a pattern-matching method on Node
|
46
|
-
class << self
|
47
|
-
def def_matcher(method_name, pattern_str)
|
48
|
-
compiler = RuboCop::NodePattern::Compiler.new(pattern_str, 'self')
|
49
|
-
src = "def #{method_name}(" \
|
50
|
-
"#{compiler.emit_param_list});" \
|
51
|
-
"#{compiler.emit_method_code};end"
|
52
|
-
|
53
|
-
file, lineno = *caller.first.split(':')
|
54
|
-
class_eval(src, file, lineno.to_i)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# @see http://rubydoc.info/gems/ast/AST/Node:initialize
|
59
|
-
def initialize(type, children = [], properties = {})
|
60
|
-
@mutable_attributes = {}
|
61
|
-
|
62
|
-
# ::AST::Node#initialize freezes itself.
|
63
|
-
super
|
64
|
-
|
65
|
-
# #parent= may be invoked multiple times for a node because there are
|
66
|
-
# pending nodes while constructing AST and they are replaced later.
|
67
|
-
# For example, `lvar` and `send` type nodes are initially created as an
|
68
|
-
# `ident` type node and fixed to the appropriate type later.
|
69
|
-
# So, the #parent attribute needs to be mutable.
|
70
|
-
each_child_node do |child_node|
|
71
|
-
child_node.parent = self unless child_node.complete?
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
Parser::Meta::NODE_TYPES.each do |node_type|
|
76
|
-
method_name = "#{node_type.to_s.gsub(/\W/, '')}_type?"
|
77
|
-
define_method(method_name) do
|
78
|
-
type == node_type
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# Returns the parent node, or `nil` if the receiver is a root node.
|
83
|
-
#
|
84
|
-
# @return [Node, nil] the parent node or `nil`
|
85
|
-
def parent
|
86
|
-
@mutable_attributes[:parent]
|
87
|
-
end
|
88
|
-
|
89
|
-
def parent=(node)
|
90
|
-
@mutable_attributes[:parent] = node
|
91
|
-
end
|
92
|
-
|
93
|
-
def complete!
|
94
|
-
@mutable_attributes.freeze
|
95
|
-
each_child_node(&:complete!)
|
96
|
-
end
|
97
|
-
|
98
|
-
def complete?
|
99
|
-
@mutable_attributes.frozen?
|
100
|
-
end
|
101
|
-
|
102
|
-
protected :parent=
|
103
|
-
|
104
|
-
# Override `AST::Node#updated` so that `AST::Processor` does not try to
|
105
|
-
# mutate our ASTs. Since we keep references from children to parents and
|
106
|
-
# not just the other way around, we cannot update an AST and share identical
|
107
|
-
# subtrees. Rather, the entire AST must be copied any time any part of it
|
108
|
-
# is changed.
|
109
|
-
#
|
110
|
-
def updated(type = nil, children = nil, properties = {})
|
111
|
-
properties[:location] ||= @location
|
112
|
-
Node.new(type || @type, children || @children, properties)
|
113
|
-
end
|
114
|
-
|
115
|
-
# Returns the index of the receiver node in its siblings. (Sibling index
|
116
|
-
# uses zero based numbering.)
|
117
|
-
#
|
118
|
-
# @return [Integer] the index of the receiver node in its siblings
|
119
|
-
def sibling_index
|
120
|
-
parent.children.index { |sibling| sibling.equal?(self) }
|
121
|
-
end
|
122
|
-
|
123
|
-
# Calls the given block for each ancestor node from parent to root.
|
124
|
-
# If no block is given, an `Enumerator` is returned.
|
125
|
-
#
|
126
|
-
# @overload each_ancestor
|
127
|
-
# Yield all nodes.
|
128
|
-
# @overload each_ancestor(type)
|
129
|
-
# Yield only nodes matching the type.
|
130
|
-
# @param [Symbol] type a node type
|
131
|
-
# @overload each_ancestor(type_a, type_b, ...)
|
132
|
-
# Yield only nodes matching any of the types.
|
133
|
-
# @param [Symbol] type_a a node type
|
134
|
-
# @param [Symbol] type_b a node type
|
135
|
-
# @overload each_ancestor(types)
|
136
|
-
# Yield only nodes matching any of types in the array.
|
137
|
-
# @param [Array<Symbol>] types an array containing node types
|
138
|
-
# @yieldparam [Node] node each ancestor node
|
139
|
-
# @return [self] if a block is given
|
140
|
-
# @return [Enumerator] if no block is given
|
141
|
-
def each_ancestor(*types, &block)
|
142
|
-
return to_enum(__method__, *types) unless block_given?
|
143
|
-
|
144
|
-
if types.empty?
|
145
|
-
visit_ancestors(&block)
|
146
|
-
else
|
147
|
-
visit_ancestors_with_types(types, &block)
|
148
|
-
end
|
149
|
-
|
150
|
-
self
|
151
|
-
end
|
152
|
-
|
153
|
-
# Returns an array of ancestor nodes.
|
154
|
-
# This is a shorthand for `node.each_ancestor.to_a`.
|
155
|
-
#
|
156
|
-
# @return [Array<Node>] an array of ancestor nodes
|
157
|
-
def ancestors
|
158
|
-
each_ancestor.to_a
|
159
|
-
end
|
160
|
-
|
161
|
-
# Calls the given block for each child node.
|
162
|
-
# If no block is given, an `Enumerator` is returned.
|
163
|
-
#
|
164
|
-
# Note that this is different from `node.children.each { |child| ... }`
|
165
|
-
# which yields all children including non-node elements.
|
166
|
-
#
|
167
|
-
# @overload each_child_node
|
168
|
-
# Yield all nodes.
|
169
|
-
# @overload each_child_node(type)
|
170
|
-
# Yield only nodes matching the type.
|
171
|
-
# @param [Symbol] type a node type
|
172
|
-
# @overload each_child_node(type_a, type_b, ...)
|
173
|
-
# Yield only nodes matching any of the types.
|
174
|
-
# @param [Symbol] type_a a node type
|
175
|
-
# @param [Symbol] type_b a node type
|
176
|
-
# @overload each_child_node(types)
|
177
|
-
# Yield only nodes matching any of types in the array.
|
178
|
-
# @param [Array<Symbol>] types an array containing node types
|
179
|
-
# @yieldparam [Node] node each child node
|
180
|
-
# @return [self] if a block is given
|
181
|
-
# @return [Enumerator] if no block is given
|
182
|
-
def each_child_node(*types)
|
183
|
-
return to_enum(__method__, *types) unless block_given?
|
184
|
-
|
185
|
-
children.each do |child|
|
186
|
-
next unless child.is_a?(Node)
|
187
|
-
yield child if types.empty? || types.include?(child.type)
|
188
|
-
end
|
189
|
-
|
190
|
-
self
|
191
|
-
end
|
192
|
-
|
193
|
-
# Returns an array of child nodes.
|
194
|
-
# This is a shorthand for `node.each_child_node.to_a`.
|
195
|
-
#
|
196
|
-
# @return [Array<Node>] an array of child nodes
|
197
|
-
def child_nodes
|
198
|
-
each_child_node.to_a
|
199
|
-
end
|
200
|
-
|
201
|
-
# Calls the given block for each descendant node with depth first order.
|
202
|
-
# If no block is given, an `Enumerator` is returned.
|
203
|
-
#
|
204
|
-
# @overload each_descendant
|
205
|
-
# Yield all nodes.
|
206
|
-
# @overload each_descendant(type)
|
207
|
-
# Yield only nodes matching the type.
|
208
|
-
# @param [Symbol] type a node type
|
209
|
-
# @overload each_descendant(type_a, type_b, ...)
|
210
|
-
# Yield only nodes matching any of the types.
|
211
|
-
# @param [Symbol] type_a a node type
|
212
|
-
# @param [Symbol] type_b a node type
|
213
|
-
# @overload each_descendant(types)
|
214
|
-
# Yield only nodes matching any of types in the array.
|
215
|
-
# @param [Array<Symbol>] types an array containing node types
|
216
|
-
# @yieldparam [Node] node each descendant node
|
217
|
-
# @return [self] if a block is given
|
218
|
-
# @return [Enumerator] if no block is given
|
219
|
-
def each_descendant(*types, &block)
|
220
|
-
return to_enum(__method__, *types) unless block_given?
|
221
|
-
|
222
|
-
if types.empty?
|
223
|
-
visit_descendants(&block)
|
224
|
-
else
|
225
|
-
visit_descendants_with_types(types, &block)
|
226
|
-
end
|
227
|
-
|
228
|
-
self
|
229
|
-
end
|
230
|
-
|
231
|
-
# Returns an array of descendant nodes.
|
232
|
-
# This is a shorthand for `node.each_descendant.to_a`.
|
233
|
-
#
|
234
|
-
# @return [Array<Node>] an array of descendant nodes
|
235
|
-
def descendants
|
236
|
-
each_descendant.to_a
|
237
|
-
end
|
238
|
-
|
239
|
-
# Calls the given block for the receiver and each descendant node in
|
240
|
-
# depth-first order.
|
241
|
-
# If no block is given, an `Enumerator` is returned.
|
242
|
-
#
|
243
|
-
# This method would be useful when you treat the receiver node as the root
|
244
|
-
# of a tree and want to iterate over all nodes in the tree.
|
245
|
-
#
|
246
|
-
# @overload each_node
|
247
|
-
# Yield all nodes.
|
248
|
-
# @overload each_node(type)
|
249
|
-
# Yield only nodes matching the type.
|
250
|
-
# @param [Symbol] type a node type
|
251
|
-
# @overload each_node(type_a, type_b, ...)
|
252
|
-
# Yield only nodes matching any of the types.
|
253
|
-
# @param [Symbol] type_a a node type
|
254
|
-
# @param [Symbol] type_b a node type
|
255
|
-
# @overload each_node(types)
|
256
|
-
# Yield only nodes matching any of types in the array.
|
257
|
-
# @param [Array<Symbol>] types an array containing node types
|
258
|
-
# @yieldparam [Node] node each node
|
259
|
-
# @return [self] if a block is given
|
260
|
-
# @return [Enumerator] if no block is given
|
261
|
-
def each_node(*types, &block)
|
262
|
-
return to_enum(__method__, *types) unless block_given?
|
263
|
-
|
264
|
-
yield self if types.empty? || types.include?(type)
|
265
|
-
|
266
|
-
if types.empty?
|
267
|
-
visit_descendants(&block)
|
268
|
-
else
|
269
|
-
visit_descendants_with_types(types, &block)
|
270
|
-
end
|
271
|
-
|
272
|
-
self
|
273
|
-
end
|
274
|
-
|
275
|
-
def source
|
276
|
-
loc.expression.source
|
277
|
-
end
|
278
|
-
|
279
|
-
def source_range
|
280
|
-
loc.expression
|
281
|
-
end
|
282
|
-
|
283
|
-
## Destructuring
|
284
|
-
|
285
|
-
def_matcher :receiver, '{(send $_ ...) (block (send $_ ...) ...)}'
|
286
|
-
def_matcher :method_name, '{(send _ $_ ...) (block (send _ $_ ...) ...)}'
|
287
|
-
def_matcher :method_args, '{(send _ _ $...) (block (send _ _ $...) ...)}'
|
288
|
-
# Note: for masgn, #asgn_rhs will be an array node
|
289
|
-
def_matcher :asgn_rhs, '[assignment? (... $_)]'
|
290
|
-
def_matcher :str_content, '(str $_)'
|
291
|
-
|
292
|
-
def const_name
|
293
|
-
return unless const_type?
|
294
|
-
namespace, name = *self
|
295
|
-
if namespace && !namespace.cbase_type?
|
296
|
-
"#{namespace.const_name}::#{name}"
|
297
|
-
else
|
298
|
-
name.to_s
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
def_matcher :defined_module0, <<-PATTERN
|
303
|
-
{(class (const $_ $_) ...)
|
304
|
-
(module (const $_ $_) ...)
|
305
|
-
(casgn $_ $_ (send (const nil {:Class :Module}) :new ...))
|
306
|
-
(casgn $_ $_ (block (send (const nil {:Class :Module}) :new ...) ...))}
|
307
|
-
PATTERN
|
308
|
-
private :defined_module0
|
309
|
-
|
310
|
-
def defined_module
|
311
|
-
namespace, name = *defined_module0
|
312
|
-
s(:const, namespace, name) if name
|
313
|
-
end
|
314
|
-
|
315
|
-
def defined_module_name
|
316
|
-
(const = defined_module) && const.const_name
|
317
|
-
end
|
318
|
-
|
319
|
-
## Searching the AST
|
320
|
-
|
321
|
-
def parent_module_name
|
322
|
-
# what class or module is this method/constant/etc definition in?
|
323
|
-
# returns nil if answer cannot be determined
|
324
|
-
ancestors = each_ancestor(:class, :module, :sclass, :casgn, :block)
|
325
|
-
result = ancestors.map do |ancestor|
|
326
|
-
parent_module_name_part(ancestor) { |full_name| return full_name }
|
327
|
-
end.compact.reverse.join('::')
|
328
|
-
result.empty? ? 'Object' : result
|
329
|
-
end
|
330
|
-
|
331
|
-
## Predicates
|
332
|
-
|
333
|
-
def modifier_form?
|
334
|
-
loc.respond_to?(:end) && loc.end.nil?
|
335
|
-
end
|
336
|
-
|
337
|
-
def multiline?
|
338
|
-
expr = loc.expression
|
339
|
-
expr && (expr.first_line != expr.last_line)
|
340
|
-
end
|
341
|
-
|
342
|
-
def single_line?
|
343
|
-
!multiline?
|
344
|
-
end
|
345
|
-
|
346
|
-
def asgn_method_call?
|
347
|
-
!COMPARISON_OPERATORS.include?(method_name) &&
|
348
|
-
method_name.to_s.end_with?('='.freeze)
|
349
|
-
end
|
350
|
-
|
351
|
-
def_matcher :equals_asgn?, '{lvasgn ivasgn cvasgn gvasgn casgn masgn}'
|
352
|
-
def_matcher :shorthand_asgn?, '{op_asgn or_asgn and_asgn}'
|
353
|
-
def_matcher :assignment?, '{equals_asgn? shorthand_asgn? asgn_method_call?}'
|
354
|
-
|
355
|
-
def literal?
|
356
|
-
LITERALS.include?(type)
|
357
|
-
end
|
358
|
-
|
359
|
-
def basic_literal?
|
360
|
-
BASIC_LITERALS.include?(type)
|
361
|
-
end
|
362
|
-
|
363
|
-
def truthy_literal?
|
364
|
-
TRUTHY_LITERALS.include?(type)
|
365
|
-
end
|
366
|
-
|
367
|
-
def falsey_literal?
|
368
|
-
FALSEY_LITERALS.include?(type)
|
369
|
-
end
|
370
|
-
|
371
|
-
def mutable_literal?
|
372
|
-
MUTABLE_LITERALS.include?(type)
|
373
|
-
end
|
374
|
-
|
375
|
-
def immutable_literal?
|
376
|
-
IMMUTABLE_LITERALS.include?(type)
|
377
|
-
end
|
378
|
-
|
379
|
-
[:literal, :basic_literal].each do |kind|
|
380
|
-
recursive_kind = :"recursive_#{kind}?"
|
381
|
-
kind_filter = :"#{kind}?"
|
382
|
-
define_method(recursive_kind) do
|
383
|
-
case type
|
384
|
-
when :send
|
385
|
-
receiver, method_name, *args = *self
|
386
|
-
COMPARISON_OPERATORS.include?(method_name) &&
|
387
|
-
receiver.send(recursive_kind) &&
|
388
|
-
args.all?(&recursive_kind)
|
389
|
-
when :begin, :pair, *OPERATOR_KEYWORDS, *COMPOSITE_LITERALS
|
390
|
-
children.all?(&recursive_kind)
|
391
|
-
else
|
392
|
-
send(kind_filter)
|
393
|
-
end
|
394
|
-
end
|
395
|
-
end
|
396
|
-
|
397
|
-
def variable?
|
398
|
-
VARIABLES.include?(type)
|
399
|
-
end
|
400
|
-
|
401
|
-
def reference?
|
402
|
-
REFERENCES.include?(type)
|
403
|
-
end
|
404
|
-
|
405
|
-
def keyword?
|
406
|
-
return true if special_keyword? || keyword_not?
|
407
|
-
return false unless KEYWORDS.include?(type)
|
408
|
-
|
409
|
-
!OPERATOR_KEYWORDS.include?(type) || loc.operator.is?(type.to_s)
|
410
|
-
end
|
411
|
-
|
412
|
-
def special_keyword?
|
413
|
-
SPECIAL_KEYWORDS.include?(source)
|
414
|
-
end
|
415
|
-
|
416
|
-
def keyword_not?
|
417
|
-
_receiver, method_name, *args = *self
|
418
|
-
args.empty? && method_name == :! && loc.selector.is?('not'.freeze)
|
419
|
-
end
|
420
|
-
|
421
|
-
def keyword_bang?
|
422
|
-
_receiver, method_name, *args = *self
|
423
|
-
args.empty? && method_name == :! && loc.selector.is?('!'.freeze)
|
424
|
-
end
|
425
|
-
|
426
|
-
def unary_operation?
|
427
|
-
return false unless loc.respond_to?(:selector) && loc.selector
|
428
|
-
Cop::Util.operator?(loc.selector.source.to_sym) &&
|
429
|
-
source_range.begin_pos == loc.selector.begin_pos
|
430
|
-
end
|
431
|
-
|
432
|
-
def binary_operation?
|
433
|
-
return false unless loc.respond_to?(:selector) && loc.selector
|
434
|
-
Cop::Util.operator?(method_name) &&
|
435
|
-
source_range.begin_pos != loc.selector.begin_pos
|
436
|
-
end
|
437
|
-
|
438
|
-
def chained?
|
439
|
-
return false if parent.nil? || !parent.send_type?
|
440
|
-
receiver, _method_name, *_args = *parent
|
441
|
-
equal?(receiver)
|
442
|
-
end
|
443
|
-
|
444
|
-
def_matcher :command?, '(send nil %1 ...)'
|
445
|
-
def_matcher :lambda?, '(block (send nil :lambda) ...)'
|
446
|
-
def_matcher :proc?, <<-PATTERN
|
447
|
-
{(block (send nil :proc) ...)
|
448
|
-
(block (send (const nil :Proc) :new) ...)
|
449
|
-
(send (const nil :Proc) :new)}
|
450
|
-
PATTERN
|
451
|
-
def_matcher :lambda_or_proc?, '{lambda? proc?}'
|
452
|
-
|
453
|
-
def_matcher :class_constructor?, <<-PATTERN
|
454
|
-
{ (send (const nil {:Class :Module}) :new ...)
|
455
|
-
(block (send (const nil {:Class :Module}) :new ...) ...)}
|
456
|
-
PATTERN
|
457
|
-
|
458
|
-
def_matcher :module_definition?, <<-PATTERN
|
459
|
-
{class module (casgn _ _ class_constructor?)}
|
460
|
-
PATTERN
|
461
|
-
|
462
|
-
# Some expressions are evaluated for their value, some for their side
|
463
|
-
# effects, and some for both
|
464
|
-
# If we know that an expression is useful only for its side effects, that
|
465
|
-
# means we can transform it in ways which preserve the side effects, but
|
466
|
-
# change the return value
|
467
|
-
# So, does the return value of this node matter? If we changed it to
|
468
|
-
# `(...; nil)`, might that affect anything?
|
469
|
-
#
|
470
|
-
# rubocop:disable Metrics/MethodLength
|
471
|
-
def value_used?
|
472
|
-
# Be conservative and return true if we're not sure
|
473
|
-
return false if parent.nil?
|
474
|
-
|
475
|
-
case parent.type
|
476
|
-
when :array, :defined?, :dstr, :dsym, :eflipflop, :erange, :float,
|
477
|
-
:hash, :iflipflop, :irange, :not, :pair, :regexp, :str, :sym, :when,
|
478
|
-
:xstr
|
479
|
-
parent.value_used?
|
480
|
-
when :begin, :kwbegin
|
481
|
-
begin_value_used?
|
482
|
-
when :for
|
483
|
-
for_value_used?
|
484
|
-
when :case, :if
|
485
|
-
case_if_value_used?
|
486
|
-
when :while, :until, :while_post, :until_post
|
487
|
-
while_until_value_used?
|
488
|
-
else
|
489
|
-
true
|
490
|
-
end
|
491
|
-
end
|
492
|
-
# rubocop:enable Metrics/MethodLength
|
493
|
-
|
494
|
-
# Some expressions are evaluated for their value, some for their side
|
495
|
-
# effects, and some for both
|
496
|
-
# If we know that expressions are useful only for their return values, and
|
497
|
-
# have no side effects, that means we can reorder them, change the number
|
498
|
-
# of times they are evaluated, or replace them with other expressions which
|
499
|
-
# are equivalent in value
|
500
|
-
# So, is evaluation of this node free of side effects?
|
501
|
-
#
|
502
|
-
def pure?
|
503
|
-
# Be conservative and return false if we're not sure
|
504
|
-
case type
|
505
|
-
when :__FILE__, :__LINE__, :const, :cvar, :defined?, :false, :float,
|
506
|
-
:gvar, :int, :ivar, :lvar, :nil, :str, :sym, :true, :regopt
|
507
|
-
true
|
508
|
-
when :and, :array, :begin, :case, :dstr, :dsym, :eflipflop, :ensure,
|
509
|
-
:erange, :for, :hash, :if, :iflipflop, :irange, :kwbegin, :not, :or,
|
510
|
-
:pair, :regexp, :until, :until_post, :when, :while, :while_post
|
511
|
-
child_nodes.all?(&:pure?)
|
512
|
-
else
|
513
|
-
false
|
514
|
-
end
|
515
|
-
end
|
516
|
-
|
517
|
-
protected
|
518
|
-
|
519
|
-
def visit_descendants(&block)
|
520
|
-
children.each do |child|
|
521
|
-
next unless child.is_a?(Node)
|
522
|
-
yield child
|
523
|
-
child.visit_descendants(&block)
|
524
|
-
end
|
525
|
-
end
|
526
|
-
|
527
|
-
def visit_descendants_with_types(types, &block)
|
528
|
-
children.each do |child|
|
529
|
-
next unless child.is_a?(Node)
|
530
|
-
yield child if types.include?(child.type)
|
531
|
-
child.visit_descendants_with_types(types, &block)
|
532
|
-
end
|
533
|
-
end
|
534
|
-
|
535
|
-
private
|
536
|
-
|
537
|
-
def visit_ancestors
|
538
|
-
last_node = self
|
539
|
-
|
540
|
-
while (current_node = last_node.parent)
|
541
|
-
yield current_node
|
542
|
-
last_node = current_node
|
543
|
-
end
|
544
|
-
end
|
545
|
-
|
546
|
-
def visit_ancestors_with_types(types)
|
547
|
-
last_node = self
|
548
|
-
|
549
|
-
while (current_node = last_node.parent)
|
550
|
-
yield current_node if types.include?(current_node.type)
|
551
|
-
last_node = current_node
|
552
|
-
end
|
553
|
-
end
|
554
|
-
|
555
|
-
def begin_value_used?
|
556
|
-
# the last child node determines the value of the parent
|
557
|
-
sibling_index == parent.children.size - 1 ? parent.value_used? : false
|
558
|
-
end
|
559
|
-
|
560
|
-
def for_value_used?
|
561
|
-
# `for var in enum; body; end`
|
562
|
-
# (for <var> <enum> <body>)
|
563
|
-
sibling_index == 2 ? parent.value_used? : true
|
564
|
-
end
|
565
|
-
|
566
|
-
def case_if_value_used?
|
567
|
-
# (case <condition> <when...>)
|
568
|
-
# (if <condition> <truebranch> <falsebranch>)
|
569
|
-
sibling_index.zero? ? true : parent.value_used?
|
570
|
-
end
|
571
|
-
|
572
|
-
def while_until_value_used?
|
573
|
-
# (while <condition> <body>) -> always evaluates to `nil`
|
574
|
-
sibling_index.zero?
|
575
|
-
end
|
576
|
-
|
577
|
-
def parent_module_name_part(node)
|
578
|
-
case node.type
|
579
|
-
when :class, :module, :casgn
|
580
|
-
# TODO: if constant name has cbase (leading ::), then we don't need
|
581
|
-
# to keep traversing up through nested classes/modules
|
582
|
-
node.defined_module_name
|
583
|
-
when :sclass
|
584
|
-
yield parent_module_name_for_sclass(node)
|
585
|
-
else # block
|
586
|
-
parent_module_name_for_block(node) { yield nil }
|
587
|
-
end
|
588
|
-
end
|
589
|
-
|
590
|
-
def parent_module_name_for_sclass(sclass_node)
|
591
|
-
# TODO: look for constant definition and see if it is nested
|
592
|
-
# inside a class or module
|
593
|
-
subject = sclass_node.children[0]
|
594
|
-
|
595
|
-
if subject.const_type?
|
596
|
-
"#<Class:#{subject.const_name}>"
|
597
|
-
elsif subject.self_type?
|
598
|
-
"#<Class:#{sclass_node.parent_module_name}>"
|
599
|
-
end
|
600
|
-
end
|
601
|
-
|
602
|
-
def parent_module_name_for_block(ancestor)
|
603
|
-
if ancestor.method_name == :class_eval
|
604
|
-
# `class_eval` with no receiver applies to whatever module or class
|
605
|
-
# we are currently in
|
606
|
-
return unless (receiver = ancestor.receiver)
|
607
|
-
yield unless receiver.const_type?
|
608
|
-
receiver.const_name
|
609
|
-
elsif !new_class_or_module_block?(ancestor)
|
610
|
-
yield
|
611
|
-
end
|
612
|
-
end
|
613
|
-
|
614
|
-
def new_class_or_module_block?(block_node)
|
615
|
-
receiver = block_node.receiver
|
616
|
-
|
617
|
-
block_node.method_name == :new &&
|
618
|
-
receiver && receiver.const_type? &&
|
619
|
-
(receiver.const_name == 'Class' || receiver.const_name == 'Module') &&
|
620
|
-
block_node.parent &&
|
621
|
-
block_node.parent.casgn_type?
|
622
|
-
end
|
623
|
-
end
|
624
|
-
end
|