Skip to content

Commit 01597e5

Browse files
authored
Merge pull request #1115 from rubocop-hq/improve-move-node-corrections
Take into account comments when moving nodes
2 parents 71c66db + c2cd558 commit 01597e5

File tree

6 files changed

+95
-9
lines changed

6 files changed

+95
-9
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Master (Unreleased)
44

5+
* Fix `HooksBeforeExamples`, `LeadingSubject`, `LetBeforeExamples` and `ScatteredLet` autocorrection to take into account inline comments and comments immediately before the moved node. ([@Darhazer][])
6+
57
## 2.1.0 (2020-12-17)
68

79
* Fix `RSpec/FilePath` false positive for relative file path runs with long namespaces. ([@ahukkanen][])

lib/rubocop-rspec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
require_relative 'rubocop/cop/rspec/mixin/top_level_group'
1616
require_relative 'rubocop/cop/rspec/mixin/variable'
1717
require_relative 'rubocop/cop/rspec/mixin/final_end_location'
18+
require_relative 'rubocop/cop/rspec/mixin/comments_help'
1819
require_relative 'rubocop/cop/rspec/mixin/empty_line_separation'
1920

2021
require_relative 'rubocop/rspec/concept'
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# frozen_string_literal: true
2+
3+
module RuboCop
4+
module Cop
5+
module RSpec
6+
# Help methods for working with nodes containing comments.
7+
module CommentsHelp
8+
include FinalEndLocation
9+
10+
def source_range_with_comment(node)
11+
begin_pos = begin_pos_with_comment(node).begin_pos
12+
end_pos = end_line_position(node).end_pos
13+
14+
Parser::Source::Range.new(buffer, begin_pos, end_pos)
15+
end
16+
17+
def begin_pos_with_comment(node)
18+
first_comment = processed_source.ast_with_comments[node].first
19+
20+
start_line_position(first_comment || node)
21+
end
22+
23+
def start_line_position(node)
24+
buffer.line_range(node.loc.line)
25+
end
26+
27+
def end_line_position(node)
28+
end_line = buffer.line_for_position(final_end_location(node).end_pos)
29+
buffer.line_range(end_line)
30+
end
31+
32+
def buffer
33+
processed_source.buffer
34+
end
35+
end
36+
end
37+
end
38+
end

lib/rubocop/rspec/corrector/move_node.rb

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module Corrector
66
# Helper methods to move a node
77
class MoveNode
88
include RuboCop::Cop::RangeHelp
9+
include RuboCop::Cop::RSpec::CommentsHelp
910
include RuboCop::Cop::RSpec::FinalEndLocation
1011

1112
attr_reader :original, :corrector, :processed_source
@@ -17,20 +18,16 @@ def initialize(node, corrector, processed_source)
1718
end
1819

1920
def move_before(other)
20-
position = other.loc.expression
21-
indent = ' ' * other.loc.column
22-
newline_indent = "\n#{indent}"
21+
position = start_line_position(other)
2322

24-
corrector.insert_before(position, source(original) + newline_indent)
23+
corrector.insert_before(position, "#{source(original)}\n")
2524
corrector.remove(node_range_with_surrounding_space(original))
2625
end
2726

2827
def move_after(other)
29-
position = final_end_location(other)
30-
indent = ' ' * other.loc.column
31-
newline_indent = "\n#{indent}"
28+
position = end_line_position(other)
3229

33-
corrector.insert_after(position, newline_indent + source(original))
30+
corrector.insert_after(position, "\n#{source(original)}")
3431
corrector.remove(node_range_with_surrounding_space(original))
3532
end
3633

@@ -41,7 +38,7 @@ def source(node)
4138
end
4239

4340
def node_range(node)
44-
node.loc.expression.with(end_pos: final_end_location(node).end_pos)
41+
source_range_with_comment(node)
4542
end
4643

4744
def node_range_with_surrounding_space(node)

spec/rubocop/cop/rspec/hooks_before_examples_spec.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,27 @@
9494
RUBY
9595
end
9696

97+
it 'works with comments' do
98+
expect_offense(<<-RUBY)
99+
RSpec.describe User do
100+
it { is_expected.to be_after_before_hook } # h
101+
# setup the system
102+
# with multiline comment
103+
before { setup } # some setup
104+
^^^^^^^^^^^^^^^^ Move `before` above the examples in the group.
105+
end
106+
RUBY
107+
108+
expect_correction(<<-RUBY)
109+
RSpec.describe User do
110+
# setup the system
111+
# with multiline comment
112+
before { setup } # some setup
113+
it { is_expected.to be_after_before_hook } # h
114+
end
115+
RUBY
116+
end
117+
97118
it 'does not flag hooks before the examples' do
98119
expect_no_offenses(<<-RUBY)
99120
RSpec.describe User do

spec/rubocop/cop/rspec/scattered_let_spec.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,33 @@
4949
RUBY
5050
end
5151

52+
it 'works with comments' do
53+
expect_offense(<<-RUBY)
54+
RSpec.describe User do
55+
let(:a) { a } # a comment
56+
# example comment
57+
it { expect(subject.foo).to eq(a) }
58+
it { expect(subject.fu).to eq(b) } # inline example comment
59+
# define the second letter
60+
# with a multi-line description
61+
let(:b) { b } # inline explanation as well
62+
^^^^^^^^^^^^^ Group all let/let! blocks in the example group together.
63+
end
64+
RUBY
65+
66+
expect_correction(<<-RUBY)
67+
RSpec.describe User do
68+
let(:a) { a } # a comment
69+
# define the second letter
70+
# with a multi-line description
71+
let(:b) { b } # inline explanation as well
72+
# example comment
73+
it { expect(subject.foo).to eq(a) }
74+
it { expect(subject.fu).to eq(b) } # inline example comment
75+
end
76+
RUBY
77+
end
78+
5279
it 'flags `let` at different nesting levels' do
5380
expect_offense(<<-RUBY)
5481
describe User do

0 commit comments

Comments
 (0)