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.
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
-
#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.
68 69 70 |
# File 'lib/simplecov/static_coverage_extractor.rb', line 68 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 on parse
failure, which callers treat as "couldn't extract, fall back to empty
hashes".
24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/simplecov/static_coverage_extractor.rb', line 24 def call(source) 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
72 73 74 |
# File 'lib/simplecov/static_coverage_extractor.rb', line 72 def method_identity(_class_name, name, start_line, *) [name, start_line] 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 parsing fails, signaling callers to keep every Coverage entry.
54 55 56 57 58 59 60 61 62 |
# File 'lib/simplecov/static_coverage_extractor.rb', line 54 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 |