rubocop-rspec 1.39.0 → 1.43.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -0
  3. data/CODE_OF_CONDUCT.md +17 -0
  4. data/README.md +1 -61
  5. data/config/default.yml +148 -20
  6. data/lib/rubocop-rspec.rb +4 -1
  7. data/lib/rubocop/cop/rspec/align_left_let_brace.rb +12 -19
  8. data/lib/rubocop/cop/rspec/align_right_let_brace.rb +12 -19
  9. data/lib/rubocop/cop/rspec/any_instance.rb +1 -1
  10. data/lib/rubocop/cop/rspec/around_block.rb +1 -1
  11. data/lib/rubocop/cop/rspec/base.rb +74 -0
  12. data/lib/rubocop/cop/rspec/be.rb +2 -2
  13. data/lib/rubocop/cop/rspec/be_eql.rb +6 -6
  14. data/lib/rubocop/cop/rspec/before_after_all.rb +1 -1
  15. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +19 -17
  16. data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +14 -12
  17. data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +27 -12
  18. data/lib/rubocop/cop/rspec/context_method.rb +7 -9
  19. data/lib/rubocop/cop/rspec/context_wording.rb +3 -3
  20. data/lib/rubocop/cop/rspec/cop.rb +2 -86
  21. data/lib/rubocop/cop/rspec/describe_class.rb +20 -27
  22. data/lib/rubocop/cop/rspec/describe_method.rb +14 -6
  23. data/lib/rubocop/cop/rspec/describe_symbol.rb +2 -2
  24. data/lib/rubocop/cop/rspec/described_class.rb +12 -9
  25. data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +1 -1
  26. data/lib/rubocop/cop/rspec/dialect.rb +5 -12
  27. data/lib/rubocop/cop/rspec/empty_example_group.rb +91 -7
  28. data/lib/rubocop/cop/rspec/empty_hook.rb +6 -10
  29. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +5 -7
  30. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +5 -9
  31. data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +8 -8
  32. data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +5 -9
  33. data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +6 -6
  34. data/lib/rubocop/cop/rspec/example_length.rb +1 -1
  35. data/lib/rubocop/cop/rspec/example_without_description.rb +1 -1
  36. data/lib/rubocop/cop/rspec/example_wording.rb +10 -11
  37. data/lib/rubocop/cop/rspec/expect_actual.rb +8 -11
  38. data/lib/rubocop/cop/rspec/expect_change.rb +10 -35
  39. data/lib/rubocop/cop/rspec/expect_in_hook.rb +3 -3
  40. data/lib/rubocop/cop/rspec/expect_output.rb +2 -2
  41. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +24 -21
  42. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +20 -22
  43. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +7 -8
  44. data/lib/rubocop/cop/rspec/file_path.rb +54 -20
  45. data/lib/rubocop/cop/rspec/focus.rb +7 -11
  46. data/lib/rubocop/cop/rspec/hook_argument.rb +16 -23
  47. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +13 -14
  48. data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +1 -1
  49. data/lib/rubocop/cop/rspec/implicit_expect.rb +7 -15
  50. data/lib/rubocop/cop/rspec/implicit_subject.rb +16 -11
  51. data/lib/rubocop/cop/rspec/instance_spy.rb +18 -12
  52. data/lib/rubocop/cop/rspec/instance_variable.rb +4 -8
  53. data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +3 -6
  54. data/lib/rubocop/cop/rspec/it_behaves_like.rb +5 -6
  55. data/lib/rubocop/cop/rspec/iterated_expectation.rb +1 -1
  56. data/lib/rubocop/cop/rspec/leading_subject.rb +24 -21
  57. data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +2 -5
  58. data/lib/rubocop/cop/rspec/let_before_examples.rb +13 -11
  59. data/lib/rubocop/cop/rspec/let_setup.rb +21 -6
  60. data/lib/rubocop/cop/rspec/message_chain.rb +7 -6
  61. data/lib/rubocop/cop/rspec/message_expectation.rb +2 -2
  62. data/lib/rubocop/cop/rspec/message_spies.rb +2 -3
  63. data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +1 -1
  64. data/lib/rubocop/cop/rspec/multiple_describes.rb +11 -8
  65. data/lib/rubocop/cop/rspec/multiple_expectations.rb +7 -11
  66. data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +148 -0
  67. data/lib/rubocop/cop/rspec/multiple_subjects.rb +18 -19
  68. data/lib/rubocop/cop/rspec/named_subject.rb +2 -2
  69. data/lib/rubocop/cop/rspec/nested_groups.rb +12 -13
  70. data/lib/rubocop/cop/rspec/not_to_not.rb +5 -6
  71. data/lib/rubocop/cop/rspec/overwriting_setup.rb +1 -1
  72. data/lib/rubocop/cop/rspec/pending.rb +1 -1
  73. data/lib/rubocop/cop/rspec/predicate_matcher.rb +32 -69
  74. data/lib/rubocop/cop/rspec/rails/http_status.rb +7 -9
  75. data/lib/rubocop/cop/rspec/receive_counts.rb +15 -17
  76. data/lib/rubocop/cop/rspec/receive_never.rb +12 -12
  77. data/lib/rubocop/cop/rspec/repeated_description.rb +1 -1
  78. data/lib/rubocop/cop/rspec/repeated_example.rb +2 -2
  79. data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +12 -2
  80. data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +1 -1
  81. data/lib/rubocop/cop/rspec/return_from_stub.rb +12 -22
  82. data/lib/rubocop/cop/rspec/scattered_let.rb +8 -11
  83. data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
  84. data/lib/rubocop/cop/rspec/shared_context.rb +8 -21
  85. data/lib/rubocop/cop/rspec/shared_examples.rb +7 -9
  86. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +15 -18
  87. data/lib/rubocop/cop/rspec/subject_stub.rb +25 -53
  88. data/lib/rubocop/cop/rspec/unspecified_exception.rb +1 -1
  89. data/lib/rubocop/cop/rspec/variable_definition.rb +56 -0
  90. data/lib/rubocop/cop/rspec/variable_name.rb +66 -0
  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 +14 -11
  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 +2 -6
  97. data/lib/rubocop/rspec/{blank_line_separation.rb → empty_line_separation.rb} +13 -10
  98. data/lib/rubocop/rspec/example_group.rb +21 -49
  99. data/lib/rubocop/rspec/factory_bot.rb +7 -1
  100. data/lib/rubocop/rspec/language.rb +6 -4
  101. data/lib/rubocop/rspec/language/node_pattern.rb +10 -1
  102. data/lib/rubocop/rspec/top_level_describe.rb +2 -2
  103. data/lib/rubocop/rspec/top_level_group.rb +57 -0
  104. data/lib/rubocop/rspec/variable.rb +16 -0
  105. data/lib/rubocop/rspec/version.rb +1 -1
  106. metadata +32 -11
@@ -30,7 +30,8 @@ module RuboCop
30
30
  # it { is_expected.to have_http_status :success }
31
31
  # it { is_expected.to have_http_status :error }
32
32
  #
33
- class HttpStatus < Cop
33
+ class HttpStatus < Base
34
+ extend AutoCorrector
34
35
  include ConfigurableEnforcedStyle
35
36
 
36
37
  def_node_matcher :http_status, <<-PATTERN
@@ -42,14 +43,9 @@ module RuboCop
42
43
  checker = checker_class.new(ast_node)
43
44
  return unless checker.offensive?
44
45
 
45
- add_offense(checker.node, message: checker.message)
46
- end
47
- end
48
-
49
- def autocorrect(node)
50
- lambda do |corrector|
51
- checker = checker_class.new(node)
52
- corrector.replace(node.loc.expression, checker.preferred_style)
46
+ add_offense(checker.node, message: checker.message) do |corrector|
47
+ corrector.replace(checker.node, checker.preferred_style)
48
+ end
53
49
  end
54
50
  end
55
51
 
@@ -70,6 +66,7 @@ module RuboCop
70
66
  'to describe HTTP status code.'
71
67
 
72
68
  attr_reader :node
69
+
73
70
  def initialize(node)
74
71
  @node = node
75
72
  end
@@ -110,6 +107,7 @@ module RuboCop
110
107
  ALLOWED_STATUSES = %i[error success missing redirect].freeze
111
108
 
112
109
  attr_reader :node
110
+
113
111
  def initialize(node)
114
112
  @node = node
115
113
  end
@@ -23,7 +23,9 @@ module RuboCop
23
23
  # expect(foo).to receive(:bar).at_most(:once)
24
24
  # expect(foo).to receive(:bar).at_most(:twice).times
25
25
  #
26
- class ReceiveCounts < Cop
26
+ class ReceiveCounts < Base
27
+ extend AutoCorrector
28
+
27
29
  MSG = 'Use `%<alternative>s` instead of `%<original>s`.'
28
30
 
29
31
  def_node_matcher :receive_counts, <<-PATTERN
@@ -38,27 +40,23 @@ module RuboCop
38
40
 
39
41
  offending_range = range(node, offending_node)
40
42
 
41
- add_offense(
42
- offending_node,
43
- message: message_for(offending_node, offending_range.source),
44
- location: offending_range
45
- )
43
+ msg = message_for(offending_node, offending_range.source)
44
+ add_offense(offending_range, message: msg) do |corrector|
45
+ autocorrect(corrector, offending_node, offending_range)
46
+ end
46
47
  end
47
48
  end
48
49
 
49
- def autocorrect(node)
50
- lambda do |corrector|
51
- replacement = matcher_for(
52
- node.method_name,
53
- node.first_argument.source.to_i
54
- )
50
+ private
55
51
 
56
- original = range(node.parent, node)
57
- corrector.replace(original, replacement)
58
- end
59
- end
52
+ def autocorrect(corrector, node, range)
53
+ replacement = matcher_for(
54
+ node.method_name,
55
+ node.first_argument.source.to_i
56
+ )
60
57
 
61
- private
58
+ corrector.replace(range, replacement)
59
+ end
62
60
 
63
61
  def message_for(node, source)
64
62
  alternative = matcher_for(
@@ -13,26 +13,26 @@ module RuboCop
13
13
  # # good
14
14
  # expect(foo).not_to receive(:bar)
15
15
  #
16
- class ReceiveNever < Cop
16
+ class ReceiveNever < Base
17
+ extend AutoCorrector
17
18
  MSG = 'Use `not_to receive` instead of `never`.'
18
19
 
19
20
  def_node_search :method_on_stub?, '(send nil? :receive ...)'
20
21
 
21
22
  def on_send(node)
22
- return unless node.method_name == :never && method_on_stub?(node)
23
+ return unless node.method?(:never) && method_on_stub?(node)
23
24
 
24
- add_offense(
25
- node,
26
- location: :selector
27
- )
25
+ add_offense(node.loc.selector) do |corrector|
26
+ autocorrect(corrector, node)
27
+ end
28
28
  end
29
29
 
30
- def autocorrect(node)
31
- lambda do |corrector|
32
- corrector.replace(node.parent.loc.selector, 'not_to')
33
- range = node.loc.dot.with(end_pos: node.loc.selector.end_pos)
34
- corrector.remove(range)
35
- end
30
+ private
31
+
32
+ def autocorrect(corrector, node)
33
+ corrector.replace(node.parent.loc.selector, 'not_to')
34
+ range = node.loc.dot.with(end_pos: node.loc.selector.end_pos)
35
+ corrector.remove(range)
36
36
  end
37
37
  end
38
38
  end
@@ -40,7 +40,7 @@ module RuboCop
40
40
  # end
41
41
  # end
42
42
  #
43
- class RepeatedDescription < Cop
43
+ class RepeatedDescription < Base
44
44
  MSG = "Don't repeat descriptions within an example group."
45
45
 
46
46
  def on_block(node)
@@ -15,7 +15,7 @@ module RuboCop
15
15
  # expect(user).to be_valid
16
16
  # end
17
17
  #
18
- class RepeatedExample < Cop
18
+ class RepeatedExample < Base
19
19
  MSG = "Don't repeat examples within an example group."
20
20
 
21
21
  def on_block(node)
@@ -41,7 +41,7 @@ module RuboCop
41
41
  def example_signature(example)
42
42
  key_parts = [example.metadata, example.implementation]
43
43
 
44
- if example.definition.method_name == :its
44
+ if example.definition.method?(:its)
45
45
  key_parts << example.definition.arguments
46
46
  end
47
47
 
@@ -34,7 +34,16 @@ module RuboCop
34
34
  # it { cool_predicate }
35
35
  # end
36
36
  #
37
- class RepeatedExampleGroupBody < Cop
37
+ # # good
38
+ # context Array do
39
+ # it { is_expected.to respond_to :each }
40
+ # end
41
+ #
42
+ # context Hash do
43
+ # it { is_expected.to respond_to :each }
44
+ # end
45
+ #
46
+ class RepeatedExampleGroupBody < Base
38
47
  MSG = 'Repeated %<group>s block body on line(s) %<loc>s'
39
48
 
40
49
  def_node_matcher :several_example_groups?, <<-PATTERN
@@ -43,6 +52,7 @@ module RuboCop
43
52
 
44
53
  def_node_matcher :metadata, '(block (send _ _ _ $...) ...)'
45
54
  def_node_matcher :body, '(block _ args $...)'
55
+ def_node_matcher :const_arg, '(block (send _ _ $const ...) ...)'
46
56
 
47
57
  def_node_matcher :skip_or_pending?, <<-PATTERN
48
58
  (block <(send nil? {:skip :pending}) ...>)
@@ -75,7 +85,7 @@ module RuboCop
75
85
  end
76
86
 
77
87
  def signature_keys(group)
78
- [metadata(group), body(group)]
88
+ [metadata(group), body(group), const_arg(group)]
79
89
  end
80
90
 
81
91
  def message(group, repeats)
@@ -43,7 +43,7 @@ module RuboCop
43
43
  # # example group
44
44
  # end
45
45
  #
46
- class RepeatedExampleGroupDescription < Cop
46
+ class RepeatedExampleGroupDescription < Base
47
47
  MSG = 'Repeated %<group>s block description on line(s) %<loc>s'
48
48
 
49
49
  def_node_matcher :several_example_groups?, <<-PATTERN
@@ -33,49 +33,41 @@ module RuboCop
33
33
  # # also good as the returned value is dynamic
34
34
  # allow(Foo).to receive(:bar) { bar.baz }
35
35
  #
36
- class ReturnFromStub < Cop
36
+ class ReturnFromStub < Base
37
+ extend AutoCorrector
37
38
  include ConfigurableEnforcedStyle
38
39
 
39
40
  MSG_AND_RETURN = 'Use `and_return` for static values.'
40
41
  MSG_BLOCK = 'Use block for static values.'
41
42
 
42
43
  def_node_search :contains_stub?, '(send nil? :receive (...))'
44
+ def_node_matcher :stub_with_block?, '(block #contains_stub? ...)'
43
45
  def_node_search :and_return_value, <<-PATTERN
44
46
  $(send _ :and_return $(...))
45
47
  PATTERN
46
48
 
47
49
  def on_send(node)
48
- return unless contains_stub?(node)
49
50
  return unless style == :block
51
+ return unless contains_stub?(node)
50
52
 
51
53
  check_and_return_call(node)
52
54
  end
53
55
 
54
56
  def on_block(node)
55
- return unless contains_stub?(node)
56
57
  return unless style == :and_return
58
+ return unless stub_with_block?(node)
57
59
 
58
60
  check_block_body(node)
59
61
  end
60
62
 
61
- def autocorrect(node)
62
- if style == :block
63
- AndReturnCallCorrector.new(node)
64
- else
65
- BlockBodyCorrector.new(node)
66
- end
67
- end
68
-
69
63
  private
70
64
 
71
65
  def check_and_return_call(node)
72
66
  and_return_value(node) do |and_return, args|
73
67
  unless dynamic?(args)
74
- add_offense(
75
- and_return,
76
- location: :selector,
77
- message: MSG_BLOCK
78
- )
68
+ add_offense(and_return.loc.selector, message: MSG_BLOCK) do |corr|
69
+ AndReturnCallCorrector.new(and_return).call(corr)
70
+ end
79
71
  end
80
72
  end
81
73
  end
@@ -83,11 +75,9 @@ module RuboCop
83
75
  def check_block_body(block)
84
76
  body = block.body
85
77
  unless dynamic?(body) # rubocop:disable Style/GuardClause
86
- add_offense(
87
- block,
88
- location: :begin,
89
- message: MSG_AND_RETURN
90
- )
78
+ add_offense(block.loc.begin, message: MSG_AND_RETURN) do |corrector|
79
+ BlockBodyCorrector.new(block).call(corrector)
80
+ end
91
81
  end
92
82
  end
93
83
 
@@ -152,7 +142,7 @@ module RuboCop
152
142
  return if heredoc?
153
143
 
154
144
  corrector.replace(
155
- block.loc.expression,
145
+ block,
156
146
  "#{block.send_node.source}.and_return(#{body.source})"
157
147
  )
158
148
  end
@@ -26,7 +26,9 @@ module RuboCop
26
26
  # let!(:baz) { 3 }
27
27
  # end
28
28
  #
29
- class ScatteredLet < Cop
29
+ class ScatteredLet < Base
30
+ extend AutoCorrector
31
+
30
32
  MSG = 'Group all let/let! blocks in the example group together.'
31
33
 
32
34
  def on_block(node)
@@ -35,15 +37,6 @@ module RuboCop
35
37
  check_let_declarations(node.body)
36
38
  end
37
39
 
38
- def autocorrect(node)
39
- lambda do |corrector|
40
- first_let = find_first_let(node.parent)
41
- RuboCop::RSpec::Corrector::MoveNode.new(
42
- node, corrector, processed_source
43
- ).move_after(first_let)
44
- end
45
- end
46
-
47
40
  private
48
41
 
49
42
  def check_let_declarations(body)
@@ -53,7 +46,11 @@ module RuboCop
53
46
  lets.each_with_index do |node, idx|
54
47
  next if node.sibling_index == first_let.sibling_index + idx
55
48
 
56
- add_offense(node)
49
+ add_offense(node) do |corrector|
50
+ RuboCop::RSpec::Corrector::MoveNode.new(
51
+ node, corrector, processed_source
52
+ ).move_after(first_let)
53
+ end
57
54
  end
58
55
  end
59
56
 
@@ -22,7 +22,7 @@ module RuboCop
22
22
  # end
23
23
  # end
24
24
  #
25
- class ScatteredSetup < Cop
25
+ class ScatteredSetup < Base
26
26
  MSG = 'Do not define multiple `%<hook_name>s` hooks in the same '\
27
27
  'example group (also defined on %<lines>s).'
28
28
 
@@ -50,7 +50,9 @@ module RuboCop
50
50
  # end
51
51
  # end
52
52
  #
53
- class SharedContext < Cop
53
+ class SharedContext < Base
54
+ extend AutoCorrector
55
+
54
56
  MSG_EXAMPLES = "Use `shared_examples` when you don't "\
55
57
  'define context.'
56
58
 
@@ -68,22 +70,14 @@ module RuboCop
68
70
 
69
71
  def on_block(node)
70
72
  context_with_only_examples(node) do
71
- add_shared_item_offense(node.send_node, MSG_EXAMPLES)
73
+ add_offense(node.send_node, message: MSG_EXAMPLES) do |corrector|
74
+ corrector.replace(node.send_node.loc.selector, 'shared_examples')
75
+ end
72
76
  end
73
77
 
74
78
  examples_with_only_context(node) do
75
- add_shared_item_offense(node.send_node, MSG_CONTEXT)
76
- end
77
- end
78
-
79
- def autocorrect(node)
80
- lambda do |corrector|
81
- context_with_only_examples(node.parent) do
82
- corrector.replace(node.loc.selector, 'shared_examples')
83
- end
84
-
85
- examples_with_only_context(node.parent) do
86
- corrector.replace(node.loc.selector, 'shared_context')
79
+ add_offense(node.send_node, message: MSG_CONTEXT) do |corrector|
80
+ corrector.replace(node.send_node.loc.selector, 'shared_context')
87
81
  end
88
82
  end
89
83
  end
@@ -97,13 +91,6 @@ module RuboCop
97
91
  def examples_with_only_context(node)
98
92
  shared_example(node) { yield if context?(node) && !examples?(node) }
99
93
  end
100
-
101
- def add_shared_item_offense(node, message)
102
- add_offense(
103
- node,
104
- message: message
105
- )
106
- end
107
94
  end
108
95
  end
109
96
  end
@@ -20,7 +20,9 @@ module RuboCop
20
20
  # shared_examples_for 'foo bar baz'
21
21
  # include_examples 'foo bar baz'
22
22
  #
23
- class SharedExamples < Cop
23
+ class SharedExamples < Base
24
+ extend AutoCorrector
25
+
24
26
  def_node_matcher :shared_examples,
25
27
  (SharedGroups::ALL + Includes::ALL).send_pattern
26
28
 
@@ -30,14 +32,9 @@ module RuboCop
30
32
  next unless ast_node&.sym_type?
31
33
 
32
34
  checker = Checker.new(ast_node)
33
- add_offense(checker.node, message: checker.message)
34
- end
35
- end
36
-
37
- def autocorrect(node)
38
- lambda do |corrector|
39
- checker = Checker.new(node)
40
- corrector.replace(node.loc.expression, checker.preferred_style)
35
+ add_offense(checker.node, message: checker.message) do |corrector|
36
+ corrector.replace(checker.node, checker.preferred_style)
37
+ end
41
38
  end
42
39
  end
43
40
 
@@ -47,6 +44,7 @@ module RuboCop
47
44
  'to titleize shared examples.'
48
45
 
49
46
  attr_reader :node
47
+
50
48
  def initialize(node)
51
49
  @node = node
52
50
  end
@@ -16,7 +16,9 @@ module RuboCop
16
16
  # allow(foo).to receive(:bar, :baz)
17
17
  # allow(foo).to receive("bar.baz")
18
18
  #
19
- class SingleArgumentMessageChain < Cop
19
+ class SingleArgumentMessageChain < Base
20
+ extend AutoCorrector
21
+
20
22
  MSG = 'Use `%<recommended>s` instead of calling '\
21
23
  '`%<called>s` with a single argument.'
22
24
 
@@ -30,22 +32,23 @@ module RuboCop
30
32
  message_chain(node) do |arg|
31
33
  return if valid_usage?(arg)
32
34
 
33
- add_offense(node, location: :selector)
34
- end
35
- end
35
+ method = node.method_name
36
+ msg = format(MSG, recommended: replacement(method), called: method)
36
37
 
37
- def autocorrect(node)
38
- lambda do |corrector|
39
- corrector.replace(node.loc.selector, replacement(node.method_name))
40
- message_chain(node) do |arg|
41
- autocorrect_hash_arg(corrector, arg) if single_key_hash?(arg)
42
- autocorrect_array_arg(corrector, arg) if arg.array_type?
38
+ add_offense(node.loc.selector, message: msg) do |corrector|
39
+ autocorrect(corrector, node, method, arg)
43
40
  end
44
41
  end
45
42
  end
46
43
 
47
44
  private
48
45
 
46
+ def autocorrect(corrector, node, method, arg)
47
+ corrector.replace(node.loc.selector, replacement(method))
48
+ autocorrect_hash_arg(corrector, arg) if single_key_hash?(arg)
49
+ autocorrect_array_arg(corrector, arg) if arg.array_type?
50
+ end
51
+
49
52
  def valid_usage?(node)
50
53
  return true unless node.literal? || node.array_type?
51
54
 
@@ -63,7 +66,7 @@ module RuboCop
63
66
  def autocorrect_hash_arg(corrector, arg)
64
67
  key, value = *arg.children.first
65
68
 
66
- corrector.replace(arg.loc.expression, key_to_arg(key))
69
+ corrector.replace(arg, key_to_arg(key))
67
70
  corrector.insert_after(arg.parent.loc.end,
68
71
  ".and_return(#{value.source})")
69
72
  end
@@ -71,7 +74,7 @@ module RuboCop
71
74
  def autocorrect_array_arg(corrector, arg)
72
75
  value = arg.children.first
73
76
 
74
- corrector.replace(arg.loc.expression, value.source)
77
+ corrector.replace(arg, value.source)
75
78
  end
76
79
 
77
80
  def key_to_arg(node)
@@ -82,12 +85,6 @@ module RuboCop
82
85
  def replacement(method)
83
86
  method.equal?(:receive_message_chain) ? 'receive' : 'stub'
84
87
  end
85
-
86
- def message(node)
87
- method = node.method_name
88
-
89
- format(MSG, recommended: replacement(method), called: method)
90
- end
91
88
  end
92
89
  end
93
90
  end