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
@@ -133,9 +133,7 @@ module RuboCop
|
|
133
133
|
end
|
134
134
|
|
135
135
|
def all_cop_names
|
136
|
-
@all_cop_names ||= Cop::Cop.
|
137
|
-
cop_name == UNNEEDED_DISABLE
|
138
|
-
end
|
136
|
+
@all_cop_names ||= Cop::Cop.registry.names - [UNNEEDED_DISABLE]
|
139
137
|
end
|
140
138
|
|
141
139
|
def comment_only_line?(line_number)
|
data/lib/rubocop/config.rb
CHANGED
@@ -27,7 +27,7 @@ module RuboCop
|
|
27
27
|
'The `Rails/DefaultScope` cop no longer exists.',
|
28
28
|
'Style/SingleSpaceBeforeFirstArg' =>
|
29
29
|
'The `Style/SingleSpaceBeforeFirstArg` cop has been renamed to ' \
|
30
|
-
'`Style/SpaceBeforeFirstArg
|
30
|
+
'`Style/SpaceBeforeFirstArg.`',
|
31
31
|
'Lint/SpaceBeforeFirstArg' =>
|
32
32
|
'The `Lint/SpaceBeforeFirstArg` cop has been removed, since it was a ' \
|
33
33
|
'duplicate of `Style/SpaceBeforeFirstArg`. Please use ' \
|
@@ -37,9 +37,60 @@ module RuboCop
|
|
37
37
|
'use `Style/SpaceAroundKeyword` instead.',
|
38
38
|
'Style/SpaceBeforeModifierKeyword' =>
|
39
39
|
'The `Style/SpaceBeforeModifierKeyword` cop has been removed. Please ' \
|
40
|
-
'use `Style/SpaceAroundKeyword` instead.'
|
40
|
+
'use `Style/SpaceAroundKeyword` instead.',
|
41
|
+
'Style/MethodCallParentheses' =>
|
42
|
+
'The `Style/MethodCallParentheses` cop has been renamed to ' \
|
43
|
+
'`Style/MethodCallWithoutArgsParentheses`.',
|
44
|
+
'Lint/Eval' =>
|
45
|
+
'The `Lint/Eval` cop has been renamed to `Security/Eval`.'
|
41
46
|
}.freeze
|
42
47
|
|
48
|
+
OBSOLETE_PARAMETERS = [
|
49
|
+
{
|
50
|
+
cop: 'Style/SpaceAroundOperators',
|
51
|
+
parameter: 'MultiSpaceAllowedForOperators',
|
52
|
+
alternative: 'If your intention was to allow extra spaces ' \
|
53
|
+
'for alignment, please use AllowForAlignment: ' \
|
54
|
+
'true instead.'
|
55
|
+
},
|
56
|
+
{
|
57
|
+
cop: 'AllCops',
|
58
|
+
parameter: 'RunRailsCops',
|
59
|
+
alternative: "Use the following configuration instead:\n" \
|
60
|
+
"Rails:\n Enabled: true"
|
61
|
+
},
|
62
|
+
{
|
63
|
+
cop: 'Style/CaseIndentation',
|
64
|
+
parameter: 'IndentWhenRelativeTo',
|
65
|
+
alternative: '`IndentWhenRelativeTo` has been renamed to ' \
|
66
|
+
'`EnforcedStyle`'
|
67
|
+
},
|
68
|
+
{
|
69
|
+
cop: 'Lint/BlockAlignment',
|
70
|
+
parameter: 'AlignWith',
|
71
|
+
alternative: '`AlignWith` has been renamed to ' \
|
72
|
+
'`EnforcedStyleAlignWith`'
|
73
|
+
},
|
74
|
+
{
|
75
|
+
cop: 'Lint/EndAlignment',
|
76
|
+
parameter: 'AlignWith',
|
77
|
+
alternative: '`AlignWith` has been renamed to ' \
|
78
|
+
'`EnforcedStyleAlignWith`'
|
79
|
+
},
|
80
|
+
{
|
81
|
+
cop: 'Lint/DefEndAlignment',
|
82
|
+
parameter: 'AlignWith',
|
83
|
+
alternative: '`AlignWith` has been renamed to ' \
|
84
|
+
'`EnforcedStyleAlignWith`'
|
85
|
+
},
|
86
|
+
{
|
87
|
+
cop: 'Rails/UniqBeforePluck',
|
88
|
+
parameter: 'EnforcedMode',
|
89
|
+
alternative: '`EnforcedMode` has been renamed to ' \
|
90
|
+
'`EnforcedStyle`'
|
91
|
+
}
|
92
|
+
].freeze
|
93
|
+
|
43
94
|
attr_reader :loaded_path
|
44
95
|
|
45
96
|
def initialize(hash = {}, loaded_path = nil)
|
@@ -142,13 +193,11 @@ module RuboCop
|
|
142
193
|
end
|
143
194
|
|
144
195
|
def cop_enabled?(cop)
|
145
|
-
|
146
|
-
|
147
|
-
if (dept_config = self[department])
|
196
|
+
if (dept_config = self[cop.department.to_s])
|
148
197
|
return false if dept_config['Enabled'] == false
|
149
198
|
end
|
150
199
|
|
151
|
-
for_cop(cop).empty? || for_cop(cop)
|
200
|
+
for_cop(cop).empty? || for_cop(cop).fetch('Enabled', true)
|
152
201
|
end
|
153
202
|
|
154
203
|
def validate
|
@@ -161,9 +210,8 @@ module RuboCop
|
|
161
210
|
ConfigLoader.default_configuration.key?(key)
|
162
211
|
end
|
163
212
|
|
164
|
-
|
213
|
+
reject_obsolete_cops_and_parameters
|
165
214
|
warn_about_unrecognized_cops(invalid_cop_names)
|
166
|
-
reject_obsolete_parameters
|
167
215
|
check_target_ruby
|
168
216
|
validate_parameter_names(valid_cop_names)
|
169
217
|
validate_enforced_styles(valid_cop_names)
|
@@ -259,7 +307,7 @@ module RuboCop
|
|
259
307
|
end
|
260
308
|
|
261
309
|
# There could be a custom cop with this name. If so, don't warn
|
262
|
-
next if Cop::Cop.
|
310
|
+
next if Cop::Cop.registry.contains_cop_matching?([name])
|
263
311
|
|
264
312
|
warn Rainbow("Warning: unrecognized cop #{name} found in " \
|
265
313
|
"#{loaded_path}").yellow
|
@@ -286,42 +334,52 @@ module RuboCop
|
|
286
334
|
|
287
335
|
def validate_enforced_styles(valid_cop_names)
|
288
336
|
valid_cop_names.each do |name|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
337
|
+
styles = self[name].select { |key, _| key.start_with?('Enforced') }
|
338
|
+
|
339
|
+
styles.each do |style_name, style|
|
340
|
+
supported_key = RuboCop::Cop::Util.to_supported_styles(style_name)
|
341
|
+
valid = ConfigLoader.default_configuration[name][supported_key]
|
342
|
+
next unless valid
|
343
|
+
next if valid.include?(style)
|
344
|
+
|
345
|
+
msg = "invalid #{style_name} '#{style}' for #{name} found in " \
|
346
|
+
"#{loaded_path}\n" \
|
347
|
+
"Valid choices are: #{valid.join(', ')}"
|
348
|
+
raise ValidationError, msg
|
349
|
+
end
|
297
350
|
end
|
298
351
|
end
|
299
352
|
|
300
|
-
def
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
353
|
+
def reject_obsolete_cops_and_parameters
|
354
|
+
messages = [
|
355
|
+
obsolete_cops,
|
356
|
+
obsolete_parameters
|
357
|
+
].flatten.compact
|
358
|
+
return if messages.empty?
|
359
|
+
|
360
|
+
raise ValidationError, messages.join("\n")
|
361
|
+
end
|
362
|
+
|
363
|
+
def obsolete_parameters
|
364
|
+
OBSOLETE_PARAMETERS.map do |params|
|
365
|
+
obsolete_parameter_message(params[:cop], params[:parameter],
|
366
|
+
params[:alternative])
|
367
|
+
end
|
309
368
|
end
|
310
369
|
|
311
|
-
def
|
370
|
+
def obsolete_parameter_message(cop, parameter, alternative)
|
312
371
|
return unless self[cop] && self[cop].key?(parameter)
|
313
372
|
|
314
|
-
|
315
|
-
|
316
|
-
|
373
|
+
"obsolete parameter #{parameter} (for #{cop}) " \
|
374
|
+
"found in #{loaded_path}" \
|
375
|
+
"\n#{alternative}"
|
317
376
|
end
|
318
377
|
|
319
|
-
def
|
320
|
-
OBSOLETE_COPS.
|
321
|
-
next unless key?(cop_name) || key?(
|
322
|
-
message
|
378
|
+
def obsolete_cops
|
379
|
+
OBSOLETE_COPS.map do |cop_name, message|
|
380
|
+
next unless key?(cop_name) || key?(Cop::Badge.parse(cop_name).cop_name)
|
381
|
+
message + "\n(obsolete configuration found in #{loaded_path}, please" \
|
323
382
|
' update it)'
|
324
|
-
raise ValidationError, message
|
325
383
|
end
|
326
384
|
end
|
327
385
|
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Identifier of all cops containing a department and cop name.
|
6
|
+
#
|
7
|
+
# All cops are identified by their badge. For example, the badge
|
8
|
+
# for `RuboCop::Cop::Style::Tab` is `Style/Tab`. Badges can be
|
9
|
+
# parsed as either `Department/CopName` or just `CopName` to allow
|
10
|
+
# for badge references in source files that omit the department
|
11
|
+
# for RuboCop to infer.
|
12
|
+
class Badge
|
13
|
+
# Error raised when a badge parse fails.
|
14
|
+
class InvalidBadge < Error
|
15
|
+
MSG = 'Invalid badge %<badge>p. ' \
|
16
|
+
'Expected `Department/CopName` or `CopName`.'.freeze
|
17
|
+
|
18
|
+
def initialize(token)
|
19
|
+
super(format(MSG, badge: token))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :department, :cop_name
|
24
|
+
|
25
|
+
def self.for(class_name)
|
26
|
+
new(*class_name.split('::').last(2))
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.parse(identifier)
|
30
|
+
parts = identifier.split('/', 2)
|
31
|
+
|
32
|
+
raise InvalidBadge, identifier if parts.size > 2
|
33
|
+
|
34
|
+
if parts.one?
|
35
|
+
new(nil, *parts)
|
36
|
+
else
|
37
|
+
new(*parts)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(department, cop_name)
|
42
|
+
@department = department.to_sym if department
|
43
|
+
@cop_name = cop_name
|
44
|
+
end
|
45
|
+
|
46
|
+
def ==(other)
|
47
|
+
hash == other.hash
|
48
|
+
end
|
49
|
+
alias eql? ==
|
50
|
+
|
51
|
+
def hash
|
52
|
+
[department, cop_name].hash
|
53
|
+
end
|
54
|
+
|
55
|
+
def match?(other)
|
56
|
+
cop_name == other.cop_name &&
|
57
|
+
(!qualified? || department == other.department)
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_s
|
61
|
+
qualified? ? "#{department}/#{cop_name}" : cop_name
|
62
|
+
end
|
63
|
+
|
64
|
+
def qualified?
|
65
|
+
!department.nil?
|
66
|
+
end
|
67
|
+
|
68
|
+
def with_department(department)
|
69
|
+
self.class.new(department, cop_name)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -34,7 +34,7 @@ module RuboCop
|
|
34
34
|
|
35
35
|
duplicated_gem_nodes.each do |nodes|
|
36
36
|
nodes[1..-1].each do |node|
|
37
|
-
|
37
|
+
register_offense(
|
38
38
|
node,
|
39
39
|
node.method_args.first.to_a.first,
|
40
40
|
nodes.first.loc.line
|
@@ -54,7 +54,7 @@ module RuboCop
|
|
54
54
|
.values
|
55
55
|
end
|
56
56
|
|
57
|
-
def
|
57
|
+
def register_offense(node, gem_name, line_of_first_occurence)
|
58
58
|
line_range = node.loc.column...node.loc.last_column
|
59
59
|
|
60
60
|
add_offense(
|
@@ -17,18 +17,26 @@ module RuboCop
|
|
17
17
|
#
|
18
18
|
# gem 'rspec'
|
19
19
|
class OrderedGems < Cop
|
20
|
-
MSG = '
|
20
|
+
MSG = 'Gems should be sorted in an alphabetical order within their '\
|
21
|
+
'section of the Gemfile. '\
|
22
|
+
'Gem `%s` should appear before `%s`.'.freeze
|
21
23
|
def investigate(processed_source)
|
22
24
|
return if processed_source.ast.nil?
|
23
25
|
gem_declarations(processed_source.ast)
|
24
26
|
.each_cons(2) do |previous, current|
|
25
27
|
next unless consecutive_lines(previous, current)
|
26
|
-
next unless
|
27
|
-
|
28
|
+
next unless case_insensitive_out_of_order?(
|
29
|
+
current.children[2].children.first.to_s,
|
30
|
+
previous.children[2].children.first.to_s
|
31
|
+
)
|
28
32
|
register_offense(previous, current)
|
29
33
|
end
|
30
34
|
end
|
31
35
|
|
36
|
+
def case_insensitive_out_of_order?(string_a, string_b)
|
37
|
+
1 > string_a.casecmp(string_b)
|
38
|
+
end
|
39
|
+
|
32
40
|
def consecutive_lines(previous, current)
|
33
41
|
previous.source_range.last_line == current.source_range.first_line - 1
|
34
42
|
end
|
@@ -45,6 +53,38 @@ module RuboCop
|
|
45
53
|
)
|
46
54
|
end
|
47
55
|
|
56
|
+
def autocorrect(node)
|
57
|
+
previous = previous_declaration(node)
|
58
|
+
|
59
|
+
current_range = declaration_with_comment(node)
|
60
|
+
previous_range = declaration_with_comment(previous)
|
61
|
+
|
62
|
+
lambda do |corrector|
|
63
|
+
swap_range(corrector, current_range, previous_range)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def declaration_with_comment(node)
|
68
|
+
buffer = processed_source.buffer
|
69
|
+
begin_pos = node.loc.expression.begin_pos
|
70
|
+
end_line = buffer.line_for_position(node.loc.expression.end_pos)
|
71
|
+
end_pos = buffer.line_range(end_line).end_pos
|
72
|
+
Parser::Source::Range.new(buffer, begin_pos, end_pos)
|
73
|
+
end
|
74
|
+
|
75
|
+
def swap_range(corrector, range1, range2)
|
76
|
+
src1 = range1.source
|
77
|
+
src2 = range2.source
|
78
|
+
corrector.replace(range1, src2)
|
79
|
+
corrector.replace(range2, src1)
|
80
|
+
end
|
81
|
+
|
82
|
+
def previous_declaration(node)
|
83
|
+
declarations = gem_declarations(processed_source.ast)
|
84
|
+
node_index = declarations.find_index(node)
|
85
|
+
declarations.to_a[node_index - 1]
|
86
|
+
end
|
87
|
+
|
48
88
|
def_node_search :gem_declarations, <<-PATTERN
|
49
89
|
(:send, nil, :gem, ...)
|
50
90
|
PATTERN
|
@@ -5,7 +5,9 @@ module RuboCop
|
|
5
5
|
# Commissioner class is responsible for processing the AST and delegating
|
6
6
|
# work to the specified cops.
|
7
7
|
class Commissioner
|
8
|
-
include RuboCop::
|
8
|
+
include RuboCop::AST::Traversal
|
9
|
+
|
10
|
+
CopError = Struct.new(:error, :line, :column)
|
9
11
|
|
10
12
|
attr_reader :errors
|
11
13
|
|
@@ -26,19 +28,19 @@ module RuboCop
|
|
26
28
|
# to continue iterating over the children of a node.
|
27
29
|
# However, if we know that a certain node type (like `int`) never has
|
28
30
|
# child nodes, there is no reason to pay the cost of calling `super`.
|
29
|
-
no_child_callbacks =
|
31
|
+
no_child_callbacks = NO_CHILD_NODES.map do |type|
|
30
32
|
:"on_#{type}"
|
31
33
|
end
|
32
34
|
|
33
35
|
callback_methods.each do |callback|
|
34
|
-
next unless
|
36
|
+
next unless method_defined?(callback)
|
35
37
|
class_eval <<-EOS, __FILE__, __LINE__
|
36
38
|
def #{callback}(node)
|
37
39
|
@callbacks[:"#{callback}"] ||= @cops.select do |cop|
|
38
40
|
cop.respond_to?(:"#{callback}")
|
39
41
|
end
|
40
42
|
@callbacks[:#{callback}].each do |cop|
|
41
|
-
with_cop_error_handling(cop) do
|
43
|
+
with_cop_error_handling(cop, node) do
|
42
44
|
cop.send(:#{callback}, node)
|
43
45
|
end
|
44
46
|
end
|
@@ -67,6 +69,10 @@ module RuboCop
|
|
67
69
|
|
68
70
|
def remove_irrelevant_cops(filename)
|
69
71
|
@cops.reject! { |cop| cop.excluded_file?(filename) }
|
72
|
+
@cops.reject! do |cop|
|
73
|
+
cop.class.respond_to?(:support_target_ruby_version?) &&
|
74
|
+
!cop.class.support_target_ruby_version?(cop.target_ruby_version)
|
75
|
+
end
|
70
76
|
end
|
71
77
|
|
72
78
|
def reset_callbacks
|
@@ -92,11 +98,16 @@ module RuboCop
|
|
92
98
|
end
|
93
99
|
end
|
94
100
|
|
95
|
-
def with_cop_error_handling(cop)
|
101
|
+
def with_cop_error_handling(cop, node = nil)
|
96
102
|
yield
|
97
103
|
rescue => e
|
98
104
|
raise e if @options[:raise_error]
|
99
|
-
|
105
|
+
if node
|
106
|
+
line = node.loc.line
|
107
|
+
column = node.loc.column
|
108
|
+
end
|
109
|
+
error = CopError.new(e, line, column)
|
110
|
+
@errors[cop] << error
|
100
111
|
end
|
101
112
|
end
|
102
113
|
end
|
data/lib/rubocop/cop/cop.rb
CHANGED
@@ -3,58 +3,6 @@ require 'uri'
|
|
3
3
|
|
4
4
|
module RuboCop
|
5
5
|
module Cop
|
6
|
-
class AmbiguousCopName < RuboCop::Error; end
|
7
|
-
|
8
|
-
# Store for all cops with helper functions
|
9
|
-
class CopStore < ::Array
|
10
|
-
# @return [Array<String>] list of types for current cops.
|
11
|
-
def types
|
12
|
-
@types ||= map(&:cop_type).uniq!
|
13
|
-
end
|
14
|
-
|
15
|
-
# @return [Array<Cop>] Cops for that specific type.
|
16
|
-
def with_type(type)
|
17
|
-
CopStore.new(select { |c| c.cop_type == type })
|
18
|
-
end
|
19
|
-
|
20
|
-
# @return [Array<Cop>] Cops not for a specific type.
|
21
|
-
def without_type(type)
|
22
|
-
CopStore.new(reject { |c| c.cop_type == type })
|
23
|
-
end
|
24
|
-
|
25
|
-
def qualified_cop_name(name, origin)
|
26
|
-
return name if cop_names.include?(name)
|
27
|
-
|
28
|
-
basename = File.basename(name)
|
29
|
-
found_ns = types.map(&:capitalize).select do |ns|
|
30
|
-
cop_names.include?("#{ns}/#{basename}")
|
31
|
-
end
|
32
|
-
|
33
|
-
case found_ns.size
|
34
|
-
when 0 then name # No namespace found. Deal with it later in caller.
|
35
|
-
when 1 then cop_name_with_namespace(name, origin, basename, found_ns[0])
|
36
|
-
else raise AmbiguousCopName,
|
37
|
-
"Ambiguous cop name `#{name}` used in #{origin} needs " \
|
38
|
-
'namespace qualifier. Did you mean ' \
|
39
|
-
"#{found_ns.map { |ns| "#{ns}/#{basename}" }.join(' or ')}"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def cop_name_with_namespace(name, origin, basename, found_ns)
|
44
|
-
if name != basename && found_ns != File.dirname(name).to_sym
|
45
|
-
warn "#{origin}: #{name} has the wrong namespace - should be " \
|
46
|
-
"#{found_ns}"
|
47
|
-
end
|
48
|
-
"#{found_ns}/#{basename}"
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def cop_names
|
54
|
-
@cop_names ||= Set.new(map(&:cop_name))
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
6
|
# A scaffold for concrete cops.
|
59
7
|
#
|
60
8
|
# The Cop class is meant to be extended.
|
@@ -75,9 +23,9 @@ module RuboCop
|
|
75
23
|
# end
|
76
24
|
# end
|
77
25
|
class Cop
|
78
|
-
extend RuboCop::Sexp
|
26
|
+
extend RuboCop::AST::Sexp
|
79
27
|
extend NodePattern::Macros
|
80
|
-
include RuboCop::Sexp
|
28
|
+
include RuboCop::AST::Sexp
|
81
29
|
include Util
|
82
30
|
include IgnoredNode
|
83
31
|
include AutocorrectLogic
|
@@ -85,34 +33,42 @@ module RuboCop
|
|
85
33
|
attr_reader :config, :offenses, :corrections
|
86
34
|
attr_accessor :processed_source # TODO: Bad design.
|
87
35
|
|
88
|
-
@
|
36
|
+
@registry = Registry.new
|
37
|
+
|
38
|
+
class << self
|
39
|
+
attr_reader :registry
|
40
|
+
end
|
89
41
|
|
90
42
|
def self.all
|
91
|
-
|
43
|
+
registry.without_department(:Test).cops
|
92
44
|
end
|
93
45
|
|
94
46
|
def self.qualified_cop_name(name, origin)
|
95
|
-
|
47
|
+
registry.qualified_cop_name(name, origin)
|
96
48
|
end
|
97
49
|
|
98
50
|
def self.non_rails
|
99
|
-
|
51
|
+
registry.without_department(:Rails)
|
100
52
|
end
|
101
53
|
|
102
54
|
def self.inherited(subclass)
|
103
|
-
|
55
|
+
registry.enlist(subclass)
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.badge
|
59
|
+
@badge ||= Badge.for(name)
|
104
60
|
end
|
105
61
|
|
106
62
|
def self.cop_name
|
107
|
-
|
63
|
+
badge.to_s
|
108
64
|
end
|
109
65
|
|
110
|
-
def self.
|
111
|
-
|
66
|
+
def self.department
|
67
|
+
badge.department
|
112
68
|
end
|
113
69
|
|
114
70
|
def self.lint?
|
115
|
-
|
71
|
+
department == :Lint
|
116
72
|
end
|
117
73
|
|
118
74
|
# Returns true if the cop name or the cop namespace matches any of the
|
@@ -121,7 +77,7 @@ module RuboCop
|
|
121
77
|
return false unless given_names
|
122
78
|
|
123
79
|
given_names.include?(cop_name) ||
|
124
|
-
given_names.include?(
|
80
|
+
given_names.include?(department.to_s)
|
125
81
|
end
|
126
82
|
|
127
83
|
def initialize(config = nil, options = nil)
|
@@ -141,25 +97,6 @@ module RuboCop
|
|
141
97
|
@cop_config ||= @config.for_cop(self)
|
142
98
|
end
|
143
99
|
|
144
|
-
def debug?
|
145
|
-
@options[:debug]
|
146
|
-
end
|
147
|
-
|
148
|
-
def display_cop_names?
|
149
|
-
debug? || @options[:display_cop_names] ||
|
150
|
-
@config.for_all_cops['DisplayCopNames']
|
151
|
-
end
|
152
|
-
|
153
|
-
def display_style_guide?
|
154
|
-
(style_guide_url || reference_url) &&
|
155
|
-
(@options[:display_style_guide] ||
|
156
|
-
config.for_all_cops['DisplayStyleGuide'])
|
157
|
-
end
|
158
|
-
|
159
|
-
def extra_details?
|
160
|
-
@options[:extra_details] || config.for_all_cops['ExtraDetails']
|
161
|
-
end
|
162
|
-
|
163
100
|
def message(_node = nil)
|
164
101
|
self.class::MSG
|
165
102
|
end
|
@@ -172,7 +109,7 @@ module RuboCop
|
|
172
109
|
severity = custom_severity || severity || default_severity
|
173
110
|
|
174
111
|
message ||= message(node)
|
175
|
-
message =
|
112
|
+
message = annotate(message)
|
176
113
|
|
177
114
|
status = enabled_line?(location.line) ? correct(node) : :disabled
|
178
115
|
|
@@ -232,36 +169,12 @@ module RuboCop
|
|
232
169
|
!relevant_file?(file)
|
233
170
|
end
|
234
171
|
|
235
|
-
def style_guide_url
|
236
|
-
url = cop_config['StyleGuide']
|
237
|
-
return nil if url.nil? || url.empty?
|
238
|
-
|
239
|
-
base_url = config.for_all_cops['StyleGuideBaseURL']
|
240
|
-
return url if base_url.nil? || base_url.empty?
|
241
|
-
|
242
|
-
URI.join(base_url, url).to_s
|
243
|
-
end
|
244
|
-
|
245
|
-
def reference_url
|
246
|
-
url = cop_config['Reference']
|
247
|
-
url.nil? || url.empty? ? nil : url
|
248
|
-
end
|
249
|
-
|
250
|
-
def details
|
251
|
-
details = cop_config && cop_config['Details']
|
252
|
-
details.nil? || details.empty? ? nil : details
|
253
|
-
end
|
254
|
-
|
255
172
|
private
|
256
173
|
|
257
|
-
def
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
links = [style_guide_url, reference_url].compact.join(', ')
|
262
|
-
message = "#{message} (#{links})"
|
263
|
-
end
|
264
|
-
message
|
174
|
+
def annotate(message)
|
175
|
+
RuboCop::Cop::MessageAnnotator.new(
|
176
|
+
config, cop_config, @options
|
177
|
+
).annotate(message, name)
|
265
178
|
end
|
266
179
|
|
267
180
|
def file_name_matches_any?(file, parameter, default_result)
|