Module: Prism::Merge::NestedStatementWalker

Defined in:
lib/prism/merge/nested_statement_walker.rb

Overview

Shared recursive traversal helpers for nested Prism statement bodies.

This stays in prism-merge rather than ast-merge because the reusable seam is Prism node structure (CallNode blocks plus conditional branches), not a parser-agnostic merge primitive.

Class Method Summary collapse

Class Method Details

.extract_statements(body_node) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/prism/merge/nested_statement_walker.rb', line 60

def extract_statements(body_node)
  return [] unless body_node

  body = body_node.respond_to?(:body) ? body_node.body : nil
  return body if body.is_a?(Array)

  statements = body_node.respond_to?(:statements) ? body_node.statements : nil
  statement_body = statements.respond_to?(:body) ? statements.body : nil
  return statement_body if statement_body.is_a?(Array)

  []
end

.nested_statement_children(node) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/prism/merge/nested_statement_walker.rb', line 45

def nested_statement_children(node)
  case NodeTypeNormalizer.canonical_type(node.type.to_s, :prism)
  when :call
    node.block ? [{ kind: :call_block, body: node.block.body }] : []
  when :if
    conditional_children(node, :if_body, :if_subsequent)
  when :unless
    conditional_children(node, :unless_body, :unless_subsequent)
  when :else
    node.statements ? [{ kind: :else_body, body: node.statements }] : []
  else
    []
  end
end

.walk(body_node, &block) ⇒ Object



13
14
15
16
17
18
19
20
21
22
# File 'lib/prism/merge/nested_statement_walker.rb', line 13

def walk(body_node, &block)
  return enum_for(__method__, body_node) unless block

  extract_statements(body_node).each do |node|
    yield node
    nested_statement_children(node).each do |child|
      walk(child[:body], &block)
    end
  end
end

.walk_with_context(body_node, next_context:, context_stack: [], &block) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/prism/merge/nested_statement_walker.rb', line 24

def walk_with_context(body_node, next_context:, context_stack: [], &block)
  return enum_for(__method__, body_node, context_stack: context_stack, next_context: next_context) unless block

  extract_statements(body_node).each do |node|
    yield node, context_stack

    nested_statement_children(node).each do |child|
      walk_with_context(
        child[:body],
        context_stack: next_context.call(
          node: node,
          child_kind: child[:kind],
          current_context: context_stack
        ),
        next_context: next_context,
        &block
      )
    end
  end
end