rubocop 1.39.0 → 1.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +65 -9
  4. data/exe/rubocop +1 -1
  5. data/lib/rubocop/comment_config.rb +5 -0
  6. data/lib/rubocop/config.rb +33 -9
  7. data/lib/rubocop/config_loader.rb +14 -5
  8. data/lib/rubocop/config_loader_resolver.rb +1 -1
  9. data/lib/rubocop/config_validator.rb +1 -1
  10. data/lib/rubocop/cop/badge.rb +9 -4
  11. data/lib/rubocop/cop/base.rb +26 -17
  12. data/lib/rubocop/cop/commissioner.rb +8 -3
  13. data/lib/rubocop/cop/cop.rb +1 -1
  14. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +22 -6
  15. data/lib/rubocop/cop/internal_affairs/cop_description.rb +3 -1
  16. data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
  17. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  18. data/lib/rubocop/cop/layout/empty_lines.rb +2 -0
  19. data/lib/rubocop/cop/layout/extra_spacing.rb +10 -6
  20. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +38 -2
  21. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +49 -2
  22. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +61 -2
  23. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +52 -2
  24. data/lib/rubocop/cop/layout/indentation_style.rb +3 -1
  25. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +5 -0
  26. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  27. data/lib/rubocop/cop/layout/line_length.rb +2 -0
  28. data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +51 -2
  29. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +49 -2
  30. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +53 -2
  31. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +58 -2
  32. data/lib/rubocop/cop/layout/redundant_line_break.rb +2 -2
  33. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +1 -1
  34. data/lib/rubocop/cop/layout/trailing_whitespace.rb +6 -2
  35. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  36. data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
  37. data/lib/rubocop/cop/lint/constant_resolution.rb +4 -0
  38. data/lib/rubocop/cop/lint/debugger.rb +3 -1
  39. data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
  40. data/lib/rubocop/cop/lint/duplicate_branch.rb +0 -2
  41. data/lib/rubocop/cop/lint/duplicate_methods.rb +19 -8
  42. data/lib/rubocop/cop/lint/empty_block.rb +1 -5
  43. data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
  44. data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
  45. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -5
  46. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -0
  47. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +13 -3
  48. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  49. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +10 -12
  50. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -4
  51. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +4 -3
  52. data/lib/rubocop/cop/lint/void.rb +6 -6
  53. data/lib/rubocop/cop/metrics/block_length.rb +9 -4
  54. data/lib/rubocop/cop/metrics/class_length.rb +10 -5
  55. data/lib/rubocop/cop/metrics/method_length.rb +9 -4
  56. data/lib/rubocop/cop/metrics/module_length.rb +10 -5
  57. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +6 -3
  58. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  59. data/lib/rubocop/cop/mixin/allowed_identifiers.rb +2 -2
  60. data/lib/rubocop/cop/mixin/annotation_comment.rb +13 -6
  61. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +21 -9
  62. data/lib/rubocop/cop/mixin/first_element_line_break.rb +11 -7
  63. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +28 -5
  64. data/lib/rubocop/cop/mixin/line_length_help.rb +8 -1
  65. data/lib/rubocop/cop/mixin/method_complexity.rb +5 -3
  66. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +5 -3
  67. data/lib/rubocop/cop/mixin/percent_array.rb +3 -5
  68. data/lib/rubocop/cop/mixin/require_library.rb +2 -0
  69. data/lib/rubocop/cop/mixin/rescue_node.rb +3 -3
  70. data/lib/rubocop/cop/mixin/statement_modifier.rb +15 -1
  71. data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +2 -0
  72. data/lib/rubocop/cop/naming/inclusive_language.rb +4 -1
  73. data/lib/rubocop/cop/registry.rb +29 -14
  74. data/lib/rubocop/cop/style/array_intersect.rb +111 -0
  75. data/lib/rubocop/cop/style/concat_array_literals.rb +66 -0
  76. data/lib/rubocop/cop/style/documentation.rb +1 -1
  77. data/lib/rubocop/cop/style/guard_clause.rb +36 -5
  78. data/lib/rubocop/cop/style/if_with_semicolon.rb +4 -4
  79. data/lib/rubocop/cop/style/inverse_methods.rb +2 -0
  80. data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -1
  81. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  82. data/lib/rubocop/cop/style/redundant_argument.rb +3 -0
  83. data/lib/rubocop/cop/style/redundant_constant_base.rb +85 -0
  84. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +39 -0
  85. data/lib/rubocop/cop/style/redundant_return.rb +7 -0
  86. data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
  87. data/lib/rubocop/cop/style/require_order.rb +140 -0
  88. data/lib/rubocop/cop/style/safe_navigation.rb +35 -6
  89. data/lib/rubocop/cop/style/select_by_regexp.rb +8 -4
  90. data/lib/rubocop/cop/style/semicolon.rb +2 -1
  91. data/lib/rubocop/cop/style/string_literals.rb +1 -5
  92. data/lib/rubocop/cop/style/symbol_proc.rb +2 -4
  93. data/lib/rubocop/cop/team.rb +1 -1
  94. data/lib/rubocop/cop/util.rb +32 -5
  95. data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
  96. data/lib/rubocop/cop/variable_force.rb +20 -29
  97. data/lib/rubocop/cops_documentation_generator.rb +22 -3
  98. data/lib/rubocop/directive_comment.rb +1 -1
  99. data/lib/rubocop/file_patterns.rb +43 -0
  100. data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
  101. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  102. data/lib/rubocop/formatter.rb +3 -1
  103. data/lib/rubocop/options.rb +8 -0
  104. data/lib/rubocop/path_util.rb +34 -16
  105. data/lib/rubocop/result_cache.rb +1 -1
  106. data/lib/rubocop/rspec/cop_helper.rb +4 -1
  107. data/lib/rubocop/rspec/support.rb +2 -2
  108. data/lib/rubocop/server/core.rb +1 -1
  109. data/lib/rubocop/target_finder.rb +1 -1
  110. data/lib/rubocop/target_ruby.rb +1 -1
  111. data/lib/rubocop/version.rb +1 -1
  112. data/lib/rubocop.rb +16 -6
  113. metadata +10 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 881807be0f0f6eea20bd13bd8f08fdb158a5b155c8d3a22fd748683a68c1fef1
4
- data.tar.gz: 2a8e7d4b02f1ba468e02a4c20f8e3b830ce2a1d8ff0210f86aaeafab597c8c88
3
+ metadata.gz: 77b5fe782c4a109e75c380273e08f38b9c61eb519f11f19a606a380080f1f0a2
4
+ data.tar.gz: fa67b5a3f120d6f1538963f9ddbc8bd0508b7f54763bd7c76da725054c9e0459
5
5
  SHA512:
6
- metadata.gz: 11ea36bec754b07912e06b5481f964d10a6dbf5bfd56f99d8a8842ca46d56ae03a342a283d843336f977760c28a697ee995aa98268254a55b1218fa57a9fb5c7
7
- data.tar.gz: b5096cb4589d9bafdab0b6ab409ea9e7841dc06b274aeb7f7d5a26e703cb216c2a428d695fb2a087637467f1cdd5ac005398c66ee3e7d28d49cb4b203a87667d
6
+ metadata.gz: 1475ad1af84e34c10ccf4905247b6e1090e0bd2969d6eb5ef2c4f4dec116841d438b42c5f4c84678870ffac0703f663e1f1ea79ce588b74caca27162f5ad6c07
7
+ data.tar.gz: 267189e76baac7ebc2632d3249957987ba9a3db3df26fa1bf7abe4510a7f9baf8cf5bec399b024d1e900accd1b55f2a5c72e8ab3686d1edc656272ef9723bdaf
data/README.md CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
53
53
  in your `Gemfile`:
54
54
 
55
55
  ```rb
56
- gem 'rubocop', '~> 1.39', require: false
56
+ gem 'rubocop', '~> 1.41', 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
@@ -161,7 +161,9 @@ AllCops:
161
161
  Bundler/DuplicatedGem:
162
162
  Description: 'Checks for duplicate gem entries in Gemfile.'
163
163
  Enabled: true
164
+ Severity: warning
164
165
  VersionAdded: '0.46'
166
+ VersionChanged: '1.40'
165
167
  Include:
166
168
  - '**/*.gemfile'
167
169
  - '**/Gemfile'
@@ -213,7 +215,9 @@ Bundler/InsecureProtocolSource:
213
215
  because HTTP requests are insecure. Please change your source to
214
216
  'https://rubygems.org' if possible, or 'http://rubygems.org' if not.
215
217
  Enabled: true
218
+ Severity: warning
216
219
  VersionAdded: '0.50'
220
+ VersionChanged: '1.40'
217
221
  AllowHttpProtocol: true
218
222
  Include:
219
223
  - '**/*.gemfile'
@@ -252,14 +256,18 @@ Gemspec/DependencyVersion:
252
256
  Gemspec/DeprecatedAttributeAssignment:
253
257
  Description: Checks that deprecated attribute assignments are not set in a gemspec file.
254
258
  Enabled: pending
259
+ Severity: warning
255
260
  VersionAdded: '1.30'
261
+ VersionChanged: '1.40'
256
262
  Include:
257
263
  - '**/*.gemspec'
258
264
 
259
265
  Gemspec/DuplicatedAssignment:
260
266
  Description: 'An attribute assignment method calls should be listed only once in a gemspec.'
261
267
  Enabled: true
268
+ Severity: warning
262
269
  VersionAdded: '0.52'
270
+ VersionChanged: '1.40'
263
271
  Include:
264
272
  - '**/*.gemspec'
265
273
 
@@ -278,7 +286,9 @@ Gemspec/OrderedDependencies:
278
286
  Gemspec/RequireMFA:
279
287
  Description: 'Checks that the gemspec has metadata to require Multi-Factor Authentication from RubyGems.'
280
288
  Enabled: pending
289
+ Severity: warning
281
290
  VersionAdded: '1.23'
291
+ VersionChanged: '1.40'
282
292
  Reference:
283
293
  - https://guides.rubygems.org/mfa-requirement-opt-in/
284
294
  Include:
@@ -287,8 +297,9 @@ Gemspec/RequireMFA:
287
297
  Gemspec/RequiredRubyVersion:
288
298
  Description: 'Checks that `required_ruby_version` of gemspec is specified and equal to `TargetRubyVersion` of .rubocop.yml.'
289
299
  Enabled: true
300
+ Severity: warning
290
301
  VersionAdded: '0.52'
291
- VersionChanged: '1.22'
302
+ VersionChanged: '1.40'
292
303
  Include:
293
304
  - '**/*.gemspec'
294
305
 
@@ -296,7 +307,9 @@ Gemspec/RubyVersionGlobalsUsage:
296
307
  Description: Checks usage of RUBY_VERSION in gemspec.
297
308
  StyleGuide: '#no-ruby-version-in-the-gemspec'
298
309
  Enabled: true
310
+ Severity: warning
299
311
  VersionAdded: '0.72'
312
+ VersionChanged: '1.40'
300
313
  Include:
301
314
  - '**/*.gemspec'
302
315
 
@@ -378,8 +391,9 @@ Layout/AssignmentIndentation:
378
391
  Checks the indentation of the first line of the
379
392
  right-hand-side of a multi-line assignment.
380
393
  Enabled: true
394
+ SafeAutoCorrect: false
381
395
  VersionAdded: '0.49'
382
- VersionChanged: '0.77'
396
+ VersionChanged: '1.40'
383
397
  # By default the indentation width from `Layout/IndentationWidth` is used,
384
398
  # but it can be overridden by setting this parameter.
385
399
  IndentationWidth: ~
@@ -748,6 +762,7 @@ Layout/FirstArrayElementLineBreak:
748
762
  multi-line array.
749
763
  Enabled: false
750
764
  VersionAdded: '0.49'
765
+ AllowMultilineFinalElement: false
751
766
 
752
767
  Layout/FirstHashElementIndentation:
753
768
  Description: 'Checks the indentation of the first key in a hash literal.'
@@ -780,6 +795,7 @@ Layout/FirstHashElementLineBreak:
780
795
  multi-line hash.
781
796
  Enabled: false
782
797
  VersionAdded: '0.49'
798
+ AllowMultilineFinalElement: false
783
799
 
784
800
  Layout/FirstMethodArgumentLineBreak:
785
801
  Description: >-
@@ -787,6 +803,7 @@ Layout/FirstMethodArgumentLineBreak:
787
803
  multi-line method call.
788
804
  Enabled: false
789
805
  VersionAdded: '0.49'
806
+ AllowMultilineFinalElement: false
790
807
 
791
808
  Layout/FirstMethodParameterLineBreak:
792
809
  Description: >-
@@ -794,6 +811,7 @@ Layout/FirstMethodParameterLineBreak:
794
811
  multi-line method parameter definition.
795
812
  Enabled: false
796
813
  VersionAdded: '0.49'
814
+ AllowMultilineFinalElement: false
797
815
 
798
816
  Layout/FirstParameterIndentation:
799
817
  Description: >-
@@ -1053,6 +1071,7 @@ Layout/MultilineArrayLineBreaks:
1053
1071
  starts on a separate line.
1054
1072
  Enabled: false
1055
1073
  VersionAdded: '0.67'
1074
+ AllowMultilineFinalElement: false
1056
1075
 
1057
1076
  Layout/MultilineAssignmentLayout:
1058
1077
  Description: 'Check for a newline after the assignment operator in multi-line assignments.'
@@ -1103,6 +1122,7 @@ Layout/MultilineHashKeyLineBreaks:
1103
1122
  starts on a separate line.
1104
1123
  Enabled: false
1105
1124
  VersionAdded: '0.67'
1125
+ AllowMultilineFinalElement: false
1106
1126
 
1107
1127
  Layout/MultilineMethodArgumentLineBreaks:
1108
1128
  Description: >-
@@ -1110,6 +1130,7 @@ Layout/MultilineMethodArgumentLineBreaks:
1110
1130
  starts on a separate line.
1111
1131
  Enabled: false
1112
1132
  VersionAdded: '0.67'
1133
+ AllowMultilineFinalElement: false
1113
1134
 
1114
1135
  Layout/MultilineMethodCallBraceLayout:
1115
1136
  Description: >-
@@ -1164,6 +1185,7 @@ Layout/MultilineMethodParameterLineBreaks:
1164
1185
  starts on a separate line.
1165
1186
  Enabled: false
1166
1187
  VersionAdded: '1.32'
1188
+ AllowMultilineFinalElement: false
1167
1189
 
1168
1190
  Layout/MultilineOperationIndentation:
1169
1191
  Description: >-
@@ -1643,7 +1665,7 @@ Lint/DeprecatedConstants:
1643
1665
  Description: 'Checks for deprecated constants.'
1644
1666
  Enabled: pending
1645
1667
  VersionAdded: '1.8'
1646
- VersionChanged: '1.22'
1668
+ VersionChanged: '1.40'
1647
1669
  # You can configure deprecated constants.
1648
1670
  # If there is an alternative method, you can set alternative value as `Alternative`.
1649
1671
  # And you can set the deprecated version as `DeprecatedVersion`.
@@ -1670,6 +1692,12 @@ Lint/DeprecatedConstants:
1670
1692
  'Random::DEFAULT':
1671
1693
  Alternative: 'Random.new'
1672
1694
  DeprecatedVersion: '3.0'
1695
+ 'Struct::Group':
1696
+ Alternative: 'Etc::Group'
1697
+ DeprecatedVersion: '3.0'
1698
+ 'Struct::Passwd':
1699
+ Alternative: 'Etc::Passwd'
1700
+ DeprecatedVersion: '3.0'
1673
1701
 
1674
1702
  Lint/DeprecatedOpenSSLConstant:
1675
1703
  Description: "Don't use algorithm constants for `OpenSSL::Cipher` and `OpenSSL::Digest`."
@@ -1894,11 +1922,11 @@ Lint/InheritException:
1894
1922
  - runtime_error
1895
1923
 
1896
1924
  Lint/InterpolationCheck:
1897
- Description: 'Raise warning for interpolation in single q strs.'
1925
+ Description: 'Checks for interpolation in a single quoted string.'
1898
1926
  Enabled: true
1899
- Safe: false
1927
+ SafeAutoCorrect: false
1900
1928
  VersionAdded: '0.50'
1901
- VersionChanged: '0.87'
1929
+ VersionChanged: '1.40'
1902
1930
 
1903
1931
  Lint/LambdaWithoutLiteralBlock:
1904
1932
  Description: 'Checks uses of lambda without a literal block.'
@@ -2806,6 +2834,7 @@ Naming/MethodParameterName:
2806
2834
  - as
2807
2835
  - at
2808
2836
  - by
2837
+ - cc
2809
2838
  - db
2810
2839
  - id
2811
2840
  - if
@@ -3013,6 +3042,11 @@ Style/ArrayCoercion:
3013
3042
  Enabled: false
3014
3043
  VersionAdded: '0.88'
3015
3044
 
3045
+ Style/ArrayIntersect:
3046
+ Description: 'Use `array1.intersect?(array2)` instead of `(array1 & array2).any?`.'
3047
+ Enabled: 'pending'
3048
+ VersionAdded: '1.40'
3049
+
3016
3050
  Style/ArrayJoin:
3017
3051
  Description: 'Use Array#join instead of Array#*.'
3018
3052
  StyleGuide: '#array-join'
@@ -3392,6 +3426,11 @@ Style/CommentedKeyword:
3392
3426
  VersionAdded: '0.51'
3393
3427
  VersionChanged: '1.19'
3394
3428
 
3429
+ Style/ConcatArrayLiterals:
3430
+ Description: 'Enforces the use of `Array#push(item)` instead of `Array#concat([item])` to avoid redundant array literals.'
3431
+ Enabled: pending
3432
+ VersionAdded: '1.41'
3433
+
3395
3434
  Style/ConditionalAssignment:
3396
3435
  Description: >-
3397
3436
  Use the return value of `if` and `case` statements for
@@ -4660,10 +4699,12 @@ Style/RedundantArgument:
4660
4699
  Enabled: pending
4661
4700
  Safe: false
4662
4701
  VersionAdded: '1.4'
4663
- VersionChanged: '1.7'
4702
+ VersionChanged: '1.40'
4664
4703
  Methods:
4665
4704
  # Array#join
4666
4705
  join: ''
4706
+ # Array#sum
4707
+ sum: 0
4667
4708
  # String#split
4668
4709
  split: ' '
4669
4710
  # String#chomp
@@ -4698,6 +4739,16 @@ Style/RedundantConditional:
4698
4739
  Enabled: true
4699
4740
  VersionAdded: '0.50'
4700
4741
 
4742
+ Style/RedundantConstantBase:
4743
+ Description: Avoid redundant `::` prefix on constant.
4744
+ Enabled: pending
4745
+ VersionAdded: '1.40'
4746
+
4747
+ Style/RedundantDoubleSplatHashBraces:
4748
+ Description: 'Checks for redundant uses of double splat hash braces.'
4749
+ Enabled: pending
4750
+ VersionAdded: '1.41'
4751
+
4701
4752
  Style/RedundantEach:
4702
4753
  Description: 'Checks for redundant `each`.'
4703
4754
  Enabled: pending
@@ -4838,6 +4889,12 @@ Style/RegexpLiteral:
4838
4889
  # are found in the regexp string.
4839
4890
  AllowInnerSlashes: false
4840
4891
 
4892
+ Style/RequireOrder:
4893
+ Description: Sort `require` and `require_relative` in alphabetical order.
4894
+ Enabled: false
4895
+ SafeAutoCorrect: false
4896
+ VersionAdded: '1.40'
4897
+
4841
4898
  Style/RescueModifier:
4842
4899
  Description: 'Avoid using rescue in its modifier form.'
4843
4900
  StyleGuide: '#no-rescue-modifiers'
@@ -5122,12 +5179,11 @@ Style/SymbolProc:
5122
5179
  Enabled: true
5123
5180
  Safe: false
5124
5181
  VersionAdded: '0.26'
5125
- VersionChanged: '1.28'
5182
+ VersionChanged: '1.40'
5126
5183
  AllowMethodsWithArguments: false
5127
5184
  # A list of method names to be always allowed by the check.
5128
5185
  # The names should be fairly unique, otherwise you'll end up ignoring lots of code.
5129
5186
  AllowedMethods:
5130
- - respond_to
5131
5187
  - define_method
5132
5188
  AllowedPatterns: []
5133
5189
  IgnoredMethods: [] # deprecated
data/exe/rubocop CHANGED
@@ -11,8 +11,8 @@ exit exit_status if server_cli.exit?
11
11
  if RuboCop::Server.running?
12
12
  exit_status = RuboCop::Server::ClientCommand::Exec.new.run
13
13
  else
14
- require 'rubocop'
15
14
  require 'benchmark'
15
+ require 'rubocop'
16
16
 
17
17
  cli = RuboCop::CLI.new
18
18
 
@@ -31,6 +31,7 @@ module RuboCop
31
31
 
32
32
  def initialize(processed_source)
33
33
  @processed_source = processed_source
34
+ @no_directives = !processed_source.raw_source.include?('rubocop')
34
35
  end
35
36
 
36
37
  def cop_enabled_at_line?(cop, line_number)
@@ -74,6 +75,8 @@ module RuboCop
74
75
  end
75
76
 
76
77
  def analyze # rubocop:todo Metrics/AbcSize
78
+ return {} if @no_directives
79
+
77
80
  analyses = Hash.new { |hash, key| hash[key] = CopAnalysis.new([], nil) }
78
81
  inject_disabled_cops_directives(analyses)
79
82
 
@@ -146,6 +149,8 @@ module RuboCop
146
149
  end
147
150
 
148
151
  def each_directive
152
+ return if @no_directives
153
+
149
154
  processed_source.comments.each do |comment|
150
155
  directive = DirectiveComment.new(comment)
151
156
  yield directive if directive.cop_names
@@ -21,17 +21,23 @@ module RuboCop
21
21
  DEFAULT_RAILS_VERSION = 5.0
22
22
  attr_reader :loaded_path
23
23
 
24
+ # rubocop:disable Metrics/AbcSize
24
25
  def initialize(hash = {}, loaded_path = nil)
25
26
  @loaded_path = loaded_path
26
27
  @for_cop = Hash.new do |h, cop|
27
- qualified_cop_name = Cop::Registry.qualified_cop_name(cop, loaded_path)
28
+ cop_name = cop.respond_to?(:cop_name) ? cop.cop_name : cop
29
+ qualified_cop_name = Cop::Registry.qualified_cop_name(cop_name, loaded_path)
28
30
  cop_options = self[qualified_cop_name].dup || {}
29
31
  cop_options['Enabled'] = enable_cop?(qualified_cop_name, cop_options)
30
- h[cop] = cop_options
32
+ h[cop] = h[cop_name] = cop_options
31
33
  end
32
34
  @hash = hash
33
35
  @validator = ConfigValidator.new(self)
36
+
37
+ @badge_config_cache = {}.compare_by_identity
38
+ @clusivity_config_exists_cache = {}
34
39
  end
40
+ # rubocop:enable Metrics/AbcSize
35
41
 
36
42
  def self.create(hash, path, check: true)
37
43
  config = new(hash, path)
@@ -116,14 +122,31 @@ module RuboCop
116
122
  # Note: the 'Enabled' attribute is calculated according to the department's
117
123
  # and 'AllCops' configuration; other attributes are not inherited.
118
124
  def for_cop(cop)
119
- @for_cop[cop.respond_to?(:cop_name) ? cop.cop_name : cop]
125
+ @for_cop[cop]
120
126
  end
121
127
 
122
128
  # @return [Config] for the given cop merged with that of its department (if any)
123
129
  # Note: the 'Enabled' attribute is same as that returned by `for_cop`
124
130
  def for_badge(badge)
125
- cop_config = for_cop(badge.to_s)
126
- fetch(badge.department.to_s) { return cop_config }.merge(cop_config)
131
+ @badge_config_cache[badge] ||= begin
132
+ department_config = self[badge.department_name]
133
+ cop_config = for_cop(badge.to_s)
134
+ if department_config
135
+ department_config.merge(cop_config)
136
+ else
137
+ cop_config
138
+ end
139
+ end
140
+ end
141
+
142
+ # @return [Boolean] whether config for this badge has 'Include' or 'Exclude' keys
143
+ # @api private
144
+ def clusivity_config_for_badge?(badge)
145
+ exists = @clusivity_config_exists_cache[badge.to_s]
146
+ return exists unless exists.nil?
147
+
148
+ cop_config = for_badge(badge)
149
+ @clusivity_config_exists_cache[badge.to_s] = cop_config['Include'] || cop_config['Exclude']
127
150
  end
128
151
 
129
152
  # @return [Config] for the given department name.
@@ -215,7 +238,7 @@ module RuboCop
215
238
  # directory since that wouldn't work.
216
239
  def base_dir_for_path_parameters
217
240
  @base_dir_for_path_parameters ||=
218
- if File.basename(loaded_path).start_with?('.rubocop') &&
241
+ if loaded_path && File.basename(loaded_path).start_with?('.rubocop') &&
219
242
  loaded_path != File.join(Dir.home, ConfigLoader::DOTFILE)
220
243
  File.expand_path(File.dirname(loaded_path))
221
244
  else
@@ -272,9 +295,10 @@ module RuboCop
272
295
  return nil unless lock_file_path
273
296
 
274
297
  File.foreach(lock_file_path) do |line|
275
- # If rails is in Gemfile.lock or gems.lock, there should be a line like:
276
- # rails (X.X.X)
277
- result = line.match(/^\s+rails\s+\((\d+\.\d+)/)
298
+ # If Rails (or one of its frameworks) is in Gemfile.lock or gems.lock, there should be
299
+ # a line like:
300
+ # railties (X.X.X)
301
+ result = line.match(/^\s+railties\s+\((\d+\.\d+)/)
278
302
  return result.captures.first.to_f if result
279
303
  end
280
304
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'erb'
4
- require 'yaml'
5
4
  require 'pathname'
5
+ require 'yaml'
6
6
  require_relative 'config_finder'
7
7
 
8
8
  module RuboCop
@@ -42,18 +42,18 @@ module RuboCop
42
42
 
43
43
  hash = load_yaml_configuration(path)
44
44
 
45
- # Resolve requires first in case they define additional cops
46
45
  loaded_features = resolver.resolve_requires(path, hash)
47
46
  add_loaded_features(loaded_features)
48
47
 
49
- add_missing_namespaces(path, hash)
50
-
51
48
  resolver.override_department_setting_for_cops({}, hash)
52
49
  resolver.resolve_inheritance_from_gems(hash)
53
50
  resolver.resolve_inheritance(path, hash, file, debug?)
54
-
55
51
  hash.delete('inherit_from')
56
52
 
53
+ # Adding missing namespaces only after resolving requires & inheritance,
54
+ # since both can introduce new cops that need to be considered here.
55
+ add_missing_namespaces(path, hash)
56
+
57
57
  Config.create(hash, path, check: check)
58
58
  end
59
59
 
@@ -137,6 +137,15 @@ module RuboCop
137
137
  end
138
138
  end
139
139
 
140
+ # @api private
141
+ def inject_defaults!(project_root)
142
+ path = File.join(project_root, 'config', 'default.yml')
143
+ config = load_file(path)
144
+ new_config = ConfigLoader.merge_with_default(config, path)
145
+ puts "configuration from #{path}" if debug?
146
+ @default_configuration = new_config
147
+ end
148
+
140
149
  # Returns the path RuboCop inferred as the root of the project. No file
141
150
  # searches will go past this directory.
142
151
  # @deprecated Use `RuboCop::ConfigFinder.project_root` instead.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yaml'
4
3
  require 'pathname'
4
+ require 'yaml'
5
5
 
6
6
  module RuboCop
7
7
  # A help class for ConfigLoader that handles configuration resolution.
@@ -162,7 +162,7 @@ module RuboCop
162
162
  return unless syntax_config && default_config.merge(syntax_config) != default_config
163
163
 
164
164
  raise ValidationError,
165
- "configuration for Syntax cop found in #{smart_loaded_path}\n" \
165
+ "configuration for Lint/Syntax cop found in #{smart_loaded_path}\n" \
166
166
  'It\'s not possible to disable this cop.'
167
167
  end
168
168
 
@@ -10,7 +10,7 @@ module RuboCop
10
10
  # allow for badge references in source files that omit the department for
11
11
  # RuboCop to infer.
12
12
  class Badge
13
- attr_reader :department, :cop_name
13
+ attr_reader :department, :department_name, :cop_name
14
14
 
15
15
  def self.for(class_name)
16
16
  parts = class_name.split('::')
@@ -18,19 +18,23 @@ module RuboCop
18
18
  new(name_deep_enough ? parts[2..] : parts.last(2))
19
19
  end
20
20
 
21
+ @parse_cache = {}
22
+
21
23
  def self.parse(identifier)
22
- new(identifier.split('/').map { |i| camel_case(i) })
24
+ @parse_cache[identifier] ||= new(identifier.split('/').map! { |i| camel_case(i) })
23
25
  end
24
26
 
25
27
  def self.camel_case(name_part)
26
28
  return 'RSpec' if name_part == 'rspec'
29
+ return name_part unless name_part.match?(/^[a-z]|_[a-z]/)
27
30
 
28
- name_part.gsub(/^\w|_\w/) { |match| match[-1, 1].upcase }
31
+ name_part.gsub(/^[a-z]|_[a-z]/) { |match| match[-1, 1].upcase }
29
32
  end
30
33
 
31
34
  def initialize(class_name_parts)
32
35
  department_parts = class_name_parts[0...-1]
33
36
  @department = (department_parts.join('/').to_sym unless department_parts.empty?)
37
+ @department_name = @department&.to_s
34
38
  @cop_name = class_name_parts.last
35
39
  end
36
40
 
@@ -40,7 +44,8 @@ module RuboCop
40
44
  alias eql? ==
41
45
 
42
46
  def hash
43
- [department, cop_name].hash
47
+ # Do hashing manually to reduce Array allocations.
48
+ department.hash ^ cop_name.hash # rubocop:disable Security/CompoundHash
44
49
  end
45
50
 
46
51
  def match?(other)
@@ -107,8 +107,7 @@ module RuboCop
107
107
  def add_global_offense(message = nil, severity: nil)
108
108
  severity = find_severity(nil, severity)
109
109
  message = find_message(nil, message)
110
- @current_offenses <<
111
- Offense.new(severity, Offense::NO_LOCATION, message, name, :unsupported)
110
+ current_offenses << Offense.new(severity, Offense::NO_LOCATION, message, name, :unsupported)
112
111
  end
113
112
 
114
113
  # Adds an offense on the specified range (or node with an expression)
@@ -126,7 +125,7 @@ module RuboCop
126
125
 
127
126
  status, corrector = enabled_line?(range.line) ? correct(range, &block) : :disabled
128
127
 
129
- @current_offenses << Offense.new(severity, range, message, name, status, corrector)
128
+ current_offenses << Offense.new(severity, range, message, name, status, corrector)
130
129
  end
131
130
 
132
131
  # This method should be overridden when a cop's behavior depends
@@ -187,7 +186,7 @@ module RuboCop
187
186
  def self.match?(given_names)
188
187
  return false unless given_names
189
188
 
190
- given_names.include?(cop_name) || given_names.include?(department.to_s)
189
+ given_names.include?(cop_name) || given_names.include?(badge.department_name)
191
190
  end
192
191
 
193
192
  def cop_name
@@ -225,6 +224,8 @@ module RuboCop
225
224
  end
226
225
 
227
226
  def relevant_file?(file)
227
+ return true unless @config.clusivity_config_for_badge?(self.class.badge)
228
+
228
229
  file == RuboCop::AST::ProcessedSource::STRING_SOURCE_NAME ||
229
230
  (file_name_matches_any?(file, 'Include', true) &&
230
231
  !file_name_matches_any?(file, 'Exclude', false))
@@ -292,7 +293,7 @@ module RuboCop
292
293
  end
293
294
 
294
295
  def apply_correction(corrector)
295
- @current_corrector&.merge!(corrector) if corrector
296
+ current_corrector&.merge!(corrector) if corrector
296
297
  end
297
298
 
298
299
  ### Reserved for Commissioner:
@@ -305,22 +306,37 @@ module RuboCop
305
306
  @currently_disabled_lines ||= Set.new
306
307
  end
307
308
 
309
+ def current_corrector
310
+ @current_corrector ||= Corrector.new(@processed_source) if @processed_source.valid_syntax?
311
+ end
312
+
313
+ def current_offenses
314
+ @current_offenses ||= []
315
+ end
316
+
308
317
  private_class_method def self.restrict_on_send
309
318
  @restrict_on_send ||= self::RESTRICT_ON_SEND.to_a.freeze
310
319
  end
311
320
 
312
321
  # Called before any investigation
313
322
  def begin_investigation(processed_source)
314
- @current_offenses = []
323
+ @current_offenses = nil
315
324
  @current_offense_locations = nil
316
325
  @currently_disabled_lines = nil
317
326
  @processed_source = processed_source
318
- @current_corrector = Corrector.new(@processed_source) if @processed_source.valid_syntax?
327
+ @current_corrector = nil
319
328
  end
320
329
 
330
+ # rubocop:disable Layout/ClassStructure
331
+ EMPTY_OFFENSES = [].freeze
332
+ private_constant :EMPTY_OFFENSES
333
+ # rubocop:enable Layout/ClassStructure
334
+
321
335
  # Called to complete an investigation
322
336
  def complete_investigation
323
- InvestigationReport.new(self, processed_source, @current_offenses, @current_corrector)
337
+ InvestigationReport.new(
338
+ self, processed_source, @current_offenses || EMPTY_OFFENSES, @current_corrector
339
+ )
324
340
  ensure
325
341
  reset_investigation
326
342
  end
@@ -412,15 +428,8 @@ module RuboCop
412
428
  patterns = cop_config[parameter]
413
429
  return default_result unless patterns
414
430
 
415
- path = nil
416
- patterns.any? do |pattern|
417
- # Try to match the absolute path, as Exclude properties are absolute.
418
- next true if match_path?(pattern, file)
419
-
420
- # Try with relative path.
421
- path ||= config.path_relative_to_config(file)
422
- match_path?(pattern, path)
423
- end
431
+ patterns = FilePatterns.from(patterns)
432
+ patterns.match?(config.path_relative_to_config(file)) || patterns.match?(file)
424
433
  end
425
434
 
426
435
  def enabled_line?(line_number)
@@ -82,7 +82,8 @@ module RuboCop
82
82
  @cops.each { |cop| cop.send :begin_investigation, processed_source }
83
83
  if processed_source.valid_syntax?
84
84
  invoke(:on_new_investigation, @cops)
85
- invoke(:investigate, @forces, processed_source)
85
+ invoke_with_argument(:investigate, @forces, processed_source)
86
+
86
87
  walk(processed_source.ast) unless @cops.empty?
87
88
  invoke(:on_investigation_end, @cops)
88
89
  else
@@ -149,8 +150,12 @@ module RuboCop
149
150
  map
150
151
  end
151
152
 
152
- def invoke(callback, cops, *args)
153
- cops.each { |cop| with_cop_error_handling(cop) { cop.send(callback, *args) } }
153
+ def invoke(callback, cops)
154
+ cops.each { |cop| with_cop_error_handling(cop) { cop.send(callback) } }
155
+ end
156
+
157
+ def invoke_with_argument(callback, cops, arg)
158
+ cops.each { |cop| with_cop_error_handling(cop) { cop.send(callback, arg) } }
154
159
  end
155
160
 
156
161
  # Allow blind rescues here, since we're absorbing and packaging or
@@ -97,7 +97,7 @@ module RuboCop
97
97
 
98
98
  def begin_investigation(processed_source)
99
99
  super
100
- @offenses = @current_offenses
100
+ @offenses = current_offenses
101
101
  @last_corrector = @current_corrector
102
102
  end
103
103