Class: RSpecTracer::Tracker::DeclaredGlobs Private

Inherits:
Object
  • Object
show all
Defined in:
lib/rspec_tracer/tracker/declared_globs.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.

Observer #3 in the 2.0 tracker pipeline (CoverageAdapter = #1, IOHooks = #2). Walks user-declared glob patterns at boot, digests each matching file, and emits :declared Inputs. Declared globs cover inputs that cannot be auto-observed - files no app code reads (Gemfile.lock, .rspec-tracer), or files that might not be rendered during a given run (a newly-added template).

Exposes #covers? so IOHooks can skip paths the declared-globs walk already observed. ARCHITECTURE rule (Input taxonomy): “if the user declares a glob that covers the same files we auto- intercept, the declared glob takes precedence.”

Graceful degradation (CLAUDE.md): an unreadable declared file is skipped silently - the tracer never propagates failure into the user’s test suite. Identity-based Set dedup collapses overlap when two globs match the same file.

Constant Summary collapse

FNMATCH_FLAGS =

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.

FNM_PATHNAME keeps ‘*` from eating `/` so globs walk directory boundaries predictably. FNM_EXTGLOB enables `a,b` alternation so `coverage_track_files ’app,lib/*/.rb’‘ (a real pattern in the sample projects) matches the same files `Dir.glob` would.

File::FNM_PATHNAME | File::FNM_EXTGLOB

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root:, globs: []) ⇒ DeclaredGlobs

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.



41
42
43
44
45
# File 'lib/rspec_tracer/tracker/declared_globs.rb', line 41

def initialize(root:, globs: [])
  @root = File.expand_path(root)
  @root_prefix = "#{@root}/"
  @globs = Array(globs).flatten.compact.map(&:to_s).uniq.freeze
end

Instance Attribute Details

#globsObject (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.



37
38
39
# File 'lib/rspec_tracer/tracker/declared_globs.rb', line 37

def globs
  @globs
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.



37
38
39
# File 'lib/rspec_tracer/tracker/declared_globs.rb', line 37

def root
  @root
end

Instance Method Details

#attribute_to(example_ids) ⇒ 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.

Per-example attribution. Declared inputs attach to every example in the suite (per-example narrowing is available via the per-example ‘tracks:` DSL). Each example gets its own Set copy so downstream mutation of one example’s input set does not leak into siblings.



70
71
72
73
# File 'lib/rspec_tracer/tracker/declared_globs.rb', line 70

def attribute_to(example_ids)
  inputs = walk
  example_ids.to_h { |id| [id, Set.new(inputs)] }
end

#covers?(path) ⇒ Boolean

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.

O(N_globs) per call; N is typically 1-10. Absolute paths only - the callers (IOHooks precedence, NewFileDetector diff) always hold absolute paths. Paths outside root never match.

Returns:

  • (Boolean)


57
58
59
60
61
62
63
# File 'lib/rspec_tracer/tracker/declared_globs.rb', line 57

def covers?(path)
  return false if @globs.empty?
  return false unless path.start_with?(@root_prefix)

  rel = path[@root_prefix.length..]
  @globs.any? { |glob| File.fnmatch?(glob, rel, FNMATCH_FLAGS) }
end

#walkObject

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.

Memoized across calls - the architecture constraint is “glob walk at boot is a single pass; result cached for the life of the tracker instance.”



50
51
52
# File 'lib/rspec_tracer/tracker/declared_globs.rb', line 50

def walk
  @walk ||= compute_walk
end