Module: Rigor::CLI::CoverageScan

Defined in:
lib/rigor/cli/coverage_scan.rb

Overview

Shared type-precision scan behind both rigor coverage (the dedicated command) and rigor check --coverage (the in-run coverage block). Walks each file's AST, types every expression via Scope#type_of, and accumulates the precision-tier breakdown into a CoverageReport. Extracted so the two surfaces stay byte-identical on the same file set.

Class Method Summary collapse

Class Method Details

.precision_report(files:, configuration:) ⇒ Rigor::CLI::CoverageReport

Parameters:

Returns:



23
24
25
26
27
28
29
# File 'lib/rigor/cli/coverage_scan.rb', line 23

def precision_report(files:, configuration:)
  scope = Scope.empty(environment: project_environment(configuration))
  scanner = Inference::PrecisionScanner.new(scope: scope)
  accumulator = CoverageAccumulator.new
  files.each { |path| scan_into(path, scanner, accumulator, configuration) }
  accumulator.to_report(files, {})
end

.project_environment(configuration) ⇒ Object



31
32
33
34
35
36
# File 'lib/rigor/cli/coverage_scan.rb', line 31

def project_environment(configuration)
  Environment.for_project(
    libraries: configuration.libraries,
    signature_paths: configuration.signature_paths
  )
end

.scan_into(path, scanner, accumulator, configuration) ⇒ Object

Parses one file and feeds the scan result (or a parse-error record) into accumulator. scanner / accumulator are a matched pair — a PrecisionScanner + CoverageAccumulator, or a ProtectionScanner + ProtectionAccumulator — both of which respond to scan(node) and absorb(path, result).



41
42
43
44
45
46
47
48
49
50
# File 'lib/rigor/cli/coverage_scan.rb', line 41

def scan_into(path, scanner, accumulator, configuration)
  source = File.read(path)
  parse_result = Prism.parse(source, filepath: path, version: configuration.target_ruby)
  if parse_result.errors.any?
    accumulator.record_parse_error(path, parse_result.errors)
    return
  end

  accumulator.absorb(path, scanner.scan(parse_result.value))
end