Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c19d83e
Implement method coverage
sferik Sep 14, 2026
c7cf3b8
Do not leave a method coverage counter pending when a define_method c…
sferik Sep 14, 2026
90d08e4
Count method coverage for the initialize of Java subclasses
sferik Sep 14, 2026
34ecb4a
Only build the parser's per-line coverage array when lines are being …
sferik Sep 14, 2026
032c5fc
Use a plain list for a file's method coverage entries
sferik Sep 14, 2026
86e4423
Do the method coverage hand-off from one place per interpreted method…
sferik Sep 15, 2026
15e85ab
Rewrite the method coverage comments in plain, compact English
sferik Sep 15, 2026
664db68
Count method coverage for methods defined by an eval
sferik Sep 16, 2026
107c4ad
Set the line and source span of blocks that follow command arguments
sferik Sep 16, 2026
8ba51d8
Encode the operand of the method coverage instruction
sferik Sep 16, 2026
533a68a
Report whether a line was actually counted
sferik Sep 16, 2026
9f9b455
Keep the unknown span marker out of method coverage keys
sferik Sep 16, 2026
caf18c6
Key a method coverage entry by the name it was defined under
sferik Sep 16, 2026
9894de3
Detach method coverage counters when measurement stops
sferik Sep 16, 2026
b9ee86c
Let the super-forwarding scan skip the method coverage instructions
sferik Sep 16, 2026
a12ddd6
Clear a method coverage counter atomically
sferik Sep 16, 2026
102a76f
Build the coverage result outside the CoverageData lock
sferik Sep 16, 2026
f2756ad
Keep method registration off the lock when methods are not measured
sferik Sep 16, 2026
3f3421c
Read and clear the coverage counts in one step
sferik Sep 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/src/main/java/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,8 @@ public DynamicMethod putMethod(ThreadContext context, String id, DynamicMethod m
method.setImplementationClass(methodLocation);
}

if (context.runtime.isCoverageEnabled()) context.runtime.getCoverageData().registerMethod(id, method);

DynamicMethod oldMethod = methodLocation.getMethodsForWrite().put(id, method);

if (oldMethod != null && oldMethod.isRefined()) {
Expand Down
1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/ast/DefHolder.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class DefHolder {
public IRubyObject value;

public int line;
public int column = -1;
public Object singleton = null;
public ByteList dotOrColon;

Expand Down
14 changes: 14 additions & 0 deletions core/src/main/java/org/jruby/ast/DefNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,18 @@ public interface DefNode {
* @return the line (zero-offset)
*/
int getEndLine();

/**
* Zero-based byte column where the source of this definition starts: the def keyword, or the opening brace
* of a block. -1 if unknown.
* @return the column
*/
int getStartColumn();

/**
* Zero-based byte column just after the source of this definition ends: after the end keyword, or after
* the closing brace of a block. -1 if unknown.
* @return the column
*/
int getEndColumn();
}
5 changes: 5 additions & 0 deletions core/src/main/java/org/jruby/ast/DefnNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ public DefnNode(int line, RubySymbol name, ArgsNode argsNode, StaticScope scope,
super(line, name, argsNode, scope, bodyNode, endLine);
}

public DefnNode(int line, int startColumn, RubySymbol name, ArgsNode argsNode, StaticScope scope, Node bodyNode,
int endLine, int endColumn) {
super(line, startColumn, name, argsNode, scope, bodyNode, endLine, endColumn);
}

public NodeType getNodeType() {
return NodeType.DEFNNODE;
}
Expand Down
7 changes: 6 additions & 1 deletion core/src/main/java/org/jruby/ast/DefsNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ public class DefsNode extends MethodDefNode implements INameNode {

public DefsNode(int line, Node receiverNode, RubySymbol name, ArgsNode argsNode,
StaticScope scope, Node bodyNode, int endLine) {
super(line, name, argsNode, scope, bodyNode, endLine);
this(line, -1, receiverNode, name, argsNode, scope, bodyNode, endLine, -1);
}

public DefsNode(int line, int startColumn, Node receiverNode, RubySymbol name, ArgsNode argsNode,
StaticScope scope, Node bodyNode, int endLine, int endColumn) {
super(line, startColumn, name, argsNode, scope, bodyNode, endLine, endColumn);

assert receiverNode != null : "receiverNode is not null";

Expand Down
27 changes: 26 additions & 1 deletion core/src/main/java/org/jruby/ast/IterNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ public class IterNode extends Node implements DefNode {

// What static scoping relationship exists when it comes into being.
private final StaticScope scope;
private final int endLine;
private int endLine;
private int startColumn = -1;
private int endColumn = -1;

/**
* Used by ForNode only.
Expand Down Expand Up @@ -117,4 +119,27 @@ public List<Node> childNodes() {
public int getEndLine() {
return endLine;
}

public int getStartColumn() {
return startColumn;
}

public int getEndColumn() {
return endColumn;
}

/**
* Record the source span of this block: from its opening brace or do keyword through its closing brace or
* end keyword. For a lambda: from the start of the parameter list, or just after "->" when there is none,
* through the end of the body.
*
* @param startColumn zero-based byte column of the first character
* @param endLine zero-based line of the last character
* @param endColumn zero-based byte column just after the last character
*/
public void setSourceSpan(int startColumn, int endLine, int endColumn) {
this.startColumn = startColumn;
this.endLine = endLine;
this.endColumn = endColumn;
}
}
17 changes: 17 additions & 0 deletions core/src/main/java/org/jruby/ast/MethodDefNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,27 @@ public abstract class MethodDefNode extends Node implements INameNode, DefNode {
protected final StaticScope scope;
protected final Node bodyNode;
protected final int endLine;
protected final int startColumn;
protected final int endColumn;
// We lazily compile methods in IR but Ruby expects next and break to raise syntax error so we will eagerly
// build methods which contain those two keywords.
protected boolean containsNextBreak = false;

public MethodDefNode(int line, RubySymbol name, ArgsNode argsNode, StaticScope scope, Node bodyNode, int endLine) {
this(line, -1, name, argsNode, scope, bodyNode, endLine, -1);
}

public MethodDefNode(int line, int startColumn, RubySymbol name, ArgsNode argsNode, StaticScope scope, Node bodyNode,
int endLine, int endColumn) {
super(line, bodyNode.containsVariableAssignment());

this.name = name;
this.argsNode = argsNode;
this.scope = scope;
this.bodyNode = bodyNode;
this.endLine = endLine;
this.startColumn = startColumn;
this.endColumn = endColumn;
}

/**
Expand Down Expand Up @@ -98,6 +107,14 @@ public int getEndLine() {
return endLine;
}

public int getStartColumn() {
return startColumn;
}

public int getEndColumn() {
return endColumn;
}

public void setContainsNextBreak() {
containsNextBreak = true;
}
Expand Down
Loading
Loading