module SimpleCov::StaticCoverageExtractor::ValuePositions
def call(root)
An identity set (a `compare_by_identity` Hash used as a set) of the
def call(root) positions = {} #: Hash[untyped, bool] positions.compare_by_identity mark(root, true, positions) positions end
def else_clause(node)
def else_clause(node) node.public_send(ELSE_CLAUSE_METHOD) end
def mark(node, in_value, positions)
def mark(node, in_value, positions) return unless node.is_a?(::Prism::Node) positions[node] = true if in_value children = tail_children(node, in_value) node.compact_child_nodes.each do |child| mark(child, children.any? { |c| c.equal?(child) }, positions) end end
def subsequent(node)
`case/in` (CaseMatchNode) is intentionally not a tail construct: its
of a case, under whichever accessor this Prism version exposes.
The `else`/`elsif` clause of an if-like node, and the `else` clause
def subsequent(node) node.is_a?(::Prism::IfNode) ? node.public_send(IF_NODE_SUBSEQUENT_METHOD) : else_clause(node) end
def tail_children(node, in_value)
itself is not (the method still returns its last expression), so it
void default. A method body is a tail context even when the `def`
The children of `node` that inherit its tail position; empty for the
def tail_children(node, in_value) # A method body is a tail context even when the `def` is not. return [node.body] if node.is_a?(::Prism::DefNode) return [] unless in_value case node when ::Prism::StatementsNode then [node.body.last] when ::Prism::IfNode, ::Prism::UnlessNode then [node.statements, subsequent(node)] when ::Prism::CaseNode then [*node.conditions, else_clause(node)] when ::Prism::ElseNode, ::Prism::WhenNode, ::Prism::BeginNode, ::Prism::ProgramNode then [node.statements] else [] end end