rubocop 1.5.0 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +52 -7
- data/config/obsoletion.yml +196 -0
- data/lib/rubocop.rb +14 -0
- data/lib/rubocop/cli/command/suggest_extensions.rb +21 -8
- data/lib/rubocop/config.rb +8 -5
- data/lib/rubocop/config_loader.rb +10 -6
- data/lib/rubocop/config_loader_resolver.rb +21 -4
- data/lib/rubocop/config_obsoletion.rb +64 -262
- data/lib/rubocop/config_obsoletion/changed_enforced_styles.rb +33 -0
- data/lib/rubocop/config_obsoletion/changed_parameter.rb +21 -0
- data/lib/rubocop/config_obsoletion/cop_rule.rb +34 -0
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +44 -0
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +44 -0
- data/lib/rubocop/config_obsoletion/removed_cop.rb +41 -0
- data/lib/rubocop/config_obsoletion/renamed_cop.rb +34 -0
- data/lib/rubocop/config_obsoletion/rule.rb +41 -0
- data/lib/rubocop/config_obsoletion/split_cop.rb +27 -0
- data/lib/rubocop/config_validator.rb +11 -4
- data/lib/rubocop/cop/base.rb +17 -15
- data/lib/rubocop/cop/cop.rb +2 -2
- data/lib/rubocop/cop/correctors/string_literal_corrector.rb +6 -8
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +3 -2
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +145 -0
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +19 -3
- data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +26 -0
- data/lib/rubocop/cop/layout/line_length.rb +6 -16
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +7 -3
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -10
- data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +1 -0
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -0
- data/lib/rubocop/cop/layout/space_before_brackets.rb +64 -0
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +13 -10
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -2
- data/lib/rubocop/cop/lint/ambiguous_assignment.rb +59 -0
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +7 -2
- data/lib/rubocop/cop/lint/duplicate_branch.rb +64 -2
- data/lib/rubocop/cop/lint/interpolation_check.rb +7 -2
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +50 -17
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -11
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +13 -0
- data/lib/rubocop/cop/lint/unreachable_loop.rb +17 -0
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/migration/department_name.rb +1 -1
- data/lib/rubocop/cop/mixin/string_help.rb +4 -1
- data/lib/rubocop/cop/naming/accessor_method_name.rb +15 -1
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +59 -5
- data/lib/rubocop/cop/naming/variable_number.rb +3 -1
- data/lib/rubocop/cop/registry.rb +10 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +3 -1
- data/lib/rubocop/cop/style/character_literal.rb +10 -11
- data/lib/rubocop/cop/style/collection_methods.rb +14 -1
- data/lib/rubocop/cop/style/commented_keyword.rb +22 -5
- data/lib/rubocop/cop/style/float_division.rb +44 -1
- data/lib/rubocop/cop/style/for.rb +2 -0
- data/lib/rubocop/cop/style/hash_except.rb +95 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +4 -0
- data/lib/rubocop/cop/style/ip_addresses.rb +1 -1
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +12 -2
- data/lib/rubocop/cop/style/lambda_call.rb +2 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +3 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +16 -6
- data/lib/rubocop/cop/style/method_def_parentheses.rb +7 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +26 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +3 -1
- data/lib/rubocop/cop/style/mutable_constant.rb +13 -3
- data/lib/rubocop/cop/style/perl_backrefs.rb +86 -9
- data/lib/rubocop/cop/style/raise_args.rb +2 -0
- data/lib/rubocop/cop/style/redundant_argument.rb +21 -2
- data/lib/rubocop/cop/style/redundant_freeze.rb +8 -4
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +24 -8
- data/lib/rubocop/cop/style/single_line_block_params.rb +30 -7
- data/lib/rubocop/cop/style/single_line_methods.rb +4 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +24 -8
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -13
- data/lib/rubocop/cop/style/string_concatenation.rb +26 -1
- data/lib/rubocop/cop/style/string_literals.rb +14 -8
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +4 -3
- data/lib/rubocop/cop/style/symbol_proc.rb +5 -4
- data/lib/rubocop/cop/util.rb +3 -1
- data/lib/rubocop/ext/regexp_node.rb +31 -9
- data/lib/rubocop/ext/regexp_parser.rb +21 -3
- data/lib/rubocop/formatter/emacs_style_formatter.rb +2 -0
- data/lib/rubocop/formatter/simple_text_formatter.rb +2 -0
- data/lib/rubocop/formatter/tap_formatter.rb +2 -0
- data/lib/rubocop/lockfile.rb +40 -0
- data/lib/rubocop/options.rb +9 -9
- data/lib/rubocop/rspec/cop_helper.rb +0 -4
- data/lib/rubocop/rspec/expect_offense.rb +34 -22
- data/lib/rubocop/runner.rb +16 -1
- data/lib/rubocop/target_finder.rb +4 -2
- data/lib/rubocop/util.rb +16 -0
- data/lib/rubocop/version.rb +8 -2
- metadata +33 -5
@@ -3,7 +3,10 @@
|
|
3
3
|
module RuboCop
|
4
4
|
class CLI
|
5
5
|
module Command
|
6
|
-
#
|
6
|
+
# Suggest RuboCop extensions to install based on Gemfile dependencies.
|
7
|
+
# Only primary dependencies are evaluated, so if a dependency depends on a
|
8
|
+
# gem with an extension, it is not suggested. However, if an extension is
|
9
|
+
# a transitive dependency, it will not be suggested.
|
7
10
|
# @api private
|
8
11
|
class SuggestExtensions < Base
|
9
12
|
# Combination of short and long formatter names.
|
@@ -18,14 +21,17 @@ module RuboCop
|
|
18
21
|
puts 'Tip: Based on detected gems, the following '\
|
19
22
|
'RuboCop extension libraries might be helpful:'
|
20
23
|
|
21
|
-
extensions.each do |extension|
|
24
|
+
extensions.sort.each do |extension|
|
22
25
|
puts " * #{extension} (http://github.com/rubocop-hq/#{extension})"
|
23
26
|
end
|
24
27
|
|
25
28
|
puts
|
26
|
-
puts 'You can opt out of this message by adding the following to your config
|
29
|
+
puts 'You can opt out of this message by adding the following to your config '\
|
30
|
+
'(see https://docs.rubocop.org/rubocop/extensions.html#extension-suggestions '\
|
31
|
+
'for more options):'
|
27
32
|
puts ' AllCops:'
|
28
33
|
puts ' SuggestExtensions: false'
|
34
|
+
|
29
35
|
puts if @options[:display_time]
|
30
36
|
end
|
31
37
|
|
@@ -46,15 +52,22 @@ module RuboCop
|
|
46
52
|
end
|
47
53
|
|
48
54
|
def extensions
|
49
|
-
|
50
|
-
|
55
|
+
return [] unless lockfile.dependencies.any?
|
56
|
+
|
57
|
+
extensions = @config_store.for_pwd.for_all_cops['SuggestExtensions'] || {}
|
58
|
+
extensions.select { |_, v| (Array(v) & dependent_gems).any? }.keys - installed_gems
|
59
|
+
end
|
51
60
|
|
52
|
-
|
61
|
+
def lockfile
|
62
|
+
@lockfile ||= Lockfile.new
|
53
63
|
end
|
54
64
|
|
55
65
|
def dependent_gems
|
56
|
-
|
57
|
-
|
66
|
+
lockfile.dependencies.map(&:name)
|
67
|
+
end
|
68
|
+
|
69
|
+
def installed_gems
|
70
|
+
lockfile.gems.map(&:name)
|
58
71
|
end
|
59
72
|
|
60
73
|
def puts(*args)
|
data/lib/rubocop/config.rb
CHANGED
@@ -50,8 +50,8 @@ module RuboCop
|
|
50
50
|
self
|
51
51
|
end
|
52
52
|
|
53
|
-
def_delegators :@hash, :[], :[]=, :delete, :each, :key?, :keys, :each_key,
|
54
|
-
:fetch, :map, :merge, :to_h, :to_hash, :transform_values
|
53
|
+
def_delegators :@hash, :[], :[]=, :delete, :dig, :each, :key?, :keys, :each_key,
|
54
|
+
:fetch, :map, :merge, :replace, :to_h, :to_hash, :transform_values
|
55
55
|
def_delegators :@validator, :validate, :target_ruby_version
|
56
56
|
|
57
57
|
def to_s
|
@@ -281,6 +281,9 @@ module RuboCop
|
|
281
281
|
end
|
282
282
|
|
283
283
|
def enable_cop?(qualified_cop_name, cop_options)
|
284
|
+
# If the cop is explicitly enabled, the other checks can be skipped.
|
285
|
+
return true if cop_options['Enabled'] == true
|
286
|
+
|
284
287
|
department = department_of(qualified_cop_name)
|
285
288
|
cop_enabled = cop_options.fetch('Enabled') do
|
286
289
|
!for_all_cops['DisabledByDefault']
|
@@ -292,10 +295,10 @@ module RuboCop
|
|
292
295
|
end
|
293
296
|
|
294
297
|
def department_of(qualified_cop_name)
|
295
|
-
cop_department,
|
296
|
-
return nil if
|
298
|
+
*cop_department, _ = qualified_cop_name.split('/')
|
299
|
+
return nil if cop_department.empty?
|
297
300
|
|
298
|
-
self[cop_department]
|
301
|
+
self[cop_department.join('/')]
|
299
302
|
end
|
300
303
|
end
|
301
304
|
end
|
@@ -31,6 +31,7 @@ module RuboCop
|
|
31
31
|
|
32
32
|
def clear_options
|
33
33
|
@debug = nil
|
34
|
+
@loaded_features = []
|
34
35
|
FileFinder.root_level = nil
|
35
36
|
end
|
36
37
|
|
@@ -177,12 +178,9 @@ module RuboCop
|
|
177
178
|
@loaded_features.flatten.compact
|
178
179
|
end
|
179
180
|
|
180
|
-
private
|
181
|
-
|
182
|
-
|
183
|
-
File.absolute_path(file.is_a?(RemoteConfig) ? file.file : file)
|
184
|
-
end
|
185
|
-
|
181
|
+
# @api private
|
182
|
+
# Used to add features that were required inside a config or from
|
183
|
+
# the CLI using `--require`.
|
186
184
|
def add_loaded_features(loaded_features)
|
187
185
|
if instance_variable_defined?(:@loaded_features)
|
188
186
|
instance_variable_get(:@loaded_features) << loaded_features
|
@@ -191,6 +189,12 @@ module RuboCop
|
|
191
189
|
end
|
192
190
|
end
|
193
191
|
|
192
|
+
private
|
193
|
+
|
194
|
+
def file_path(file)
|
195
|
+
File.absolute_path(file.is_a?(RemoteConfig) ? file.file : file)
|
196
|
+
end
|
197
|
+
|
194
198
|
def find_project_dotfile(target_dir)
|
195
199
|
find_file_upwards(DOTFILE, target_dir, project_root)
|
196
200
|
end
|
@@ -20,12 +20,13 @@ module RuboCop
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
# rubocop:disable Metrics/MethodLength
|
24
|
-
def resolve_inheritance(path, hash, file, debug)
|
23
|
+
def resolve_inheritance(path, hash, file, debug) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
25
24
|
inherited_files = Array(hash['inherit_from'])
|
26
25
|
base_configs(path, inherited_files, file)
|
27
26
|
.reverse.each_with_index do |base_config, index|
|
28
27
|
override_department_setting_for_cops(base_config, hash)
|
28
|
+
override_enabled_for_disabled_departments(base_config, hash)
|
29
|
+
|
29
30
|
base_config.each do |k, v|
|
30
31
|
next unless v.is_a?(Hash)
|
31
32
|
|
@@ -39,7 +40,6 @@ module RuboCop
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
end
|
42
|
-
# rubocop:enable Metrics/MethodLength
|
43
43
|
|
44
44
|
def resolve_inheritance_from_gems(hash)
|
45
45
|
gems = hash.delete('inherit_gem')
|
@@ -75,6 +75,7 @@ module RuboCop
|
|
75
75
|
end
|
76
76
|
|
77
77
|
config = handle_disabled_by_default(config, default_configuration) if disabled_by_default
|
78
|
+
override_enabled_for_disabled_departments(default_configuration, config)
|
78
79
|
|
79
80
|
opts = { inherit_mode: config['inherit_mode'] || {},
|
80
81
|
unset_nil: unset_nil }
|
@@ -122,10 +123,26 @@ module RuboCop
|
|
122
123
|
end
|
123
124
|
end
|
124
125
|
|
126
|
+
# If a cop was previously explicitly enabled, but then superseded by the
|
127
|
+
# department being disabled, disable it.
|
128
|
+
def override_enabled_for_disabled_departments(base_hash, derived_hash)
|
129
|
+
cops_to_disable = derived_hash.each_key.with_object([]) do |key, cops|
|
130
|
+
next unless disabled?(derived_hash, key)
|
131
|
+
|
132
|
+
cops.concat(base_hash.keys.grep(Regexp.new("^#{key}/")))
|
133
|
+
end
|
134
|
+
|
135
|
+
cops_to_disable.each do |cop_name|
|
136
|
+
next unless base_hash.dig(cop_name, 'Enabled') == true
|
137
|
+
|
138
|
+
derived_hash.replace(merge({ cop_name => { 'Enabled' => false } }, derived_hash))
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
125
142
|
private
|
126
143
|
|
127
144
|
def disabled?(hash, department)
|
128
|
-
hash[department] && hash[department]['Enabled'] == false
|
145
|
+
hash[department].is_a?(Hash) && hash[department]['Enabled'] == false
|
129
146
|
end
|
130
147
|
|
131
148
|
def duplicate_setting?(base_hash, derived_hash, key, inherited_file)
|
@@ -4,233 +4,40 @@ module RuboCop
|
|
4
4
|
# This class handles obsolete configuration.
|
5
5
|
# @api private
|
6
6
|
class ConfigObsoletion
|
7
|
-
|
8
|
-
|
9
|
-
'
|
10
|
-
'
|
11
|
-
'
|
12
|
-
'
|
13
|
-
|
14
|
-
|
15
|
-
'
|
16
|
-
'
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
'Lint/StringConversionInInterpolation' => 'Lint/RedundantStringCoercion',
|
28
|
-
'Lint/UnneededCopDisableDirective' => 'Lint/RedundantCopDisableDirective',
|
29
|
-
'Lint/UnneededCopEnableDirective' => 'Lint/RedundantCopEnableDirective',
|
30
|
-
'Lint/UnneededRequireStatement' => 'Lint/RedundantRequireStatement',
|
31
|
-
'Lint/UnneededSplatExpansion' => 'Lint/RedundantSplatExpansion',
|
32
|
-
'Naming/UncommunicativeBlockParamName' => 'Naming/BlockParameterName',
|
33
|
-
'Naming/UncommunicativeMethodParamName' => 'Naming/MethodParameterName',
|
34
|
-
'Style/DeprecatedHashMethods' => 'Style/PreferredHashMethods',
|
35
|
-
'Style/MethodCallParentheses' => 'Style/MethodCallWithoutArgsParentheses',
|
36
|
-
'Style/OpMethod' => 'Naming/BinaryOperatorParameterName',
|
37
|
-
'Style/SingleSpaceBeforeFirstArg' => 'Layout/SpaceBeforeFirstArg',
|
38
|
-
'Style/UnneededCapitalW' => 'Style/RedundantCapitalW',
|
39
|
-
'Style/UnneededCondition' => 'Style/RedundantCondition',
|
40
|
-
'Style/UnneededInterpolation' => 'Style/RedundantInterpolation',
|
41
|
-
'Style/UnneededPercentQ' => 'Style/RedundantPercentQ',
|
42
|
-
'Style/UnneededSort' => 'Style/RedundantSort'
|
43
|
-
}.map do |old_name, new_name|
|
44
|
-
[old_name, "The `#{old_name}` cop has been renamed to `#{new_name}`."]
|
45
|
-
end
|
46
|
-
|
47
|
-
MOVED_COPS = {
|
48
|
-
'Security' => 'Lint/Eval',
|
49
|
-
'Naming' => %w[Style/ClassAndModuleCamelCase Style/ConstantName
|
50
|
-
Style/FileName Style/MethodName Style/PredicateName
|
51
|
-
Style/VariableName Style/VariableNumber
|
52
|
-
Style/AccessorMethodName Style/AsciiIdentifiers],
|
53
|
-
'Layout' => %w[Lint/BlockAlignment Lint/EndAlignment
|
54
|
-
Lint/DefEndAlignment Metrics/LineLength],
|
55
|
-
'Lint' => 'Style/FlipFlop'
|
56
|
-
}.map do |new_department, old_names|
|
57
|
-
Array(old_names).map do |old_name|
|
58
|
-
[old_name, "The `#{old_name}` cop has been moved to " \
|
59
|
-
"`#{new_department}/#{old_name.split('/').last}`."]
|
7
|
+
DEFAULT_RULES_FILE = File.join(ConfigLoader::RUBOCOP_HOME, 'config', 'obsoletion.yml')
|
8
|
+
COP_RULE_CLASSES = {
|
9
|
+
'renamed' => RenamedCop,
|
10
|
+
'removed' => RemovedCop,
|
11
|
+
'split' => SplitCop,
|
12
|
+
'extracted' => ExtractedCop
|
13
|
+
}.freeze
|
14
|
+
PARAMETER_RULE_CLASSES = {
|
15
|
+
'changed_parameters' => ChangedParameter,
|
16
|
+
'changed_enforced_styles' => ChangedEnforcedStyles
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
attr_reader :rules, :warnings
|
20
|
+
|
21
|
+
class << self
|
22
|
+
attr_accessor :files
|
23
|
+
|
24
|
+
def legacy_cop_names
|
25
|
+
# Used by DepartmentName#qualified_legacy_cop_name
|
26
|
+
new(Config.new).rules.select(&:cop_rule?).map(&:old_name)
|
60
27
|
end
|
61
28
|
end
|
62
29
|
|
63
|
-
|
64
|
-
|
65
|
-
'Layout/SpaceBeforeModifierKeyword' => 'Layout/SpaceAroundKeyword',
|
66
|
-
'Lint/RescueWithoutErrorClass' => 'Style/RescueStandardError',
|
67
|
-
'Style/SpaceAfterControlKeyword' => 'Layout/SpaceAroundKeyword',
|
68
|
-
'Style/SpaceBeforeModifierKeyword' => 'Layout/SpaceAroundKeyword',
|
69
|
-
'Style/TrailingComma' => 'Style/TrailingCommaInArguments, ' \
|
70
|
-
'Style/TrailingCommaInArrayLiteral, and/or ' \
|
71
|
-
'Style/TrailingCommaInHashLiteral',
|
72
|
-
'Style/TrailingCommaInLiteral' => 'Style/TrailingCommaInArrayLiteral ' \
|
73
|
-
'and/or ' \
|
74
|
-
'Style/TrailingCommaInHashLiteral',
|
75
|
-
'Style/BracesAroundHashParameters' => nil
|
76
|
-
}.map do |old_name, other_cops|
|
77
|
-
if other_cops
|
78
|
-
more = ". Please use #{other_cops} instead".gsub(%r{[A-Z]\w+/\w+},
|
79
|
-
'`\&`')
|
80
|
-
end
|
81
|
-
[old_name, "The `#{old_name}` cop has been removed#{more}."]
|
82
|
-
end
|
83
|
-
|
84
|
-
REMOVED_COPS_WITH_REASON = {
|
85
|
-
'Lint/InvalidCharacterLiteral' => 'it was never being actually triggered',
|
86
|
-
'Lint/SpaceBeforeFirstArg' =>
|
87
|
-
'it was a duplicate of `Layout/SpaceBeforeFirstArg`. Please use ' \
|
88
|
-
'`Layout/SpaceBeforeFirstArg` instead',
|
89
|
-
'Style/MethodMissingSuper' => 'it has been superseded by `Lint/MissingSuper`. Please use ' \
|
90
|
-
'`Lint/MissingSuper` instead',
|
91
|
-
'Lint/UselessComparison' => 'it has been superseded by '\
|
92
|
-
'`Lint/BinaryOperatorWithIdenticalOperands`. Please use '\
|
93
|
-
'`Lint/BinaryOperatorWithIdenticalOperands` instead'
|
94
|
-
}.map do |cop_name, reason|
|
95
|
-
[cop_name, "The `#{cop_name}` cop has been removed since #{reason}."]
|
96
|
-
end
|
97
|
-
|
98
|
-
SPLIT_COPS = {
|
99
|
-
'Style/MethodMissing' =>
|
100
|
-
'The `Style/MethodMissing` cop has been split into ' \
|
101
|
-
'`Style/MethodMissingSuper` and `Style/MissingRespondToMissing`.'
|
102
|
-
}.to_a
|
103
|
-
|
104
|
-
OBSOLETE_COPS = Hash[*(RENAMED_COPS + MOVED_COPS + REMOVED_COPS +
|
105
|
-
REMOVED_COPS_WITH_REASON + SPLIT_COPS).flatten]
|
106
|
-
|
107
|
-
# Parameters can be deprecated but not disabled by setting `severity: :warning`
|
108
|
-
OBSOLETE_PARAMETERS = [
|
109
|
-
{
|
110
|
-
cops: %w[Layout/SpaceAroundOperators Style/SpaceAroundOperators],
|
111
|
-
parameters: 'MultiSpaceAllowedForOperators',
|
112
|
-
alternative: 'If your intention was to allow extra spaces for ' \
|
113
|
-
'alignment, please use AllowForAlignment: true instead.'
|
114
|
-
},
|
115
|
-
{
|
116
|
-
cops: 'Style/Encoding',
|
117
|
-
parameters: %w[EnforcedStyle SupportedStyles
|
118
|
-
AutoCorrectEncodingComment],
|
119
|
-
alternative: 'Style/Encoding no longer supports styles. ' \
|
120
|
-
'The "never" behavior is always assumed.'
|
121
|
-
},
|
122
|
-
{
|
123
|
-
cops: 'Style/IfUnlessModifier',
|
124
|
-
parameters: 'MaxLineLength',
|
125
|
-
alternative: '`Style/IfUnlessModifier: MaxLineLength` has been ' \
|
126
|
-
'removed. Use `Layout/LineLength: Max` instead'
|
127
|
-
},
|
128
|
-
{
|
129
|
-
cops: 'Style/WhileUntilModifier',
|
130
|
-
parameters: 'MaxLineLength',
|
131
|
-
alternative: '`Style/WhileUntilModifier: MaxLineLength` has been ' \
|
132
|
-
'removed. Use `Layout/LineLength: Max` instead'
|
133
|
-
},
|
134
|
-
{
|
135
|
-
cops: 'AllCops',
|
136
|
-
parameters: 'RunRailsCops',
|
137
|
-
alternative: "Use the following configuration instead:\n" \
|
138
|
-
"Rails:\n Enabled: true"
|
139
|
-
},
|
140
|
-
{
|
141
|
-
cops: 'Layout/CaseIndentation',
|
142
|
-
parameters: 'IndentWhenRelativeTo',
|
143
|
-
alternative: '`IndentWhenRelativeTo` has been renamed to ' \
|
144
|
-
'`EnforcedStyle`'
|
145
|
-
},
|
146
|
-
{
|
147
|
-
cops: %w[Lint/BlockAlignment Layout/BlockAlignment Lint/EndAlignment
|
148
|
-
Layout/EndAlignment Lint/DefEndAlignment
|
149
|
-
Layout/DefEndAlignment],
|
150
|
-
parameters: 'AlignWith',
|
151
|
-
alternative: '`AlignWith` has been renamed to `EnforcedStyleAlignWith`'
|
152
|
-
},
|
153
|
-
{
|
154
|
-
cops: 'Rails/UniqBeforePluck',
|
155
|
-
parameters: 'EnforcedMode',
|
156
|
-
alternative: '`EnforcedMode` has been renamed to `EnforcedStyle`'
|
157
|
-
},
|
158
|
-
{
|
159
|
-
cops: 'Style/MethodCallWithArgsParentheses',
|
160
|
-
parameters: 'IgnoredMethodPatterns',
|
161
|
-
alternative: '`IgnoredMethodPatterns` has been renamed to ' \
|
162
|
-
'`IgnoredPatterns`'
|
163
|
-
},
|
164
|
-
{
|
165
|
-
cops: %w[Performance/Count Performance/Detect],
|
166
|
-
parameters: 'SafeMode',
|
167
|
-
alternative: '`SafeMode` has been removed. ' \
|
168
|
-
'Use `SafeAutoCorrect` instead.'
|
169
|
-
},
|
170
|
-
{
|
171
|
-
cops: 'Bundler/GemComment',
|
172
|
-
parameters: 'Whitelist',
|
173
|
-
alternative: '`Whitelist` has been renamed to `IgnoredGems`.'
|
174
|
-
},
|
175
|
-
{
|
176
|
-
cops: %w[
|
177
|
-
Lint/SafeNavigationChain Lint/SafeNavigationConsistency
|
178
|
-
Style/NestedParenthesizedCalls Style/SafeNavigation
|
179
|
-
Style/TrivialAccessors
|
180
|
-
],
|
181
|
-
parameters: 'Whitelist',
|
182
|
-
alternative: '`Whitelist` has been renamed to `AllowedMethods`.'
|
183
|
-
},
|
184
|
-
{
|
185
|
-
cops: 'Style/IpAddresses',
|
186
|
-
parameters: 'Whitelist',
|
187
|
-
alternative: '`Whitelist` has been renamed to `AllowedAddresses`.'
|
188
|
-
},
|
189
|
-
{
|
190
|
-
cops: 'Naming/HeredocDelimiterNaming',
|
191
|
-
parameters: 'Blacklist',
|
192
|
-
alternative: '`Blacklist` has been renamed to `ForbiddenDelimiters`.'
|
193
|
-
},
|
194
|
-
{
|
195
|
-
cops: 'Naming/PredicateName',
|
196
|
-
parameters: 'NamePrefixBlacklist',
|
197
|
-
alternative: '`NamePrefixBlacklist` has been renamed to ' \
|
198
|
-
'`ForbiddenPrefixes`.'
|
199
|
-
},
|
200
|
-
{
|
201
|
-
cops: 'Naming/PredicateName',
|
202
|
-
parameters: 'NameWhitelist',
|
203
|
-
alternative: '`NameWhitelist` has been renamed to ' \
|
204
|
-
'`AllowedMethods`.'
|
205
|
-
},
|
206
|
-
{
|
207
|
-
cops: %w[Metrics/BlockLength Metrics/MethodLength],
|
208
|
-
parameters: 'ExcludedMethods',
|
209
|
-
alternative: '`ExcludedMethods` has been renamed to `IgnoredMethods`.',
|
210
|
-
severity: :warning
|
211
|
-
}
|
212
|
-
].freeze
|
213
|
-
|
214
|
-
OBSOLETE_ENFORCED_STYLES = [
|
215
|
-
{
|
216
|
-
cop: 'Layout/IndentationConsistency',
|
217
|
-
parameter: 'EnforcedStyle',
|
218
|
-
enforced_style: 'rails',
|
219
|
-
alternative: '`EnforcedStyle: rails` has been renamed to ' \
|
220
|
-
'`EnforcedStyle: indented_internal_methods`'
|
221
|
-
}
|
222
|
-
].freeze
|
223
|
-
|
224
|
-
attr_reader :warnings
|
30
|
+
# Can be extended by extension libraries to add their own obsoletions
|
31
|
+
self.files = [DEFAULT_RULES_FILE]
|
225
32
|
|
226
33
|
def initialize(config)
|
227
34
|
@config = config
|
35
|
+
@rules = load_rules
|
228
36
|
@warnings = []
|
229
37
|
end
|
230
38
|
|
231
|
-
def
|
232
|
-
messages =
|
233
|
-
obsolete_enforced_style].flatten.compact
|
39
|
+
def reject_obsolete!
|
40
|
+
messages = obsoletions.flatten.compact
|
234
41
|
return if messages.empty?
|
235
42
|
|
236
43
|
raise ValidationError, messages.join("\n")
|
@@ -238,64 +45,59 @@ module RuboCop
|
|
238
45
|
|
239
46
|
private
|
240
47
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
48
|
+
# Default rules for obsoletions are in config/obsoletion.yml
|
49
|
+
# Additional rules files can be added with `RuboCop::ConfigObsoletion.files << filename`
|
50
|
+
def load_rules
|
51
|
+
rules = self.class.files.each_with_object({}) do |filename, hash|
|
52
|
+
hash.merge!(YAML.safe_load(File.read(filename))) do |_key, first, second|
|
53
|
+
first.merge(second)
|
54
|
+
end
|
248
55
|
end
|
249
|
-
end
|
250
56
|
|
251
|
-
|
252
|
-
|
253
|
-
obsolete_enforced_style_message(params[:cop], params[:parameter],
|
254
|
-
params[:enforced_style],
|
255
|
-
params[:alternative])
|
256
|
-
end
|
257
|
-
end
|
57
|
+
cop_rules = rules.slice(*COP_RULE_CLASSES.keys)
|
58
|
+
parameter_rules = rules.slice(*PARAMETER_RULE_CLASSES.keys)
|
258
59
|
|
259
|
-
|
260
|
-
|
60
|
+
load_cop_rules(cop_rules).concat(load_parameter_rules(parameter_rules))
|
61
|
+
end
|
261
62
|
|
262
|
-
|
63
|
+
# Cop rules are keyed by the name of the original cop
|
64
|
+
def load_cop_rules(rules)
|
65
|
+
rules.flat_map do |rule_type, data|
|
66
|
+
data.map do |cop_name, configuration|
|
67
|
+
next unless configuration # allow configurations to be disabled with `CopName: ~`
|
263
68
|
|
264
|
-
|
265
|
-
|
69
|
+
COP_RULE_CLASSES[rule_type].new(@config, cop_name, configuration)
|
70
|
+
end.compact
|
71
|
+
end
|
266
72
|
end
|
267
73
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
74
|
+
# Parameter rules may apply to multiple cops and multiple parameters
|
75
|
+
# and are given as an array. Each combination is turned into a separate
|
76
|
+
# rule object.
|
77
|
+
def load_parameter_rules(rules)
|
78
|
+
rules.flat_map do |rule_type, data|
|
79
|
+
data.flat_map do |configuration|
|
80
|
+
cops = Array(configuration['cops'])
|
81
|
+
parameters = Array(configuration['parameters'])
|
82
|
+
|
83
|
+
cops.product(parameters).map do |cop, parameter|
|
84
|
+
PARAMETER_RULE_CLASSES[rule_type].new(@config, cop, parameter, configuration)
|
85
|
+
end
|
277
86
|
end
|
278
|
-
|
279
|
-
messages
|
280
87
|
end
|
281
88
|
end
|
282
89
|
|
283
|
-
def
|
284
|
-
|
285
|
-
|
286
|
-
@config[cop]&.key?(param)
|
287
|
-
end
|
288
|
-
next if obsolete_parameters.empty?
|
90
|
+
def obsoletions
|
91
|
+
rules.map do |rule|
|
92
|
+
next unless rule.violated?
|
289
93
|
|
290
|
-
|
291
|
-
|
292
|
-
|
94
|
+
if rule.warning?
|
95
|
+
@warnings.push(rule.message)
|
96
|
+
next
|
293
97
|
end
|
294
|
-
end
|
295
|
-
end
|
296
98
|
|
297
|
-
|
298
|
-
|
99
|
+
rule.message
|
100
|
+
end
|
299
101
|
end
|
300
102
|
end
|
301
103
|
end
|