rubocop 1.5.2 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +5 -2
  4. data/config/obsoletion.yml +196 -0
  5. data/lib/rubocop.rb +10 -0
  6. data/lib/rubocop/cli/command/suggest_extensions.rb +16 -44
  7. data/lib/rubocop/config_obsoletion.rb +63 -263
  8. data/lib/rubocop/config_obsoletion/changed_enforced_styles.rb +33 -0
  9. data/lib/rubocop/config_obsoletion/changed_parameter.rb +21 -0
  10. data/lib/rubocop/config_obsoletion/cop_rule.rb +34 -0
  11. data/lib/rubocop/config_obsoletion/extracted_cop.rb +44 -0
  12. data/lib/rubocop/config_obsoletion/parameter_rule.rb +44 -0
  13. data/lib/rubocop/config_obsoletion/removed_cop.rb +41 -0
  14. data/lib/rubocop/config_obsoletion/renamed_cop.rb +34 -0
  15. data/lib/rubocop/config_obsoletion/rule.rb +41 -0
  16. data/lib/rubocop/config_obsoletion/split_cop.rb +27 -0
  17. data/lib/rubocop/config_validator.rb +11 -4
  18. data/lib/rubocop/cop/base.rb +17 -15
  19. data/lib/rubocop/cop/cop.rb +2 -2
  20. data/lib/rubocop/cop/correctors/string_literal_corrector.rb +6 -8
  21. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -1
  22. data/lib/rubocop/cop/layout/line_length.rb +6 -16
  23. data/lib/rubocop/cop/migration/department_name.rb +1 -1
  24. data/lib/rubocop/cop/mixin/string_help.rb +4 -1
  25. data/lib/rubocop/cop/naming/accessor_method_name.rb +15 -1
  26. data/lib/rubocop/cop/style/character_literal.rb +10 -11
  27. data/lib/rubocop/cop/style/float_division.rb +44 -1
  28. data/lib/rubocop/cop/style/if_unless_modifier.rb +4 -0
  29. data/lib/rubocop/cop/style/ip_addresses.rb +1 -1
  30. data/lib/rubocop/cop/style/perl_backrefs.rb +86 -9
  31. data/lib/rubocop/cop/style/redundant_argument.rb +14 -1
  32. data/lib/rubocop/cop/style/single_line_block_params.rb +30 -7
  33. data/lib/rubocop/cop/style/sole_nested_conditional.rb +12 -6
  34. data/lib/rubocop/cop/style/special_global_vars.rb +1 -13
  35. data/lib/rubocop/cop/style/string_concatenation.rb +19 -0
  36. data/lib/rubocop/cop/style/string_literals.rb +14 -8
  37. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +4 -3
  38. data/lib/rubocop/formatter/emacs_style_formatter.rb +2 -0
  39. data/lib/rubocop/formatter/simple_text_formatter.rb +2 -0
  40. data/lib/rubocop/formatter/tap_formatter.rb +2 -0
  41. data/lib/rubocop/lockfile.rb +40 -0
  42. data/lib/rubocop/version.rb +1 -1
  43. metadata +14 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77baac77fdf5ed6293449d9653e1caeadc94b18e49bbd5115176c3681b8ed752
4
- data.tar.gz: 677ced7d3409d54555aaba855aec07fac0717bdb100eef4ea0196d68688247d6
3
+ metadata.gz: ae0bcfc68121984fb71e933b1a00aa8d418d99dd4005cce76e986d6c387c0e50
4
+ data.tar.gz: '0465797f84ca499f634aac95e745a4192bb62d68f5d935b4a7e21b925893b131'
5
5
  SHA512:
6
- metadata.gz: d083c6f78d892e14780bc3ab2cadf4b4208b87ab3dae357df39cc5dcbd9c2a18ff416795cd73a39c0d743fd07923ccbd092b916be3e738114558aa2b37f724cc
7
- data.tar.gz: 6a5e0502cfbc9c0c5c11f075b89a91ea7ae4ec1b70134fbe6930caca9f7959282dea23f9358db291cca2a4e1fa72e830a1717c1c845528024eb89d23e6368379
6
+ metadata.gz: eb0e28d3926209e380aed52e134801e3e206cf9ca1bace01e133223ddfe37507a888a70b629cefb7711951eaffd089078daa0a7065cf0730ccfd79febe80f1ff
7
+ data.tar.gz: 17fcb97b537f9529a5bb484d85f5873f1745905712472586550f463cf689465f12aaa291efcf9371babc17b8ca7e5b2d5a99d7f6a46c800fdb3dba8dca58989e
data/README.md CHANGED
@@ -51,7 +51,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
51
51
  in your `Gemfile`:
52
52
 
53
53
  ```rb
54
- gem 'rubocop', '~> 1.5', require: false
54
+ gem 'rubocop', '~> 1.6', require: false
55
55
  ```
56
56
 
57
57
  See [versioning](https://docs.rubocop.org/rubocop/1.0/versioning.html) for further details.
@@ -3209,9 +3209,10 @@ Style/ExponentialNotation:
3209
3209
  Style/FloatDivision:
3210
3210
  Description: 'For performing float division, coerce one side only.'
3211
3211
  StyleGuide: '#float-division'
3212
- Reference: 'https://github.com/rubocop-hq/ruby-style-guide/issues/628'
3212
+ Reference: 'https://blog.rubystyle.guide/ruby/2019/06/21/float-division.html'
3213
3213
  Enabled: true
3214
3214
  VersionAdded: '0.72'
3215
+ VersionChanged: '1.6'
3215
3216
  EnforcedStyle: single_coerce
3216
3217
  SupportedStyles:
3217
3218
  - left_coerce
@@ -4025,6 +4026,7 @@ Style/RedundantArgument:
4025
4026
  Enabled: pending
4026
4027
  Safe: false
4027
4028
  VersionAdded: '1.4'
4029
+ VersionChanged: '1.6'
4028
4030
  Methods:
4029
4031
  # Array#join
4030
4032
  join: ''
@@ -4272,7 +4274,7 @@ Style/SingleLineBlockParams:
4272
4274
  Description: 'Enforces the names of some block params.'
4273
4275
  Enabled: false
4274
4276
  VersionAdded: '0.16'
4275
- VersionChanged: '0.47'
4277
+ VersionChanged: '1.6'
4276
4278
  Methods:
4277
4279
  - reduce:
4278
4280
  - acc
@@ -4345,6 +4347,7 @@ Style/StringConcatenation:
4345
4347
  Enabled: true
4346
4348
  Safe: false
4347
4349
  VersionAdded: '0.89'
4350
+ VersionChanged: '1.6'
4348
4351
 
4349
4352
  Style/StringHashKeys:
4350
4353
  Description: 'Prefer symbols instead of strings as hash keys.'
@@ -0,0 +1,196 @@
1
+ # Configuration of obsolete/deprecated cops used by `ConfigObsoletion`
2
+
3
+ # Cops that were renamed
4
+ renamed:
5
+ Layout/AlignArguments: Layout/ArgumentAlignment
6
+ Layout/AlignArray: Layout/ArrayAlignment
7
+ Layout/AlignHash: Layout/HashAlignment
8
+ Layout/AlignParameters: Layout/ParameterAlignment
9
+ Layout/IndentArray: Layout/FirstArrayElementIndentation
10
+ Layout/IndentAssignment: Layout/AssignmentIndentation
11
+ Layout/IndentFirstArgument: Layout/FirstArgumentIndentation
12
+ Layout/IndentFirstArrayElement: Layout/FirstArrayElementIndentation
13
+ Layout/IndentFirstHashElement: Layout/FirstHashElementIndentation
14
+ Layout/IndentFirstParameter: Layout/FirstParameterIndentation
15
+ Layout/IndentHash: Layout/FirstHashElementIndentation
16
+ Layout/IndentHeredoc: Layout/HeredocIndentation
17
+ Layout/LeadingBlankLines: Layout/LeadingEmptyLines
18
+ Layout/Tab: Layout/IndentationStyle
19
+ Layout/TrailingBlankLines: Layout/TrailingEmptyLines
20
+ Lint/BlockAlignment: Layout/BlockAlignment
21
+ Lint/DefEndAlignment: Layout/DefEndAlignment
22
+ Lint/DuplicatedKey: Lint/DuplicateHashKey
23
+ Lint/EndAlignment: Layout/EndAlignment
24
+ Lint/EndInMethod: Style/EndBlock
25
+ Lint/Eval: Security/Eval
26
+ Lint/HandleExceptions: Lint/SuppressedException
27
+ Lint/MultipleCompare: Lint/MultipleComparison
28
+ Lint/StringConversionInInterpolation: Lint/RedundantStringCoercion
29
+ Lint/UnneededCopDisableDirective: Lint/RedundantCopDisableDirective
30
+ Lint/UnneededCopEnableDirective: Lint/RedundantCopEnableDirective
31
+ Lint/UnneededRequireStatement: Lint/RedundantRequireStatement
32
+ Lint/UnneededSplatExpansion: Lint/RedundantSplatExpansion
33
+ Metrics/LineLength: Layout/LineLength
34
+ Naming/UncommunicativeBlockParamName: Naming/BlockParameterName
35
+ Naming/UncommunicativeMethodParamName: Naming/MethodParameterName
36
+ Style/AccessorMethodName: Naming/AccessorMethodName
37
+ Style/AsciiIdentifiers: Naming/AsciiIdentifiers
38
+ Style/ClassAndModuleCamelCase: Naming/ClassAndModuleCamelCase
39
+ Style/ConstantName: Naming/ConstantName
40
+ Style/DeprecatedHashMethods: Style/PreferredHashMethods
41
+ Style/FileName: Naming/FileName
42
+ Style/FlipFlop: Lint/FlipFlop
43
+ Style/MethodCallParentheses: Style/MethodCallWithoutArgsParentheses
44
+ Style/MethodName: Naming/MethodName
45
+ Style/OpMethod: Naming/BinaryOperatorParameterName
46
+ Style/PredicateName: Naming/PredicateName
47
+ Style/SingleSpaceBeforeFirstArg: Layout/SpaceBeforeFirstArg
48
+ Style/UnneededCapitalW: Style/RedundantCapitalW
49
+ Style/UnneededCondition: Style/RedundantCondition
50
+ Style/UnneededInterpolation: Style/RedundantInterpolation
51
+ Style/UnneededPercentQ: Style/RedundantPercentQ
52
+ Style/UnneededSort: Style/RedundantSort
53
+ Style/VariableName: Naming/VariableName
54
+ Style/VariableNumber: Naming/VariableNumber
55
+
56
+ # Cops that were removed
57
+ removed:
58
+ Layout/SpaceAfterControlKeyword:
59
+ alternatives: Layout/SpaceAroundKeyword
60
+ Layout/SpaceBeforeModifierKeyword:
61
+ alternatives: Layout/SpaceAroundKeyword
62
+ Lint/InvalidCharacterLiteral:
63
+ reason: it was never being actually triggered
64
+ Lint/RescueWithoutErrorClass:
65
+ alternatives: Style/RescueStandardError
66
+ Lint/SpaceBeforeFirstArg:
67
+ reason: >
68
+ it was a duplicate of `Layout/SpaceBeforeFirstArg`. Please use
69
+ `Layout/SpaceBeforeFirstArg` instead
70
+ Lint/UselessComparison:
71
+ reason: >
72
+ it has been superseded by
73
+ `Lint/BinaryOperatorWithIdenticalOperands`. Please use
74
+ `Lint/BinaryOperatorWithIdenticalOperands` instead
75
+ Style/BracesAroundHashParameters: true
76
+ Style/MethodMissingSuper:
77
+ reason: >
78
+ it has been superseded by `Lint/MissingSuper`. Please use
79
+ `Lint/MissingSuper` instead
80
+ Style/SpaceAfterControlKeyword:
81
+ alternatives: Layout/SpaceAroundKeyword
82
+ Style/SpaceBeforeModifierKeyword:
83
+ alternatives: Layout/SpaceAroundKeyword
84
+ Style/TrailingComma:
85
+ alternatives:
86
+ - Style/TrailingCommaInArguments
87
+ - Style/TrailingCommaInArrayLiteral
88
+ - Style/TrailingCommaInHashLiteral
89
+ Style/TrailingCommaInLiteral:
90
+ alternatives:
91
+ - Style/TrailingCommaInArrayLiteral
92
+ - Style/TrailingCommaInHashLiteral
93
+
94
+ # Cops split into multiple other cops
95
+ split:
96
+ Style/MethodMissing:
97
+ alternatives:
98
+ - Style/MethodMissingSuper
99
+ - Style/MissingRespondToMissing
100
+
101
+ # Cops that were extracted into a different gem
102
+ extracted:
103
+ Performance/*: rubocop-performance
104
+ Rails/*: rubocop-rails
105
+
106
+ # Cop parameters that have been changed
107
+ # Can be treated as a warning instead of a failure with `severity: warning`
108
+ changed_parameters:
109
+ - cops:
110
+ - Layout/SpaceAroundOperators
111
+ - Style/SpaceAroundOperators
112
+ parameters: MultiSpaceAllowedForOperators
113
+ reason: >
114
+ If your intention was to allow extra spaces for alignment, please
115
+ use `AllowForAlignment: true` instead.
116
+ - cops: Style/Encoding
117
+ parameters:
118
+ - EnforcedStyle
119
+ - SupportedStyles
120
+ - AutoCorrectEncodingComment
121
+ reason: '`Style/Encoding` no longer supports styles. The "never" behavior is always assumed.'
122
+ - cops: Style/IfUnlessModifier
123
+ parameters: MaxLineLength
124
+ reason: >
125
+ `Style/IfUnlessModifier: MaxLineLength` has been removed.
126
+ Use `Layout/LineLength: Max` instead
127
+ - cops: Style/WhileUntilModifier
128
+ parameters: MaxLineLength
129
+ reason: >
130
+ `Style/WhileUntilModifier: MaxLineLength` has been removed.
131
+ Use `Layout/LineLength: Max` instead
132
+ - cops: AllCops
133
+ parameters: RunRailsCops
134
+ reason: |-
135
+ Use the following configuration instead:
136
+ Rails:
137
+ Enabled: true
138
+ - cops: Layout/CaseIndentation
139
+ parameters: IndentWhenRelativeTo
140
+ alternative: EnforcedStyle
141
+ - cops:
142
+ - Lint/BlockAlignment
143
+ - Layout/BlockAlignment
144
+ - Lint/EndAlignment
145
+ - Layout/EndAlignment
146
+ - Lint/DefEndAlignment
147
+ - Layout/DefEndAlignment
148
+ parameters: AlignWith
149
+ alternative: EnforcedStyleAlignWith
150
+ - cops: Rails/UniqBeforePluck
151
+ parameters: EnforcedMode
152
+ alternative: EnforcedStyle
153
+ - cops: Style/MethodCallWithArgsParentheses
154
+ parameters: IgnoredMethodPatterns
155
+ alternative: IgnoredPatterns
156
+ - cops:
157
+ - Performance/Count
158
+ - Performance/Detect
159
+ parameters: SafeMode
160
+ reason: "`SafeMode` has been removed. Use `SafeAutoCorrect` instead."
161
+ - cops: Bundler/GemComment
162
+ parameters: Whitelist
163
+ alternative: IgnoredGems
164
+ - cops:
165
+ - Lint/SafeNavigationChain
166
+ - Lint/SafeNavigationConsistency
167
+ - Style/NestedParenthesizedCalls
168
+ - Style/SafeNavigation
169
+ - Style/TrivialAccessors
170
+ parameters: Whitelist
171
+ alternative: AllowedMethods
172
+ - cops: Style/IpAddresses
173
+ parameters: Whitelist
174
+ alternative: AllowedAddresses
175
+ - cops: Naming/HeredocDelimiterNaming
176
+ parameters: Blacklist
177
+ alternative: ForbiddenDelimiters
178
+ - cops: Naming/PredicateName
179
+ parameters: NamePrefixBlacklist
180
+ alternative: ForbiddenPrefixes
181
+ - cops: Naming/PredicateName
182
+ parameters: NameWhitelist
183
+ alternative: AllowedMethods
184
+ - cops:
185
+ - Metrics/BlockLength
186
+ - Metrics/MethodLength
187
+ parameters: ExcludedMethods
188
+ alternative: IgnoredMethods
189
+ severity: warning
190
+
191
+ # Enforced styles that have been removed or replaced
192
+ changed_enforced_styles:
193
+ - cops: Layout/IndentationConsistency
194
+ parameters: EnforcedStyle
195
+ value: rails
196
+ alternative: indented_internal_methods
@@ -632,9 +632,19 @@ require_relative 'rubocop/cached_data'
632
632
  require_relative 'rubocop/config'
633
633
  require_relative 'rubocop/config_loader_resolver'
634
634
  require_relative 'rubocop/config_loader'
635
+ require_relative 'rubocop/config_obsoletion/rule'
636
+ require_relative 'rubocop/config_obsoletion/cop_rule'
637
+ require_relative 'rubocop/config_obsoletion/parameter_rule'
638
+ require_relative 'rubocop/config_obsoletion/changed_enforced_styles'
639
+ require_relative 'rubocop/config_obsoletion/changed_parameter'
640
+ require_relative 'rubocop/config_obsoletion/extracted_cop'
641
+ require_relative 'rubocop/config_obsoletion/removed_cop'
642
+ require_relative 'rubocop/config_obsoletion/renamed_cop'
643
+ require_relative 'rubocop/config_obsoletion/split_cop'
635
644
  require_relative 'rubocop/config_obsoletion'
636
645
  require_relative 'rubocop/config_store'
637
646
  require_relative 'rubocop/config_validator'
647
+ require_relative 'rubocop/lockfile'
638
648
  require_relative 'rubocop/target_finder'
639
649
  require_relative 'rubocop/directive_comment'
640
650
  require_relative 'rubocop/comment_config'
@@ -3,7 +3,10 @@
3
3
  module RuboCop
4
4
  class CLI
5
5
  module Command
6
- # Run all the selected cops and report the result.
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.
@@ -11,39 +14,6 @@ module RuboCop
11
14
 
12
15
  self.command_name = :suggest_extensions
13
16
 
14
- class << self
15
- # Gems that the current bundle depends on
16
- # Suggestions are only made for gems that are 1st party dependencies
17
- def dependent_gems
18
- bundler do |gems|
19
- gems.dependencies.map(&:name)
20
- end
21
- end
22
-
23
- # All installed gems in the current bundle
24
- # If a suggestion is installed but not depended on, it still should not
25
- # be suggested.
26
- def installed_gems
27
- bundler do
28
- # Load specs from the lockfile without trying to resolve them
29
- return [] unless Bundler.default_lockfile
30
-
31
- lockfile = Bundler.read_file(Bundler.default_lockfile)
32
- Bundler::LockfileParser.new(lockfile).specs.map(&:name)
33
- end
34
- end
35
-
36
- private
37
-
38
- def bundler
39
- return [] unless defined?(Bundler)
40
-
41
- yield Bundler.load
42
- rescue Bundler::BundlerError
43
- []
44
- end
45
- end
46
-
47
17
  def run
48
18
  return if skip? || extensions.none?
49
19
 
@@ -82,25 +52,27 @@ module RuboCop
82
52
  end
83
53
 
84
54
  def extensions
85
- return [] unless dependent_gems.any?
55
+ return [] unless lockfile.dependencies.any?
86
56
 
87
- @extensions ||= begin
88
- extensions = @config_store.for_pwd.for_all_cops['SuggestExtensions'] || {}
89
- extensions.select { |_, v| (Array(v) & dependent_gems).any? }.keys - installed_gems
90
- end
57
+ extensions = @config_store.for_pwd.for_all_cops['SuggestExtensions'] || {}
58
+ extensions.select { |_, v| (Array(v) & dependent_gems).any? }.keys - installed_gems
91
59
  end
92
60
 
93
- def puts(*args)
94
- output = (@options[:stderr] ? $stderr : $stdout)
95
- output.puts(*args)
61
+ def lockfile
62
+ @lockfile ||= Lockfile.new
96
63
  end
97
64
 
98
65
  def dependent_gems
99
- @dependent_gems ||= self.class.dependent_gems
66
+ lockfile.dependencies.map(&:name)
100
67
  end
101
68
 
102
69
  def installed_gems
103
- @installed_gems ||= self.class.installed_gems
70
+ lockfile.gems.map(&:name)
71
+ end
72
+
73
+ def puts(*args)
74
+ output = (@options[:stderr] ? $stderr : $stdout)
75
+ output.puts(*args)
104
76
  end
105
77
  end
106
78
  end
@@ -4,233 +4,40 @@ module RuboCop
4
4
  # This class handles obsolete configuration.
5
5
  # @api private
6
6
  class ConfigObsoletion
7
- RENAMED_COPS = {
8
- 'Layout/AlignArguments' => 'Layout/ArgumentAlignment',
9
- 'Layout/AlignArray' => 'Layout/ArrayAlignment',
10
- 'Layout/AlignHash' => 'Layout/HashAlignment',
11
- 'Layout/AlignParameters' => 'Layout/ParameterAlignment',
12
- 'Layout/IndentArray' => 'Layout/FirstArrayElementIndentation',
13
- 'Layout/IndentAssignment' => 'Layout/AssignmentIndentation',
14
- 'Layout/IndentFirstArgument' => 'Layout/FirstArgumentIndentation',
15
- 'Layout/IndentFirstArrayElement' => 'Layout/FirstArrayElementIndentation',
16
- 'Layout/IndentFirstHashElement' => 'Layout/FirstHashElementIndentation',
17
- 'Layout/IndentFirstParameter' => 'Layout/FirstParameterIndentation',
18
- 'Layout/IndentHash' => 'Layout/FirstHashElementIndentation',
19
- 'Layout/IndentHeredoc' => 'Layout/HeredocIndentation',
20
- 'Layout/LeadingBlankLines' => 'Layout/LeadingEmptyLines',
21
- 'Layout/Tab' => 'Layout/IndentationStyle',
22
- 'Layout/TrailingBlankLines' => 'Layout/TrailingEmptyLines',
23
- 'Lint/DuplicatedKey' => 'Lint/DuplicateHashKey',
24
- 'Lint/EndInMethod' => 'Style/EndBlock',
25
- 'Lint/HandleExceptions' => 'Lint/SuppressedException',
26
- 'Lint/MultipleCompare' => 'Lint/MultipleComparison',
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
- REMOVED_COPS = {
64
- 'Layout/SpaceAfterControlKeyword' => 'Layout/SpaceAroundKeyword',
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 reject_obsolete_cops_and_parameters
232
- messages = [obsolete_cops, obsolete_parameters,
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,57 @@ module RuboCop
238
45
 
239
46
  private
240
47
 
241
- def obsolete_cops
242
- OBSOLETE_COPS.map do |cop_name, message|
243
- next unless @config.key?(cop_name) ||
244
- @config.key?(Cop::Badge.parse(cop_name).cop_name)
245
-
246
- message + "\n(obsolete configuration found in " \
247
- "#{smart_loaded_path}, please update it)"
248
- end
249
- end
250
-
251
- def obsolete_enforced_style
252
- OBSOLETE_ENFORCED_STYLES.map do |params|
253
- obsolete_enforced_style_message(params[:cop], params[:parameter],
254
- params[:enforced_style],
255
- params[:alternative])
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
256
55
  end
257
- end
258
-
259
- def obsolete_enforced_style_message(cop, param, enforced_style, alternative)
260
- style = @config[cop]&.detect { |key, _| key.start_with?(param) }
261
56
 
262
- return unless style && style[1] == enforced_style
57
+ cop_rules = rules.slice(*COP_RULE_CLASSES.keys)
58
+ parameter_rules = rules.slice(*PARAMETER_RULE_CLASSES.keys)
263
59
 
264
- "obsolete `#{param}: #{enforced_style}` (for #{cop}) found in " \
265
- "#{smart_loaded_path}\n#{alternative}"
60
+ load_cop_rules(cop_rules).concat(load_parameter_rules(parameter_rules))
266
61
  end
267
62
 
268
- def obsolete_parameters
269
- OBSOLETE_PARAMETERS.collect do |params|
270
- messages = obsolete_parameter_message(params[:cops], params[:parameters],
271
- params[:alternative])
272
-
273
- # Warnings are collected separately and not added to the error message
274
- if messages && params.fetch(:severity, :error) == :warning
275
- @warnings.concat(messages)
276
- next
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 |configuration|
67
+ COP_RULE_CLASSES[rule_type].new(@config, *configuration)
277
68
  end
278
-
279
- messages
280
69
  end
281
70
  end
282
71
 
283
- def obsolete_parameter_message(cops, parameters, alternative)
284
- Array(cops).map do |cop|
285
- obsolete_parameters = Array(parameters).select do |param|
286
- @config[cop]&.key?(param)
287
- end
288
- next if obsolete_parameters.empty?
289
-
290
- obsolete_parameters.map do |parameter|
291
- "obsolete parameter #{parameter} (for #{cop}) found in " \
292
- "#{smart_loaded_path}\n#{alternative}"
72
+ # Parameter rules may apply to multiple cops and multiple parameters
73
+ # and are given as an array. Each combination is turned into a separate
74
+ # rule object.
75
+ def load_parameter_rules(rules)
76
+ rules.flat_map do |rule_type, data|
77
+ data.flat_map do |configuration|
78
+ cops = Array(configuration['cops'])
79
+ parameters = Array(configuration['parameters'])
80
+
81
+ cops.product(parameters).map do |cop, parameter|
82
+ PARAMETER_RULE_CLASSES[rule_type].new(@config, cop, parameter, configuration)
83
+ end
293
84
  end
294
85
  end
295
86
  end
296
87
 
297
- def smart_loaded_path
298
- PathUtil.smart_path(@config.loaded_path)
88
+ def obsoletions
89
+ rules.map do |rule|
90
+ next unless rule.violated?
91
+
92
+ if rule.warning?
93
+ @warnings.push(rule.message)
94
+ next
95
+ end
96
+
97
+ rule.message
98
+ end
299
99
  end
300
100
  end
301
101
  end