Module: Rigor::Source::NodeWalker
- Defined in:
- lib/rigor/source/node_walker.rb,
sig/rigor/source.rbs
Overview
Yields every Prism::Node reachable from a root in DFS pre-order.
The walker is the source-positioning analogue to NodeLocator: where the locator answers "what node
is at this point?", the walker enumerates the full set of Prism nodes for tooling that needs to
operate on each one (coverage probes, lint passes, IDE outlines).
Non-Prism children (literals embedded in node attributes, virtual nodes, or nil slots) are silently
skipped so callers can rely on every yielded value responding to the Prism::Node API.
Issue #318 — a Prism::DefinedNode's operand is never evaluated at runtime (defined? inspects the
expression statically; it does not run it), so the walk yields the DefinedNode itself but does NOT
descend into its value subtree. Every consumer of this walker treats a yielded node as "reachable,
evaluated code" (mutation/break/return scans, the check-rules main-pass oracle, coverage and precision
probes); walking into the operand would make them reason about code that can never run, which is
exactly the false-positive class the issue reports (defined?(@x) && ... flagging a call that is
actually inert).
Class Method Summary collapse
-
.each(root) {|node| ... } ⇒ Enumerator
When no block is given.
-
.each_with_ancestors(root) {|node, ancestors| ... } ⇒ Enumerator
Like NodeWalker.each, but also yields the node's lexical ancestor chain (outermost first, EXCLUDING the node itself).
- .walk(node) {|node| ... } ⇒ Object
- .walk_with_ancestors(node, ancestors, &block) ⇒ Object
Instance Method Summary collapse
- #self?.each {|arg0| ... } ⇒ Object
- #self?.each_with_ancestors {|arg0, arg1| ... } ⇒ Object
- #self?.walk {|arg0| ... } ⇒ void
- #self?.walk_with_ancestors {|arg0, arg1| ... } ⇒ void
Class Method Details
.each(root) {|node| ... } ⇒ Enumerator
Returns when no block is given.
30 31 32 33 34 35 |
# File 'lib/rigor/source/node_walker.rb', line 30 def each(root, &) return to_enum(__method__, root) unless block_given? walk(root, &) nil end |
.each_with_ancestors(root) {|node, ancestors| ... } ⇒ Enumerator
Like each, but also yields the node's lexical ancestor chain (outermost first, EXCLUDING the node
itself). The yielded ancestors array is the live descent stack — callers that retain it past the
block invocation MUST copy it (Plugin::NodeContext does). Used by the plugin engine to give
node_rule blocks their enclosing class / method / block context (ADR-37 slice 1d).
54 55 56 57 58 59 |
# File 'lib/rigor/source/node_walker.rb', line 54 def each_with_ancestors(root, &) return to_enum(__method__, root) unless block_given? walk_with_ancestors(root, [], &) nil end |
.walk(node) {|node| ... } ⇒ Object
37 38 39 40 41 42 43 44 |
# File 'lib/rigor/source/node_walker.rb', line 37 def walk(node, &) return unless node.is_a?(Prism::Node) yield node return if node.is_a?(Prism::DefinedNode) node.rigor_each_child { |child| walk(child, &) } end |
.walk_with_ancestors(node, ancestors, &block) ⇒ Object
61 62 63 64 65 66 67 68 69 70 |
# File 'lib/rigor/source/node_walker.rb', line 61 def walk_with_ancestors(node, ancestors, &block) return unless node.is_a?(Prism::Node) block.call(node, ancestors) return if node.is_a?(Prism::DefinedNode) ancestors.push(node) node.rigor_each_child { |child| walk_with_ancestors(child, ancestors, &block) } ancestors.pop end |
Instance Method Details
#self? ⇒ nil #self? ⇒ Enumerator[untyped, nil]
25 26 |
# File 'sig/rigor/source.rbs', line 25
def self?.each: (untyped root) { (untyped) -> void } -> nil
| (untyped root) -> Enumerator[untyped, nil]
|
#self? ⇒ nil #self? ⇒ Enumerator[untyped, nil]
28 29 |
# File 'sig/rigor/source.rbs', line 28
def self?.each_with_ancestors: (untyped root) { (untyped, Array[untyped]) -> void } -> nil
| (untyped root) -> Enumerator[untyped, nil]
|
#self?.walk {|arg0| ... } ⇒ void
This method returns an undefined value.
27 |
# File 'sig/rigor/source.rbs', line 27
def self?.walk: (untyped node) { (untyped) -> void } -> void
|
#self?.walk_with_ancestors {|arg0, arg1| ... } ⇒ void
This method returns an undefined value.
30 |
# File 'sig/rigor/source.rbs', line 30
def self?.walk_with_ancestors: (untyped node, Array[untyped] ancestors) { (untyped, Array[untyped]) -> void } -> void
|