rubocop 0.73.0 → 0.74.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/bin/console +1 -0
  4. data/config/default.yml +2 -1
  5. data/lib/rubocop.rb +3 -0
  6. data/lib/rubocop/ast/node.rb +1 -7
  7. data/lib/rubocop/config.rb +17 -537
  8. data/lib/rubocop/config_obsoletion.rb +201 -0
  9. data/lib/rubocop/config_validator.rb +239 -0
  10. data/lib/rubocop/cop/layout/extra_spacing.rb +14 -53
  11. data/lib/rubocop/cop/layout/indentation_width.rb +19 -5
  12. data/lib/rubocop/cop/layout/space_around_operators.rb +42 -23
  13. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +22 -40
  14. data/lib/rubocop/cop/lint/debugger.rb +0 -2
  15. data/lib/rubocop/cop/lint/empty_interpolation.rb +4 -4
  16. data/lib/rubocop/cop/lint/erb_new_arguments.rb +56 -0
  17. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +7 -8
  18. data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +6 -6
  19. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +6 -1
  20. data/lib/rubocop/cop/metrics/line_length.rb +6 -0
  21. data/lib/rubocop/cop/mixin/documentation_comment.rb +0 -2
  22. data/lib/rubocop/cop/mixin/interpolation.rb +27 -0
  23. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +87 -0
  24. data/lib/rubocop/cop/mixin/surrounding_space.rb +7 -5
  25. data/lib/rubocop/cop/style/commented_keyword.rb +8 -28
  26. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -3
  27. data/lib/rubocop/cop/style/constant_visibility.rb +13 -2
  28. data/lib/rubocop/cop/style/guard_clause.rb +39 -10
  29. data/lib/rubocop/cop/style/lambda.rb +0 -2
  30. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +4 -6
  31. data/lib/rubocop/cop/style/variable_interpolation.rb +6 -16
  32. data/lib/rubocop/path_util.rb +1 -1
  33. data/lib/rubocop/processed_source.rb +4 -0
  34. data/lib/rubocop/rspec/expect_offense.rb +4 -1
  35. data/lib/rubocop/version.rb +1 -1
  36. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 65d141c7453c4d515c8e6a54e88cbc82305193f9fdd078148939550973c06eef
4
- data.tar.gz: 78246e2ffa87ef9a0206e73227f323bfd9d1fdf97f565660c12f52854d2e75f0
3
+ metadata.gz: 7299e4e21bbddcdbfec2725fec41c384d50867b70a986d87ea0f6f7f08dd3ebe
4
+ data.tar.gz: 504dae598bbb526afed6bc9ecc56d86a27656d535bf52e30c85e7ab005af99f3
5
5
  SHA512:
6
- metadata.gz: 48f6c20451589a69ebf28b1dacb70193d9baa0b6a5c6a5f2c065c00df2a7df284575705ac65027f4884b0673d1b62babf862ad2c9bdb461f909c4b38cb15a138
7
- data.tar.gz: ea5877d8c872db2adf5f45e6613d01881227b7a22394c8e661fb41e78b5a9d75fb2662471a1876f287718092120ef2953105f27392c2a741273f9dd131544b29
6
+ metadata.gz: 57b94e3a5a06724249509077ada410188ad29b52ae6dfda9d8b56582cc08bdb443a60e75744abf0d2ac664b3124db18e3e5382f72ccacfd4be64faf2c489b0ae
7
+ data.tar.gz: fb563b7256b89462268c6b3dc4b5cbf626764d2a3097dc5a332187a78c4f7d9d0c80c6dd2ba83692d48ba354696467329a87acf25474261a24bd9bffcd42f35a
data/README.md CHANGED
@@ -52,7 +52,7 @@ haven't reached version 1.0 yet). To prevent an unwanted RuboCop update you
52
52
  might want to use a conservative version lock in your `Gemfile`:
53
53
 
54
54
  ```rb
55
- gem 'rubocop', '~> 0.73.0', require: false
55
+ gem 'rubocop', '~> 0.74.0', require: false
56
56
  ```
57
57
 
58
58
  ## Quickstart
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'bundler/setup'
4
5
  require 'pry'
5
6
  require 'rubocop'
6
7
 
@@ -1662,6 +1662,7 @@ Lint/UnneededSplatExpansion:
1662
1662
  Description: 'Checks for splat unnecessarily being called on literals.'
1663
1663
  Enabled: true
1664
1664
  VersionAdded: '0.43'
1665
+ VersionChanged: '0.74'
1665
1666
 
1666
1667
  Lint/UnreachableCode:
1667
1668
  Description: 'Unreachable code.'
@@ -3052,7 +3053,7 @@ Style/MultilineWhenThen:
3052
3053
  Description: 'Do not use then for multi-line when statement.'
3053
3054
  StyleGuide: '#no-then'
3054
3055
  Enabled: true
3055
- VersionAdded: '0.72'
3056
+ VersionAdded: '0.73'
3056
3057
 
3057
3058
  Style/MultipleComparison:
3058
3059
  Description: >-
@@ -122,6 +122,7 @@ require_relative 'rubocop/cop/mixin/ignored_pattern'
122
122
  require_relative 'rubocop/cop/mixin/ignored_methods'
123
123
  require_relative 'rubocop/cop/mixin/ignored_method_patterns'
124
124
  require_relative 'rubocop/cop/mixin/integer_node'
125
+ require_relative 'rubocop/cop/mixin/interpolation'
125
126
  require_relative 'rubocop/cop/mixin/match_range'
126
127
  require_relative 'rubocop/cop/mixin/method_complexity'
127
128
  require_relative 'rubocop/cop/mixin/method_preference'
@@ -586,7 +587,9 @@ require_relative 'rubocop/cached_data'
586
587
  require_relative 'rubocop/config'
587
588
  require_relative 'rubocop/config_loader_resolver'
588
589
  require_relative 'rubocop/config_loader'
590
+ require_relative 'rubocop/config_obsoletion'
589
591
  require_relative 'rubocop/config_store'
592
+ require_relative 'rubocop/config_validator'
590
593
  require_relative 'rubocop/target_finder'
591
594
  require_relative 'rubocop/token'
592
595
  require_relative 'rubocop/comment_config'
@@ -306,8 +306,6 @@ module RuboCop
306
306
  {(send $_ ...) (block (send $_ ...) ...)}
307
307
  PATTERN
308
308
 
309
- # Note: for masgn, #asgn_rhs will be an array node
310
- def_node_matcher :asgn_rhs, '[assignment? (... $_)]'
311
309
  def_node_matcher :str_content, '(str $_)'
312
310
 
313
311
  def const_name
@@ -480,7 +478,7 @@ module RuboCop
480
478
  end
481
479
 
482
480
  def_node_matcher :guard_clause?, <<~PATTERN
483
- [{(send nil? {:raise :fail} ...) return break next} single_line?]
481
+ [${(send nil? {:raise :fail} ...) return break next} single_line?]
484
482
  PATTERN
485
483
 
486
484
  def_node_matcher :proc?, <<~PATTERN
@@ -497,10 +495,6 @@ module RuboCop
497
495
  (block (send (const nil? {:Class :Module}) :new ...) ...)}
498
496
  PATTERN
499
497
 
500
- def_node_matcher :module_definition?, <<~PATTERN
501
- {class module (casgn _ _ class_constructor?)}
502
- PATTERN
503
-
504
498
  # Some expressions are evaluated for their value, some for their side
505
499
  # effects, and some for both
506
500
  # If we know that an expression is useful only for its side effects, that
@@ -8,237 +8,12 @@ module RuboCop
8
8
  # file from which it was read. Several different Configs can be used
9
9
  # during a run of the rubocop program, if files in several
10
10
  # directories are inspected.
11
-
12
- # rubocop:disable Metrics/ClassLength
13
11
  class Config
14
12
  include PathUtil
15
13
  include FileFinder
14
+ extend Forwardable
16
15
 
17
- COMMON_PARAMS = %w[Exclude Include Severity inherit_mode
18
- AutoCorrect StyleGuide Details].freeze
19
- INTERNAL_PARAMS = %w[Description StyleGuide VersionAdded
20
- VersionChanged Reference Safe SafeAutoCorrect].freeze
21
-
22
- # 2.3 is the oldest officially supported Ruby version.
23
- DEFAULT_RUBY_VERSION = 2.3
24
- KNOWN_RUBIES = [2.3, 2.4, 2.5, 2.6, 2.7].freeze
25
- OBSOLETE_RUBIES = {
26
- 1.9 => '0.50', 2.0 => '0.50', 2.1 => '0.58', 2.2 => '0.69'
27
- }.freeze
28
- RUBY_VERSION_FILENAME = '.ruby-version'
29
16
  DEFAULT_RAILS_VERSION = 5.0
30
- OBSOLETE_COPS = {
31
- 'Style/FlipFlop' =>
32
- 'The `Style/FlipFlop` cop has been moved to `Lint/FlipFlop`.',
33
- 'Style/TrailingComma' =>
34
- 'The `Style/TrailingComma` cop no longer exists. Please use ' \
35
- '`Style/TrailingCommaInArguments`, ' \
36
- '`Style/TrailingCommaInArrayLiteral`, and/or ' \
37
- '`Style/TrailingCommaInHashLiteral` instead.',
38
- 'Style/TrailingCommaInLiteral' =>
39
- 'The `Style/TrailingCommaInLiteral` cop no longer exists. Please use ' \
40
- '`Style/TrailingCommaInArrayLiteral` and/or ' \
41
- '`Style/TrailingCommaInHashLiteral` instead.',
42
- 'Rails/DefaultScope' =>
43
- 'The `Rails/DefaultScope` cop no longer exists.',
44
- 'Lint/InvalidCharacterLiteral' =>
45
- 'The `Lint/InvalidCharacterLiteral` cop has been removed since it ' \
46
- 'was never being actually triggered.',
47
- 'Style/SingleSpaceBeforeFirstArg' =>
48
- 'The `Style/SingleSpaceBeforeFirstArg` cop has been renamed to ' \
49
- '`Layout/SpaceBeforeFirstArg`.',
50
- 'Lint/RescueWithoutErrorClass' =>
51
- 'The `Lint/RescueWithoutErrorClass` cop has been replaced by ' \
52
- '`Style/RescueStandardError`.',
53
- 'Lint/SpaceBeforeFirstArg' =>
54
- 'The `Lint/SpaceBeforeFirstArg` cop has been removed, since it was a ' \
55
- 'duplicate of `Layout/SpaceBeforeFirstArg`. Please use ' \
56
- '`Layout/SpaceBeforeFirstArg` instead.',
57
- 'Layout/FirstParameterIndentation' =>
58
- 'The `Layout/FirstParameterIndentation` cop has been renamed to ' \
59
- '`Layout/IndentFirstArgument`.',
60
- 'Layout/IndentArray' =>
61
- 'The `Layout/IndentArray` cop has been renamed to ' \
62
- '`Layout/IndentFirstArrayElement`.',
63
- 'Layout/IndentHash' =>
64
- 'The `Layout/IndentHash` cop has been renamed to ' \
65
- '`Layout/IndentFirstHashElement`.',
66
- 'Layout/SpaceAfterControlKeyword' =>
67
- 'The `Layout/SpaceAfterControlKeyword` cop has been removed. Please ' \
68
- 'use `Layout/SpaceAroundKeyword` instead.',
69
- 'Layout/SpaceBeforeModifierKeyword' =>
70
- 'The `Layout/SpaceBeforeModifierKeyword` cop has been removed. ' \
71
- 'Please use `Layout/SpaceAroundKeyword` instead.',
72
- 'Style/SpaceAfterControlKeyword' =>
73
- 'The `Style/SpaceAfterControlKeyword` cop has been removed. Please ' \
74
- 'use `Layout/SpaceAroundKeyword` instead.',
75
- 'Style/SpaceBeforeModifierKeyword' =>
76
- 'The `Style/SpaceBeforeModifierKeyword` cop has been removed. Please ' \
77
- 'use `Layout/SpaceAroundKeyword` instead.',
78
- 'Style/MethodCallParentheses' =>
79
- 'The `Style/MethodCallParentheses` cop has been renamed to ' \
80
- '`Style/MethodCallWithoutArgsParentheses`.',
81
- 'Lint/Eval' =>
82
- 'The `Lint/Eval` cop has been renamed to `Security/Eval`.',
83
- 'Style/DeprecatedHashMethods' =>
84
- 'The `Style/DeprecatedHashMethods` cop has been renamed to ' \
85
- '`Style/PreferredHashMethods`.',
86
- 'Style/AccessorMethodName' =>
87
- 'The `Style/AccessorMethodName` cop has been moved to ' \
88
- '`Naming/AccessorMethodName`.',
89
- 'Style/AsciiIdentifiers' =>
90
- 'The `Style/AsciiIdentifiers` cop has been moved to ' \
91
- '`Naming/AccessorMethodName`.',
92
- 'Style/OpMethod' =>
93
- 'The `Style/OpMethod` cop has been renamed and moved to ' \
94
- '`Naming/BinaryOperatorParameterName`.',
95
- 'Style/ClassAndModuleCamelCase' =>
96
- 'The `Style/ClassAndModuleCamelCase` cop has been renamed to ' \
97
- '`Naming/ClassAndModuleCamelCase`.',
98
- 'Style/ConstantName' =>
99
- 'The `Style/ConstantName` cop has been renamed to ' \
100
- '`Naming/ConstantName`.',
101
- 'Style/FileName' =>
102
- 'The `Style/FileName` cop has been renamed to `Naming/FileName`.',
103
- 'Style/MethodName' =>
104
- 'The `Style/MethodName` cop has been renamed to ' \
105
- '`Naming/MethodName`.',
106
- 'Style/PredicateName' =>
107
- 'The `Style/PredicateName` cop has been renamed to ' \
108
- '`Naming/PredicateName`.',
109
- 'Style/VariableName' =>
110
- 'The `Style/VariableName` cop has been renamed to ' \
111
- '`Naming/VariableName`.',
112
- 'Style/VariableNumber' =>
113
- 'The `Style/VariableNumber` cop has been renamed to ' \
114
- '`Naming/VariableNumber`.',
115
- 'Lint/BlockAlignment' =>
116
- 'The `Lint/BlockAlignment` cop has been renamed to ' \
117
- '`Layout/BlockAlignment`.',
118
- 'Lint/EndAlignment' =>
119
- 'The `Lint/EndAlignment` cop has been renamed to ' \
120
- '`Layout/EndAlignment`.',
121
- 'Lint/DefEndAlignment' =>
122
- 'The `Lint/DefEndAlignment` cop has been renamed to ' \
123
- '`Layout/DefEndAlignment`.',
124
- 'Style/MethodMissing' =>
125
- 'The `Style/MethodMissing` cop has been split into ' \
126
- '`Style/MethodMissingSuper` and `Style/MissingRespondToMissing`.'
127
- }.freeze
128
-
129
- OBSOLETE_PARAMETERS = [
130
- {
131
- cop: 'Layout/SpaceAroundOperators',
132
- parameter: 'MultiSpaceAllowedForOperators',
133
- alternative: 'If your intention was to allow extra spaces ' \
134
- 'for alignment, please use AllowForAlignment: ' \
135
- 'true instead.'
136
- },
137
- {
138
- cop: 'Style/Encoding',
139
- parameter: 'EnforcedStyle',
140
- alternative: 'Style/Encoding no longer supports styles. ' \
141
- 'The "never" behavior is always assumed.'
142
- },
143
- {
144
- cop: 'Style/Encoding',
145
- parameter: 'SupportedStyles',
146
- alternative: 'Style/Encoding no longer supports styles. ' \
147
- 'The "never" behavior is always assumed.'
148
- },
149
- {
150
- cop: 'Style/Encoding',
151
- parameter: 'AutoCorrectEncodingComment',
152
- alternative: 'Style/Encoding no longer supports styles. ' \
153
- 'The "never" behavior is always assumed.'
154
- },
155
- {
156
- cop: 'Style/IfUnlessModifier',
157
- parameter: 'MaxLineLength',
158
- alternative:
159
- '`Style/IfUnlessModifier: MaxLineLength` has been removed. Use ' \
160
- '`Metrics/LineLength: Max` instead'
161
- },
162
- {
163
- cop: 'Style/SpaceAroundOperators',
164
- parameter: 'MultiSpaceAllowedForOperators',
165
- alternative: 'If your intention was to allow extra spaces ' \
166
- 'for alignment, please use AllowForAlignment: ' \
167
- 'true instead.'
168
- },
169
- {
170
- cop: 'Style/WhileUntilModifier',
171
- parameter: 'MaxLineLength',
172
- alternative:
173
- '`Style/WhileUntilModifier: MaxLineLength` has been removed. Use ' \
174
- '`Metrics/LineLength: Max` instead'
175
- },
176
- {
177
- cop: 'AllCops',
178
- parameter: 'RunRailsCops',
179
- alternative: "Use the following configuration instead:\n" \
180
- "Rails:\n Enabled: true"
181
- },
182
- {
183
- cop: 'Layout/CaseIndentation',
184
- parameter: 'IndentWhenRelativeTo',
185
- alternative: '`IndentWhenRelativeTo` has been renamed to ' \
186
- '`EnforcedStyle`'
187
- },
188
- {
189
- cop: 'Lint/BlockAlignment',
190
- parameter: 'AlignWith',
191
- alternative: '`AlignWith` has been renamed to ' \
192
- '`EnforcedStyleAlignWith`'
193
- },
194
- {
195
- cop: 'Layout/BlockAlignment',
196
- parameter: 'AlignWith',
197
- alternative: '`AlignWith` has been renamed to ' \
198
- '`EnforcedStyleAlignWith`'
199
- },
200
- {
201
- cop: 'Lint/EndAlignment',
202
- parameter: 'AlignWith',
203
- alternative: '`AlignWith` has been renamed to ' \
204
- '`EnforcedStyleAlignWith`'
205
- },
206
- {
207
- cop: 'Layout/EndAlignment',
208
- parameter: 'AlignWith',
209
- alternative: '`AlignWith` has been renamed to ' \
210
- '`EnforcedStyleAlignWith`'
211
- },
212
- {
213
- cop: 'Lint/DefEndAlignment',
214
- parameter: 'AlignWith',
215
- alternative: '`AlignWith` has been renamed to ' \
216
- '`EnforcedStyleAlignWith`'
217
- },
218
- {
219
- cop: 'Layout/DefEndAlignment',
220
- parameter: 'AlignWith',
221
- alternative: '`AlignWith` has been renamed to ' \
222
- '`EnforcedStyleAlignWith`'
223
- },
224
- {
225
- cop: 'Rails/UniqBeforePluck',
226
- parameter: 'EnforcedMode',
227
- alternative: '`EnforcedMode` has been renamed to ' \
228
- '`EnforcedStyle`'
229
- }
230
- ].freeze
231
-
232
- OBSOLETE_ENFORCED_STYLES = [
233
- {
234
- cop: 'Layout/IndentationConsistency',
235
- parameter: 'EnforcedStyle',
236
- enforced_style: 'rails',
237
- alternative: '`EnforcedStyle: rails` has been renamed to ' \
238
- '`EnforcedStyle: indented_internal_methods`'
239
- }
240
- ].freeze
241
-
242
17
  attr_reader :loaded_path
243
18
 
244
19
  def initialize(hash = {}, loaded_path = nil)
@@ -250,6 +25,7 @@ module RuboCop
250
25
  h[cop] = cop_options
251
26
  end
252
27
  @hash = hash
28
+ @validator = ConfigValidator.new(self)
253
29
  end
254
30
 
255
31
  def self.create(hash, path)
@@ -260,54 +36,14 @@ module RuboCop
260
36
  deprecation_check do |deprecation_message|
261
37
  warn("#{loaded_path} - #{deprecation_message}")
262
38
  end
263
- validate
39
+ @validator.validate
264
40
  make_excludes_absolute
265
41
  self
266
42
  end
267
43
 
268
- def [](key)
269
- @hash[key]
270
- end
271
-
272
- def []=(key, value)
273
- @hash[key] = value
274
- end
275
-
276
- def delete(key)
277
- @hash.delete(key)
278
- end
279
-
280
- def each(&block)
281
- @hash.each(&block)
282
- end
283
-
284
- def key?(key)
285
- @hash.key?(key)
286
- end
287
-
288
- def keys
289
- @hash.keys
290
- end
291
-
292
- def each_key(&block)
293
- @hash.each_key(&block)
294
- end
295
-
296
- def map(&block)
297
- @hash.map(&block)
298
- end
299
-
300
- def merge(other_hash)
301
- @hash.merge(other_hash)
302
- end
303
-
304
- def to_h
305
- @hash
306
- end
307
-
308
- def to_hash
309
- @hash
310
- end
44
+ def_delegators :@hash, :[], :[]=, :delete, :each, :key?, :keys, :each_key,
45
+ :map, :merge, :to_h, :to_hash
46
+ def_delegators :@validator, :validate, :target_ruby_version
311
47
 
312
48
  def to_s
313
49
  @to_s ||= @hash.to_s
@@ -319,7 +55,7 @@ module RuboCop
319
55
 
320
56
  def make_excludes_absolute
321
57
  each_key do |key|
322
- validate_section_presence(key)
58
+ @validator.validate_section_presence(key)
323
59
  next unless self[key]['Exclude']
324
60
 
325
61
  self[key]['Exclude'].map! do |exclude_elem|
@@ -364,25 +100,6 @@ module RuboCop
364
100
  @for_all_cops ||= self['AllCops'] || {}
365
101
  end
366
102
 
367
- def validate
368
- # Don't validate RuboCop's own files. Avoids infinite recursion.
369
- base_config_path = File.expand_path(File.join(ConfigLoader::RUBOCOP_HOME,
370
- 'config'))
371
- return if File.expand_path(loaded_path).start_with?(base_config_path)
372
-
373
- valid_cop_names, invalid_cop_names = keys.partition do |key|
374
- ConfigLoader.default_configuration.key?(key)
375
- end
376
-
377
- reject_obsolete_cops_and_parameters
378
- warn_about_unrecognized_cops(invalid_cop_names)
379
- check_target_ruby
380
- validate_parameter_names(valid_cop_names)
381
- validate_enforced_styles(valid_cop_names)
382
- validate_syntax_cop
383
- reject_mutually_exclusive_defaults
384
- end
385
-
386
103
  def file_to_include?(file)
387
104
  relative_file_path = path_relative_to_config(file)
388
105
 
@@ -461,26 +178,6 @@ module RuboCop
461
178
  end
462
179
  end
463
180
 
464
- def target_ruby_version
465
- @target_ruby_version ||= begin
466
- if for_all_cops['TargetRubyVersion']
467
- @target_ruby_version_source = :rubocop_yml
468
-
469
- for_all_cops['TargetRubyVersion'].to_f
470
- elsif target_ruby_version_from_version_file
471
- @target_ruby_version_source = :ruby_version_file
472
-
473
- target_ruby_version_from_version_file
474
- elsif target_ruby_version_from_bundler_lock_file
475
- @target_ruby_version_source = :bundler_lock_file
476
-
477
- target_ruby_version_from_bundler_lock_file
478
- else
479
- DEFAULT_RUBY_VERSION
480
- end
481
- end
482
- end
483
-
484
181
  def target_rails_version
485
182
  @target_rails_version ||=
486
183
  if for_all_cops['TargetRailsVersion']
@@ -492,214 +189,22 @@ module RuboCop
492
189
  end
493
190
  end
494
191
 
495
- private
496
-
497
- def warn_about_unrecognized_cops(invalid_cop_names)
498
- invalid_cop_names.each do |name|
499
- # There could be a custom cop with this name. If so, don't warn
500
- next if Cop::Cop.registry.contains_cop_matching?([name])
501
-
502
- # Special case for inherit_mode, which is a directive that we keep in
503
- # the configuration (even though it's not a cop), because it's easier
504
- # to do so than to pass the value around to various methods.
505
- next if name == 'inherit_mode'
506
-
507
- warn Rainbow("Warning: unrecognized cop #{name} found in " \
508
- "#{smart_loaded_path}").yellow
509
- end
510
- end
511
-
512
- def validate_syntax_cop
513
- syntax_config = self['Lint/Syntax']
514
- default_config = ConfigLoader.default_configuration['Lint/Syntax']
515
-
516
- return unless syntax_config &&
517
- default_config.merge(syntax_config) != default_config
518
-
519
- raise ValidationError,
520
- "configuration for Syntax cop found in #{smart_loaded_path}\n" \
521
- 'It\'s not possible to disable this cop.'
522
- end
523
-
524
- def validate_section_presence(name)
525
- return unless key?(name) && self[name].nil?
526
-
527
- raise ValidationError,
528
- "empty section #{name} found in #{smart_loaded_path}"
529
- end
530
-
531
- def validate_parameter_names(valid_cop_names)
532
- valid_cop_names.each do |name|
533
- validate_section_presence(name)
534
- default_config = ConfigLoader.default_configuration[name]
535
-
536
- self[name].each_key do |param|
537
- next if COMMON_PARAMS.include?(param) || default_config.key?(param)
538
-
539
- message =
540
- "Warning: #{name} does not support #{param} parameter.\n\n" \
541
- "Supported parameters are:\n\n" \
542
- " - #{(default_config.keys - INTERNAL_PARAMS).join("\n - ")}\n"
543
-
544
- warn Rainbow(message).yellow.to_s
545
- end
546
- end
547
- end
548
-
549
- def validate_enforced_styles(valid_cop_names)
550
- valid_cop_names.each do |name|
551
- styles = self[name].select { |key, _| key.start_with?('Enforced') }
552
-
553
- styles.each do |style_name, style|
554
- supported_key = RuboCop::Cop::Util.to_supported_styles(style_name)
555
- valid = ConfigLoader.default_configuration[name][supported_key]
556
-
557
- next unless valid
558
- next if valid.include?(style)
559
- next if validate_support_and_has_list(name, style, valid)
560
-
561
- msg = "invalid #{style_name} '#{style}' for #{name} found in " \
562
- "#{smart_loaded_path}\n" \
563
- "Valid choices are: #{valid.join(', ')}"
564
- raise ValidationError, msg
565
- end
566
- end
567
- end
568
-
569
- def validate_support_and_has_list(name, formats, valid)
570
- ConfigLoader.default_configuration[name]['AllowMultipleStyles'] &&
571
- formats.is_a?(Array) &&
572
- formats.all? { |format| valid.include?(format) }
573
- end
574
-
575
- def reject_obsolete_cops_and_parameters
576
- messages = [
577
- obsolete_cops,
578
- obsolete_parameters,
579
- obsolete_enforced_style
580
- ].flatten.compact
581
- return if messages.empty?
582
-
583
- raise ValidationError, messages.join("\n")
584
- end
585
-
586
- def obsolete_parameters
587
- OBSOLETE_PARAMETERS.map do |params|
588
- obsolete_parameter_message(params[:cop], params[:parameter],
589
- params[:alternative])
590
- end
591
- end
592
-
593
- def obsolete_parameter_message(cop, parameter, alternative)
594
- return unless self[cop]&.key?(parameter)
595
-
596
- "obsolete parameter #{parameter} (for #{cop}) " \
597
- "found in #{smart_loaded_path}" \
598
- "\n#{alternative}"
599
- end
600
-
601
- def obsolete_cops
602
- OBSOLETE_COPS.map do |cop_name, message|
603
- next unless key?(cop_name) || key?(Cop::Badge.parse(cop_name).cop_name)
604
-
605
- message + "\n(obsolete configuration found in #{smart_loaded_path}," \
606
- ' please update it)'
607
- end
608
- end
609
-
610
- def obsolete_enforced_style
611
- OBSOLETE_ENFORCED_STYLES.map do |params|
612
- obsolete_enforced_style_message(params[:cop], params[:parameter],
613
- params[:enforced_style],
614
- params[:alternative])
615
- end
616
- end
617
-
618
- def obsolete_enforced_style_message(cop, param, enforced_style, alternative)
619
- style = self[cop]&.detect { |key, _| key.start_with?(param) }
620
-
621
- return unless style && style[1] == enforced_style
622
-
623
- "obsolete `#{param}: #{enforced_style}` (for #{cop}) " \
624
- "found in #{smart_loaded_path}" \
625
- "\n#{alternative}"
192
+ def smart_loaded_path
193
+ PathUtil.smart_path(@loaded_path)
626
194
  end
627
195
 
628
- def check_target_ruby
629
- return if KNOWN_RUBIES.include?(target_ruby_version)
630
-
631
- msg = if OBSOLETE_RUBIES.include?(target_ruby_version)
632
- "RuboCop found unsupported Ruby version #{target_ruby_version} " \
633
- "in #{target_ruby_source}. #{target_ruby_version}-compatible " \
634
- 'analysis was dropped after version ' \
635
- "#{OBSOLETE_RUBIES[target_ruby_version]}."
636
- else
637
- 'RuboCop found unknown Ruby version ' \
638
- "#{target_ruby_version.inspect} in #{target_ruby_source}."
639
- end
640
-
641
- msg += "\nSupported versions: #{KNOWN_RUBIES.join(', ')}"
642
-
643
- raise ValidationError, msg
644
- end
196
+ def bundler_lock_file_path
197
+ return nil unless loaded_path
645
198
 
646
- def target_ruby_source
647
- case @target_ruby_version_source
648
- when :ruby_version_file
649
- "`#{RUBY_VERSION_FILENAME}`"
650
- when :bundler_lock_file
651
- "`#{bundler_lock_file_path}`"
652
- when :rubocop_yml
653
- "`TargetRubyVersion` parameter (in #{smart_loaded_path})"
199
+ base_path = base_dir_for_path_parameters
200
+ ['gems.locked', 'Gemfile.lock'].each do |file_name|
201
+ path = find_file_upwards(file_name, base_path)
202
+ return path if path
654
203
  end
204
+ nil
655
205
  end
656
206
 
657
- def ruby_version_file
658
- @ruby_version_file ||=
659
- find_file_upwards(RUBY_VERSION_FILENAME, base_dir_for_path_parameters)
660
- end
661
-
662
- def target_ruby_version_from_version_file
663
- file = ruby_version_file
664
- return unless file && File.file?(file)
665
-
666
- @target_ruby_version_from_version_file ||=
667
- File.read(file).match(/\A(ruby-)?(?<version>\d+\.\d+)/) do |md|
668
- md[:version].to_f
669
- end
670
- end
671
-
672
- def target_ruby_version_from_bundler_lock_file
673
- @target_ruby_version_from_bundler_lock_file ||=
674
- read_ruby_version_from_bundler_lock_file
675
- end
676
-
677
- def read_ruby_version_from_bundler_lock_file
678
- lock_file_path = bundler_lock_file_path
679
- return nil unless lock_file_path
680
-
681
- in_ruby_section = false
682
- File.foreach(lock_file_path) do |line|
683
- # If ruby is in Gemfile.lock or gems.lock, there should be two lines
684
- # towards the bottom of the file that look like:
685
- # RUBY VERSION
686
- # ruby W.X.YpZ
687
- # We ultimately want to match the "ruby W.X.Y.pZ" line, but there's
688
- # extra logic to make sure we only start looking once we've seen the
689
- # "RUBY VERSION" line.
690
- in_ruby_section ||= line.match(/^\s*RUBY\s*VERSION\s*$/)
691
- next unless in_ruby_section
692
-
693
- # We currently only allow this feature to work with MRI ruby. If jruby
694
- # (or something else) is used by the project, it's lock file will have a
695
- # line that looks like:
696
- # RUBY VERSION
697
- # ruby W.X.YpZ (jruby x.x.x.x)
698
- # The regex won't match in this situation.
699
- result = line.match(/^\s*ruby\s+(\d+\.\d+)[p.\d]*\s*$/)
700
- return result.captures.first.to_f if result
701
- end
702
- end
207
+ private
703
208
 
704
209
  def target_rails_version_from_bundler_lock_file
705
210
  @target_rails_version_from_bundler_lock_file ||=
@@ -718,26 +223,6 @@ module RuboCop
718
223
  end
719
224
  end
720
225
 
721
- def bundler_lock_file_path
722
- return nil unless loaded_path
723
-
724
- base_path = base_dir_for_path_parameters
725
- ['gems.locked', 'Gemfile.lock'].each do |file_name|
726
- path = find_file_upwards(file_name, base_path)
727
- return path if path
728
- end
729
- nil
730
- end
731
-
732
- def reject_mutually_exclusive_defaults
733
- disabled_by_default = for_all_cops['DisabledByDefault']
734
- enabled_by_default = for_all_cops['EnabledByDefault']
735
- return unless disabled_by_default && enabled_by_default
736
-
737
- msg = 'Cops cannot be both enabled by default and disabled by default'
738
- raise ValidationError, msg
739
- end
740
-
741
226
  def enable_cop?(qualified_cop_name, cop_options)
742
227
  cop_department, cop_name = qualified_cop_name.split('/')
743
228
  department = cop_name.nil?
@@ -751,10 +236,5 @@ module RuboCop
751
236
 
752
237
  cop_options.fetch('Enabled') { !for_all_cops['DisabledByDefault'] }
753
238
  end
754
-
755
- def smart_loaded_path
756
- PathUtil.smart_path(@loaded_path)
757
- end
758
239
  end
759
- # rubocop:enable Metrics/ClassLength
760
240
  end