Module: RSpecTracer::LineStub

Defined in:
lib/rspec_tracer/line_stub.rb

Overview

Per-engine line-stub builder for files that need a synthetic all-nil-but-executable-lines coverage array. Used by Reporters::CoverageJsonReporter when a tracked file is in coverage_tracked_files but has no recorded coverage (file never loaded during this run).

Lives at the top level of lib/rspec_tracer so the per-engine branches sit outside the tracker_coverage_gate's 100%-line+branch contract (the JRuby branch cannot be exercised on MRI; cross-engine coverage rollup would require fork-per-engine CI work that isn't justified for stub-line generation).

Methods use def self.x (not module_function) so future mutation gating maps to the singleton form -- module_function attaches methods to an anonymous singleton that mutant cannot observe.

Class Method Summary collapse

Class Method Details

.for(file_path) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Internal helper for the tracer pipeline.



22
23
24
25
26
27
28
29
30
31
# File 'lib/rspec_tracer/line_stub.rb', line 22

def self.for(file_path)
  case RUBY_ENGINE
  when 'ruby'
    ruby(file_path)
  when 'jruby'
    jruby(file_path)
  else
    File.foreach(file_path).map { nil }
  end
end

.jruby(file_path) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Internal helper for the tracer pipeline.



48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/rspec_tracer/line_stub.rb', line 48

def self.jruby(file_path)
  lines = File.foreach(file_path).map { nil }
  root_node = ::JRuby.parse(File.read(file_path, encoding: 'UTF-8'))
  visitor = org.jruby.ast.visitor.NodeVisitor.impl do |_name, node|
    if node.newline?
      ln = node.respond_to?(:position) ? node.position.line : node.line
      lines[ln] = 0
    end
    node.child_nodes.each { |child| child&.accept(visitor) }
  end
  root_node.accept(visitor)
  lines
end

.ruby(file_path) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Internal helper for the tracer pipeline.



35
36
37
38
39
40
41
42
43
44
# File 'lib/rspec_tracer/line_stub.rb', line 35

def self.ruby(file_path)
  lines = File.foreach(file_path).map { nil }
  iseqs = [::RubyVM::InstructionSequence.compile_file(file_path)]
  until iseqs.empty?
    iseq = iseqs.pop
    iseq.trace_points.each { |line_number, type| lines[line_number - 1] = 0 if type == :line }
    iseq.each_child { |child| iseqs << child }
  end
  lines
end