rubocop 1.18.1 → 1.19.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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +24 -6
  4. data/lib/rubocop.rb +4 -0
  5. data/lib/rubocop/cli.rb +18 -0
  6. data/lib/rubocop/config_loader_resolver.rb +22 -7
  7. data/lib/rubocop/config_validator.rb +18 -5
  8. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
  9. data/lib/rubocop/cop/correctors/require_library_corrector.rb +23 -0
  10. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  11. data/lib/rubocop/cop/internal_affairs.rb +2 -0
  12. data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +34 -0
  13. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +71 -0
  14. data/lib/rubocop/cop/layout/class_structure.rb +5 -1
  15. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +9 -0
  16. data/lib/rubocop/cop/layout/end_alignment.rb +10 -2
  17. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
  18. data/lib/rubocop/cop/layout/hash_alignment.rb +22 -18
  19. data/lib/rubocop/cop/layout/heredoc_indentation.rb +0 -7
  20. data/lib/rubocop/cop/layout/indentation_style.rb +2 -2
  21. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  22. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +36 -17
  23. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +21 -9
  24. data/lib/rubocop/cop/layout/space_around_operators.rb +12 -1
  25. data/lib/rubocop/cop/layout/space_before_comment.rb +1 -1
  26. data/lib/rubocop/cop/layout/space_inside_parens.rb +5 -5
  27. data/lib/rubocop/cop/layout/trailing_whitespace.rb +24 -1
  28. data/lib/rubocop/cop/lint/ambiguous_range.rb +105 -0
  29. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +5 -2
  30. data/lib/rubocop/cop/lint/duplicate_branch.rb +2 -1
  31. data/lib/rubocop/cop/lint/duplicate_methods.rb +8 -5
  32. data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -1
  33. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  34. data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
  35. data/lib/rubocop/cop/mixin/hash_transform_method.rb +6 -1
  36. data/lib/rubocop/cop/mixin/heredoc.rb +7 -0
  37. data/lib/rubocop/cop/mixin/percent_array.rb +10 -7
  38. data/lib/rubocop/cop/mixin/require_library.rb +59 -0
  39. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  40. data/lib/rubocop/cop/naming/inclusive_language.rb +18 -1
  41. data/lib/rubocop/cop/style/block_delimiters.rb +31 -0
  42. data/lib/rubocop/cop/style/comment_annotation.rb +50 -6
  43. data/lib/rubocop/cop/style/commented_keyword.rb +2 -1
  44. data/lib/rubocop/cop/style/conditional_assignment.rb +19 -5
  45. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +1 -7
  46. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  47. data/lib/rubocop/cop/style/explicit_block_argument.rb +32 -7
  48. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +8 -2
  49. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  50. data/lib/rubocop/cop/style/hash_transform_keys.rb +0 -3
  51. data/lib/rubocop/cop/style/identical_conditional_branches.rb +30 -5
  52. data/lib/rubocop/cop/style/method_def_parentheses.rb +10 -1
  53. data/lib/rubocop/cop/style/missing_else.rb +7 -0
  54. data/lib/rubocop/cop/style/mutable_constant.rb +6 -8
  55. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +88 -0
  56. data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
  57. data/lib/rubocop/cop/style/semicolon.rb +32 -24
  58. data/lib/rubocop/cop/style/single_line_block_params.rb +3 -1
  59. data/lib/rubocop/cop/style/single_line_methods.rb +25 -15
  60. data/lib/rubocop/cop/style/special_global_vars.rb +21 -0
  61. data/lib/rubocop/cop/style/word_array.rb +20 -2
  62. data/lib/rubocop/cop/util.rb +7 -2
  63. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -1
  64. data/lib/rubocop/options.rb +1 -1
  65. data/lib/rubocop/version.rb +1 -1
  66. metadata +11 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 885ddbf92c177482e1be63255a018fcda8be3a10e76f30628b2fc1a1e9405188
4
- data.tar.gz: e67837d33ac5625327dff10d9317c4fd2fb6b9c7b543c73326ab32aea0e6066f
3
+ metadata.gz: 184ca6701160d34e5fe8f659e159842f397bfe07edbc27df159b7793fd8a0a3c
4
+ data.tar.gz: d891042df8d86850afbf19b0d0e81f4255e909f0775b32eb675b3766d0266561
5
5
  SHA512:
6
- metadata.gz: 6e72582647c14682bae1d594feb36fa464ced9096e3146e95b6ea534b8483115bf2770a4c727fc3f2d4e3c1ae80f65c41a55b393858ac28cbb962c55fa5717f9
7
- data.tar.gz: d92789df44f307cb341226be7e397936af7dbfd045fa7aa23f8ba34aeddc846d79439e464e3ce9ac197c3c4220384ebff5ba76982c6871957a1a4bbf44167967
6
+ metadata.gz: 6b0ed04638cfa650324684315fcf4c8a99b93fa66c1dce39efa7c76605bbd78a7c4e4b4d6fc6ac608d2ebbb52604f6f9fbccf23e5d097c637b1b6c879601d70b
7
+ data.tar.gz: f1310e4f3a7285ecf642edf6e99500decb0d1aa74b676adf38ee6c65c9f1f4cf3124853102a50da51e896a6b9780b3db9156fa4e075f60139f01d239d13ab898
data/README.md CHANGED
@@ -54,7 +54,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
54
54
  in your `Gemfile`:
55
55
 
56
56
  ```rb
57
- gem 'rubocop', '~> 1.18', require: false
57
+ gem 'rubocop', '~> 1.19', require: false
58
58
  ```
59
59
 
60
60
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -1434,6 +1434,13 @@ Lint/AmbiguousOperator:
1434
1434
  VersionAdded: '0.17'
1435
1435
  VersionChanged: '0.83'
1436
1436
 
1437
+ Lint/AmbiguousRange:
1438
+ Description: Checks for ranges with ambiguous boundaries.
1439
+ Enabled: pending
1440
+ VersionAdded: '1.19'
1441
+ SafeAutoCorrect: false
1442
+ RequireParenthesesForMethodChains: false
1443
+
1437
1444
  Lint/AmbiguousRegexpLiteral:
1438
1445
  Description: >-
1439
1446
  Checks for ambiguous regexp literals in the first argument of
@@ -1809,7 +1816,7 @@ Lint/MissingCopEnableDirective:
1809
1816
  Lint/MissingSuper:
1810
1817
  Description: >-
1811
1818
  This cop checks for the presence of constructors and lifecycle callbacks
1812
- without calls to `super`'.
1819
+ without calls to `super`.
1813
1820
  Enabled: true
1814
1821
  VersionAdded: '0.89'
1815
1822
  VersionChanged: '1.4'
@@ -1824,7 +1831,6 @@ Lint/MultipleComparison:
1824
1831
  Enabled: true
1825
1832
  VersionAdded: '0.47'
1826
1833
  VersionChanged: '1.1'
1827
- AllowMethodComparison: true
1828
1834
 
1829
1835
  Lint/NestedMethodDefinition:
1830
1836
  Description: 'Do not use nested method definitions.'
@@ -2557,6 +2563,7 @@ Naming/InclusiveLanguage:
2557
2563
  - denylist
2558
2564
  - block
2559
2565
  slave:
2566
+ WholeWord: true
2560
2567
  Suggestions: ['replica', 'secondary', 'follower']
2561
2568
 
2562
2569
  Naming/MemoizedInstanceVariableName:
@@ -3150,12 +3157,14 @@ Style/CommentAnnotation:
3150
3157
  - HACK
3151
3158
  - REVIEW
3152
3159
  - NOTE
3160
+ RequireColon: true
3153
3161
 
3154
3162
  Style/CommentedKeyword:
3155
3163
  Description: 'Do not place comments on the same line as certain keywords.'
3156
3164
  Enabled: true
3165
+ SafeAutoCorrect: false
3157
3166
  VersionAdded: '0.51'
3158
- VersionChanged: '1.7'
3167
+ VersionChanged: '1.19'
3159
3168
 
3160
3169
  Style/ConditionalAssignment:
3161
3170
  Description: >-
@@ -3602,8 +3611,9 @@ Style/IdenticalConditionalBranches:
3602
3611
  line at the end of each branch, which can validly be moved
3603
3612
  out of the conditional.
3604
3613
  Enabled: true
3614
+ SafeAutoCorrect: false
3605
3615
  VersionAdded: '0.36'
3606
- VersionChanged: '1.16'
3616
+ VersionChanged: '1.19'
3607
3617
 
3608
3618
  Style/IfInsideElse:
3609
3619
  Description: 'Finds if nodes inside else, which can be converted to elsif.'
@@ -3928,6 +3938,7 @@ Style/MultipleComparison:
3928
3938
  Enabled: true
3929
3939
  VersionAdded: '0.49'
3930
3940
  VersionChanged: '1.1'
3941
+ AllowMethodComparison: true
3931
3942
 
3932
3943
  Style/MutableConstant:
3933
3944
  Description: 'Do not assign mutable objects to constants.'
@@ -4151,6 +4162,7 @@ Style/OptionHash:
4151
4162
  - args
4152
4163
  - params
4153
4164
  - parameters
4165
+ Allowlist: []
4154
4166
 
4155
4167
  Style/OptionalArguments:
4156
4168
  Description: >-
@@ -4403,6 +4415,11 @@ Style/RedundantSelfAssignment:
4403
4415
  Safe: false
4404
4416
  VersionAdded: '0.90'
4405
4417
 
4418
+ Style/RedundantSelfAssignmentBranch:
4419
+ Description: 'Checks for places where conditional branch makes redundant self-assignment.'
4420
+ Enabled: pending
4421
+ VersionAdded: '1.19'
4422
+
4406
4423
  Style/RedundantSort:
4407
4424
  Description: >-
4408
4425
  Use `min` instead of `sort.first`,
@@ -4574,6 +4591,7 @@ Style/SpecialGlobalVars:
4574
4591
  VersionAdded: '0.13'
4575
4592
  VersionChanged: '0.36'
4576
4593
  SafeAutoCorrect: false
4594
+ RequireEnglish: true
4577
4595
  EnforcedStyle: use_english_names
4578
4596
  SupportedStyles:
4579
4597
  - use_perl_names
@@ -4894,7 +4912,7 @@ Style/VariableInterpolation:
4894
4912
 
4895
4913
  Style/WhenThen:
4896
4914
  Description: 'Use when x then ... for one-line cases.'
4897
- StyleGuide: '#one-line-cases'
4915
+ StyleGuide: '#no-when-semicolons'
4898
4916
  Enabled: true
4899
4917
  VersionAdded: '0.9'
4900
4918
 
@@ -4918,7 +4936,7 @@ Style/WordArray:
4918
4936
  StyleGuide: '#percent-w'
4919
4937
  Enabled: true
4920
4938
  VersionAdded: '0.9'
4921
- VersionChanged: '0.36'
4939
+ VersionChanged: '1.19'
4922
4940
  EnforcedStyle: percent
4923
4941
  SupportedStyles:
4924
4942
  # percent style: %w(word1 word2)
data/lib/rubocop.rb CHANGED
@@ -111,6 +111,7 @@ require_relative 'rubocop/cop/mixin/percent_literal'
111
111
  require_relative 'rubocop/cop/mixin/preceding_following_alignment'
112
112
  require_relative 'rubocop/cop/mixin/preferred_delimiters'
113
113
  require_relative 'rubocop/cop/mixin/rational_literal'
114
+ require_relative 'rubocop/cop/mixin/require_library'
114
115
  require_relative 'rubocop/cop/mixin/rescue_node'
115
116
  require_relative 'rubocop/cop/mixin/safe_assignment'
116
117
  require_relative 'rubocop/cop/mixin/space_after_punctuation'
@@ -144,6 +145,7 @@ require_relative 'rubocop/cop/correctors/ordered_gem_corrector'
144
145
  require_relative 'rubocop/cop/correctors/parentheses_corrector'
145
146
  require_relative 'rubocop/cop/correctors/percent_literal_corrector'
146
147
  require_relative 'rubocop/cop/correctors/punctuation_corrector'
148
+ require_relative 'rubocop/cop/correctors/require_library_corrector'
147
149
  require_relative 'rubocop/cop/correctors/space_corrector'
148
150
  require_relative 'rubocop/cop/correctors/string_literal_corrector'
149
151
  require_relative 'rubocop/cop/correctors/unused_arg_corrector'
@@ -260,6 +262,7 @@ require_relative 'rubocop/cop/layout/trailing_whitespace'
260
262
  require_relative 'rubocop/cop/lint/ambiguous_assignment'
261
263
  require_relative 'rubocop/cop/lint/ambiguous_block_association'
262
264
  require_relative 'rubocop/cop/lint/ambiguous_operator'
265
+ require_relative 'rubocop/cop/lint/ambiguous_range'
263
266
  require_relative 'rubocop/cop/lint/ambiguous_regexp_literal'
264
267
  require_relative 'rubocop/cop/lint/assignment_in_condition'
265
268
  require_relative 'rubocop/cop/lint/big_decimal_new'
@@ -510,6 +513,7 @@ require_relative 'rubocop/cop/style/redundant_assignment'
510
513
  require_relative 'rubocop/cop/style/redundant_fetch_block'
511
514
  require_relative 'rubocop/cop/style/redundant_file_extension_in_require'
512
515
  require_relative 'rubocop/cop/style/redundant_self_assignment'
516
+ require_relative 'rubocop/cop/style/redundant_self_assignment_branch'
513
517
  require_relative 'rubocop/cop/style/sole_nested_conditional'
514
518
  require_relative 'rubocop/cop/style/static_class'
515
519
  require_relative 'rubocop/cop/style/method_called_on_do_end_block'
data/lib/rubocop/cli.rb CHANGED
@@ -8,6 +8,11 @@ module RuboCop
8
8
  STATUS_OFFENSES = 1
9
9
  STATUS_ERROR = 2
10
10
  STATUS_INTERRUPTED = 128 + Signal.list['INT']
11
+ DEFAULT_PARALLEL_OPTIONS = %i[
12
+ color debug display_style_guide display_time display_only_fail_level_offenses
13
+ display_only_failed except extra_details fail_level fix_layout format
14
+ ignore_disable_comments lint only only_guide_cops require safe
15
+ ].freeze
11
16
 
12
17
  class Finished < RuntimeError; end
13
18
 
@@ -37,6 +42,7 @@ module RuboCop
37
42
  else
38
43
  act_on_options
39
44
  validate_options_vs_config
45
+ parallel_by_default!
40
46
  apply_default_formatter
41
47
  execute_runners
42
48
  end
@@ -84,6 +90,18 @@ module RuboCop
84
90
  'with AllCops: UseCache: false is not allowed.'
85
91
  end
86
92
 
93
+ def parallel_by_default!
94
+ # See https://github.com/rubocop/rubocop/pull/4537 for JRuby and Windows constraints.
95
+ return if RUBY_ENGINE != 'ruby' || RuboCop::Platform.windows?
96
+
97
+ if (@options.keys - DEFAULT_PARALLEL_OPTIONS).empty? &&
98
+ @config_store.for_pwd.for_all_cops['UseCache'] != false
99
+ puts 'Use parallel by default.' if @options[:debug]
100
+
101
+ @options[:parallel] = true
102
+ end
103
+ end
104
+
87
105
  def act_on_options
88
106
  set_options_to_config_loader
89
107
 
@@ -23,7 +23,7 @@ module RuboCop
23
23
  def resolve_inheritance(path, hash, file, debug) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
24
24
  inherited_files = Array(hash['inherit_from'])
25
25
  base_configs(path, inherited_files, file)
26
- .reverse.each_with_index do |base_config, index|
26
+ .each_with_index.reverse_each do |base_config, index|
27
27
  override_department_setting_for_cops(base_config, hash)
28
28
  override_enabled_for_disabled_departments(base_config, hash)
29
29
 
@@ -108,7 +108,7 @@ module RuboCop
108
108
  result.delete(key)
109
109
  elsif merge_hashes?(base_hash, derived_hash, key)
110
110
  result[key] = merge(base_hash[key], derived_hash[key], **opts)
111
- elsif should_union?(base_hash, key, opts[:inherit_mode])
111
+ elsif should_union?(derived_hash, base_hash, opts[:inherit_mode], key)
112
112
  result[key] = base_hash[key] | derived_hash[key]
113
113
  elsif opts[:debug]
114
114
  warn_on_duplicate_setting(base_hash, derived_hash, key, **opts)
@@ -183,11 +183,26 @@ module RuboCop
183
183
  local_inherit || hash['inherit_mode'] || {}
184
184
  end
185
185
 
186
- def should_union?(base_hash, key, inherit_mode)
187
- base_hash[key].is_a?(Array) &&
188
- inherit_mode &&
189
- inherit_mode['merge'] &&
190
- inherit_mode['merge'].include?(key)
186
+ def should_union?(derived_hash, base_hash, root_mode, key)
187
+ return false unless base_hash[key].is_a?(Array)
188
+
189
+ derived_mode = derived_hash['inherit_mode']
190
+ return false if should_override?(derived_mode, key)
191
+ return true if should_merge?(derived_mode, key)
192
+
193
+ base_mode = base_hash['inherit_mode']
194
+ return false if should_override?(base_mode, key)
195
+ return true if should_merge?(base_mode, key)
196
+
197
+ should_merge?(root_mode, key)
198
+ end
199
+
200
+ def should_merge?(mode, key)
201
+ mode && mode['merge'] && mode['merge'].include?(key)
202
+ end
203
+
204
+ def should_override?(mode, key)
205
+ mode && mode['override'] && mode['override'].include?(key)
191
206
  end
192
207
 
193
208
  def merge_hashes?(base_hash, derived_hash, key)
@@ -104,12 +104,9 @@ module RuboCop
104
104
  # to do so than to pass the value around to various methods.
105
105
  next if name == 'inherit_mode'
106
106
 
107
- suggestions = NameSimilarity.find_similar_names(name, Cop::Registry.global.map(&:cop_name))
108
- suggestion = "Did you mean `#{suggestions.join('`, `')}`?" if suggestions.any?
109
-
110
107
  message = <<~MESSAGE.rstrip
111
- unrecognized cop #{name} found in #{smart_loaded_path}
112
- #{suggestion}
108
+ unrecognized cop or department #{name} found in #{smart_loaded_path}
109
+ #{suggestion(name)}
113
110
  MESSAGE
114
111
 
115
112
  unknown_cops << message
@@ -117,6 +114,22 @@ module RuboCop
117
114
  raise ValidationError, unknown_cops.join("\n") if unknown_cops.any?
118
115
  end
119
116
 
117
+ def suggestion(name)
118
+ registry = Cop::Registry.global
119
+ departments = registry.departments.map(&:to_s)
120
+ suggestions = NameSimilarity.find_similar_names(name, departments + registry.map(&:cop_name))
121
+ if suggestions.any?
122
+ "Did you mean `#{suggestions.join('`, `')}`?"
123
+ else
124
+ # Department names can contain slashes, e.g. Chef/Correctness, but there's no support for
125
+ # the concept of higher level departments in RuboCop. It's a flat structure. So if the user
126
+ # tries to configure a "top level department", we hint that it's the bottom level
127
+ # departments that should be configured.
128
+ suggestions = departments.select { |department| department.start_with?("#{name}/") }
129
+ "#{name} is not a department. Use `#{suggestions.join('`, `')}`." if suggestions.any?
130
+ end
131
+ end
132
+
120
133
  def validate_syntax_cop
121
134
  syntax_config = @config['Lint/Syntax']
122
135
  default_config = ConfigLoader.default_configuration['Lint/Syntax']
@@ -24,7 +24,7 @@ module RuboCop
24
24
  # gem 'rubocop'
25
25
  # # For tests
26
26
  # gem 'rspec'
27
- class OrderedGems < Cop
27
+ class OrderedGems < Cop # rubocop:disable InternalAffairs/InheritDeprecatedCopClass
28
28
  include ConfigurableEnforcedStyle
29
29
  include OrderedGemNode
30
30
 
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This class ensures a require statement is present for a standard library
6
+ # determined by the variable library_name
7
+ class RequireLibraryCorrector
8
+ extend RangeHelp
9
+
10
+ class << self
11
+ def correct(corrector, node, library_name)
12
+ node = node.parent while node.parent?
13
+ node = node.children.first if node.begin_type?
14
+ corrector.insert_before(node, require_statement(library_name))
15
+ end
16
+
17
+ def require_statement(library_name)
18
+ "require '#{library_name}'\n"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -50,7 +50,7 @@ module RuboCop
50
50
  # spec.add_dependency 'rubocop'
51
51
  # # For tests
52
52
  # spec.add_dependency 'rspec'
53
- class OrderedDependencies < Cop
53
+ class OrderedDependencies < Cop # rubocop:disable InternalAffairs/InheritDeprecatedCopClass
54
54
  include ConfigurableEnforcedStyle
55
55
  include OrderedGemNode
56
56
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'internal_affairs/empty_line_between_expect_offense_and_correction'
4
4
  require_relative 'internal_affairs/example_description'
5
+ require_relative 'internal_affairs/inherit_deprecated_cop_class'
5
6
  require_relative 'internal_affairs/method_name_equal'
6
7
  require_relative 'internal_affairs/node_destructuring'
7
8
  require_relative 'internal_affairs/node_matcher_directive'
@@ -12,4 +13,5 @@ require_relative 'internal_affairs/redundant_let_rubocop_config_new'
12
13
  require_relative 'internal_affairs/redundant_location_argument'
13
14
  require_relative 'internal_affairs/redundant_message_argument'
14
15
  require_relative 'internal_affairs/style_detected_api_use'
16
+ require_relative 'internal_affairs/undefined_config'
15
17
  require_relative 'internal_affairs/useless_message_assertion'
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # `RuboCop::Cop::Cop` is deprecated and will be removed in Rubocop 2.0.
7
+ # Your custom cop class should inherit from `RuboCop::Cop::Base` instead of
8
+ # `RuboCop::Cop::Cop`.
9
+ #
10
+ # See "v1 Upgrade Notes" for more details:
11
+ # https://docs.rubocop.org/rubocop/v1_upgrade_notes.html
12
+ #
13
+ # @example
14
+ # # bad
15
+ # class Foo < Cop
16
+ # end
17
+ #
18
+ # # good
19
+ # class Foo < Base
20
+ # end
21
+ #
22
+ class InheritDeprecatedCopClass < Base
23
+ MSG = 'Use `Base` instead of `Cop`.'
24
+
25
+ def on_class(node)
26
+ return unless (parent_class = node.parent_class)
27
+ return unless parent_class.children.last == :Cop
28
+
29
+ add_offense(parent_class)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Looks for references to a cop configuration key that isn't defined in config/default.yml.
7
+ class UndefinedConfig < Base
8
+ ALLOWED_CONFIGURATIONS = %w[
9
+ Safe SafeAutoCorrect AutoCorrect Severity StyleGuide Details Reference Include Exclude
10
+ ].freeze
11
+ RESTRICT_ON_SEND = %i[[] fetch].freeze
12
+ MSG = '`%<name>s` is not defined in the configuration for `%<cop>s` ' \
13
+ 'in `config/default.yml`.'
14
+
15
+ # @!method cop_class_def(node)
16
+ def_node_search :cop_class_def, <<~PATTERN
17
+ (class _ (const _ {:Base :Cop}) ...)
18
+ PATTERN
19
+
20
+ # @!method cop_config_accessor?(node)
21
+ def_node_matcher :cop_config_accessor?, <<~PATTERN
22
+ (send (send nil? :cop_config) {:[] :fetch} ${str sym}...)
23
+ PATTERN
24
+
25
+ def on_new_investigation
26
+ super
27
+ return unless processed_source.ast
28
+
29
+ cop_class = cop_class_def(processed_source.ast).first
30
+ return unless (@cop_class_name = extract_cop_name(cop_class))
31
+
32
+ @config_for_cop = RuboCop::ConfigLoader.default_configuration.for_cop(@cop_class_name)
33
+ end
34
+
35
+ def on_send(node)
36
+ return unless cop_class_name
37
+ return unless (config_name_node = cop_config_accessor?(node))
38
+ return if always_allowed?(config_name_node)
39
+ return if configuration_key_defined?(config_name_node)
40
+
41
+ message = format(MSG, name: config_name_node.value, cop: cop_class_name)
42
+ add_offense(config_name_node, message: message)
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :config_for_cop, :cop_class_name
48
+
49
+ def extract_cop_name(class_node)
50
+ return unless class_node
51
+
52
+ segments = [class_node].concat(
53
+ class_node.each_ancestor(:class, :module).take_while do |n|
54
+ n.identifier.short_name != :Cop
55
+ end
56
+ )
57
+
58
+ segments.reverse_each.map { |s| s.identifier.short_name }.join('/')
59
+ end
60
+
61
+ def always_allowed?(node)
62
+ ALLOWED_CONFIGURATIONS.include?(node.value)
63
+ end
64
+
65
+ def configuration_key_defined?(node)
66
+ config_for_cop.key?(node.value)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end