Class: Mutineer::Project::SubjectVisitor

Inherits:
Prism::Visitor
  • Object
show all
Defined in:
lib/mutineer/project.rb

Overview

Walks an AST, maintaining a namespace stack, emitting Subjects. Nested inside Project to signal its private role.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file) ⇒ SubjectVisitor

Returns a new instance of SubjectVisitor.



27
28
29
30
31
32
33
# File 'lib/mutineer/project.rb', line 27

def initialize(file)
  @file = file
  @namespace_stack = []
  @subjects = []
  @singleton_depth = 0
  super()
end

Instance Attribute Details

#subjectsObject (readonly)

Returns the value of attribute subjects.



25
26
27
# File 'lib/mutineer/project.rb', line 25

def subjects
  @subjects
end

Instance Method Details

#visit_class_node(node) ⇒ Object



35
36
37
38
39
# File 'lib/mutineer/project.rb', line 35

def visit_class_node(node)
  @namespace_stack.push(extract_constant_name(node.constant_path))
  super
  @namespace_stack.pop
end

#visit_def_node(node) ⇒ Object



60
61
62
63
64
65
66
67
68
69
# File 'lib/mutineer/project.rb', line 60

def visit_def_node(node)
  @subjects << Subject.new(
    file: @file,
    namespace: @namespace_stack.dup,
    name: node.name,
    singleton: !node.receiver.nil? || @singleton_depth.positive?,
    def_node: node
  )
  super
end

#visit_module_node(node) ⇒ Object



41
42
43
44
45
# File 'lib/mutineer/project.rb', line 41

def visit_module_node(node)
  @namespace_stack.push(extract_constant_name(node.constant_path))
  super
  @namespace_stack.pop
end

#visit_singleton_class_node(node) ⇒ Object

Methods inside class << self are class methods of the enclosing namespace, but their def nodes have no receiver — track the singleton context so they're recorded as singleton (so redefine targets the singleton_class, not instances). class << some_other_obj can't be represented against the namespace, so its defs are skipped (not recursed).



52
53
54
55
56
57
58
# File 'lib/mutineer/project.rb', line 52

def visit_singleton_class_node(node)
  return unless node.expression.is_a?(Prism::SelfNode)

  @singleton_depth += 1
  super
  @singleton_depth -= 1
end