Class: RSpecTracer::Tracker::CoverageAdapter Private

Inherits:
Object
  • Object
show all
Defined in:
lib/rspec_tracer/tracker/coverage_adapter.rb

Overview

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

Wraps Ruby’s built-in ::Coverage module. The first observer in the 2.0 tracker pipeline – ingests the per-file line-coverage bitmap that MRI/JRuby maintain natively, normalizes the two possible shapes (array vs SimpleCov-style hash) and emits Tracker::Input values for the files touched between two peeks.

All state lives on the instance; no reads from RSpecTracer.*. Pass root, filters, and mode at construction time.

Content digest is SHA256 hex (see Input’s file-level comment). Changing the algorithm is a storage schema_version bump.

Constant Summary collapse

MODES =

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

::Coverage.peek_result returns one of two shapes:

:array -- { path => [hit_counts | nil, ...] }           (default)
:hash  -- { path => { lines: [...], branches: {...} } } (SimpleCov
                                                        with branch
                                                        coverage)

:auto detects on the first peek by sniffing a value’s type.

%i[auto array hash].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root:, filters: [], mode: :auto) ⇒ CoverageAdapter

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 method on the tracer pipeline.

Raises:

  • (ArgumentError)


39
40
41
42
43
44
45
46
47
# File 'lib/rspec_tracer/tracker/coverage_adapter.rb', line 39

def initialize(root:, filters: [], mode: :auto)
  raise ArgumentError, "invalid mode: #{mode.inspect}, allowed: #{MODES}" \
    unless MODES.include?(mode)

  @root = File.expand_path(root)
  @root_prefix = "#{@root}/"
  @filters = filters
  @mode = mode
end

Instance Attribute Details

#filtersObject (readonly)

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



35
36
37
# File 'lib/rspec_tracer/tracker/coverage_adapter.rb', line 35

def filters
  @filters
end

#modeObject (readonly)

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



35
36
37
# File 'lib/rspec_tracer/tracker/coverage_adapter.rb', line 35

def mode
  @mode
end

#rootObject (readonly)

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



35
36
37
# File 'lib/rspec_tracer/tracker/coverage_adapter.rb', line 35

def root
  @root
end

Instance Method Details

#compute_diff(before, after) ⇒ 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.

Pure function: returns Set<Input> for files whose line arrays changed between ‘before` and `after`. Handles nil line entries (unexecutable lines) correctly – nil<->nil is not a delta, any other transition is.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/rspec_tracer/tracker/coverage_adapter.rb', line 102

def compute_diff(before, after)
  changed = Set.new
  (before.keys | after.keys).each do |path|
    next unless delta?(before[path], after[path])

    changed << Input.for_file(
      path: path,
      kind: :ruby,
      digest: file_digest(path),
      root: @root
    )
  end
  changed
end

#peekObject

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.

Snapshot of the current coverage state: { absolute_path => Array<Integer|nil> } for files under project root that survive the user filter. Hash-mode input is reduced to its :lines component – 2.0 ignores branch coverage (same as 1.x; noted in the upgrade docs).



54
55
56
# File 'lib/rspec_tracer/tracker/coverage_adapter.rb', line 54

def peek
  peek_normalized { |path| filtered?(path) }
end

#peek_unfilteredObject

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.

Same shape as #peek but only filters by ‘@root_prefix` – skips the user `filters` filter. The coverage.json emitter (`Reporters::CoverageJsonReporter`) calls this at finalize to capture cumulative coverage matching legacy semantics: 1.x’s CoverageReporter#peek_coverage applied no ‘filters` filter at peek time and let `coverage_filters` do the final exclusion. Routing the emitter’s finalize peek through this method keeps the lib/-wide ‘::Coverage.peek_result` call-site count at 3 (one per file: this adapter, rspec/installation, and tracker/loaded_files_tracker) instead of adding a fourth.



68
69
70
# File 'lib/rspec_tracer/tracker/coverage_adapter.rb', line 68

def peek_unfiltered
  peek_normalized { false }
end

#peek_unfiltered_fullObject

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.

Same root-prefix scoping as #peek_unfiltered, but preserves Coverage’s full per-file shape (Hash ‘{ lines: […], branches: … }` in hash mode; Array<Integer|nil> in array mode) instead of reducing hash entries to their `:lines` component.

Lone caller is the SimpleCov interop shim (‘Reporters::CoverageJsonReporter::SimpleCovInterop`): when SimpleCov has `enable_coverage :branch`, Coverage runs in hash mode and the prepended `Coverage.result` MUST hand back the branches sub-hash so SimpleCov’s branch-coverage report path has data to render. The legacy ‘peek_unfiltered` strips branches because the user-facing `coverage.json` shape is documented as `Array<Integer|nil>` per file (1.x compatibility); do not change `peek_unfiltered` to do otherwise without bumping the storage schema.



87
88
89
90
91
92
93
94
95
96
# File 'lib/rspec_tracer/tracker/coverage_adapter.rb', line 87

def peek_unfiltered_full
  raw = ::Coverage.peek_result
  @mode = detect_mode(raw) if @mode == :auto

  raw.each_with_object({}) do |(path, stats), acc|
    next unless path.start_with?(@root_prefix)

    acc[path] = stats
  end
end