Module: Ruby::Coverage

Defined in:
lib/ruby/coverage.rb,
lib/ruby/coverage/version.rb,
ext/ruby/coverage/coverage.c

Defined Under Namespace

Classes: Tracer

Constant Summary collapse

VERSION =
"0.0.1"

Class Method Summary collapse

Class Method Details

.executable_lines(iseq) ⇒ Object

Walk the instruction sequence to find which lines carry a RUBY_EVENT_LINE event — these are the executable lines.

Lines without this event (comments, ‘else`, `end`, blank lines) remain nil in the counts array, matching the nil/0 distinction used by Ruby’s built-in Coverage module.

Recurses into child ISeqs (methods, blocks, lambdas) via ‘each_child` so that all executable lines across the entire compilation unit are collected.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/ruby/coverage.rb', line 43

def executable_lines(iseq)
	lines = []
	current_line = nil
	
	iseq.to_a[13].each do |element|
		case element
		when Integer          then current_line = element
		when :RUBY_EVENT_LINE then lines << current_line
		end
	end
	
	iseq.each_child{|child| lines.concat(executable_lines(child))}
	
	lines.sort!
	lines.uniq!
	lines
end

.peek_resultObject

Return the current line-count data without stopping the tracer.

The returned hash has the same shape as ‘::Coverage.peek_result`:

{ "/absolute/path.rb" => { lines: [nil, 0, 3, nil, ...] }, ... }


99
100
101
# File 'lib/ruby/coverage.rb', line 99

def peek_result
	@files.transform_values{|counts| {lines: counts}}
end

.result(stop: true, clear: false) ⇒ Object

Return coverage results, optionally stopping or clearing the tracer.



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/ruby/coverage.rb', line 110

def result(stop: true, clear: false)
	result = peek_result
	
	if stop
		@tracer&.stop
		@tracer = nil
		@files  = {}
	elsif clear
		@tracer&.stop
		@files  = {}
		@tracer = Tracer.new do |path, iseq|
			@files[path] ||= begin
				counts = []
				executable_lines(iseq).each{|line| counts[line] = 0}
				counts
			end
		end
		@tracer.start
	end
	
	result
end

.running?Boolean

Whether coverage is currently being tracked.

Returns:

  • (Boolean)


89
90
91
# File 'lib/ruby/coverage.rb', line 89

def running?
	!@tracer.nil?
end

.startObject

Start coverage tracking.

The callback receives (path, iseq) for each newly compiled file and must return a Ruby Array to use as the line-count store for that file, or nil to skip it. Executable lines are pre-initialised to 0; non-executable lines remain nil.

Safe to call multiple times; subsequent calls are no-ops. Returns self.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/ruby/coverage.rb', line 70

def start
	return self if @tracer
	
	@files  = {}
	@tracer = Tracer.new do |path, iseq|
		@files[path] ||= begin
			counts = []
			executable_lines(iseq).each{|line| counts[line] = 0}
			counts
		end
	end
	@tracer.start
	
	self
end