Module: SimpleCov::StaticCoverageExtractor
- Extended by:
- StaticCoverageExtractor
- Included in:
- StaticCoverageExtractor
- Defined in:
- lib/simplecov/static_coverage_extractor.rb,
lib/simplecov/static_coverage_extractor/visitor.rb,
lib/simplecov/static_coverage_extractor/prism_compat.rb,
lib/simplecov/static_coverage_extractor/value_position.rb,
lib/simplecov/static_coverage_extractor/method_collector.rb,
lib/simplecov/static_coverage_extractor/condition_folding.rb,
lib/simplecov/static_coverage_extractor/location_conventions.rb
Overview
Static enumeration of the branches and methods Ruby's Coverage library
would have reported if a file had been loaded with branches: true /
methods: true. Used by SimulateCoverage to backfill data for files
added via cover / track_files that were never required during the run,
so unloaded files contribute to the branch/method denominators
symmetrically with their line coverage (#1059).
The emitted shape mirrors Coverage.result[path] for the same file.
Position info comes from Prism's reported source locations; it doesn't
always match Coverage's byte-for-byte, but lines are reliable and
downstream consumers that key off line numbers see the data they expect.
Prism loads on the first extraction rather than with SimpleCov, so a line-only run never needs it. Where it cannot load at all (JRuby on Windows, whose FFI backend fails to open libprism), extraction answers nil like any other failure.
Defined Under Namespace
Modules: ConditionFolding, LocationConventions, MethodCollector, PrismCompat, ValuePositions Classes: Visitor
Instance Method Summary collapse
-
#branch_start_line(_type, _id, start_line) ⇒ Object
Both keys carry their start line third, after the parts that vary between recordings.
-
#call(source) ⇒ Object
Parse
sourceand return{"branches" => {...}, "methods" => {...}}matching the shapeCoverage.result[path]produces. - #method_identity(_class_name, name, start_line) ⇒ Object
-
#prism_loaded? ⇒ Boolean
Memoized, because a failed load leaves nothing in $LOADED_FEATURES and would otherwise be retried for every file.
-
#real_source_positions(source) ⇒ Object
Summarize a source file's real branch and method positions, for the
:eval_generatedfilter (#1046).
Instance Method Details
#branch_start_line(_type, _id, start_line) ⇒ Object
Both keys carry their start line third, after the parts that vary between recordings. Read through a parameter list rather than an index, because every spelling of an index answers the same for a tuple of this fixed shape. Binding an argument has only the one spelling.
81 82 83 |
# File 'lib/simplecov/static_coverage_extractor.rb', line 81 def branch_start_line(_type, _id, start_line, *) start_line end |
#call(source) ⇒ Object
Parse source and return {"branches" => {...}, "methods" => {...}}
matching the shape Coverage.result[path] produces. Returns nil when
Prism cannot load or parsing fails, which callers treat as "couldn't
extract, fall back to empty hashes".
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/simplecov/static_coverage_extractor.rb', line 27 def call(source) return nil unless prism_loaded? result = Prism.parse(source) return nil if result.failure? visitor = Visitor.new visitor.visit(result.value) {"branches" => visitor.branches, "methods" => visitor.methods} rescue # Parser errors beyond the .failure? check, unsupported AST shapes, or # anything else: fall back to empty hashes rather than crashing the whole # report. nil end |
#method_identity(_class_name, name, start_line) ⇒ Object
85 86 87 |
# File 'lib/simplecov/static_coverage_extractor.rb', line 85 def method_identity(_class_name, name, start_line, *) [name, start_line] end |
#prism_loaded? ⇒ Boolean
Memoized, because a failed load leaves nothing in $LOADED_FEATURES and would otherwise be retried for every file.
71 72 73 74 75 |
# File 'lib/simplecov/static_coverage_extractor.rb', line 71 def prism_loaded? return @prism_loaded if instance_variable_defined?(:@prism_loaded) @prism_loaded = load_prism end |
#real_source_positions(source) ⇒ Object
Summarize a source file's real branch and method positions, for the
:eval_generated filter (#1046). Answers:
{
branches: Set[start_line, ...], # e.g., [3, 12, 20]
methods: Set[[name, start_line], ...] # e.g., [[:foo, 7], [:bar, 13]]
}
Branch matching is start_line-only rather than by the full tuple. Static extraction and Coverage can still disagree on a branch's exact column positions, so matching on start_line alone tolerates those differences. Coincidental line-sharing between a real branch and an eval-generated one keeps both, an acceptable false-negative for an opt-in filter.
Returns nil when Prism cannot load or parsing fails, signaling callers to keep every Coverage entry.
59 60 61 62 63 64 65 66 67 |
# File 'lib/simplecov/static_coverage_extractor.rb', line 59 def real_source_positions(source) extracted = call(source) return nil unless extracted { branches: extracted.fetch("branches").keys.to_set { |tuple| branch_start_line(*tuple) }, methods: extracted.fetch("methods").keys.to_set { |tuple| method_identity(*tuple) } } end |