lib/covered/capture.rb
# frozen_string_literal: true # Released under the MIT License. # Copyright, 2018-2025, by Samuel Williams. require_relative "wrapper" require "coverage" module Covered # Captures Ruby coverage data and forwards it to another coverage output. class Capture < Wrapper # Start Ruby coverage collection. def start super ::Coverage.start(lines: true, eval: true) end # Clear any collected coverage data without stopping coverage. def clear super ::Coverage.result(stop: false, clear: true) end EVAL_PATHS = { "(eval)" => true, "(irb)" => true, "eval" => true } # Stop coverage collection and add the collected results to the output. # Ignores Ruby's anonymous eval paths and files that no longer exist. def finish results = ::Coverage.result results.each do |path, result| next if EVAL_PATHS.include?(path) path = self.expand_path(path) # Skip files which don't exist. This can happen if `eval` is used with an invalid/incorrect path: if File.exist?(path) @output.mark(path, 1, result[:lines]) else # warn "Skipping coverage for #{path.inspect} because it doesn't exist!" # Ignore. end end super end # Execute the given source while capturing coverage for it. # @parameter source [Covered::Source] The source to execute. # @parameter binding [Binding] The binding used to evaluate the source. # @returns [Object] The result of evaluating the source. def execute(source, binding: TOPLEVEL_BINDING) start eval(source.code!, binding, source.path, source.line_offset) ensure finish end end end