rubocop-rspec 1.42.0 → 1.44.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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -2
  3. data/config/default.yml +41 -3
  4. data/lib/rubocop-rspec.rb +2 -1
  5. data/lib/rubocop/cop/rspec/align_left_let_brace.rb +1 -1
  6. data/lib/rubocop/cop/rspec/align_right_let_brace.rb +1 -1
  7. data/lib/rubocop/cop/rspec/any_instance.rb +1 -1
  8. data/lib/rubocop/cop/rspec/around_block.rb +2 -2
  9. data/lib/rubocop/cop/rspec/base.rb +76 -0
  10. data/lib/rubocop/cop/rspec/be.rb +1 -1
  11. data/lib/rubocop/cop/rspec/be_eql.rb +1 -1
  12. data/lib/rubocop/cop/rspec/before_after_all.rb +1 -1
  13. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +1 -1
  14. data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +6 -3
  15. data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +1 -1
  16. data/lib/rubocop/cop/rspec/context_method.rb +2 -2
  17. data/lib/rubocop/cop/rspec/context_wording.rb +3 -3
  18. data/lib/rubocop/cop/rspec/cop.rb +2 -66
  19. data/lib/rubocop/cop/rspec/describe_class.rb +40 -30
  20. data/lib/rubocop/cop/rspec/describe_method.rb +14 -6
  21. data/lib/rubocop/cop/rspec/describe_symbol.rb +2 -2
  22. data/lib/rubocop/cop/rspec/described_class.rb +2 -2
  23. data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +1 -1
  24. data/lib/rubocop/cop/rspec/dialect.rb +1 -1
  25. data/lib/rubocop/cop/rspec/empty_example_group.rb +124 -6
  26. data/lib/rubocop/cop/rspec/empty_hook.rb +1 -1
  27. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +4 -8
  28. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +4 -8
  29. data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +7 -10
  30. data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +4 -8
  31. data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +5 -8
  32. data/lib/rubocop/cop/rspec/example_length.rb +1 -1
  33. data/lib/rubocop/cop/rspec/example_without_description.rb +1 -1
  34. data/lib/rubocop/cop/rspec/example_wording.rb +4 -4
  35. data/lib/rubocop/cop/rspec/expect_actual.rb +1 -1
  36. data/lib/rubocop/cop/rspec/expect_change.rb +1 -1
  37. data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
  38. data/lib/rubocop/cop/rspec/expect_output.rb +1 -1
  39. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +3 -3
  40. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +10 -6
  41. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +1 -1
  42. data/lib/rubocop/cop/rspec/file_path.rb +25 -17
  43. data/lib/rubocop/cop/rspec/focus.rb +7 -11
  44. data/lib/rubocop/cop/rspec/hook_argument.rb +5 -6
  45. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +1 -1
  46. data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +2 -3
  47. data/lib/rubocop/cop/rspec/implicit_expect.rb +1 -1
  48. data/lib/rubocop/cop/rspec/implicit_subject.rb +8 -6
  49. data/lib/rubocop/cop/rspec/instance_spy.rb +1 -1
  50. data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
  51. data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +1 -1
  52. data/lib/rubocop/cop/rspec/it_behaves_like.rb +1 -1
  53. data/lib/rubocop/cop/rspec/iterated_expectation.rb +1 -1
  54. data/lib/rubocop/cop/rspec/leading_subject.rb +24 -17
  55. data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +1 -1
  56. data/lib/rubocop/cop/rspec/let_before_examples.rb +1 -1
  57. data/lib/rubocop/cop/rspec/let_setup.rb +6 -3
  58. data/lib/rubocop/cop/rspec/message_chain.rb +1 -1
  59. data/lib/rubocop/cop/rspec/message_expectation.rb +1 -1
  60. data/lib/rubocop/cop/rspec/message_spies.rb +1 -1
  61. data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +1 -1
  62. data/lib/rubocop/cop/rspec/multiple_describes.rb +11 -8
  63. data/lib/rubocop/cop/rspec/multiple_expectations.rb +7 -11
  64. data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +148 -0
  65. data/lib/rubocop/cop/rspec/multiple_subjects.rb +1 -1
  66. data/lib/rubocop/cop/rspec/named_subject.rb +1 -1
  67. data/lib/rubocop/cop/rspec/nested_groups.rb +4 -4
  68. data/lib/rubocop/cop/rspec/not_to_not.rb +1 -1
  69. data/lib/rubocop/cop/rspec/overwriting_setup.rb +1 -1
  70. data/lib/rubocop/cop/rspec/pending.rb +1 -1
  71. data/lib/rubocop/cop/rspec/predicate_matcher.rb +7 -14
  72. data/lib/rubocop/cop/rspec/rails/http_status.rb +1 -1
  73. data/lib/rubocop/cop/rspec/receive_counts.rb +1 -1
  74. data/lib/rubocop/cop/rspec/receive_never.rb +2 -2
  75. data/lib/rubocop/cop/rspec/repeated_description.rb +1 -1
  76. data/lib/rubocop/cop/rspec/repeated_example.rb +2 -2
  77. data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +1 -1
  78. data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +1 -1
  79. data/lib/rubocop/cop/rspec/repeated_include_example.rb +103 -0
  80. data/lib/rubocop/cop/rspec/return_from_stub.rb +1 -1
  81. data/lib/rubocop/cop/rspec/scattered_let.rb +1 -1
  82. data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
  83. data/lib/rubocop/cop/rspec/shared_context.rb +1 -1
  84. data/lib/rubocop/cop/rspec/shared_examples.rb +1 -1
  85. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +1 -1
  86. data/lib/rubocop/cop/rspec/stubbed_mock.rb +172 -0
  87. data/lib/rubocop/cop/rspec/subject_stub.rb +6 -6
  88. data/lib/rubocop/cop/rspec/unspecified_exception.rb +1 -1
  89. data/lib/rubocop/cop/rspec/variable_definition.rb +6 -6
  90. data/lib/rubocop/cop/rspec/variable_name.rb +28 -9
  91. data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -1
  92. data/lib/rubocop/cop/rspec/void_expect.rb +1 -1
  93. data/lib/rubocop/cop/rspec/yield.rb +1 -1
  94. data/lib/rubocop/cop/rspec_cops.rb +3 -0
  95. data/lib/rubocop/rspec/corrector/move_node.rb +7 -5
  96. data/lib/rubocop/rspec/description_extractor.rb +1 -1
  97. data/lib/rubocop/rspec/{blank_line_separation.rb → empty_line_separation.rb} +13 -2
  98. data/lib/rubocop/rspec/example_group.rb +2 -2
  99. data/lib/rubocop/rspec/hook.rb +1 -5
  100. data/lib/rubocop/rspec/language.rb +12 -5
  101. data/lib/rubocop/rspec/language/node_pattern.rb +6 -1
  102. data/lib/rubocop/rspec/top_level_describe.rb +2 -2
  103. data/lib/rubocop/rspec/top_level_group.rb +26 -13
  104. data/lib/rubocop/rspec/variable.rb +1 -1
  105. data/lib/rubocop/rspec/version.rb +1 -1
  106. metadata +38 -6
@@ -3,7 +3,20 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
- # Check that the first argument to the top level describe is a constant.
6
+ # Check that the first argument to the top-level describe is a constant.
7
+ #
8
+ # It can be configured to ignore strings when certain metadata is passed.
9
+ #
10
+ # Ignores Rails and Aruba `type` metadata by default.
11
+ #
12
+ # @example `IgnoredMetadata` configuration
13
+ #
14
+ # # .rubocop.yml
15
+ # # RSpec/DescribeClass:
16
+ # # IgnoredMetadata:
17
+ # # type:
18
+ # # - request
19
+ # # - controller
7
20
  #
8
21
  # @example
9
22
  # # bad
@@ -21,50 +34,47 @@ module RuboCop
21
34
  #
22
35
  # describe "A feature example", type: :feature do
23
36
  # end
24
- class DescribeClass < Cop
25
- include RuboCop::RSpec::TopLevelDescribe
37
+ class DescribeClass < Base
38
+ include RuboCop::RSpec::TopLevelGroup
26
39
 
27
40
  MSG = 'The first argument to describe should be '\
28
41
  'the class or module being tested.'
29
42
 
30
- def_node_matcher :valid_describe?, <<-PATTERN
31
- {
32
- (send #{RSPEC} :describe const ...)
33
- (send #{RSPEC} :describe)
34
- }
43
+ def_node_matcher :example_group_with_ignored_metadata?, <<~PATTERN
44
+ (send #rspec? :describe ... (hash <#ignored_metadata? ...>))
35
45
  PATTERN
36
46
 
37
- def_node_matcher :describe_with_rails_metadata?, <<-PATTERN
38
- (send #{RSPEC} :describe !const ...
39
- (hash <#rails_metadata? ...>)
40
- )
47
+ def_node_matcher :not_a_const_described, <<~PATTERN
48
+ (send #rspec? :describe $[!const !#string_constant?] ...)
41
49
  PATTERN
42
50
 
43
- def_node_matcher :rails_metadata?, <<-PATTERN
44
- (pair
45
- (sym :type)
46
- (sym {
47
- :channel :controller :helper :job :mailer :model :request
48
- :routing :view :feature :system :mailbox
49
- }
50
- )
51
- )
51
+ def_node_matcher :sym_pair, <<~PATTERN
52
+ (pair $sym $sym)
52
53
  PATTERN
53
54
 
54
- def on_top_level_describe(node, (described_value, _))
55
- return if shared_group?(root_node)
56
- return if valid_describe?(node)
57
- return if describe_with_rails_metadata?(node)
58
- return if string_constant_describe?(described_value)
55
+ def on_top_level_group(node)
56
+ return if example_group_with_ignored_metadata?(node.send_node)
59
57
 
60
- add_offense(described_value)
58
+ not_a_const_described(node.send_node) do |described|
59
+ add_offense(described)
60
+ end
61
61
  end
62
62
 
63
63
  private
64
64
 
65
- def string_constant_describe?(described_value)
66
- described_value.str_type? &&
67
- described_value.value =~ /^((::)?[A-Z]\w*)+$/
65
+ def ignored_metadata?(node)
66
+ sym_pair(node) do |key, value|
67
+ ignored_metadata[key.value.to_s].to_a.include?(value.value.to_s)
68
+ end
69
+ end
70
+
71
+ def string_constant?(described)
72
+ described.str_type? &&
73
+ described.value.match?(/^(?:(?:::)?[A-Z]\w*)+$/)
74
+ end
75
+
76
+ def ignored_metadata
77
+ cop_config['IgnoredMetadata'] || {}
68
78
  end
69
79
  end
70
80
  end
@@ -16,17 +16,25 @@ module RuboCop
16
16
  #
17
17
  # describe MyClass, '.my_class_method' do
18
18
  # end
19
- class DescribeMethod < Cop
20
- include RuboCop::RSpec::TopLevelDescribe
19
+ class DescribeMethod < Base
20
+ include RuboCop::RSpec::TopLevelGroup
21
21
 
22
22
  MSG = 'The second argument to describe should be the method '\
23
23
  "being tested. '#instance' or '.class'."
24
24
 
25
- def on_top_level_describe(_node, (_, second_arg))
26
- return unless second_arg&.str_type?
27
- return if second_arg.str_content.start_with?('#', '.')
25
+ def_node_matcher :second_argument, <<~PATTERN
26
+ (block
27
+ (send #rspec? :describe _first_argument $(str _) ...) ...
28
+ )
29
+ PATTERN
28
30
 
29
- add_offense(second_arg)
31
+ def on_top_level_group(node)
32
+ second_argument = second_argument(node)
33
+
34
+ return unless second_argument
35
+ return if second_argument.str_content.start_with?('#', '.')
36
+
37
+ add_offense(second_argument)
30
38
  end
31
39
  end
32
40
  end
@@ -17,11 +17,11 @@ module RuboCop
17
17
  # end
18
18
  #
19
19
  # @see https://github.com/rspec/rspec-core/issues/1610
20
- class DescribeSymbol < Cop
20
+ class DescribeSymbol < Base
21
21
  MSG = 'Avoid describing symbols.'
22
22
 
23
23
  def_node_matcher :describe_symbol?, <<-PATTERN
24
- (send #{RSPEC} :describe $sym ...)
24
+ (send #rspec? :describe $sym ...)
25
25
  PATTERN
26
26
 
27
27
  def on_send(node)
@@ -54,7 +54,7 @@ module RuboCop
54
54
  # end
55
55
  # end
56
56
  #
57
- class DescribedClass < Cop
57
+ class DescribedClass < Base
58
58
  extend AutoCorrector
59
59
  include ConfigurableEnforcedStyle
60
60
 
@@ -142,7 +142,7 @@ module RuboCop
142
142
  if style == :described_class
143
143
  offensive_described_class?(node)
144
144
  else
145
- node.send_type? && node.method_name == :described_class
145
+ node.send_type? && node.method?(:described_class)
146
146
  end
147
147
  end
148
148
 
@@ -19,7 +19,7 @@ module RuboCop
19
19
  # end
20
20
  #
21
21
  # @see https://github.com/rubocop-hq/rubocop-rspec/issues/735
22
- class DescribedClassModuleWrapping < Cop
22
+ class DescribedClassModuleWrapping < Base
23
23
  MSG = 'Avoid opening modules and defining specs within them.'
24
24
 
25
25
  def_node_search :find_rspec_blocks,
@@ -41,7 +41,7 @@ module RuboCop
41
41
  # describe 'display name presence' do
42
42
  # # ...
43
43
  # end
44
- class Dialect < Cop
44
+ class Dialect < Base
45
45
  extend AutoCorrector
46
46
  include MethodPreference
47
47
 
@@ -33,6 +33,11 @@ module RuboCop
33
33
  # end
34
34
  # end
35
35
  #
36
+ # # good
37
+ # describe Bacon do
38
+ # pending 'will add tests later'
39
+ # end
40
+ #
36
41
  # @example configuration
37
42
  #
38
43
  # # .rubocop.yml
@@ -57,24 +62,137 @@ module RuboCop
57
62
  # end
58
63
  # end
59
64
  #
60
- class EmptyExampleGroup < Cop
65
+ class EmptyExampleGroup < Base
61
66
  MSG = 'Empty example group detected.'
62
67
 
63
- def_node_search :contains_example?, <<-PATTERN
68
+ # @!method example_group_body(node)
69
+ # Match example group blocks and yield their body
70
+ #
71
+ # @example source that matches
72
+ # describe 'example group' do
73
+ # it { is_expected.to be }
74
+ # end
75
+ #
76
+ # @param node [RuboCop::AST::Node]
77
+ # @yield [RuboCop::AST::Node] example group body
78
+ def_node_matcher :example_group_body, <<~PATTERN
79
+ (block #{ExampleGroups::ALL.send_pattern} args $_)
80
+ PATTERN
81
+
82
+ # @!method example_or_group_or_include?(node)
83
+ # Match examples, example groups and includes
84
+ #
85
+ # @example source that matches
86
+ # it { is_expected.to fly }
87
+ # describe('non-empty example groups too') { }
88
+ # it_behaves_like 'an animal'
89
+ # it_behaves_like('a cat') { let(:food) { 'milk' } }
90
+ # it_has_root_access
91
+ # skip
92
+ # it 'will be implemented later'
93
+ #
94
+ # @param node [RuboCop::AST::Node]
95
+ # @return [Array<RuboCop::AST::Node>] matching nodes
96
+ def_node_matcher :example_or_group_or_include?, <<~PATTERN
97
+ {
98
+ #{Examples::ALL.send_pattern}
99
+ #{Examples::ALL.block_pattern}
100
+ #{ExampleGroups::ALL.block_pattern}
101
+ #{Includes::ALL.send_pattern}
102
+ #{Includes::ALL.block_pattern}
103
+ (send nil? #custom_include? ...)
104
+ }
105
+ PATTERN
106
+
107
+ # @!method examples_inside_block?(node)
108
+ # Match examples defined inside a block which is not a hook
109
+ #
110
+ # @example source that matches
111
+ # %w(r g b).each do |color|
112
+ # it { is_expected.to have_color(color) }
113
+ # end
114
+ #
115
+ # @example source that does not match
116
+ # before do
117
+ # it { is_expected.to fall_into_oblivion }
118
+ # end
119
+ #
120
+ # @param node [RuboCop::AST::Node]
121
+ # @return [Array<RuboCop::AST::Node>] matching nodes
122
+ def_node_matcher :examples_inside_block?, <<~PATTERN
123
+ (block !#{Hooks::ALL.send_pattern} _ #examples?)
124
+ PATTERN
125
+
126
+ # @!method examples_directly_or_in_block?(node)
127
+ # Match examples or examples inside blocks
128
+ #
129
+ # @example source that matches
130
+ # it { expect(drink).to be_cold }
131
+ # context('when winter') { it { expect(drink).to be_hot } }
132
+ # (1..5).each { |divisor| it { is_expected.to divide_by(divisor) } }
133
+ #
134
+ # @param node [RuboCop::AST::Node]
135
+ # @return [Array<RuboCop::AST::Node>] matching nodes
136
+ def_node_matcher :examples_directly_or_in_block?, <<~PATTERN
64
137
  {
65
- #{(Examples::ALL + Includes::ALL).send_pattern}
66
- (send _ #custom_include? ...)
138
+ #example_or_group_or_include?
139
+ #examples_inside_block?
140
+ }
141
+ PATTERN
142
+
143
+ # @!method examples?(node)
144
+ # Matches examples defined in scopes where they could run
145
+ #
146
+ # @example source that matches
147
+ # it { expect(myself).to be_run }
148
+ # describe { it { i_run_as_well } }
149
+ #
150
+ # @example source that does not match
151
+ # before { it { whatever here wont run anyway } }
152
+ #
153
+ # @param node [RuboCop::AST::Node]
154
+ # @return [Array<RuboCop::AST::Node>] matching nodes
155
+ def_node_matcher :examples?, <<~PATTERN
156
+ {
157
+ #examples_directly_or_in_block?
158
+ (begin <#examples_directly_or_in_block? ...>)
67
159
  }
68
160
  PATTERN
69
161
 
70
162
  def on_block(node)
71
- return unless example_group?(node) && !contains_example?(node)
163
+ return if node.each_ancestor(:def, :defs).any?
164
+ return if node.each_ancestor(:block).any? { |block| example?(block) }
72
165
 
73
- add_offense(node.send_node)
166
+ example_group_body(node) do |body|
167
+ add_offense(node.send_node) if offensive?(body)
168
+ end
74
169
  end
75
170
 
76
171
  private
77
172
 
173
+ def offensive?(body)
174
+ return true unless body
175
+ return false if conditionals_with_examples?(body)
176
+
177
+ if body.if_type?
178
+ !examples_in_branches?(body)
179
+ else
180
+ !examples?(body)
181
+ end
182
+ end
183
+
184
+ def conditionals_with_examples?(body)
185
+ return unless body.begin_type?
186
+
187
+ body.each_descendant(:if).any? do |if_node|
188
+ examples_in_branches?(if_node)
189
+ end
190
+ end
191
+
192
+ def examples_in_branches?(if_node)
193
+ if_node.branches.any? { |branch| examples?(branch) }
194
+ end
195
+
78
196
  def custom_include?(method_name)
79
197
  custom_include_methods.include?(method_name)
80
198
  end
@@ -22,7 +22,7 @@ module RuboCop
22
22
  # create_feed
23
23
  # end
24
24
  # after(:all) { cleanup_feed }
25
- class EmptyHook < Cop
25
+ class EmptyHook < Base
26
26
  extend AutoCorrector
27
27
  include RuboCop::Cop::RangeHelp
28
28
 
@@ -41,22 +41,18 @@ module RuboCop
41
41
  # it { two }
42
42
  # end
43
43
  #
44
- class EmptyLineAfterExample < Cop
44
+ class EmptyLineAfterExample < Base
45
45
  extend AutoCorrector
46
- include RuboCop::RSpec::BlankLineSeparation
46
+ include RuboCop::RSpec::EmptyLineSeparation
47
47
 
48
48
  MSG = 'Add an empty line after `%<example>s`.'
49
49
 
50
50
  def on_block(node)
51
51
  return unless example?(node)
52
- return if last_child?(node)
53
52
  return if allowed_one_liner?(node)
54
53
 
55
- missing_separating_line(node) do |location|
56
- msg = format(MSG, example: node.method_name)
57
- add_offense(location, message: msg) do |corrector|
58
- corrector.insert_after(location.end, "\n")
59
- end
54
+ missing_separating_line_offense(node) do |method|
55
+ format(MSG, example: method)
60
56
  end
61
57
  end
62
58
 
@@ -23,21 +23,17 @@ module RuboCop
23
23
  # end
24
24
  # end
25
25
  #
26
- class EmptyLineAfterExampleGroup < Cop
26
+ class EmptyLineAfterExampleGroup < Base
27
27
  extend AutoCorrector
28
- include RuboCop::RSpec::BlankLineSeparation
28
+ include RuboCop::RSpec::EmptyLineSeparation
29
29
 
30
30
  MSG = 'Add an empty line after `%<example_group>s`.'
31
31
 
32
32
  def on_block(node)
33
33
  return unless example_group?(node)
34
- return if last_child?(node)
35
34
 
36
- missing_separating_line(node) do |location|
37
- msg = format(MSG, example_group: node.method_name)
38
- add_offense(location, message: msg) do |corrector|
39
- corrector.insert_after(location.end, "\n")
40
- end
35
+ missing_separating_line_offense(node) do |method|
36
+ format(MSG, example_group: method)
41
37
  end
42
38
  end
43
39
  end
@@ -16,24 +16,21 @@ module RuboCop
16
16
  # let(:something) { other }
17
17
  #
18
18
  # it { does_something }
19
- class EmptyLineAfterFinalLet < Cop
19
+ class EmptyLineAfterFinalLet < Base
20
20
  extend AutoCorrector
21
- include RuboCop::RSpec::BlankLineSeparation
21
+ include RuboCop::RSpec::EmptyLineSeparation
22
22
 
23
- MSG = 'Add an empty line after the last `let` block.'
23
+ MSG = 'Add an empty line after the last `%<let>s`.'
24
24
 
25
25
  def on_block(node)
26
26
  return unless example_group_with_body?(node)
27
27
 
28
- latest_let = node.body.child_nodes.select { |child| let?(child) }.last
28
+ final_let = node.body.child_nodes.reverse.find { |child| let?(child) }
29
29
 
30
- return if latest_let.nil?
31
- return if last_child?(latest_let)
30
+ return if final_let.nil?
32
31
 
33
- missing_separating_line(latest_let) do |location|
34
- add_offense(location) do |corrector|
35
- corrector.insert_after(location.end, "\n")
36
- end
32
+ missing_separating_line_offense(final_let) do |method|
33
+ format(MSG, let: method)
37
34
  end
38
35
  end
39
36
  end
@@ -33,21 +33,17 @@ module RuboCop
33
33
  #
34
34
  # it { does_something }
35
35
  #
36
- class EmptyLineAfterHook < Cop
36
+ class EmptyLineAfterHook < Base
37
37
  extend AutoCorrector
38
- include RuboCop::RSpec::BlankLineSeparation
38
+ include RuboCop::RSpec::EmptyLineSeparation
39
39
 
40
40
  MSG = 'Add an empty line after `%<hook>s`.'
41
41
 
42
42
  def on_block(node)
43
43
  return unless hook?(node)
44
- return if last_child?(node)
45
44
 
46
- missing_separating_line(node) do |location|
47
- msg = format(MSG, hook: node.method_name)
48
- add_offense(location, message: msg) do |corrector|
49
- corrector.insert_after(location.end, "\n")
50
- end
45
+ missing_separating_line_offense(node) do |method|
46
+ format(MSG, hook: method)
51
47
  end
52
48
  end
53
49
  end