rubocop 1.32.0 → 1.34.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/config/default.yml +51 -16
  4. data/config/obsoletion.yml +23 -1
  5. data/lib/rubocop/cache_config.rb +29 -0
  6. data/lib/rubocop/cli/command/auto_genenerate_config.rb +2 -2
  7. data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
  8. data/lib/rubocop/cli/command/suggest_extensions.rb +53 -15
  9. data/lib/rubocop/config_finder.rb +68 -0
  10. data/lib/rubocop/config_loader.rb +12 -40
  11. data/lib/rubocop/config_loader_resolver.rb +1 -5
  12. data/lib/rubocop/config_obsoletion/changed_parameter.rb +5 -0
  13. data/lib/rubocop/config_obsoletion/parameter_rule.rb +4 -0
  14. data/lib/rubocop/config_obsoletion.rb +7 -2
  15. data/lib/rubocop/cop/cop.rb +1 -1
  16. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +28 -0
  17. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +61 -0
  18. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  19. data/lib/rubocop/cop/layout/block_end_newline.rb +33 -5
  20. data/lib/rubocop/cop/layout/first_argument_indentation.rb +6 -1
  21. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
  22. data/lib/rubocop/cop/legacy/corrections_proxy.rb +1 -1
  23. data/lib/rubocop/cop/legacy/corrector.rb +1 -1
  24. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +21 -8
  25. data/lib/rubocop/cop/lint/debugger.rb +26 -16
  26. data/lib/rubocop/cop/lint/empty_conditional_body.rb +65 -1
  27. data/lib/rubocop/cop/lint/number_conversion.rb +24 -8
  28. data/lib/rubocop/cop/lint/shadowed_exception.rb +15 -0
  29. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +9 -1
  30. data/lib/rubocop/cop/metrics/abc_size.rb +3 -1
  31. data/lib/rubocop/cop/metrics/block_length.rb +6 -7
  32. data/lib/rubocop/cop/metrics/method_length.rb +8 -8
  33. data/lib/rubocop/cop/mixin/allowed_methods.rb +15 -1
  34. data/lib/rubocop/cop/mixin/allowed_pattern.rb +9 -1
  35. data/lib/rubocop/cop/mixin/comments_help.rb +5 -1
  36. data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -1
  37. data/lib/rubocop/cop/mixin/method_complexity.rb +4 -9
  38. data/lib/rubocop/cop/mixin/range_help.rb +2 -2
  39. data/lib/rubocop/cop/naming/predicate_name.rb +24 -3
  40. data/lib/rubocop/cop/style/block_delimiters.rb +26 -7
  41. data/lib/rubocop/cop/style/class_and_module_children.rb +4 -4
  42. data/lib/rubocop/cop/style/class_equality_comparison.rb +32 -7
  43. data/lib/rubocop/cop/style/double_negation.rb +2 -0
  44. data/lib/rubocop/cop/style/empty_heredoc.rb +15 -1
  45. data/lib/rubocop/cop/style/format_string_token.rb +21 -8
  46. data/lib/rubocop/cop/style/hash_except.rb +0 -4
  47. data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -1
  48. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -1
  49. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -7
  50. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -6
  51. data/lib/rubocop/cop/style/numeric_literals.rb +16 -1
  52. data/lib/rubocop/cop/style/numeric_predicate.rb +28 -8
  53. data/lib/rubocop/cop/style/redundant_condition.rb +19 -4
  54. data/lib/rubocop/cop/style/redundant_parentheses.rb +15 -22
  55. data/lib/rubocop/cop/style/redundant_sort.rb +21 -6
  56. data/lib/rubocop/cop/style/sole_nested_conditional.rb +14 -3
  57. data/lib/rubocop/cop/style/symbol_proc.rb +34 -9
  58. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -13
  59. data/lib/rubocop/ext/range.rb +15 -0
  60. data/lib/rubocop/feature_loader.rb +90 -0
  61. data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
  62. data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
  63. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  64. data/lib/rubocop/formatter/markdown_formatter.rb +1 -1
  65. data/lib/rubocop/formatter/tap_formatter.rb +1 -1
  66. data/lib/rubocop/result_cache.rb +22 -20
  67. data/lib/rubocop/server/cache.rb +33 -1
  68. data/lib/rubocop/server/cli.rb +19 -2
  69. data/lib/rubocop/version.rb +1 -1
  70. data/lib/rubocop.rb +2 -1
  71. metadata +13 -9
  72. data/lib/rubocop/cop/mixin/ignored_methods.rb +0 -52
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 270faf06487f8a915ef6293944db136da6fb51ec09b5613be4b848a471c858bb
4
- data.tar.gz: 1c61746959019453862c2e90b8d3250ce3f9815b1eae286f1fd5b73fb267a1cb
3
+ metadata.gz: 11dc3da37672d6576b483ea0d39db975af0044d4c960fa14944fadac1d6f5bd5
4
+ data.tar.gz: e37200a88a516b923c5c86149de704eec9147f8f35a96df30ced1a0892be8ab4
5
5
  SHA512:
6
- metadata.gz: 86966e7ff42d0f514a447c8313cc9bdc13020ec1d375e584dba8ebae5bb535a1238380a57d55dfd697c735b3f9259f59939563f4b504f08570304e4ec1c2c7af
7
- data.tar.gz: ce35c98b8b51b8b59c6c2aeac880a0618067a68f7080a2e44408a7e283471b2b57f84e57c127144632b61eaa8edf6e4369d4702c2baa222cb3b37fad38606bd5
6
+ metadata.gz: 42deab573616fd15dfee978f2009b2dafc17b4bb0cf7528c0e0a26f415bad22ede108980403c6036b0b84d28b72981b3862b915a608495bc368935c1bc1ea18b
7
+ data.tar.gz: 5afa69eeccbcf3ead2bb51f2feaf4dcd81420fa08b0b17b372909647d7b4b559fe1d76d376fec271c7b9d2e8f1ee1cb586075d9a461d5894c1263854fa6f2eea
data/README.md CHANGED
@@ -46,14 +46,14 @@ If you'd rather install RuboCop using `bundler`, add a line for it in your `Gemf
46
46
  gem 'rubocop', require: false
47
47
  ```
48
48
 
49
- RuboCop is stable between major versions, both in terms of API and cop configuration.
49
+ RuboCop is stable between minor versions, both in terms of API and cop configuration.
50
50
  We aim to ease the maintenance of RuboCop extensions and the upgrades between RuboCop
51
51
  releases. All big changes are reserved for major releases.
52
52
  To prevent an unwanted RuboCop update you might want to use a conservative version lock
53
53
  in your `Gemfile`:
54
54
 
55
55
  ```rb
56
- gem 'rubocop', '~> 1.32', require: false
56
+ gem 'rubocop', '~> 1.34', require: false
57
57
  ```
58
58
 
59
59
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -1502,7 +1502,9 @@ Lint/AmbiguousBlockAssociation:
1502
1502
  Enabled: true
1503
1503
  VersionAdded: '0.48'
1504
1504
  VersionChanged: '1.13'
1505
- IgnoredMethods: []
1505
+ AllowedMethods: []
1506
+ AllowedPatterns: []
1507
+ IgnoredMethods: [] # deprecated
1506
1508
 
1507
1509
  Lint/AmbiguousOperator:
1508
1510
  Description: >-
@@ -1602,6 +1604,7 @@ Lint/Debugger:
1602
1604
  # a user's configuration, but are otherwise not significant.
1603
1605
  Kernel:
1604
1606
  - binding.irb
1607
+ - Kernel.binding.irb
1605
1608
  Byebug:
1606
1609
  - byebug
1607
1610
  - remote_byebug
@@ -1619,6 +1622,9 @@ Lint/Debugger:
1619
1622
  - binding.pry
1620
1623
  - binding.remote_pry
1621
1624
  - binding.pry_remote
1625
+ - Kernel.binding.pry
1626
+ - Kernel.binding.remote_pry
1627
+ - Kernel.binding.pry_remote
1622
1628
  - Pry.rescue
1623
1629
  Rails:
1624
1630
  - debugger
@@ -1751,8 +1757,10 @@ Lint/EmptyClass:
1751
1757
  Lint/EmptyConditionalBody:
1752
1758
  Description: 'Checks for the presence of `if`, `elsif` and `unless` branches without a body.'
1753
1759
  Enabled: true
1760
+ SafeAutoCorrect: false
1754
1761
  AllowComments: true
1755
1762
  VersionAdded: '0.89'
1763
+ VersionChanged: '1.34'
1756
1764
 
1757
1765
  Lint/EmptyEnsure:
1758
1766
  Description: 'Checks for empty ensure block.'
@@ -1970,6 +1978,7 @@ Lint/NoReturnInBeginEndBlocks:
1970
1978
 
1971
1979
  Lint/NonAtomicFileOperation:
1972
1980
  Description: Checks for non-atomic file operations.
1981
+ StyleGuide: '#atomic-file-operations'
1973
1982
  Enabled: pending
1974
1983
  VersionAdded: '1.31'
1975
1984
  SafeAutoCorrect: false
@@ -1991,7 +2000,9 @@ Lint/NumberConversion:
1991
2000
  VersionAdded: '0.53'
1992
2001
  VersionChanged: '1.1'
1993
2002
  SafeAutoCorrect: false
1994
- IgnoredMethods: []
2003
+ AllowedMethods: []
2004
+ AllowedPatterns: []
2005
+ IgnoredMethods: [] # deprecated
1995
2006
  IgnoredClasses:
1996
2007
  - Time
1997
2008
  - DateTime
@@ -2443,7 +2454,9 @@ Metrics/AbcSize:
2443
2454
  VersionChanged: '1.5'
2444
2455
  # The ABC size is a calculated magnitude, so this number can be an Integer or
2445
2456
  # a Float.
2446
- IgnoredMethods: []
2457
+ AllowedMethods: []
2458
+ AllowedPatterns: []
2459
+ IgnoredMethods: [] # deprecated
2447
2460
  CountRepeatedAttributes: true
2448
2461
  Max: 17
2449
2462
 
@@ -2456,10 +2469,12 @@ Metrics/BlockLength:
2456
2469
  Max: 25
2457
2470
  CountAsOne: []
2458
2471
  ExcludedMethods: [] # deprecated, retained for backwards compatibility
2459
- IgnoredMethods:
2472
+ AllowedMethods:
2460
2473
  # By default, exclude the `#refine` method, as it tends to have larger
2461
2474
  # associated blocks.
2462
2475
  - refine
2476
+ AllowedPatterns: []
2477
+ IgnoredMethods: [] # deprecated
2463
2478
  Exclude:
2464
2479
  - '**/*.gemspec'
2465
2480
 
@@ -2489,7 +2504,9 @@ Metrics/CyclomaticComplexity:
2489
2504
  Enabled: true
2490
2505
  VersionAdded: '0.25'
2491
2506
  VersionChanged: '0.81'
2492
- IgnoredMethods: []
2507
+ AllowedMethods: []
2508
+ AllowedPatterns: []
2509
+ IgnoredMethods: [] # deprecated
2493
2510
  Max: 7
2494
2511
 
2495
2512
  Metrics/MethodLength:
@@ -2502,7 +2519,9 @@ Metrics/MethodLength:
2502
2519
  Max: 10
2503
2520
  CountAsOne: []
2504
2521
  ExcludedMethods: [] # deprecated, retained for backwards compatibility
2505
- IgnoredMethods: []
2522
+ AllowedMethods: []
2523
+ AllowedPatterns: []
2524
+ IgnoredMethods: [] # deprecated
2506
2525
 
2507
2526
  Metrics/ModuleLength:
2508
2527
  Description: 'Avoid modules longer than 100 lines of code.'
@@ -2530,7 +2549,9 @@ Metrics/PerceivedComplexity:
2530
2549
  Enabled: true
2531
2550
  VersionAdded: '0.25'
2532
2551
  VersionChanged: '0.81'
2533
- IgnoredMethods: []
2552
+ AllowedMethods: []
2553
+ AllowedPatterns: []
2554
+ IgnoredMethods: [] # deprecated
2534
2555
  Max: 8
2535
2556
 
2536
2557
  ################## Migration #############################
@@ -3061,7 +3082,7 @@ Style/BlockDelimiters:
3061
3082
  # This looks at the usage of a block's method to determine its type (e.g. is
3062
3083
  # the result of a `map` assigned to a variable or passed to another
3063
3084
  # method) but exceptions are permitted in the `ProceduralMethods`,
3064
- # `FunctionalMethods` and `IgnoredMethods` sections below.
3085
+ # `FunctionalMethods` and `AllowedMethods` sections below.
3065
3086
  - semantic
3066
3087
  # The `braces_for_chaining` style enforces braces around single line blocks
3067
3088
  # and do..end around multi-line blocks, except for multi-line blocks whose
@@ -3102,7 +3123,7 @@ Style/BlockDelimiters:
3102
3123
  - let!
3103
3124
  - subject
3104
3125
  - watch
3105
- IgnoredMethods:
3126
+ AllowedMethods:
3106
3127
  # Methods that can be either procedural or functional and cannot be
3107
3128
  # categorised from their usage alone, e.g.
3108
3129
  #
@@ -3119,6 +3140,8 @@ Style/BlockDelimiters:
3119
3140
  - lambda
3120
3141
  - proc
3121
3142
  - it
3143
+ AllowedPatterns: []
3144
+ IgnoredMethods: [] # deprecated
3122
3145
  # The AllowBracesOnProceduralOneLiners option is ignored unless the
3123
3146
  # EnforcedStyle is set to `semantic`. If so:
3124
3147
  #
@@ -3222,10 +3245,12 @@ Style/ClassEqualityComparison:
3222
3245
  StyleGuide: '#instance-of-vs-class-comparison'
3223
3246
  Enabled: true
3224
3247
  VersionAdded: '0.93'
3225
- IgnoredMethods:
3248
+ AllowedMethods:
3226
3249
  - ==
3227
3250
  - equal?
3228
3251
  - eql?
3252
+ AllowedPatterns: []
3253
+ IgnoredMethods: [] # deprecated
3229
3254
 
3230
3255
  Style/ClassMethods:
3231
3256
  Description: 'Use self when defining module/class methods.'
@@ -3687,7 +3712,9 @@ Style/FormatStringToken:
3687
3712
  MaxUnannotatedPlaceholdersAllowed: 1
3688
3713
  VersionAdded: '0.49'
3689
3714
  VersionChanged: '1.0'
3690
- IgnoredMethods: []
3715
+ AllowedMethods: []
3716
+ AllowedPatterns: []
3717
+ IgnoredMethods: [] # deprecated
3691
3718
 
3692
3719
  Style/FrozenStringLiteralComment:
3693
3720
  Description: >-
@@ -4006,7 +4033,8 @@ Style/MethodCallWithArgsParentheses:
4006
4033
  VersionAdded: '0.47'
4007
4034
  VersionChanged: '1.7'
4008
4035
  IgnoreMacros: true
4009
- IgnoredMethods: []
4036
+ AllowedMethods: []
4037
+ IgnoredMethods: [] # deprecated
4010
4038
  AllowedPatterns: []
4011
4039
  IgnoredPatterns: [] # deprecated
4012
4040
  IncludedMacros: []
@@ -4023,7 +4051,9 @@ Style/MethodCallWithoutArgsParentheses:
4023
4051
  Description: 'Do not use parentheses for method calls with no arguments.'
4024
4052
  StyleGuide: '#method-invocation-parens'
4025
4053
  Enabled: true
4026
- IgnoredMethods: []
4054
+ AllowedMethods: []
4055
+ AllowedPatterns: []
4056
+ IgnoredMethods: [] # deprecated
4027
4057
  VersionAdded: '0.47'
4028
4058
  VersionChanged: '0.55'
4029
4059
 
@@ -4375,6 +4405,7 @@ Style/NumericLiterals:
4375
4405
  Strict: false
4376
4406
  # You can specify allowed numbers. (e.g. port number 3000, 8080, and etc)
4377
4407
  AllowedNumbers: []
4408
+ AllowedPatterns: []
4378
4409
 
4379
4410
  Style/NumericPredicate:
4380
4411
  Description: >-
@@ -4393,7 +4424,9 @@ Style/NumericPredicate:
4393
4424
  SupportedStyles:
4394
4425
  - predicate
4395
4426
  - comparison
4396
- IgnoredMethods: []
4427
+ AllowedMethods: []
4428
+ AllowedPatterns: []
4429
+ IgnoredMethods: [] # deprecated
4397
4430
  # Exclude RSpec specs because assertions like `expect(1).to be > 0` cause
4398
4431
  # false positives.
4399
4432
  Exclude:
@@ -5030,11 +5063,13 @@ Style/SymbolProc:
5030
5063
  VersionAdded: '0.26'
5031
5064
  VersionChanged: '1.28'
5032
5065
  AllowMethodsWithArguments: false
5033
- # A list of method names to be ignored by the check.
5066
+ # A list of method names to be always allowed by the check.
5034
5067
  # The names should be fairly unique, otherwise you'll end up ignoring lots of code.
5035
- IgnoredMethods:
5068
+ AllowedMethods:
5036
5069
  - respond_to
5037
5070
  - define_method
5071
+ AllowedPatterns: []
5072
+ IgnoredMethods: [] # deprecated
5038
5073
  AllowComments: false
5039
5074
 
5040
5075
  Style/TernaryParentheses:
@@ -187,7 +187,9 @@ changed_parameters:
187
187
  - Metrics/BlockLength
188
188
  - Metrics/MethodLength
189
189
  parameters: ExcludedMethods
190
- alternative: IgnoredMethods
190
+ alternatives:
191
+ - AllowedMethods
192
+ - AllowedPatterns
191
193
  severity: warning
192
194
  - cops: Lint/Debugger
193
195
  parameters: DebuggerReceivers
@@ -202,6 +204,26 @@ changed_parameters:
202
204
  parameters: IgnoredPatterns
203
205
  alternative: AllowedPatterns
204
206
  severity: warning
207
+ - cops:
208
+ - Lint/AmbiguousBlockAssociation
209
+ - Lint/NumberConversion
210
+ - Metrics/AbcSize
211
+ - Metrics/BlockLength
212
+ - Metrics/CyclomaticComplexity
213
+ - Metrics/MethodLength
214
+ - Metrics/PerceivedComplexity
215
+ - Style/BlockDelimiters
216
+ - Style/ClassEqualityComparison
217
+ - Style/FormatStringToken
218
+ - Style/MethodCallWithArgsParentheses
219
+ - Style/MethodCallWithoutArgsParentheses
220
+ - Style/NumericPredicate
221
+ - Style/SymbolLiteral
222
+ parameters: IgnoredMethods
223
+ alternatives:
224
+ - AllowedMethods
225
+ - AllowedPatterns
226
+ severity: warning
205
227
 
206
228
  # Enforced styles that have been removed or replaced
207
229
  changed_enforced_styles:
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ # This class represents the cache config of the caching RuboCop runs.
5
+ # @api private
6
+ class CacheConfig
7
+ def self.root_dir
8
+ root = ENV.fetch('RUBOCOP_CACHE_ROOT', nil)
9
+ root ||= yield
10
+ root ||= if ENV.key?('XDG_CACHE_HOME')
11
+ # Include user ID in the path to make sure the user has write
12
+ # access.
13
+ File.join(ENV.fetch('XDG_CACHE_HOME'), Process.uid.to_s)
14
+ else
15
+ # On FreeBSD, the /home path is a symbolic link to /usr/home
16
+ # and the $HOME environment variable returns the /home path.
17
+ #
18
+ # As $HOME is a built-in environment variable, FreeBSD users
19
+ # always get a warning message.
20
+ #
21
+ # To avoid raising warn log messages on FreeBSD, we retrieve
22
+ # the real path of the home folder.
23
+ File.join(File.realpath(Dir.home), '.cache')
24
+ end
25
+
26
+ File.join(root, 'rubocop_cache')
27
+ end
28
+ end
29
+ end
@@ -98,7 +98,7 @@ module RuboCop
98
98
  def add_inheritance_from_auto_generated_file(config_file)
99
99
  file_string = " #{relative_path_to_todo_from_options_config}"
100
100
 
101
- config_file ||= ConfigLoader::DOTFILE
101
+ config_file ||= ConfigFinder::DOTFILE
102
102
 
103
103
  if File.exist?(config_file)
104
104
  files = Array(ConfigLoader.load_yaml_configuration(config_file)['inherit_from'])
@@ -113,7 +113,7 @@ module RuboCop
113
113
  write_config_file(config_file, file_string, rubocop_yml_contents)
114
114
 
115
115
  puts "Added inheritance from `#{relative_path_to_todo_from_options_config}` " \
116
- "in `#{ConfigLoader::DOTFILE}`."
116
+ "in `#{ConfigFinder::DOTFILE}`."
117
117
  end
118
118
 
119
119
  def existing_configuration(config_file)
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # Generate a .rubocop.yml file in the current directory.
7
7
  # @api private
8
8
  class InitDotfile < Base
9
- DOTFILE = ConfigLoader::DOTFILE
9
+ DOTFILE = ConfigFinder::DOTFILE
10
10
 
11
11
  self.command_name = :init
12
12
 
@@ -17,20 +17,10 @@ module RuboCop
17
17
  def run
18
18
  return if skip? || extensions.none?
19
19
 
20
- puts
21
- puts 'Tip: Based on detected gems, the following ' \
22
- 'RuboCop extension libraries might be helpful:'
23
-
24
- extensions.sort.each do |extension|
25
- puts " * #{extension} (https://rubygems.org/gems/#{extension})"
26
- end
20
+ print_install_suggestions if not_installed_extensions.any?
21
+ print_load_suggestions if installed_and_not_loaded_extensions.any?
27
22
 
28
- puts
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):'
32
- puts ' AllCops:'
33
- puts ' SuggestExtensions: false'
23
+ print_opt_out_instruction
34
24
 
35
25
  puts if @options[:display_time]
36
26
  end
@@ -48,15 +38,63 @@ module RuboCop
48
38
  !INCLUDED_FORMATTERS.include?(current_formatter)
49
39
  end
50
40
 
41
+ def print_install_suggestions
42
+ puts
43
+ puts 'Tip: Based on detected gems, the following ' \
44
+ 'RuboCop extension libraries might be helpful:'
45
+
46
+ not_installed_extensions.sort.each do |extension|
47
+ puts " * #{extension} (https://rubygems.org/gems/#{extension})"
48
+ end
49
+ end
50
+
51
+ def print_load_suggestions
52
+ puts
53
+ puts 'The following RuboCop extension libraries are installed but not loaded in config:'
54
+
55
+ installed_and_not_loaded_extensions.sort.each do |extension|
56
+ puts " * #{extension}"
57
+ end
58
+ end
59
+
60
+ def print_opt_out_instruction
61
+ puts
62
+ puts 'You can opt out of this message by adding the following to your config ' \
63
+ '(see https://docs.rubocop.org/rubocop/extensions.html#extension-suggestions ' \
64
+ 'for more options):'
65
+ puts ' AllCops:'
66
+ puts ' SuggestExtensions: false'
67
+ end
68
+
51
69
  def current_formatter
52
70
  @options[:format] || @config_store.for_pwd.for_all_cops['DefaultFormatter'] || 'p'
53
71
  end
54
72
 
55
- def extensions
73
+ def all_extensions
56
74
  return [] unless lockfile.dependencies.any?
57
75
 
58
76
  extensions = @config_store.for_pwd.for_all_cops['SuggestExtensions'] || {}
59
- extensions.select { |_, v| (Array(v) & dependent_gems).any? }.keys - installed_gems
77
+ extensions.select { |_, v| (Array(v) & dependent_gems).any? }.keys
78
+ end
79
+
80
+ def extensions
81
+ not_installed_extensions + installed_and_not_loaded_extensions
82
+ end
83
+
84
+ def installed_extensions
85
+ all_extensions & installed_gems
86
+ end
87
+
88
+ def not_installed_extensions
89
+ all_extensions - installed_gems
90
+ end
91
+
92
+ def loaded_extensions
93
+ @config_store.for_pwd.loaded_features.to_a
94
+ end
95
+
96
+ def installed_and_not_loaded_extensions
97
+ installed_extensions - loaded_extensions
60
98
  end
61
99
 
62
100
  def lockfile
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'file_finder'
4
+
5
+ module RuboCop
6
+ # This class has methods related to finding configuration path.
7
+ # @api private
8
+ class ConfigFinder
9
+ DOTFILE = '.rubocop.yml'
10
+ XDG_CONFIG = 'config.yml'
11
+ RUBOCOP_HOME = File.realpath(File.join(File.dirname(__FILE__), '..', '..'))
12
+ DEFAULT_FILE = File.join(RUBOCOP_HOME, 'config', 'default.yml')
13
+
14
+ class << self
15
+ include FileFinder
16
+
17
+ attr_writer :project_root
18
+
19
+ def find_config_path(target_dir)
20
+ find_project_dotfile(target_dir) || find_user_dotfile || find_user_xdg_config ||
21
+ DEFAULT_FILE
22
+ end
23
+
24
+ # Returns the path RuboCop inferred as the root of the project. No file
25
+ # searches will go past this directory.
26
+ def project_root
27
+ @project_root ||= find_project_root
28
+ end
29
+
30
+ private
31
+
32
+ def find_project_root
33
+ pwd = Dir.pwd
34
+ gems_file = find_last_file_upwards('Gemfile', pwd) || find_last_file_upwards('gems.rb', pwd)
35
+ return unless gems_file
36
+
37
+ File.dirname(gems_file)
38
+ end
39
+
40
+ def find_project_dotfile(target_dir)
41
+ find_file_upwards(DOTFILE, target_dir, project_root)
42
+ end
43
+
44
+ def find_user_dotfile
45
+ return unless ENV.key?('HOME')
46
+
47
+ file = File.join(Dir.home, DOTFILE)
48
+
49
+ return file if File.exist?(file)
50
+ end
51
+
52
+ def find_user_xdg_config
53
+ xdg_config_home = expand_path(ENV.fetch('XDG_CONFIG_HOME', '~/.config'))
54
+ xdg_config = File.join(xdg_config_home, 'rubocop', XDG_CONFIG)
55
+
56
+ return xdg_config if File.exist?(xdg_config)
57
+ end
58
+
59
+ def expand_path(path)
60
+ File.expand_path(path)
61
+ rescue ArgumentError
62
+ # Could happen because HOME or ID could not be determined. Fall back on
63
+ # using the path literally in that case.
64
+ path
65
+ end
66
+ end
67
+ end
68
+ end
@@ -3,6 +3,7 @@
3
3
  require 'erb'
4
4
  require 'yaml'
5
5
  require 'pathname'
6
+ require_relative 'config_finder'
6
7
 
7
8
  module RuboCop
8
9
  # Raised when a RuboCop configuration file is not found.
@@ -15,8 +16,7 @@ module RuboCop
15
16
  # during a run of the rubocop program, if files in several
16
17
  # directories are inspected.
17
18
  class ConfigLoader
18
- DOTFILE = '.rubocop.yml'
19
- XDG_CONFIG = 'config.yml'
19
+ DOTFILE = ConfigFinder::DOTFILE
20
20
  RUBOCOP_HOME = File.realpath(File.join(File.dirname(__FILE__), '..', '..'))
21
21
  DEFAULT_FILE = File.join(RUBOCOP_HOME, 'config', 'default.yml')
22
22
 
@@ -25,7 +25,7 @@ module RuboCop
25
25
 
26
26
  attr_accessor :debug, :ignore_parent_exclusion, :disable_pending_cops, :enable_pending_cops,
27
27
  :ignore_unrecognized_cops
28
- attr_writer :default_configuration, :project_root
28
+ attr_writer :default_configuration
29
29
  attr_reader :loaded_features
30
30
 
31
31
  alias debug? debug
@@ -95,8 +95,7 @@ module RuboCop
95
95
  # user's home directory is checked. If there's no .rubocop.yml
96
96
  # there either, the path to the default file is returned.
97
97
  def configuration_file_for(target_dir)
98
- find_project_dotfile(target_dir) || find_user_dotfile ||
99
- find_user_xdg_config || DEFAULT_FILE
98
+ ConfigFinder.find_config_path(target_dir)
100
99
  end
101
100
 
102
101
  def configuration_from_file(config_file, check: true)
@@ -122,7 +121,7 @@ module RuboCop
122
121
  end
123
122
 
124
123
  def add_excludes_from_files(config, config_file)
125
- exclusion_file = find_last_file_upwards(DOTFILE, config_file, project_root)
124
+ exclusion_file = find_last_file_upwards(DOTFILE, config_file, ConfigFinder.project_root)
126
125
 
127
126
  return unless exclusion_file
128
127
  return if PathUtil.relative_path(exclusion_file) == PathUtil.relative_path(config_file)
@@ -140,8 +139,14 @@ module RuboCop
140
139
 
141
140
  # Returns the path RuboCop inferred as the root of the project. No file
142
141
  # searches will go past this directory.
142
+ # @deprecated Use `RuboCop::ConfigFinder.project_root` instead.
143
143
  def project_root
144
- @project_root ||= find_project_root
144
+ warn Rainbow(<<~WARNING).yellow
145
+ `RuboCop::ConfigLoader.project_root` is deprecated and will be removed in RuboCop 2.0. \
146
+ Use `RuboCop::ConfigFinder.project_root` instead.
147
+ WARNING
148
+
149
+ ConfigFinder.project_root
145
150
  end
146
151
 
147
152
  PENDING_BANNER = <<~BANNER
@@ -187,39 +192,6 @@ module RuboCop
187
192
  File.absolute_path(file.is_a?(RemoteConfig) ? file.file : file)
188
193
  end
189
194
 
190
- def find_project_dotfile(target_dir)
191
- find_file_upwards(DOTFILE, target_dir, project_root)
192
- end
193
-
194
- def find_project_root
195
- pwd = Dir.pwd
196
- gems_file = find_last_file_upwards('Gemfile', pwd) || find_last_file_upwards('gems.rb', pwd)
197
- return unless gems_file
198
-
199
- File.dirname(gems_file)
200
- end
201
-
202
- def find_user_dotfile
203
- return unless ENV.key?('HOME')
204
-
205
- file = File.join(Dir.home, DOTFILE)
206
- return file if File.exist?(file)
207
- end
208
-
209
- def find_user_xdg_config
210
- xdg_config_home = expand_path(ENV.fetch('XDG_CONFIG_HOME', '~/.config'))
211
- xdg_config = File.join(xdg_config_home, 'rubocop', XDG_CONFIG)
212
- return xdg_config if File.exist?(xdg_config)
213
- end
214
-
215
- def expand_path(path)
216
- File.expand_path(path)
217
- rescue ArgumentError
218
- # Could happen because HOME or ID could not be determined. Fall back on
219
- # using the path literally in that case.
220
- path
221
- end
222
-
223
195
  def resolver
224
196
  @resolver ||= ConfigLoaderResolver.new
225
197
  end
@@ -11,11 +11,7 @@ module RuboCop
11
11
  config_dir = File.dirname(path)
12
12
  hash.delete('require').tap do |loaded_features|
13
13
  Array(loaded_features).each do |feature|
14
- if feature.start_with?('.')
15
- require(File.join(config_dir, feature))
16
- else
17
- require(feature)
18
- end
14
+ FeatureLoader.load(config_directory_path: config_dir, feature: feature)
19
15
  end
20
16
  end
21
17
  end
@@ -12,6 +12,11 @@ module RuboCop
12
12
 
13
13
  if alternative
14
14
  "#{base}\n`#{parameter}` has been renamed to `#{alternative.chomp}`."
15
+ elsif alternatives
16
+ "#{base}\n`#{parameter}` has been renamed to #{to_sentence(alternatives.map do |item|
17
+ "`#{item}`"
18
+ end,
19
+ connector: 'and/or')}."
15
20
  else
16
21
  "#{base}\n#{reason.chomp}"
17
22
  end
@@ -32,6 +32,10 @@ module RuboCop
32
32
  metadata['alternative']
33
33
  end
34
34
 
35
+ def alternatives
36
+ metadata['alternatives']
37
+ end
38
+
35
39
  def reason
36
40
  metadata['reason']
37
41
  end
@@ -47,10 +47,15 @@ module RuboCop
47
47
 
48
48
  # Default rules for obsoletions are in config/obsoletion.yml
49
49
  # Additional rules files can be added with `RuboCop::ConfigObsoletion.files << filename`
50
- def load_rules
50
+ def load_rules # rubocop:disable Metrics/AbcSize
51
51
  rules = self.class.files.each_with_object({}) do |filename, hash|
52
52
  hash.merge!(YAML.safe_load(File.read(filename))) do |_key, first, second|
53
- first.merge(second)
53
+ case first
54
+ when Hash
55
+ first.merge(second)
56
+ when Array
57
+ first.concat(second)
58
+ end
54
59
  end
55
60
  end
56
61
 
@@ -7,7 +7,7 @@ module RuboCop
7
7
  module Cop
8
8
  # @deprecated Use Cop::Base instead
9
9
  # Legacy scaffold for Cops.
10
- # See https://docs.rubocop.org/rubocop/cop_api_v1_changelog.html
10
+ # See https://docs.rubocop.org/rubocop/v1_upgrade_notes.html
11
11
  class Cop < Base
12
12
  attr_reader :offenses
13
13