Class: Deprecool::Scanner::DispatchVisitor

Inherits:
Prism::Visitor
  • Object
show all
Defined in:
lib/deprecool/scanner.rb

Overview

Combines the given Finder classes into one class by defining one method per Prism::Visitor hook (e.g. visit_call_node) based on all the given finders that define a method that matches that hook method name

Instance Method Summary collapse

Constructor Details

#initialize(finder_instances) ⇒ DispatchVisitor

finder_instances is the array passed to the Scanner.new class, so this would be [Ruby::V4_0_0::ToSetArguments, ..]



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/deprecool/scanner.rb', line 39

def initialize(finder_instances)
  super()

  dispatch = Hash.new { |hash, key| hash[key] = [] }
  finder_instances.each do |instance|
    # find the hooks and add the instances to the hash of hook methods
    # so { on_call_node: [ToSetArguments.new, ObjectSpaceId2ref.new,.. ], ... }
    instance.class.hook_methods.each { |hook| dispatch[hook] << instance }
  end

  dispatch.each do |hook, finders|
    # convert the instances' hooks to what prism::visitor expects
    # so finder classes must use this pattern to name the visit_node methods
    #
    # 'on_call_node'   => good
    # 'find_call_node' => bad
    visit_method = hook.to_s.sub(/\Aon_/, 'visit_').to_sym

    # define the prism::visitor hook to loop through each of the
    # related finders and call the name of the hook like so:
    #
    # def visit_call_node(node)
    #   [ToSetArguments.new, ObjectSpaceId2ref.new].each do |finder|
    #     finder.send("on_call_node", node)
    #   end
    #
    #   super(node)
    # end
    define_singleton_method(visit_method) do |node|
      finders.each { |finder| finder.send(hook, node) }
      super(node)
    end
  end
end