rubocop 1.18.3 → 1.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +22 -5
  4. data/lib/rubocop.rb +4 -0
  5. data/lib/rubocop/cli.rb +18 -0
  6. data/lib/rubocop/config_loader_resolver.rb +21 -6
  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 +33 -14
  23. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +21 -9
  24. data/lib/rubocop/cop/layout/space_around_operators.rb +8 -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/mixin/check_line_breakable.rb +2 -2
  34. data/lib/rubocop/cop/mixin/hash_transform_method.rb +6 -1
  35. data/lib/rubocop/cop/mixin/heredoc.rb +7 -0
  36. data/lib/rubocop/cop/mixin/percent_array.rb +10 -7
  37. data/lib/rubocop/cop/mixin/require_library.rb +59 -0
  38. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  39. data/lib/rubocop/cop/naming/inclusive_language.rb +18 -1
  40. data/lib/rubocop/cop/style/block_delimiters.rb +16 -0
  41. data/lib/rubocop/cop/style/commented_keyword.rb +2 -1
  42. data/lib/rubocop/cop/style/conditional_assignment.rb +19 -5
  43. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +1 -7
  44. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  45. data/lib/rubocop/cop/style/explicit_block_argument.rb +32 -7
  46. data/lib/rubocop/cop/style/hash_transform_keys.rb +0 -3
  47. data/lib/rubocop/cop/style/identical_conditional_branches.rb +30 -5
  48. data/lib/rubocop/cop/style/method_def_parentheses.rb +10 -1
  49. data/lib/rubocop/cop/style/missing_else.rb +7 -0
  50. data/lib/rubocop/cop/style/mutable_constant.rb +6 -8
  51. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +88 -0
  52. data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
  53. data/lib/rubocop/cop/style/semicolon.rb +32 -24
  54. data/lib/rubocop/cop/style/single_line_block_params.rb +3 -1
  55. data/lib/rubocop/cop/style/single_line_methods.rb +14 -9
  56. data/lib/rubocop/cop/style/special_global_vars.rb +21 -0
  57. data/lib/rubocop/cop/style/word_array.rb +20 -2
  58. data/lib/rubocop/cop/util.rb +7 -2
  59. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -1
  60. data/lib/rubocop/options.rb +1 -1
  61. data/lib/rubocop/version.rb +1 -1
  62. metadata +11 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6123e3d35feebac08e838afcff3f912fa24f7abcc71403f6368fffb346fa9bc
4
- data.tar.gz: 40f3ff08e0efc288e7a11af7016d702f743b8ab343de0c3fd045035c7ac7605f
3
+ metadata.gz: 184ca6701160d34e5fe8f659e159842f397bfe07edbc27df159b7793fd8a0a3c
4
+ data.tar.gz: d891042df8d86850afbf19b0d0e81f4255e909f0775b32eb675b3766d0266561
5
5
  SHA512:
6
- metadata.gz: 3ac2d860eccd7ac0d655649d36f64cf52ed1587357b2ef35707a1c2ced408cf645d1a8be2dd6e660c5e338c298adef876814fdf35b22f5c71da4ec5bc830e388
7
- data.tar.gz: adab3ee6563260ced11848bc9b1c62ff2641a28a6b4aca80cb703ef9136562bbdc6a2efff4670d12dee329cc7cf5306a8c9d11106ff13d9cbf5539b5094ba388
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
@@ -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:
@@ -3155,8 +3162,9 @@ Style/CommentAnnotation:
3155
3162
  Style/CommentedKeyword:
3156
3163
  Description: 'Do not place comments on the same line as certain keywords.'
3157
3164
  Enabled: true
3165
+ SafeAutoCorrect: false
3158
3166
  VersionAdded: '0.51'
3159
- VersionChanged: '1.7'
3167
+ VersionChanged: '1.19'
3160
3168
 
3161
3169
  Style/ConditionalAssignment:
3162
3170
  Description: >-
@@ -3603,8 +3611,9 @@ Style/IdenticalConditionalBranches:
3603
3611
  line at the end of each branch, which can validly be moved
3604
3612
  out of the conditional.
3605
3613
  Enabled: true
3614
+ SafeAutoCorrect: false
3606
3615
  VersionAdded: '0.36'
3607
- VersionChanged: '1.16'
3616
+ VersionChanged: '1.19'
3608
3617
 
3609
3618
  Style/IfInsideElse:
3610
3619
  Description: 'Finds if nodes inside else, which can be converted to elsif.'
@@ -3929,6 +3938,7 @@ Style/MultipleComparison:
3929
3938
  Enabled: true
3930
3939
  VersionAdded: '0.49'
3931
3940
  VersionChanged: '1.1'
3941
+ AllowMethodComparison: true
3932
3942
 
3933
3943
  Style/MutableConstant:
3934
3944
  Description: 'Do not assign mutable objects to constants.'
@@ -4152,6 +4162,7 @@ Style/OptionHash:
4152
4162
  - args
4153
4163
  - params
4154
4164
  - parameters
4165
+ Allowlist: []
4155
4166
 
4156
4167
  Style/OptionalArguments:
4157
4168
  Description: >-
@@ -4404,6 +4415,11 @@ Style/RedundantSelfAssignment:
4404
4415
  Safe: false
4405
4416
  VersionAdded: '0.90'
4406
4417
 
4418
+ Style/RedundantSelfAssignmentBranch:
4419
+ Description: 'Checks for places where conditional branch makes redundant self-assignment.'
4420
+ Enabled: pending
4421
+ VersionAdded: '1.19'
4422
+
4407
4423
  Style/RedundantSort:
4408
4424
  Description: >-
4409
4425
  Use `min` instead of `sort.first`,
@@ -4575,6 +4591,7 @@ Style/SpecialGlobalVars:
4575
4591
  VersionAdded: '0.13'
4576
4592
  VersionChanged: '0.36'
4577
4593
  SafeAutoCorrect: false
4594
+ RequireEnglish: true
4578
4595
  EnforcedStyle: use_english_names
4579
4596
  SupportedStyles:
4580
4597
  - use_perl_names
@@ -4895,7 +4912,7 @@ Style/VariableInterpolation:
4895
4912
 
4896
4913
  Style/WhenThen:
4897
4914
  Description: 'Use when x then ... for one-line cases.'
4898
- StyleGuide: '#one-line-cases'
4915
+ StyleGuide: '#no-when-semicolons'
4899
4916
  Enabled: true
4900
4917
  VersionAdded: '0.9'
4901
4918
 
@@ -4919,7 +4936,7 @@ Style/WordArray:
4919
4936
  StyleGuide: '#percent-w'
4920
4937
  Enabled: true
4921
4938
  VersionAdded: '0.9'
4922
- VersionChanged: '0.36'
4939
+ VersionChanged: '1.19'
4923
4940
  EnforcedStyle: percent
4924
4941
  SupportedStyles:
4925
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
 
@@ -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
@@ -289,12 +289,16 @@ module RuboCop
289
289
  (node.first_line - 1).downto(1) do |annotation_line|
290
290
  break unless (comment = processed_source.comment_at_line(annotation_line))
291
291
 
292
- first_comment = comment
292
+ first_comment = comment if whole_line_comment_at_line?(annotation_line)
293
293
  end
294
294
 
295
295
  start_line_position(first_comment || node)
296
296
  end
297
297
 
298
+ def whole_line_comment_at_line?(line)
299
+ /\A\s*#/.match?(processed_source.lines[line - 1])
300
+ end
301
+
298
302
  def start_line_position(node)
299
303
  buffer.line_range(node.loc.line).begin_pos - 1
300
304
  end