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).

‘def self.x` per feedback_mutation_friendly_modules so future mutation gating maps to the singleton form.

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.



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

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.



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

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.



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

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