rubocop 1.63.5 → 1.64.1

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -2
  3. data/config/default.yml +18 -2
  4. data/lib/rubocop/cli/command/show_docs_url.rb +2 -2
  5. data/lib/rubocop/config.rb +2 -3
  6. data/lib/rubocop/cop/base.rb +6 -13
  7. data/lib/rubocop/cop/bundler/gem_version.rb +3 -5
  8. data/lib/rubocop/cop/documentation.rb +16 -6
  9. data/lib/rubocop/cop/force.rb +12 -0
  10. data/lib/rubocop/cop/gemspec/dependency_version.rb +3 -5
  11. data/lib/rubocop/cop/layout/empty_comment.rb +3 -1
  12. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +3 -4
  13. data/lib/rubocop/cop/lint/erb_new_arguments.rb +21 -14
  14. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +3 -3
  15. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +9 -2
  16. data/lib/rubocop/cop/style/access_modifier_declarations.rb +50 -0
  17. data/lib/rubocop/cop/style/arguments_forwarding.rb +3 -1
  18. data/lib/rubocop/cop/style/copyright.rb +15 -10
  19. data/lib/rubocop/cop/style/documentation.rb +24 -24
  20. data/lib/rubocop/cop/style/documentation_method.rb +20 -0
  21. data/lib/rubocop/cop/style/hash_syntax.rb +18 -0
  22. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -3
  23. data/lib/rubocop/cop/style/map_into_array.rb +1 -1
  24. data/lib/rubocop/cop/style/one_line_conditional.rb +1 -1
  25. data/lib/rubocop/cop/style/redundant_line_continuation.rb +2 -1
  26. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +90 -0
  27. data/lib/rubocop/cop/style/super_arguments.rb +156 -0
  28. data/lib/rubocop/cop/style/symbol_proc.rb +32 -5
  29. data/lib/rubocop/cop/team.rb +2 -0
  30. data/lib/rubocop/formatter/disabled_config_formatter.rb +13 -9
  31. data/lib/rubocop/formatter/formatter_set.rb +7 -1
  32. data/lib/rubocop/lockfile.rb +1 -1
  33. data/lib/rubocop/lsp/routes.rb +8 -10
  34. data/lib/rubocop/lsp.rb +9 -2
  35. data/lib/rubocop/version.rb +1 -1
  36. data/lib/rubocop.rb +2 -0
  37. metadata +10 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1911c884de81dd524490fea5075e7605d3ccf82fad85ebc9d09adbe5d29637ca
4
- data.tar.gz: 8206c237dd18bbcd9769d55b1206d160ce766a21caa5c8f8ea956ae845371ea2
3
+ metadata.gz: cc79c69246529843a3d6179458d5563867515189cca9f68d34e6cba9f103a032
4
+ data.tar.gz: 2b71ef0f55a63904b93e1315417ab4bd9701c1d91f3f87087fda9046243a4176
5
5
  SHA512:
6
- metadata.gz: 429dfdfda489516f4856fa00ad50c062a172588ca4bb1006baa25213c2fb949b0781af446d689200f0a87017f47708ad49324a6644cce104f79dd42b129dd680
7
- data.tar.gz: ce8363fa68a56f9c5f36c40d1596932b1233854823c54bfb9dc36a669256dca64459186037fe10e9723a550cec0a6f11df2e1d802e4471d8c9d1e98db8c528f3
6
+ metadata.gz: 4ea1aa79a49f5a9c7331286e58563b5b92c5c8b11bc1d81dbddee107595a9588e84c7888a8fe6338b29e856740d35d56df47e8d7b485db5cc4cd6cd0f45a8406
7
+ data.tar.gz: f5bc4fb8153c6277534bc4acd22da3bb3e41ef0ca5eef2639817893fa2312b5291ca80b308151c2e315db993ea086f32f618f9ef65146b69e4b99fc50782c165
data/README.md CHANGED
@@ -5,7 +5,6 @@
5
5
  ----------
6
6
  [![Ruby Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop/rubocop)
7
7
  [![Gem Version](https://badge.fury.io/rb/rubocop.svg)](https://badge.fury.io/rb/rubocop)
8
- [![CircleCI Status](https://circleci.com/gh/rubocop/rubocop/tree/master.svg?style=svg)](https://circleci.com/gh/rubocop/rubocop/tree/master)
9
8
  [![Actions Status](https://github.com/rubocop/rubocop/workflows/CI/badge.svg?branch=master)](https://github.com/rubocop/rubocop/actions?query=workflow%3ACI)
10
9
  [![Test Coverage](https://api.codeclimate.com/v1/badges/d2d67f728e88ea84ac69/test_coverage)](https://codeclimate.com/github/rubocop/rubocop/test_coverage)
11
10
  [![Maintainability](https://api.codeclimate.com/v1/badges/d2d67f728e88ea84ac69/maintainability)](https://codeclimate.com/github/rubocop/rubocop/maintainability)
@@ -53,7 +52,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
53
52
  in your `Gemfile`:
54
53
 
55
54
  ```rb
56
- gem 'rubocop', '~> 1.63', require: false
55
+ gem 'rubocop', '~> 1.64', require: false
57
56
  ```
58
57
 
59
58
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -156,7 +156,7 @@ AllCops:
156
156
  # included.
157
157
  SuggestExtensions:
158
158
  rubocop-rails: [rails]
159
- rubocop-rspec: [rspec]
159
+ rubocop-rspec: [rspec, rspec-rails]
160
160
  rubocop-minitest: [minitest]
161
161
  rubocop-sequel: [sequel]
162
162
  rubocop-rake: [rake]
@@ -3090,6 +3090,7 @@ Style/AccessModifierDeclarations:
3090
3090
  - inline
3091
3091
  - group
3092
3092
  AllowModifiersOnSymbols: true
3093
+ AllowModifiersOnAttrs: true
3093
3094
  SafeAutoCorrect: false
3094
3095
 
3095
3096
  Style/AccessorGrouping:
@@ -3687,6 +3688,7 @@ Style/DocumentationMethod:
3687
3688
  Description: 'Checks for missing documentation comment for public methods.'
3688
3689
  Enabled: false
3689
3690
  VersionAdded: '0.43'
3691
+ AllowedMethods: []
3690
3692
  Exclude:
3691
3693
  - 'spec/**/*'
3692
3694
  - 'test/**/*'
@@ -4068,6 +4070,8 @@ Style/HashSyntax:
4068
4070
  - either
4069
4071
  # forces use of the 3.1 syntax only if all values can be omitted in the hash.
4070
4072
  - consistent
4073
+ # allow either (implicit or explicit) syntax but enforce consistency within a single hash
4074
+ - either_consistent
4071
4075
  # Force hashes that have a symbol value to use hash rockets
4072
4076
  UseHashRocketsWithSymbolValues: false
4073
4077
  # Do not suggest { a?: 1 } over { :a? => 1 } in ruby19 style
@@ -5240,6 +5244,13 @@ Style/Send:
5240
5244
  Enabled: false
5241
5245
  VersionAdded: '0.33'
5242
5246
 
5247
+ Style/SendWithLiteralMethodName:
5248
+ Description: 'Detects the use of the `public_send` method with a static method name argument.'
5249
+ Enabled: pending
5250
+ Safe: false
5251
+ AllowSend: true
5252
+ VersionAdded: '1.64'
5253
+
5243
5254
  Style/SignalException:
5244
5255
  Description: 'Checks for proper usage of fail and raise.'
5245
5256
  StyleGuide: '#prefer-raise-over-fail'
@@ -5414,6 +5425,11 @@ Style/StructInheritance:
5414
5425
  VersionAdded: '0.29'
5415
5426
  VersionChanged: '1.20'
5416
5427
 
5428
+ Style/SuperArguments:
5429
+ Description: 'Call `super` without arguments and parentheses when the signature is identical.'
5430
+ Enabled: pending
5431
+ VersionAdded: '1.64'
5432
+
5417
5433
  Style/SuperWithArgsParentheses:
5418
5434
  Description: 'Use parentheses for `super` with arguments.'
5419
5435
  StyleGuide: '#super-with-args'
@@ -5449,7 +5465,7 @@ Style/SymbolProc:
5449
5465
  Enabled: true
5450
5466
  Safe: false
5451
5467
  VersionAdded: '0.26'
5452
- VersionChanged: '1.40'
5468
+ VersionChanged: '1.64'
5453
5469
  AllowMethodsWithArguments: false
5454
5470
  # A list of method names to be always allowed by the check.
5455
5471
  # The names should be fairly unique, otherwise you'll end up ignoring lots of code.
@@ -26,10 +26,10 @@ module RuboCop
26
26
 
27
27
  cops_array.each do |cop_name|
28
28
  cop = registry_hash[cop_name]
29
-
30
29
  next if cop.empty?
31
30
 
32
- puts Cop::Documentation.url_for(cop.first, @config)
31
+ url = Cop::Documentation.url_for(cop.first, @config)
32
+ puts url if url
33
33
  end
34
34
 
35
35
  puts
@@ -319,9 +319,8 @@ module RuboCop
319
319
  # @param [Gem::Version] gem_version an object like `Gem::Version.new("7.1.2.3")`
320
320
  # @return [Float] The major and minor version, like `7.1`
321
321
  def gem_version_to_major_minor_float(gem_version)
322
- segments = gem_version.canonical_segments
323
- # segments.fetch(0).to_f + (segments.fetch(1, 0.0).to_f / 10)
324
- Float("#{segments.fetch(0)}.#{segments.fetch(1, 0)}")
322
+ segments = gem_version.segments
323
+ Float("#{segments[0]}.#{segments[1]}")
325
324
  end
326
325
 
327
326
  # @returns [Hash{String => Gem::Version}] The locked gem versions, keyed by the gems' names.
@@ -60,12 +60,15 @@ module RuboCop
60
60
  []
61
61
  end
62
62
 
63
- # Cops (other than builtin) are encouraged to implement this
63
+ # Returns an url to view this cops documentation online.
64
+ # Requires 'DocumentationBaseURL' to be set for your department.
65
+ # Will follow the convention of RuboCops own documentation structure,
66
+ # overwrite this method to accommodate your custom layout.
64
67
  # @return [String, nil]
65
68
  #
66
69
  # @api public
67
- def self.documentation_url
68
- Documentation.url_for(self) if builtin?
70
+ def self.documentation_url(config = nil)
71
+ Documentation.url_for(self, config)
69
72
  end
70
73
 
71
74
  def self.inherited(subclass)
@@ -398,16 +401,6 @@ module RuboCop
398
401
 
399
402
  ### Actually private methods
400
403
 
401
- # rubocop:disable Layout/ClassStructure
402
- def self.builtin?
403
- return false unless (m = instance_methods(false).first) # any custom method will do
404
-
405
- path, _line = instance_method(m).source_location
406
- path.start_with?(__dir__)
407
- end
408
- private_class_method :builtin?
409
- # rubocop:enable Layout/ClassStructure
410
-
411
404
  def reset_investigation
412
405
  @currently_disabled_lines = @current_offenses = @processed_source = @current_corrector = nil
413
406
  end
@@ -90,13 +90,11 @@ module RuboCop
90
90
  Array(cop_config['AllowedGems'])
91
91
  end
92
92
 
93
- def message(range)
94
- gem_specification = range.source
95
-
93
+ def message(_range)
96
94
  if required_style?
97
- format(REQUIRED_MSG, gem_specification: gem_specification)
95
+ REQUIRED_MSG
98
96
  elsif forbidden_style?
99
- format(FORBIDDEN_MSG, gem_specification: gem_specification)
97
+ FORBIDDEN_MSG
100
98
  end
101
99
  end
102
100
 
@@ -17,23 +17,33 @@ module RuboCop
17
17
  fragment = cop_class.cop_name.downcase.gsub(/[^a-z]/, '')
18
18
  base_url = base_url_for(cop_class, config)
19
19
 
20
- "#{base_url}/#{base}.html##{fragment}"
20
+ "#{base_url}/#{base}.html##{fragment}" if base_url
21
21
  end
22
22
 
23
23
  # @api private
24
24
  def base_url_for(cop_class, config)
25
- return default_base_url unless config
25
+ if config
26
+ department_name = cop_class.department.to_s
27
+ url = config.for_department(department_name)['DocumentationBaseURL']
28
+ return url if url
29
+ end
26
30
 
27
- department_name = cop_class.department.to_s
28
-
29
- config.for_department(department_name)['DocumentationBaseURL'] ||
30
- config.for_all_cops['DocumentationBaseURL']
31
+ default_base_url if builtin?(cop_class)
31
32
  end
32
33
 
33
34
  # @api private
34
35
  def default_base_url
35
36
  'https://docs.rubocop.org/rubocop'
36
37
  end
38
+
39
+ # @api private
40
+ def builtin?(cop_class)
41
+ # any custom method will do
42
+ return false unless (m = cop_class.instance_methods(false).first)
43
+
44
+ path, _line = cop_class.instance_method(m).source_location
45
+ path.start_with?(__dir__)
46
+ end
37
47
  end
38
48
  end
39
49
  end
@@ -4,6 +4,16 @@ module RuboCop
4
4
  module Cop
5
5
  # A scaffold for concrete forces.
6
6
  class Force
7
+ # @api private
8
+ class HookError < StandardError
9
+ attr_reader :joining_cop
10
+
11
+ def initialize(joining_cop)
12
+ super
13
+ @joining_cop = joining_cop
14
+ end
15
+ end
16
+
7
17
  attr_reader :cops
8
18
 
9
19
  def self.all
@@ -32,6 +42,8 @@ module RuboCop
32
42
  next unless cop.respond_to?(method_name)
33
43
 
34
44
  cop.public_send(method_name, *args)
45
+ rescue StandardError
46
+ raise HookError, cop
35
47
  end
36
48
  end
37
49
 
@@ -101,13 +101,11 @@ module RuboCop
101
101
  Array(cop_config['AllowedGems'])
102
102
  end
103
103
 
104
- def message(range)
105
- gem_specification = range.source
106
-
104
+ def message(_range)
107
105
  if required_style?
108
- format(REQUIRED_MSG, gem_specification: gem_specification)
106
+ REQUIRED_MSG
109
107
  elsif forbidden_style?
110
- format(FORBIDDEN_MSG, gem_specification: gem_specification)
108
+ FORBIDDEN_MSG
111
109
  end
112
110
  end
113
111
 
@@ -106,7 +106,9 @@ module RuboCop
106
106
  end
107
107
 
108
108
  def concat_consecutive_comments(comments)
109
- consecutive_comments = comments.chunk_while { |i, j| i.loc.line.succ == j.loc.line }
109
+ consecutive_comments = comments.chunk_while do |i, j|
110
+ i.loc.line.succ == j.loc.line && i.loc.column == j.loc.column
111
+ end
110
112
 
111
113
  consecutive_comments.map do |chunk|
112
114
  joined_text = chunk.map { |c| comment_text(c) }.join
@@ -25,8 +25,7 @@ module RuboCop
25
25
  include RangeHelp
26
26
  extend AutoCorrector
27
27
 
28
- NO_SPACE_MSG = 'Space inside string interpolation detected.'
29
- SPACE_MSG = 'Missing space inside string interpolation detected.'
28
+ MSG = '%<command>s space inside string interpolation.'
30
29
 
31
30
  def on_interpolation(begin_node)
32
31
  return if begin_node.multiline?
@@ -36,9 +35,9 @@ module RuboCop
36
35
  return if empty_brackets?(left, right, tokens: tokens)
37
36
 
38
37
  if style == :no_space
39
- no_space_offenses(begin_node, left, right, NO_SPACE_MSG)
38
+ no_space_offenses(begin_node, left, right, MSG)
40
39
  else
41
- space_offenses(begin_node, left, right, SPACE_MSG)
40
+ space_offenses(begin_node, left, right, MSG)
42
41
  end
43
42
  end
44
43
 
@@ -65,17 +65,15 @@ module RuboCop
65
65
 
66
66
  minimum_target_ruby_version 2.6
67
67
 
68
- MESSAGES = [
69
- 'Passing safe_level with the 2nd argument of `ERB.new` is ' \
70
- 'deprecated. Do not use it, and specify other arguments as ' \
71
- 'keyword arguments.',
72
- 'Passing trim_mode with the 3rd argument of `ERB.new` is ' \
73
- 'deprecated. Use keyword argument like ' \
74
- '`ERB.new(str, trim_mode: %<arg_value>s)` instead.',
75
- 'Passing eoutvar with the 4th argument of `ERB.new` is ' \
76
- 'deprecated. Use keyword argument like ' \
77
- '`ERB.new(str, eoutvar: %<arg_value>s)` instead.'
78
- ].freeze
68
+ MESSAGE_SAFE_LEVEL = 'Passing safe_level with the 2nd argument of `ERB.new` is ' \
69
+ 'deprecated. Do not use it, and specify other arguments as ' \
70
+ 'keyword arguments.'
71
+ MESSAGE_TRIM_MODE = 'Passing trim_mode with the 3rd argument of `ERB.new` is ' \
72
+ 'deprecated. Use keyword argument like ' \
73
+ '`ERB.new(str, trim_mode: %<arg_value>s)` instead.'
74
+ MESSAGE_EOUTVAR = 'Passing eoutvar with the 4th argument of `ERB.new` is ' \
75
+ 'deprecated. Use keyword argument like ' \
76
+ '`ERB.new(str, eoutvar: %<arg_value>s)` instead.'
79
77
 
80
78
  RESTRICT_ON_SEND = %i[new].freeze
81
79
 
@@ -92,10 +90,8 @@ module RuboCop
92
90
  arguments[1..3].each_with_index do |argument, i|
93
91
  next if !argument || argument.hash_type?
94
92
 
95
- message = format(MESSAGES[i], arg_value: argument.source)
96
-
97
93
  add_offense(
98
- argument.source_range, message: message
94
+ argument.source_range, message: message(i, argument.source)
99
95
  ) do |corrector|
100
96
  autocorrect(corrector, node)
101
97
  end
@@ -105,6 +101,17 @@ module RuboCop
105
101
 
106
102
  private
107
103
 
104
+ def message(positional_argument_index, arg_value)
105
+ case positional_argument_index
106
+ when 0
107
+ MESSAGE_SAFE_LEVEL
108
+ when 1
109
+ format(MESSAGE_TRIM_MODE, arg_value: arg_value)
110
+ when 2
111
+ format(MESSAGE_EOUTVAR, arg_value: arg_value)
112
+ end
113
+ end
114
+
108
115
  def autocorrect(corrector, node)
109
116
  str_arg = node.first_argument.source
110
117
 
@@ -43,13 +43,13 @@ module RuboCop
43
43
  types.map do |type|
44
44
  case type
45
45
  when :array
46
- ->(node) { node.array_type? }
46
+ lambda(&:array_type?)
47
47
  when :hash
48
- ->(node) { node.hash_type? }
48
+ lambda(&:hash_type?)
49
49
  when :heredoc
50
50
  ->(node) { heredoc_node?(node) }
51
51
  when :method_call
52
- ->(node) { node.call_type? }
52
+ lambda(&:call_type?)
53
53
  else
54
54
  raise Warning, "Unknown foldable type: #{type.inspect}. " \
55
55
  "Valid foldable types are: #{FOLDABLE_TYPES.join(', ')}."
@@ -67,13 +67,14 @@ module RuboCop
67
67
  end
68
68
 
69
69
  def ignore_mixed_hash_shorthand_syntax?(hash_node)
70
- target_ruby_version <= 3.0 || enforced_shorthand_syntax != 'consistent' ||
70
+ target_ruby_version <= 3.0 ||
71
+ !%w[consistent either_consistent].include?(enforced_shorthand_syntax) ||
71
72
  !hash_node.hash_type?
72
73
  end
73
74
 
74
75
  def ignore_hash_shorthand_syntax?(pair_node)
75
76
  target_ruby_version <= 3.0 || enforced_shorthand_syntax == 'either' ||
76
- enforced_shorthand_syntax == 'consistent' ||
77
+ %w[consistent either_consistent].include?(enforced_shorthand_syntax) ||
77
78
  !pair_node.parent.hash_type?
78
79
  end
79
80
 
@@ -172,6 +173,11 @@ module RuboCop
172
173
  hash_value_type_breakdown[:value_needed]&.any?
173
174
  end
174
175
 
176
+ def ignore_explicit_omissible_hash_shorthand_syntax?(hash_value_type_breakdown)
177
+ hash_value_type_breakdown.keys == [:value_omittable] &&
178
+ enforced_shorthand_syntax == 'either_consistent'
179
+ end
180
+
175
181
  def each_omitted_value_pair(hash_value_type_breakdown, &block)
176
182
  hash_value_type_breakdown[:value_omitted]&.each(&block)
177
183
  end
@@ -198,6 +204,7 @@ module RuboCop
198
204
 
199
205
  def no_mixed_shorthand_syntax_check(hash_value_type_breakdown)
200
206
  return if hash_with_values_that_cant_be_omitted?(hash_value_type_breakdown)
207
+ return if ignore_explicit_omissible_hash_shorthand_syntax?(hash_value_type_breakdown)
201
208
 
202
209
  each_omittable_value_pair(hash_value_type_breakdown) do |pair_node|
203
210
  hash_key_source = pair_node.key.source
@@ -8,6 +8,17 @@ module RuboCop
8
8
  # EnforcedStyle config covers only method definitions.
9
9
  # Applications of visibility methods to symbols can be controlled
10
10
  # using AllowModifiersOnSymbols config.
11
+ # Also, the visibility of `attr*` methods can be controlled using
12
+ # AllowModifiersOnAttrs config.
13
+ #
14
+ # In Ruby 3.0, `attr*` methods now return an array of defined method names
15
+ # as symbols. So we can write the modifier and `attr*` in inline style.
16
+ # AllowModifiersOnAttrs config allows `attr*` methods to be written in
17
+ # inline style without modifying applications that have been maintained
18
+ # for a long time in group style. Furthermore, developers who are not very
19
+ # familiar with Ruby may know that the modifier applies to `def`, but they
20
+ # may not know that it also applies to `attr*` methods. It would be easier
21
+ # to understand if we could write `attr*` methods in inline style.
11
22
  #
12
23
  # @safety
13
24
  # Autocorrection is not safe, because the visibility of dynamically
@@ -67,6 +78,34 @@ module RuboCop
67
78
  # private :bar, :baz
68
79
  #
69
80
  # end
81
+ #
82
+ # @example AllowModifiersOnAttrs: true (default)
83
+ # # good
84
+ # class Foo
85
+ #
86
+ # public attr_reader :bar
87
+ # protected attr_writer :baz
88
+ # private attr_accessor :qux
89
+ # private attr :quux
90
+ #
91
+ # def public_method; end
92
+ #
93
+ # private
94
+ #
95
+ # def private_method; end
96
+ #
97
+ # end
98
+ #
99
+ # @example AllowModifiersOnAttrs: false
100
+ # # bad
101
+ # class Foo
102
+ #
103
+ # public attr_reader :bar
104
+ # protected attr_writer :baz
105
+ # private attr_accessor :qux
106
+ # private attr :quux
107
+ #
108
+ # end
70
109
  class AccessModifierDeclarations < Base
71
110
  extend AutoCorrector
72
111
 
@@ -92,10 +131,17 @@ module RuboCop
92
131
  (send nil? {:private :protected :public :module_function} (sym _))
93
132
  PATTERN
94
133
 
134
+ # @!method access_modifier_with_attr?(node)
135
+ def_node_matcher :access_modifier_with_attr?, <<~PATTERN
136
+ (send nil? {:private :protected :public :module_function}
137
+ (send nil? {:attr :attr_reader :attr_writer :attr_accessor} _))
138
+ PATTERN
139
+
95
140
  def on_send(node)
96
141
  return unless node.access_modifier?
97
142
  return if ALLOWED_NODE_TYPES.include?(node.parent&.type)
98
143
  return if allow_modifiers_on_symbols?(node)
144
+ return if allow_modifiers_on_attrs?(node)
99
145
 
100
146
  if offense?(node)
101
147
  add_offense(node.loc.selector) do |corrector|
@@ -128,6 +174,10 @@ module RuboCop
128
174
  cop_config['AllowModifiersOnSymbols'] && access_modifier_with_symbol?(node)
129
175
  end
130
176
 
177
+ def allow_modifiers_on_attrs?(node)
178
+ cop_config['AllowModifiersOnAttrs'] && access_modifier_with_attr?(node)
179
+ end
180
+
131
181
  def offense?(node)
132
182
  (group_style? && access_modifier_is_inlined?(node) &&
133
183
  !right_siblings_same_inline_method?(node)) ||
@@ -29,6 +29,8 @@ module RuboCop
29
29
  #
30
30
  # Names not on this list are likely to be meaningful and are allowed by default.
31
31
  #
32
+ # This cop handles not only method forwarding but also forwarding to `super`.
33
+ #
32
34
  # @example
33
35
  # # bad
34
36
  # def foo(*args, &block)
@@ -146,7 +148,7 @@ module RuboCop
146
148
 
147
149
  restarg, kwrestarg, blockarg = extract_forwardable_args(node.arguments)
148
150
  forwardable_args = redundant_forwardable_named_args(restarg, kwrestarg, blockarg)
149
- send_nodes = node.each_descendant(:send).to_a
151
+ send_nodes = node.each_descendant(:send, :csend, :super).to_a
150
152
 
151
153
  send_classifications = classify_send_nodes(
152
154
  node, send_nodes, non_splat_or_block_pass_lvar_references(node.body), forwardable_args
@@ -58,12 +58,15 @@ module RuboCop
58
58
  end
59
59
 
60
60
  def verify_autocorrect_notice!
61
- raise Warning, AUTOCORRECT_EMPTY_WARNING if autocorrect_notice.empty?
61
+ if autocorrect_notice.nil? || autocorrect_notice.empty?
62
+ raise Warning, "#{cop_name}: #{AUTOCORRECT_EMPTY_WARNING}"
63
+ end
62
64
 
63
65
  regex = Regexp.new(notice)
64
- return if autocorrect_notice&.match?(regex)
66
+ return if autocorrect_notice.gsub(/^# */, '').match?(regex)
65
67
 
66
- raise Warning, "AutocorrectNotice '#{autocorrect_notice}' must match Notice /#{notice}/"
68
+ message = "AutocorrectNotice '#{autocorrect_notice}' must match Notice /#{notice}/"
69
+ raise Warning, "#{cop_name}: #{message}"
67
70
  end
68
71
 
69
72
  def insert_notice_before(processed_source)
@@ -77,26 +80,28 @@ module RuboCop
77
80
  return false if token_index >= processed_source.tokens.size
78
81
 
79
82
  token = processed_source.tokens[token_index]
80
- token.comment? && /^#!.*$/.match?(token.text)
83
+ token.comment? && /\A#!.*\z/.match?(token.text)
81
84
  end
82
85
 
83
86
  def encoding_token?(processed_source, token_index)
84
87
  return false if token_index >= processed_source.tokens.size
85
88
 
86
89
  token = processed_source.tokens[token_index]
87
- token.comment? && /^#.*coding\s?[:=]\s?(?:UTF|utf)-8/.match?(token.text)
90
+ token.comment? && /\A#.*coding\s?[:=]\s?(?:UTF|utf)-8/.match?(token.text)
88
91
  end
89
92
 
90
93
  def notice_found?(processed_source)
91
- notice_found = false
92
- notice_regexp = Regexp.new(notice)
94
+ notice_regexp = Regexp.new(notice.lines.map(&:strip).join)
95
+ multiline_notice = +''
93
96
  processed_source.tokens.each do |token|
94
97
  break unless token.comment?
95
98
 
96
- notice_found = notice_regexp.match?(token.text)
97
- break if notice_found
99
+ multiline_notice << token.text.sub(/\A# */, '')
100
+
101
+ break if notice_regexp.match?(token.text)
98
102
  end
99
- notice_found
103
+
104
+ multiline_notice.match?(notice_regexp)
100
105
  end
101
106
  end
102
107
  end
@@ -29,36 +29,36 @@ module RuboCop
29
29
  # end
30
30
  #
31
31
  # # allowed
32
- # # Class without body
32
+ # # Class without body
33
+ # class Person
34
+ # end
35
+ #
36
+ # # Namespace - A namespace can be a class or a module
37
+ # # Containing a class
38
+ # module Namespace
39
+ # # Description/Explanation of Person class
33
40
  # class Person
41
+ # # ...
34
42
  # end
43
+ # end
35
44
  #
36
- # # Namespace - A namespace can be a class or a module
37
- # # Containing a class
38
- # module Namespace
39
- # # Description/Explanation of Person class
40
- # class Person
41
- # # ...
42
- # end
45
+ # # Containing constant visibility declaration
46
+ # module Namespace
47
+ # class Private
43
48
  # end
44
49
  #
45
- # # Containing constant visibility declaration
46
- # module Namespace
47
- # class Private
48
- # end
49
- #
50
- # private_constant :Private
51
- # end
50
+ # private_constant :Private
51
+ # end
52
52
  #
53
- # # Containing constant definition
54
- # module Namespace
55
- # Public = Class.new
56
- # end
53
+ # # Containing constant definition
54
+ # module Namespace
55
+ # Public = Class.new
56
+ # end
57
57
  #
58
- # # Macro calls
59
- # module Namespace
60
- # extend Foo
61
- # end
58
+ # # Macro calls
59
+ # module Namespace
60
+ # extend Foo
61
+ # end
62
62
  #
63
63
  # @example AllowedConstants: ['ClassMethods']
64
64
  #
@@ -67,7 +67,7 @@ module RuboCop
67
67
  # module ClassMethods
68
68
  # # ...
69
69
  # end
70
- # end
70
+ # end
71
71
  #
72
72
  class Documentation < Base
73
73
  include DocumentationComment