rubocop 0.37.0 → 0.37.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rubocop might be problematic. Click here for more details.

Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +2 -3
  4. data/config/enabled.yml +2 -2
  5. data/lib/rubocop.rb +2 -1
  6. data/lib/rubocop/ast_node.rb +34 -17
  7. data/lib/rubocop/ast_node/traversal.rb +2 -1
  8. data/lib/rubocop/config.rb +1 -1
  9. data/lib/rubocop/cop/commissioner.rb +5 -5
  10. data/lib/rubocop/cop/corrector.rb +17 -3
  11. data/lib/rubocop/cop/lint/debugger.rb +2 -2
  12. data/lib/rubocop/cop/lint/nested_method_definition.rb +5 -1
  13. data/lib/rubocop/cop/lint/unneeded_disable.rb +1 -1
  14. data/lib/rubocop/cop/metrics/parameter_lists.rb +1 -1
  15. data/lib/rubocop/cop/performance/redundant_match.rb +2 -1
  16. data/lib/rubocop/cop/performance/redundant_merge.rb +1 -2
  17. data/lib/rubocop/cop/rails/find_each.rb +1 -1
  18. data/lib/rubocop/cop/style/block_end_newline.rb +1 -1
  19. data/lib/rubocop/cop/style/conditional_assignment.rb +25 -7
  20. data/lib/rubocop/cop/style/empty_line_between_defs.rb +13 -7
  21. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -12
  22. data/lib/rubocop/cop/style/guard_clause.rb +3 -1
  23. data/lib/rubocop/cop/style/initial_indentation.rb +1 -1
  24. data/lib/rubocop/cop/style/line_end_concatenation.rb +1 -1
  25. data/lib/rubocop/cop/style/multiline_block_layout.rb +14 -12
  26. data/lib/rubocop/cop/style/not.rb +1 -1
  27. data/lib/rubocop/cop/style/semicolon.rb +14 -7
  28. data/lib/rubocop/cop/style/space_around_keyword.rb +13 -4
  29. data/lib/rubocop/cop/style/space_around_operators.rb +2 -2
  30. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +32 -27
  31. data/lib/rubocop/cop/style/word_array.rb +1 -1
  32. data/lib/rubocop/cop/team.rb +20 -9
  33. data/lib/rubocop/cop/util.rb +4 -5
  34. data/lib/rubocop/formatter/formatter_set.rb +3 -3
  35. data/lib/rubocop/version.rb +1 -1
  36. metadata +5 -43
  37. data/.yardopts +0 -2
  38. data/CHANGELOG.md +0 -1941
  39. data/CONTRIBUTING.md +0 -68
  40. data/assets/logo.png +0 -0
  41. data/assets/output.html.erb +0 -247
  42. data/logo/rubo-logo-horizontal.png +0 -0
  43. data/logo/rubo-logo-square.png +0 -0
  44. data/logo/rubo-logo-symbol.png +0 -0
  45. data/relnotes/v0.19.0.md +0 -94
  46. data/relnotes/v0.19.1.md +0 -16
  47. data/relnotes/v0.20.0.md +0 -69
  48. data/relnotes/v0.20.1.md +0 -24
  49. data/relnotes/v0.21.0.md +0 -56
  50. data/relnotes/v0.22.0.md +0 -77
  51. data/relnotes/v0.23.0.md +0 -79
  52. data/relnotes/v0.24.0.md +0 -77
  53. data/relnotes/v0.24.1.md +0 -15
  54. data/relnotes/v0.25.0.md +0 -91
  55. data/relnotes/v0.26.0.md +0 -89
  56. data/relnotes/v0.26.1.md +0 -12
  57. data/relnotes/v0.27.0.md +0 -77
  58. data/relnotes/v0.27.1.md +0 -66
  59. data/relnotes/v0.28.0.md +0 -90
  60. data/relnotes/v0.29.0.md +0 -116
  61. data/relnotes/v0.29.1.md +0 -12
  62. data/relnotes/v0.30.0.md +0 -145
  63. data/relnotes/v0.30.1.md +0 -103
  64. data/relnotes/v0.31.0.md +0 -120
  65. data/relnotes/v0.32.0.md +0 -139
  66. data/relnotes/v0.32.1.md +0 -122
  67. data/relnotes/v0.33.0.md +0 -157
  68. data/relnotes/v0.34.0.md +0 -182
  69. data/relnotes/v0.34.1.md +0 -129
  70. data/relnotes/v0.34.2.md +0 -139
  71. data/relnotes/v0.35.0.md +0 -210
  72. data/relnotes/v0.36.0.md +0 -307
  73. data/relnotes/v0.37.0.md +0 -200
  74. data/rubocop.gemspec +0 -49
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4bdbb9f710745091d21b8fb1bc741a5964d7ad0f
4
- data.tar.gz: 0c1bdb92f40935b9d9209c78e006a444e85ad5c1
3
+ metadata.gz: b67d84c23023e9ebfbbf8c68e50d03e81e635f49
4
+ data.tar.gz: 0a3e93f819e257610f970bc086d5e99578ad4655
5
5
  SHA512:
6
- metadata.gz: 2f58d0c665369ccdcff54b88b35bd032327b0460ccb6a7b05101cbf853f6895f491636c11e59824b14cd54c87f599187ec41790902f7ff8bfd2f7a3a5febd9ba
7
- data.tar.gz: 59de02eb56cc687d3dd664ee540d7338a8968b8ffe758a72596455d2cf2c48c8103b3fe54970d19b947abef418407a2af579d0f5e4d9fd06dc0b626a18af58d9
6
+ metadata.gz: da04ad8512393920149f4ae5d0e9b284ebf91e1cff0c22df0261b432d4b30c4b1adb192df930a66e34e308a4a97c0ad5ed5024f11f99b8e55a7ce6784ed18ba2
7
+ data.tar.gz: df9eab441cdd4086a3af7a6ba5724e15cd6a047773c0acfb75ee47380e14681f3b613bfd5b69a3de2c15b54c2bc6c04d5814c271d61afc96e89d1b58c93ee8cd
data/README.md CHANGED
@@ -115,7 +115,7 @@ haven't reached version 1.0 yet). To prevent an unwanted RuboCop update you
115
115
  might want to use a conservative version locking in your `Gemfile`:
116
116
 
117
117
  ```rb
118
- gem 'rubocop', '~> 0.36.0', require: false
118
+ gem 'rubocop', '~> 0.37.1', require: false
119
119
  ```
120
120
 
121
121
  ## Basic Usage
@@ -481,9 +481,8 @@ Style/FormatString:
481
481
  Style/FrozenStringLiteralComment:
482
482
  EnforcedStyle: when_needed
483
483
  SupportedStyles:
484
- # `when_needed` will add the frozen string literal comment to files that call
485
- # `freeze` or `<<` on a string literal. It will only add the comment to files
486
- # when running Ruby 2.3.0+.
484
+ # `when_needed` will add the frozen string literal comment to files
485
+ # only when the `TargetRubyVersion` is set to 2.3+.
487
486
  - when_needed
488
487
  # `always` will always add the frozen string literal comment to a file
489
488
  # regardless of the Ruby version or if `freeze` or `<<` are called on a
@@ -620,7 +620,7 @@ Style/Semicolon:
620
620
 
621
621
  Style/SignalException:
622
622
  Description: 'Checks for proper usage of fail and raise.'
623
- StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#fail-method'
623
+ StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#prefer-raise-over-fail'
624
624
  Enabled: true
625
625
 
626
626
  Style/SingleLineBlockParams:
@@ -1239,7 +1239,7 @@ Performance/RedundantMatch:
1239
1239
  Enabled: true
1240
1240
 
1241
1241
  Performance/RedundantMerge:
1242
- Description: 'Use Hash#[]=, rather than Hash#merge! or Hash#update with a single key-value pair.'
1242
+ Description: 'Use Hash#[]=, rather than Hash#merge! with a single key-value pair.'
1243
1243
  Reference: 'https://github.com/JuanitoFatas/fast-ruby#hashmerge-vs-hash-code'
1244
1244
  Enabled: true
1245
1245
 
@@ -34,7 +34,6 @@ require 'rubocop/cop/cop'
34
34
  require 'rubocop/cop/commissioner'
35
35
  require 'rubocop/cop/corrector'
36
36
  require 'rubocop/cop/force'
37
- require 'rubocop/cop/team'
38
37
  require 'rubocop/cop/severity'
39
38
 
40
39
  require 'rubocop/cop/variable_force'
@@ -369,6 +368,8 @@ require 'rubocop/cop/rails/scope_args'
369
368
  require 'rubocop/cop/rails/time_zone'
370
369
  require 'rubocop/cop/rails/validation'
371
370
 
371
+ require 'rubocop/cop/team'
372
+
372
373
  require 'rubocop/formatter/base_formatter'
373
374
  require 'rubocop/formatter/simple_text_formatter'
374
375
  require 'rubocop/formatter/clang_style_formatter' # relies on simple text
@@ -43,8 +43,6 @@ module RuboCop
43
43
  OPERATOR_KEYWORDS = [:and, :or].freeze
44
44
  SPECIAL_KEYWORDS = %w(__FILE__ __LINE__ __ENCODING__).freeze
45
45
 
46
- RSPEC_METHODS = [:describe, :it].freeze
47
-
48
46
  # def_matcher can be used to define a pattern-matching method on Node
49
47
  class << self
50
48
  def def_matcher(method_name, pattern_str)
@@ -331,23 +329,47 @@ module RuboCop
331
329
  # to keep traversing up through nested classes/modules
332
330
  ancestor.defined_module_name
333
331
  when :sclass
334
- obj = ancestor.children[0]
335
- # TODO: look for constant definition and see if it is nested
336
- # inside a class or module
337
- return "#<Class:#{obj.const_name}>" if obj.const_type?
338
- return "#<Class:#{ancestor.parent_module_name}>" if obj.self_type?
339
- return nil
332
+ return parent_module_name_for_sclass(ancestor)
340
333
  else # block
341
- return nil if ancestor.known_dsl?
342
- if ancestor.method_name == :class_eval && ancestor.receiver
343
- return nil unless ancestor.receiver.const_type?
344
- ancestor.receiver.const_name
334
+ if ancestor.method_name == :class_eval
335
+ # `class_eval` with no receiver applies to whatever module or class
336
+ # we are currently in
337
+ next unless (receiver = ancestor.receiver)
338
+ return nil unless receiver.const_type?
339
+ receiver.const_name
340
+ elsif new_class_or_module_block?(ancestor)
341
+ # we will catch this in the `casgn` branch above
342
+ next
343
+ else
344
+ return nil
345
345
  end
346
346
  end
347
347
  end.compact.reverse.join('::')
348
348
  result.empty? ? 'Object' : result
349
349
  end
350
350
 
351
+ def parent_module_name_for_sclass(sclass_node)
352
+ # TODO: look for constant definition and see if it is nested
353
+ # inside a class or module
354
+ subject = sclass_node.children[0]
355
+
356
+ if subject.const_type?
357
+ "#<Class:#{subject.const_name}>"
358
+ elsif subject.self_type?
359
+ "#<Class:#{sclass_node.parent_module_name}>"
360
+ end
361
+ end
362
+
363
+ def new_class_or_module_block?(block_node)
364
+ receiver = block_node.receiver
365
+
366
+ block_node.method_name == :new &&
367
+ receiver && receiver.const_type? &&
368
+ (receiver.const_name == 'Class' || receiver.const_name == 'Module') &&
369
+ block_node.parent &&
370
+ block_node.parent.casgn_type?
371
+ end
372
+
351
373
  ## Predicates
352
374
 
353
375
  def multiline?
@@ -524,11 +546,6 @@ module RuboCop
524
546
  end
525
547
  end
526
548
 
527
- # Known DSL methods which eval body inside an anonymous class/module
528
- def known_dsl?
529
- RSPEC_METHODS.include?(method_name) && receiver.nil?
530
- end
531
-
532
549
  protected
533
550
 
534
551
  def visit_descendants(&block)
@@ -149,7 +149,8 @@ module RuboCop
149
149
 
150
150
  def on_block(node)
151
151
  children = node.children
152
- on_send(children[0])
152
+ child = children[0]
153
+ send(:"on_#{child.type}", child) # can be send, zsuper...
153
154
  on_args(children[1])
154
155
  return unless (child = children[2])
155
156
  send(:"on_#{child.type}", child)
@@ -255,7 +255,7 @@ module RuboCop
255
255
  end
256
256
 
257
257
  def check_obsolete_parameter(cop, parameter, alternative = nil)
258
- if key?(cop) && self[cop].key?(parameter)
258
+ if self[cop] && self[cop].key?(parameter)
259
259
  raise ValidationError, "obsolete parameter #{parameter} (for #{cop}) " \
260
260
  "found in #{loaded_path}" \
261
261
  "#{"\n" if alternative}#{alternative}"
@@ -35,6 +35,9 @@ module RuboCop
35
35
  next unless RuboCop::Node::Traversal.method_defined?(callback)
36
36
  class_eval <<-EOS, __FILE__, __LINE__
37
37
  def #{callback}(node)
38
+ @callbacks[:"#{callback}"] ||= @cops.select do |cop|
39
+ cop.respond_to?(:"#{callback}")
40
+ end
38
41
  @callbacks[:#{callback}].each do |cop|
39
42
  with_cop_error_handling(cop) do
40
43
  cop.send(:#{callback}, node)
@@ -49,7 +52,7 @@ module RuboCop
49
52
  def investigate(processed_source)
50
53
  reset_errors
51
54
  remove_irrelevant_cops(processed_source.buffer.name)
52
- setup_callbacks
55
+ reset_callbacks
53
56
  prepare(processed_source)
54
57
  invoke_custom_processing(@cops, processed_source)
55
58
  invoke_custom_processing(@forces, processed_source)
@@ -67,11 +70,8 @@ module RuboCop
67
70
  @cops.reject! { |cop| cop.excluded_file?(filename) }
68
71
  end
69
72
 
70
- def setup_callbacks
73
+ def reset_callbacks
71
74
  @callbacks.clear
72
- self.class.callback_methods.each do |method|
73
- @callbacks[method] = @cops.select { |cop| cop.respond_to?(method) }
74
- end
75
75
  end
76
76
 
77
77
  # TODO: Bad design.
@@ -31,21 +31,35 @@ module RuboCop
31
31
  #
32
32
  # corrections = [AndOrCorrector.new(node)]
33
33
  # corrector = Corrector.new(source_buffer, corrections)
34
- def initialize(source_buffer, corrections)
34
+ def initialize(source_buffer, corrections = [])
35
35
  @source_buffer = source_buffer
36
36
  @corrections = corrections
37
37
  @source_rewriter = Parser::Source::Rewriter.new(source_buffer)
38
+
39
+ @diagnostics = []
40
+ # Don't print warnings to stderr if corrections conflict with each other
41
+ @source_rewriter.diagnostics.consumer = lambda do |diagnostic|
42
+ @diagnostics << diagnostic
43
+ end
38
44
  end
39
45
 
46
+ attr_reader :corrections, :diagnostics
47
+
40
48
  # Does the actual rewrite and returns string corresponding to
41
49
  # the rewritten source.
42
50
  #
43
51
  # @return [String]
44
- # TODO: Handle conflict exceptions raised from the Source::Rewriter
45
52
  def rewrite
53
+ # rubocop:disable Lint/HandleExceptions
46
54
  @corrections.each do |correction|
47
- correction.call(self)
55
+ begin
56
+ @source_rewriter.transaction do
57
+ correction.call(self)
58
+ end
59
+ rescue ::Parser::ClobberingError
60
+ end
48
61
  end
62
+ # rubocop:enable Lint/HandleExceptions
49
63
 
50
64
  @source_rewriter.process
51
65
  end
@@ -33,8 +33,8 @@ module RuboCop
33
33
  corrector.replace(block.source_range, body.source)
34
34
  else
35
35
  range = node.source_range
36
- range = range_with_surrounding_space(range, :left, nil, false)
37
- range = range_with_surrounding_space(range, :right, nil, true)
36
+ range = range_with_surrounding_space(range, :left, false)
37
+ range = range_with_surrounding_space(range, :right, true)
38
38
  corrector.remove(range)
39
39
  end
40
40
  end
@@ -38,7 +38,11 @@ module RuboCop
38
38
 
39
39
  def find_nested_defs(node, &block)
40
40
  node.each_child_node do |child|
41
- if child.def_type? || child.defs_type?
41
+ if child.def_type?
42
+ yield child
43
+ elsif child.defs_type?
44
+ subject, = *child
45
+ next if subject.lvar_type?
42
46
  yield child
43
47
  elsif !(eval_call?(child) || class_or_module_new_call?(child))
44
48
  find_nested_defs(child, &block)
@@ -68,7 +68,7 @@ module RuboCop
68
68
 
69
69
  range = range_with_surrounding_comma(range, :right)
70
70
  # eat following spaces up to EOL, but not the newline itself
71
- range = range_with_surrounding_space(range, :right, nil, false)
71
+ range = range_with_surrounding_space(range, :right, false)
72
72
 
73
73
  corrector.remove(range)
74
74
  end
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Cop
6
6
  module Metrics
7
7
  # This cop checks for methods with too many parameters.
8
- # The maximum number of parameters in configurable.
8
+ # The maximum number of parameters is configurable.
9
9
  # On Ruby 2.0+ keyword arguments can optionally
10
10
  # be excluded from the total count.
11
11
  class ParameterLists < Cop
@@ -34,7 +34,8 @@ module RuboCop
34
34
 
35
35
  def on_send(node)
36
36
  return unless match_call?(node) &&
37
- (!node.value_used? || only_truthiness_matters?(node))
37
+ (!node.value_used? || only_truthiness_matters?(node)) &&
38
+ !(node.parent && node.parent.block_type?)
38
39
  add_offense(node, :expression, MSG)
39
40
  end
40
41
 
@@ -15,8 +15,7 @@ module RuboCop
15
15
  AREF_ASGN = '%s[%s] = %s'.freeze
16
16
  MSG = 'Use `%s` instead of `%s`.'.freeze
17
17
 
18
- def_node_matcher :redundant_merge,
19
- '(send $_ {:merge! :update} (hash $...))'
18
+ def_node_matcher :redundant_merge, '(send $_ :merge! (hash $...))'
20
19
  def_node_matcher :modifier_flow_control, '[{if while until} #modifier?]'
21
20
 
22
21
  def on_send(node)
@@ -16,7 +16,7 @@ module RuboCop
16
16
  class FindEach < Cop
17
17
  MSG = 'Use `find_each` instead of `each`.'.freeze
18
18
 
19
- SCOPE_METHODS = [:all, :where].freeze
19
+ SCOPE_METHODS = [:all, :where, :not].freeze
20
20
 
21
21
  def on_send(node)
22
22
  receiver, second_method, _selector = *node
@@ -4,7 +4,7 @@
4
4
  module RuboCop
5
5
  module Cop
6
6
  module Style
7
- # This cop checks whether the end statement of a do end blocks
7
+ # This cop checks whether the end statement of a do..end block
8
8
  # is on its own line.
9
9
  #
10
10
  # @example
@@ -8,6 +8,9 @@ module RuboCop
8
8
  # ConditionalAssignment Cop.
9
9
  module ConditionalAssignmentHelper
10
10
  EQUAL = '='.freeze
11
+ END_ALIGNMENT = 'Lint/EndAlignment'.freeze
12
+ ALIGN_WITH = 'AlignWith'.freeze
13
+ KEYWORD = 'keyword'.freeze
11
14
 
12
15
  # `elsif` branches show up in the `node` as an `else`. We need
13
16
  # to recursively iterate over all `else` branches and consider all
@@ -55,6 +58,16 @@ module RuboCop
55
58
  end
56
59
  end
57
60
 
61
+ def indent(cop, source)
62
+ if cop.config[END_ALIGNMENT] &&
63
+ cop.config[END_ALIGNMENT][ALIGN_WITH] &&
64
+ cop.config[END_ALIGNMENT][ALIGN_WITH] == KEYWORD
65
+ ' ' * source.length
66
+ else
67
+ ''
68
+ end
69
+ end
70
+
58
71
  private
59
72
 
60
73
  def expand_elsif(node, elsif_branches = [])
@@ -185,11 +198,11 @@ module RuboCop
185
198
  else
186
199
  case node.loc.keyword.source
187
200
  when IF
188
- IfCorrector.correct(node)
201
+ IfCorrector.correct(self, node)
189
202
  when UNLESS
190
- UnlessCorrector.correct(node)
203
+ UnlessCorrector.correct(self, node)
191
204
  else
192
- CaseCorrector.correct(node)
205
+ CaseCorrector.correct(self, node)
193
206
  end
194
207
  end
195
208
  end
@@ -208,7 +221,7 @@ module RuboCop
208
221
  return true if ASSIGNMENT_TYPES.include?(branch.type)
209
222
 
210
223
  if branch.send_type?
211
- _variable, method, = *branch
224
+ _receiver, method, = *branch
212
225
  return true if METHODS.include?(method)
213
226
  return true if method.to_s.end_with?(EQUAL)
214
227
  end
@@ -296,7 +309,7 @@ module RuboCop
296
309
  class << self
297
310
  include ConditionalAssignmentHelper
298
311
 
299
- def correct(node)
312
+ def correct(cop, node)
300
313
  _condition, if_branch, else_branch = *node
301
314
  if_branch = tail(if_branch)
302
315
  _variable, *_operator, if_assignment = *if_branch
@@ -311,6 +324,7 @@ module RuboCop
311
324
  correct_branches(corrector, elsif_branches)
312
325
  corrector.replace(else_branch.source_range,
313
326
  else_assignment.source)
327
+ corrector.insert_before(node.loc.end, indent(cop, lhs(if_branch)))
314
328
  end
315
329
  end
316
330
  end
@@ -321,7 +335,7 @@ module RuboCop
321
335
  class << self
322
336
  include ConditionalAssignmentHelper
323
337
 
324
- def correct(node)
338
+ def correct(cop, node)
325
339
  _condition, *when_branches, else_branch = *node
326
340
  else_branch = tail(else_branch)
327
341
  when_branches = expand_when_branches(when_branches)
@@ -333,6 +347,9 @@ module RuboCop
333
347
  correct_branches(corrector, when_branches)
334
348
  corrector.replace(else_branch.source_range,
335
349
  else_assignment.source)
350
+
351
+ corrector.insert_before(node.loc.end,
352
+ indent(cop, lhs(else_branch)))
336
353
  end
337
354
  end
338
355
  end
@@ -343,7 +360,7 @@ module RuboCop
343
360
  class << self
344
361
  include ConditionalAssignmentHelper
345
362
 
346
- def correct(node)
363
+ def correct(cop, node)
347
364
  _condition, else_branch, if_branch = *node
348
365
  if_branch = tail(if_branch)
349
366
  else_branch = tail(else_branch)
@@ -355,6 +372,7 @@ module RuboCop
355
372
  corrector.replace(if_branch.source_range, if_assignment.source)
356
373
  corrector.replace(else_branch.source_range,
357
374
  else_assignment.source)
375
+ corrector.insert_before(node.loc.end, indent(cop, lhs(if_branch)))
358
376
  end
359
377
  end
360
378
  end
@@ -7,20 +7,26 @@ module RuboCop
7
7
  # This cop checks whether method definitions are
8
8
  # separated by empty lines.
9
9
  class EmptyLineBetweenDefs < Cop
10
- include OnMethodDef
11
10
  MSG = 'Use empty lines between method definitions.'.freeze
12
11
 
13
- def on_method_def(node, _method_name, _args, _body)
14
- return unless node.parent && node.parent.begin_type?
15
-
16
- nodes = [prev_node(node), node]
12
+ # We operate on `begin` nodes, instead of using `OnMethodDef`,
13
+ # so that we can walk over pairs of consecutive nodes and
14
+ # efficiently access a node's predecessor; #prev_node ends up
15
+ # doing a linear scan over siblings, so we don't want to call
16
+ # it on each def.
17
+ def on_begin(node)
18
+ node.children.each_cons(2) do |prev, n|
19
+ nodes = [prev, n]
20
+ check_defs(nodes) if nodes.all?(&method(:def_node?))
21
+ end
22
+ end
17
23
 
18
- return unless nodes.all?(&method(:def_node?))
24
+ def check_defs(nodes)
19
25
  return if blank_lines_between?(*nodes)
20
26
  return if nodes.all?(&:single_line?) &&
21
27
  cop_config['AllowAdjacentOneLineDefs']
22
28
 
23
- add_offense(node, :keyword)
29
+ add_offense(nodes.last, :keyword)
24
30
  end
25
31
 
26
32
  private