Class: SimpleCov::StaticCoverageExtractor::Visitor

Inherits:
Prism::Visitor
  • Object
show all
Defined in:
lib/simplecov/static_coverage_extractor/visitor.rb

Overview

Prism visitor that accumulates branch and method tuples in the shape Ruby’s ‘Coverage` reports. Tuple ids are sequential across the file — `Coverage` uses sequential ids too, so this matches the conventional shape. Only defined when Prism is loadable; `StaticCoverageExtractor.available?` is the runtime gate.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeVisitor

Returns a new instance of Visitor.



29
30
31
32
33
34
35
# File 'lib/simplecov/static_coverage_extractor/visitor.rb', line 29

def initialize
  super
  @branches = {}
  @methods = {}
  @next_id = 0
  @class_stack = []
end

Instance Attribute Details

#branchesObject (readonly)

Returns the value of attribute branches.



27
28
29
# File 'lib/simplecov/static_coverage_extractor/visitor.rb', line 27

def branches
  @branches
end

#methodsObject (readonly)

Returns the value of attribute methods.



27
28
29
# File 'lib/simplecov/static_coverage_extractor/visitor.rb', line 27

def methods
  @methods
end

Instance Method Details

#visit_case_match_node(node) ⇒ Object



61
62
63
64
# File 'lib/simplecov/static_coverage_extractor/visitor.rb', line 61

def visit_case_match_node(node)
  emit_case_like(node, :in)
  super
end

#visit_case_node(node) ⇒ Object

‘case`/`when` and `case`/`in` (pattern matching) parse as CaseNode and CaseMatchNode respectively. When there’s no explicit ‘else`, Coverage synthesizes one at the case’s range.



56
57
58
59
# File 'lib/simplecov/static_coverage_extractor/visitor.rb', line 56

def visit_case_node(node)
  emit_case_like(node, :when)
  super
end

#visit_class_node(node) ⇒ Object

Track class/module nesting so method tuples carry the lexical class name. Module + Class are both treated as namespaces here since ‘Coverage` reports both as the constant.



81
82
83
# File 'lib/simplecov/static_coverage_extractor/visitor.rb', line 81

def visit_class_node(node)
  with_class(constant_name(node.constant_path)) { super }
end

#visit_def_node(node) ⇒ Object

‘def name(…)` and `def self.name(…)` both produce DefNode. The class context is the surrounding lexical class/module (or `Object` at the top level, matching `Coverage`’s convention).



92
93
94
95
96
97
98
# File 'lib/simplecov/static_coverage_extractor/visitor.rb', line 92

def visit_def_node(node)
  loc = node.location
  class_name = @class_stack.last || "Object"
  key = [class_name, node.name, loc.start_line, loc.start_column, loc.end_line, loc.end_column]
  @methods[key] = 0
  super
end

#visit_if_node(node) ⇒ Object

‘if` / `unless` / postfix-if / postfix-unless / ternary all parse as IfNode (or UnlessNode). Both carry a `then` arm (the statements body) and an optional `subsequent` (an ElseNode for `else`, another IfNode for `elsif`). When the subsequent is missing, Coverage synthesizes a `:else` arm attributed to the whole condition’s range — we do the same.



43
44
45
46
# File 'lib/simplecov/static_coverage_extractor/visitor.rb', line 43

def visit_if_node(node)
  emit_if_like(node)
  super
end

#visit_module_node(node) ⇒ Object



85
86
87
# File 'lib/simplecov/static_coverage_extractor/visitor.rb', line 85

def visit_module_node(node)
  with_class(constant_name(node.constant_path)) { super }
end

#visit_unless_node(node) ⇒ Object



48
49
50
51
# File 'lib/simplecov/static_coverage_extractor/visitor.rb', line 48

def visit_unless_node(node)
  emit_if_like(node)
  super
end

#visit_until_node(node) ⇒ Object



73
74
75
76
# File 'lib/simplecov/static_coverage_extractor/visitor.rb', line 73

def visit_until_node(node)
  emit_loop(node, :until)
  super
end

#visit_while_node(node) ⇒ Object

‘while` / `until` loops get a single `:body` arm. No synthetic else (the loop either runs the body or doesn’t).



68
69
70
71
# File 'lib/simplecov/static_coverage_extractor/visitor.rb', line 68

def visit_while_node(node)
  emit_loop(node, :while)
  super
end