Skip to content

Commit 5d4a1be

Browse files
authored
Merge pull request #960 from rubocop-hq/optimize-leading-subject
Don't spend CPU finding the same node twice
2 parents 1be4c09 + fb10f1e commit 5d4a1be

File tree

2 files changed

+39
-15
lines changed

2 files changed

+39
-15
lines changed

lib/rubocop/cop/rspec/leading_subject.rb

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,35 +43,34 @@ def on_block(node)
4343
end
4444

4545
def check_previous_nodes(node)
46-
node.parent.each_child_node do |sibling|
47-
if offending?(sibling)
48-
msg = format(MSG, offending: sibling.method_name)
49-
add_offense(node, message: msg) do |corrector|
50-
autocorrect(corrector, node)
51-
end
46+
offending_node(node) do |offender|
47+
msg = format(MSG, offending: offender.method_name)
48+
add_offense(node, message: msg) do |corrector|
49+
autocorrect(corrector, node, offender)
5250
end
53-
54-
break if offending?(sibling) || sibling.equal?(node)
5551
end
5652
end
5753

5854
private
5955

60-
def autocorrect(corrector, node)
61-
first_node = find_first_offending_node(node)
56+
def offending_node(node)
57+
node.parent.each_child_node.find do |sibling|
58+
break if sibling.equal?(node)
59+
60+
yield sibling if offending?(sibling)
61+
end
62+
end
63+
64+
def autocorrect(corrector, node, sibling)
6265
RuboCop::RSpec::Corrector::MoveNode.new(
6366
node, corrector, processed_source
64-
).move_before(first_node)
67+
).move_before(sibling)
6568
end
6669

6770
def offending?(node)
6871
let?(node) || hook?(node) || example?(node)
6972
end
7073

71-
def find_first_offending_node(node)
72-
node.parent.children.find { |sibling| offending?(sibling) }
73-
end
74-
7574
def in_spec_block?(node)
7675
node.each_ancestor(:block).any? do |ancestor|
7776
example?(ancestor)

spec/rubocop/cop/rspec/leading_subject_spec.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,29 @@
135135
end
136136
RUBY
137137
end
138+
139+
it 'checks also when subject is below a non-offending node' do
140+
expect_offense(<<~RUBY)
141+
RSpec.describe do
142+
def helper_method
143+
end
144+
145+
it { is_expected.to be_present }
146+
147+
subject { described_class.new }
148+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Declare `subject` above any other `it` declarations.
149+
end
150+
RUBY
151+
152+
expect_correction(<<~RUBY)
153+
RSpec.describe do
154+
def helper_method
155+
end
156+
157+
subject { described_class.new }
158+
it { is_expected.to be_present }
159+
160+
end
161+
RUBY
162+
end
138163
end

0 commit comments

Comments
 (0)