Skip to content

Commit b8e0df0

Browse files
committed
Give Coverage.line_stub an entry for every line of the file
The loop that padded the stub with nils compared against lines.size(), which grows as the loop appends, so it stopped about halfway to the end: a five-line method whose last statement is on line 2 got a four-entry stub. A last line with no newline was not counted at all. Pad until the stub has one entry per line, counting lines as File.foreach does, which is what CRuby's line_stub sizes its array by. SimpleCov builds the line coverage of files that were never loaded from line_stub, so those files were reported with lines missing.
1 parent efc3d82 commit b8e0df0

3 files changed

Lines changed: 19 additions & 2 deletions

File tree

‎core/src/main/java/org/jruby/parser/Parser.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ public IRubyObject getLineStub(ThreadContext context, ParseResult result, int li
243243
LineStubVisitor lineVisitor = new LineStubVisitor(context.runtime, lines);
244244
lineVisitor.visitRootNode(((RootNode) result));
245245

246-
for (int i = 0; i <= lineCount - lines.size(); i++) {
246+
while (lines.size() < lineCount) {
247247
lines.append(context, context.nil);
248248
}
249249
return lines;

‎core/src/main/java/org/jruby/parser/ParserManager.java‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,13 @@ public IRubyObject getLineStub(ThreadContext context, IRubyObject arg) {
172172
int length = contents.realSize();
173173
byte[] bytes = contents.unsafeBytes();
174174

175+
// One entry per line, as File.foreach yields them: a last line without a newline still counts.
176+
int end = begin + length;
175177
int lineCount = 0;
176-
for (int i = begin; i < length; i++) {
178+
for (int i = begin; i < end; i++) {
177179
if (bytes[i] == '\n') lineCount++;
178180
}
181+
if (length > 0 && bytes[end - 1] != '\n') lineCount++;
179182

180183
// FIXME: Semantic problem. Linenumber affects both differently due to prism being 1-indexed and AST being 0-indexed.
181184
ParseResult result = parseFile("", Options.PARSER_PRISM.load() ? 0 : -1, new LoadServiceResourceInputStream(contents.bytes()), contents.getEncoding());

‎test/jruby/test_coverage.rb‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,20 @@ def test_ternary_arms_are_line_events
432432
RUBY
433433
end
434434

435+
def test_line_stub_has_an_entry_for_every_line
436+
source = <<~'RUBY'
437+
def show
438+
@product = base_scope
439+
.includes(colors_products: :color)
440+
.find(params[:id])
441+
end
442+
RUBY
443+
with_source(source) { |path| assert_equal [0, 0, nil, nil, nil], Coverage.line_stub(path) }
444+
with_source(source.chomp) { |path| assert_equal [0, 0, nil, nil, nil], Coverage.line_stub(path) }
445+
with_source("x = 1\n\n\n\n") { |path| assert_equal [0, nil, nil, nil], Coverage.line_stub(path) }
446+
with_source("") { |path| assert_equal [], Coverage.line_stub(path) }
447+
end
448+
435449
private
436450

437451
def with_source(source)

0 commit comments

Comments
 (0)