Skip to content

Commit ac953d8

Browse files
committed
Use the new Autocorrection API
The autocorrection API was changed in Rubocop v0.87.0 (pull request rubocop/rubocop#7868). Here, I change the superclass of `RuboCop::Cop::RSpec::Cop` from `::RuboCop::Cop::Cop` to `::RuboCop::Cop::Base`. This has a few consequences: - Our `#message` methods get called with a different argument than before. It *can* be customized by defining a `#callback_argument` method, but I think it is clearer to avoid callbacks altogether. - Our `#autocorrect` methods don't get called anymore. Instead, we extend `Autocorrector`, and the `corrector` is being yielded when calling `#add_offense`, so the code is mostly moved in there. For some cases, this means that some code can be removed, which is nice. For some cases, it means that the methods get too long, or the code complexity gets too high, and in those cases I chose to just call out to an `#autocorrect` method anyway, but of course passing the `corrector` and any usable local variables along. This also means we bump the dependency of RuboCop quite a bit, from '>= 0.68.1' to '>= 0.87.0'.
1 parent e6857d8 commit ac953d8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+385
-522
lines changed

.rubocop_todo.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ InternalAffairs/MethodNameEqual:
1414
# Offense count: 1
1515
# Configuration parameters: CountComments.
1616
Metrics/ClassLength:
17-
Max: 104
17+
Max: 106

lib/rubocop/cop/rspec/align_left_let_brace.rb

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,28 @@ module RSpec
1818
# let(:a) { b }
1919
#
2020
class AlignLeftLetBrace < Cop
21+
extend AutoCorrector
22+
2123
MSG = 'Align left let brace'
2224

2325
def self.autocorrect_incompatible_with
2426
[Layout::ExtraSpacing]
2527
end
2628

27-
def investigate(_processed_source)
29+
def on_new_investigation
2830
return if processed_source.blank?
2931

30-
token_aligner.offending_tokens.each do |let|
31-
add_offense(let, location: :begin)
32-
end
33-
end
32+
token_aligner =
33+
RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :begin)
3434

35-
def autocorrect(let)
36-
lambda do |corrector|
37-
corrector.insert_before(
38-
let.loc.begin,
39-
token_aligner.indent_for(let)
40-
)
35+
token_aligner.offending_tokens.each do |let|
36+
add_offense(let.loc.begin) do |corrector|
37+
corrector.insert_before(
38+
let.loc.begin, token_aligner.indent_for(let)
39+
)
40+
end
4141
end
4242
end
43-
44-
private
45-
46-
def token_aligner
47-
@token_aligner ||=
48-
RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :begin)
49-
end
5043
end
5144
end
5245
end

lib/rubocop/cop/rspec/align_right_let_brace.rb

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,28 @@ module RSpec
1818
# let(:a) { b }
1919
#
2020
class AlignRightLetBrace < Cop
21+
extend AutoCorrector
22+
2123
MSG = 'Align right let brace'
2224

2325
def self.autocorrect_incompatible_with
2426
[Layout::ExtraSpacing]
2527
end
2628

27-
def investigate(_processed_source)
29+
def on_new_investigation
2830
return if processed_source.blank?
2931

30-
token_aligner.offending_tokens.each do |let|
31-
add_offense(let, location: :end)
32-
end
33-
end
32+
token_aligner =
33+
RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :end)
3434

35-
def autocorrect(let)
36-
lambda do |corrector|
37-
corrector.insert_before(
38-
let.loc.end,
39-
token_aligner.indent_for(let)
40-
)
35+
token_aligner.offending_tokens.each do |let|
36+
add_offense(let.loc.end) do |corrector|
37+
corrector.insert_before(
38+
let.loc.end, token_aligner.indent_for(let)
39+
)
40+
end
4141
end
4242
end
43-
44-
private
45-
46-
def token_aligner
47-
@token_aligner ||=
48-
RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :end)
49-
end
5043
end
5144
end
5245
end

lib/rubocop/cop/rspec/be.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Be < Cop
2828

2929
def on_send(node)
3030
be_without_args(node) do |matcher|
31-
add_offense(matcher, location: :selector)
31+
add_offense(matcher.loc.selector)
3232
end
3333
end
3434
end

lib/rubocop/cop/rspec/be_eql.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ module RSpec
3636
# coerce objects for comparison.
3737
#
3838
class BeEql < Cop
39+
extend AutoCorrector
40+
3941
MSG = 'Prefer `be` over `eql`.'
4042

4143
def_node_matcher :eql_type_with_identity, <<-PATTERN
@@ -44,13 +46,11 @@ class BeEql < Cop
4446

4547
def on_send(node)
4648
eql_type_with_identity(node) do |eql|
47-
add_offense(eql, location: :selector)
49+
add_offense(eql.loc.selector) do |corrector|
50+
corrector.replace(eql.loc.selector, 'be')
51+
end
4852
end
4953
end
50-
51-
def autocorrect(node)
52-
->(corrector) { corrector.replace(node.loc.selector, 'be') }
53-
end
5454
end
5555
end
5656
end

lib/rubocop/cop/rspec/capybara/current_path_expectation.rb

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ module Capybara
2424
# expect(page).to have_current_path(/widgets/)
2525
#
2626
class CurrentPathExpectation < Cop
27+
extend AutoCorrector
28+
2729
MSG = 'Do not set an RSpec expectation on `current_path` in ' \
2830
'Capybara feature specs - instead, use the ' \
2931
'`have_current_path` matcher on `page`'
@@ -47,30 +49,30 @@ class CurrentPathExpectation < Cop
4749

4850
def on_send(node)
4951
expectation_set_on_current_path(node) do
50-
add_offense(node, location: :selector)
52+
add_offense(node.loc.selector) do |corrector|
53+
next unless node.chained?
54+
55+
autocorrect(corrector, node)
56+
end
5157
end
5258
end
5359

54-
def autocorrect(node)
55-
lambda do |corrector|
56-
return unless node.chained?
60+
private
5761

58-
as_is_matcher(node.parent) do |to_sym, matcher_node|
59-
rewrite_expectation(corrector, node, to_sym, matcher_node)
60-
end
62+
def autocorrect(corrector, node)
63+
as_is_matcher(node.parent) do |to_sym, matcher_node|
64+
rewrite_expectation(corrector, node, to_sym, matcher_node)
65+
end
6166

62-
regexp_str_matcher(node.parent) do |to_sym, matcher_node, regexp|
63-
rewrite_expectation(corrector, node, to_sym, matcher_node)
64-
convert_regexp_str_to_literal(corrector, matcher_node, regexp)
65-
end
67+
regexp_str_matcher(node.parent) do |to_sym, matcher_node, regexp|
68+
rewrite_expectation(corrector, node, to_sym, matcher_node)
69+
convert_regexp_str_to_literal(corrector, matcher_node, regexp)
6670
end
6771
end
6872

69-
private
70-
7173
def rewrite_expectation(corrector, node, to_symbol, matcher_node)
7274
current_path_node = node.first_argument
73-
corrector.replace(current_path_node.loc.expression, 'page')
75+
corrector.replace(current_path_node, 'page')
7476
corrector.replace(node.parent.loc.selector, 'to')
7577
matcher_method = if to_symbol == :to
7678
'have_current_path'
@@ -84,7 +86,7 @@ def rewrite_expectation(corrector, node, to_symbol, matcher_node)
8486
def convert_regexp_str_to_literal(corrector, matcher_node, regexp_str)
8587
str_node = matcher_node.first_argument
8688
regexp_expr = Regexp.new(regexp_str).inspect
87-
corrector.replace(str_node.loc.expression, regexp_expr)
89+
corrector.replace(str_node, regexp_expr)
8890
end
8991

9092
# `have_current_path` with no options will include the querystring
@@ -97,7 +99,7 @@ def add_ignore_query_options(corrector, node)
9799
return if %i[regexp str].include?(expectation_last_child.type)
98100

99101
corrector.insert_after(
100-
expectation_last_child.loc.expression,
102+
expectation_last_child,
101103
', ignore_query: true'
102104
)
103105
end

lib/rubocop/cop/rspec/capybara/feature_methods.rb

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ module Capybara
4141
# end
4242
# end
4343
class FeatureMethods < Cop
44+
extend AutoCorrector
45+
4446
MSG = 'Use `%<replacement>s` instead of `%<method>s`.'
4547

4648
# https://git.io/v7Kwr
@@ -71,18 +73,15 @@ def on_block(node)
7173
feature_method(node) do |send_node, match|
7274
next if enabled?(match)
7375

74-
add_offense(
75-
send_node,
76-
location: :selector,
77-
message: format(MSG, method: match, replacement: MAP[match])
78-
)
76+
add_offense(send_node.loc.selector) do |corrector|
77+
corrector.replace(send_node.loc.selector, MAP[match].to_s)
78+
end
7979
end
8080
end
8181

82-
def autocorrect(node)
83-
lambda do |corrector|
84-
corrector.replace(node.loc.selector, MAP[node.method_name].to_s)
85-
end
82+
def message(range)
83+
name = range.source.to_sym
84+
format(MSG, method: name, replacement: MAP[name])
8685
end
8786

8887
private

lib/rubocop/cop/rspec/context_method.rb

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ module RSpec
2424
# # ...
2525
# end
2626
class ContextMethod < Cop
27+
extend AutoCorrector
28+
2729
MSG = 'Use `describe` for testing methods.'
2830

2931
def_node_matcher :context_method, <<-PATTERN
@@ -32,13 +34,9 @@ class ContextMethod < Cop
3234

3335
def on_block(node)
3436
context_method(node) do |context|
35-
add_offense(context)
36-
end
37-
end
38-
39-
def autocorrect(node)
40-
lambda do |corrector|
41-
corrector.replace(node.parent.loc.selector, 'describe')
37+
add_offense(context) do |corrector|
38+
corrector.replace(node.send_node.loc.selector, 'describe')
39+
end
4240
end
4341
end
4442

lib/rubocop/cop/rspec/cop.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ module RSpec
1717
# # Patterns:
1818
# # - '_test.rb$'
1919
# # - '(?:^|/)test/'
20-
class Cop < ::RuboCop::Cop::Cop
20+
class Cop < ::RuboCop::Cop::Base
2121
include RuboCop::RSpec::Language
2222
include RuboCop::RSpec::Language::NodePattern
2323

lib/rubocop/cop/rspec/described_class.rb

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ module RSpec
5555
# end
5656
#
5757
class DescribedClass < Cop
58+
extend AutoCorrector
5859
include ConfigurableEnforcedStyle
5960

6061
DESCRIBED_CLASS = 'described_class'
@@ -85,22 +86,24 @@ def on_block(node)
8586
return unless body
8687

8788
find_usage(body) do |match|
88-
add_offense(match, message: message(match.const_name))
89+
msg = message(match.const_name)
90+
add_offense(match, message: msg) do |corrector|
91+
autocorrect(corrector, match)
92+
end
8993
end
9094
end
9195

92-
def autocorrect(node)
96+
private
97+
98+
def autocorrect(corrector, match)
9399
replacement = if style == :described_class
94100
DESCRIBED_CLASS
95101
else
96102
@described_class.const_name
97103
end
98-
lambda do |corrector|
99-
corrector.replace(node.loc.expression, replacement)
100-
end
101-
end
102104

103-
private
105+
corrector.replace(match, replacement)
106+
end
104107

105108
def find_usage(node, &block)
106109
yield(node) if offensive?(node)

0 commit comments

Comments
 (0)