Skip to content

Commit 57f5658

Browse files
committed
Better support for heredocs.
1 parent f549233 commit 57f5658

File tree

2 files changed

+102
-28
lines changed

2 files changed

+102
-28
lines changed

lib/rubocop/socketry/layout/consistent_blank_line_indentation.rb

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ def on_new_investigation
5353
processed_source.lines.each_with_index do |line, index|
5454
line_number = index + 1
5555

56+
unless delta = indentation_deltas[line_number]
57+
# Skip this line (e.g., non-squiggly heredoc content):
58+
next
59+
end
60+
5661
# Check blank lines for correct indentation:
5762
if line.strip.empty?
5863
expected_indentation = indentation(current_level)
@@ -69,8 +74,6 @@ def on_new_investigation
6974
end
7075
end
7176

72-
# Apply indentation delta for this line:
73-
delta = indentation_deltas[line_number] || 0
7477
current_level += delta
7578
end
7679
end
@@ -99,6 +102,21 @@ def walk_ast_for_indentation(node, deltas)
99102
deltas[location.line] += 1
100103
deltas[location.last_line] -= 1
101104
end
105+
when :dstr
106+
if location = node.location
107+
if body = location.heredoc_body
108+
if location.expression.source.start_with?("<<~")
109+
# Squiggly heredoc - indentation is significant, add deltas
110+
deltas[body.line] += 1
111+
deltas[body.last_line] -= 1
112+
else
113+
# Non-squiggly heredoc - ignore indentation on these lines
114+
(body.line..body.last_line).each do |line|
115+
deltas[line] = nil
116+
end
117+
end
118+
end
119+
end
102120
end
103121

104122
node.children.each do |child|

test/rubocop/socketry/layout/consistent_blank_line_indentation.rb

Lines changed: 82 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
2929
report = investigator.investigate(processed_source)
3030
offenses = report.offenses
31-
expect(offenses.length).to be == 1
31+
expect(offenses).not.to be(:empty?)
3232
expect(offenses.first.message).to be(:include?, message)
3333
end
3434
end
@@ -53,7 +53,7 @@
5353
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
5454
report = investigator.investigate(processed_source)
5555
offenses = report.offenses
56-
expect(offenses.length).to be == 0
56+
expect(offenses).to be(:empty?)
5757
end
5858
end
5959

@@ -65,7 +65,7 @@
6565
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
6666
report = investigator.investigate(processed_source)
6767
offenses = report.offenses
68-
expect(offenses.length).to be == 1
68+
expect(offenses).not.to be(:empty?)
6969
expect(offenses.first.message).to be(:include?, message)
7070
end
7171
end
@@ -78,7 +78,7 @@
7878
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
7979
report = investigator.investigate(processed_source)
8080
offenses = report.offenses
81-
expect(offenses.length).to be == 0
81+
expect(offenses).to be(:empty?)
8282
end
8383
end
8484

@@ -90,7 +90,7 @@
9090
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
9191
report = investigator.investigate(processed_source)
9292
offenses = report.offenses
93-
expect(offenses.length).to be == 1
93+
expect(offenses).not.to be(:empty?)
9494
expect(offenses.first.message).to be(:include?, message)
9595
end
9696
end
@@ -103,7 +103,7 @@
103103
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
104104
report = investigator.investigate(processed_source)
105105
offenses = report.offenses
106-
expect(offenses.length).to be == 0
106+
expect(offenses).to be(:empty?)
107107
end
108108
end
109109

@@ -115,7 +115,7 @@
115115
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
116116
report = investigator.investigate(processed_source)
117117
offenses = report.offenses
118-
expect(offenses.length).to be == 1
118+
expect(offenses).not.to be(:empty?)
119119
expect(offenses.first.message).to be(:include?, message)
120120
end
121121
end
@@ -128,7 +128,7 @@
128128
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
129129
report = investigator.investigate(processed_source)
130130
offenses = report.offenses
131-
expect(offenses.length).to be == 0
131+
expect(offenses).to be(:empty?)
132132
end
133133
end
134134

@@ -140,7 +140,7 @@
140140
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
141141
report = investigator.investigate(processed_source)
142142
offenses = report.offenses
143-
expect(offenses.length).to be == 1
143+
expect(offenses).not.to be(:empty?)
144144
expect(offenses.first.message).to be(:include?, message)
145145
end
146146
end
@@ -153,7 +153,7 @@
153153
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
154154
report = investigator.investigate(processed_source)
155155
offenses = report.offenses
156-
expect(offenses.length).to be == 0
156+
expect(offenses).to be(:empty?)
157157
end
158158
end
159159

@@ -165,7 +165,7 @@
165165
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
166166
report = investigator.investigate(processed_source)
167167
offenses = report.offenses
168-
expect(offenses.length).to be == 1
168+
expect(offenses).not.to be(:empty?)
169169
expect(offenses.first.message).to be(:include?, message)
170170
end
171171
end
@@ -178,7 +178,7 @@
178178
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
179179
report = investigator.investigate(processed_source)
180180
offenses = report.offenses
181-
expect(offenses.length).to be == 0
181+
expect(offenses).to be(:empty?)
182182
end
183183
end
184184

@@ -190,7 +190,7 @@
190190
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
191191
report = investigator.investigate(processed_source)
192192
offenses = report.offenses
193-
expect(offenses.length).to be == 1
193+
expect(offenses).not.to be(:empty?)
194194
expect(offenses.first.message).to be(:include?, message)
195195
end
196196
end
@@ -203,7 +203,7 @@
203203
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
204204
report = investigator.investigate(processed_source)
205205
offenses = report.offenses
206-
expect(offenses.length).to be == 0
206+
expect(offenses).to be(:empty?)
207207
end
208208
end
209209

@@ -215,7 +215,7 @@
215215
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
216216
report = investigator.investigate(processed_source)
217217
offenses = report.offenses
218-
expect(offenses.length).to be == 1
218+
expect(offenses).not.to be(:empty?)
219219
expect(offenses.first.message).to be(:include?, message)
220220
end
221221
end
@@ -228,7 +228,7 @@
228228
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
229229
report = investigator.investigate(processed_source)
230230
offenses = report.offenses
231-
expect(offenses.length).to be == 0
231+
expect(offenses).to be(:empty?)
232232
end
233233
end
234234

@@ -240,7 +240,7 @@
240240
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
241241
report = investigator.investigate(processed_source)
242242
offenses = report.offenses
243-
expect(offenses.length).to be == 1
243+
expect(offenses).not.to be(:empty?)
244244
expect(offenses.first.message).to be(:include?, message)
245245
end
246246
end
@@ -253,7 +253,7 @@
253253
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
254254
report = investigator.investigate(processed_source)
255255
offenses = report.offenses
256-
expect(offenses.length).to be == 0
256+
expect(offenses).to be(:empty?)
257257
end
258258
end
259259

@@ -265,7 +265,7 @@
265265
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
266266
report = investigator.investigate(processed_source)
267267
offenses = report.offenses
268-
expect(offenses.length).to be == 1
268+
expect(offenses).not.to be(:empty?)
269269
expect(offenses.first.message).to be(:include?, message)
270270
end
271271
end
@@ -278,7 +278,7 @@
278278
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
279279
report = investigator.investigate(processed_source)
280280
offenses = report.offenses
281-
expect(offenses.length).to be == 0
281+
expect(offenses).to be(:empty?)
282282
end
283283
end
284284

@@ -290,7 +290,7 @@
290290
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
291291
report = investigator.investigate(processed_source)
292292
offenses = report.offenses
293-
expect(offenses.length).to be == 1
293+
expect(offenses).not.to be(:empty?)
294294
expect(offenses.first.message).to be(:include?, message)
295295
end
296296
end
@@ -303,7 +303,7 @@
303303
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
304304
report = investigator.investigate(processed_source)
305305
offenses = report.offenses
306-
expect(offenses.length).to be == 0
306+
expect(offenses).to be(:empty?)
307307
end
308308
end
309309

@@ -315,7 +315,7 @@
315315
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
316316
report = investigator.investigate(processed_source)
317317
offenses = report.offenses
318-
expect(offenses.length).to be == 1
318+
expect(offenses).not.to be(:empty?)
319319
expect(offenses.first.message).to be(:include?, message)
320320
end
321321
end
@@ -328,7 +328,7 @@
328328
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
329329
report = investigator.investigate(processed_source)
330330
offenses = report.offenses
331-
expect(offenses.length).to be == 0
331+
expect(offenses).to be(:empty?)
332332
end
333333
end
334334

@@ -340,7 +340,7 @@
340340
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
341341
report = investigator.investigate(processed_source)
342342
offenses = report.offenses
343-
expect(offenses.length).to be == 1
343+
expect(offenses).not.to be(:empty?)
344344
expect(offenses.first.message).to be(:include?, message)
345345
end
346346
end
@@ -362,7 +362,63 @@
362362
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
363363
report = investigator.investigate(processed_source)
364364
offenses = report.offenses
365-
expect(offenses.length).to be == 0
365+
expect(offenses).to be(:empty?)
366+
end
367+
end
368+
369+
with "a heredoc with proper indentation" do
370+
let(:source) {"def foo\n\tputs <<~FOO\n\t\tHello\n\t\tWorld\n\tFOO\nend\n"}
371+
372+
it "does not register an offense when heredoc is properly indented" do
373+
processed_source = RuboCop::ProcessedSource.new(source, RUBY_VERSION.to_f)
374+
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
375+
report = investigator.investigate(processed_source)
376+
offenses = report.offenses
377+
expect(offenses).to be(:empty?)
378+
end
379+
end
380+
381+
with "a heredoc with correct body indentation" do
382+
let(:source) {"def foo\n\tputs <<~FOO\n\t\tHello\n\t\tWorld\n\tFOO\nend\n"}
383+
it "does not register an offense for properly indented heredoc body" do
384+
processed_source = RuboCop::ProcessedSource.new(source, RUBY_VERSION.to_f)
385+
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
386+
report = investigator.investigate(processed_source)
387+
offenses = report.offenses
388+
expect(offenses).to be(:empty?)
389+
end
390+
end
391+
392+
with "a heredoc with incorrect body indentation" do
393+
let(:source) {"def foo\n\tputs <<~FOO\n\n\t\tHello World\n\tFOO\nend\n"}
394+
it "registers an offense for unindented heredoc body" do
395+
processed_source = RuboCop::ProcessedSource.new(source, RUBY_VERSION.to_f)
396+
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
397+
report = investigator.investigate(processed_source)
398+
offenses = report.offenses
399+
expect(offenses).not.to be(:empty?)
400+
end
401+
end
402+
403+
with "a non-squiggly heredoc with any indentation" do
404+
let(:source) {"def foo\n\tputs <<-FOO\n\t\tHello\n\t\tWorld\n\tFOO\nend\n"}
405+
it "does not register an offense for non-squiggly heredoc content" do
406+
processed_source = RuboCop::ProcessedSource.new(source, RUBY_VERSION.to_f)
407+
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
408+
report = investigator.investigate(processed_source)
409+
offenses = report.offenses
410+
expect(offenses).to be(:empty?)
411+
end
412+
end
413+
414+
with "a plain heredoc with any indentation" do
415+
let(:source) {"def foo\n\tputs <<FOO\n\t\tHello\n\t\tWorld\n\tFOO\nend\n"}
416+
it "does not register an offense for plain heredoc content" do
417+
processed_source = RuboCop::ProcessedSource.new(source, RUBY_VERSION.to_f)
418+
investigator = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
419+
report = investigator.investigate(processed_source)
420+
offenses = report.offenses
421+
expect(offenses).to be(:empty?)
366422
end
367423
end
368424
end

0 commit comments

Comments
 (0)