Sha256: eeab03a34519dafa84b44a2b6975453b237eaa0da518efa29d7efa8224420d18

Contents?: true

Size: 1.87 KB

Versions: 6

Compression:

Stored size: 1.87 KB

Contents

# frozen_string_literal: true

require 'ast'
require 'set'
module I18n::Tasks::Scanners
  class RubyAstCallFinder
    include AST::Processor::Mixin

    # @param receiver_messages [Set<Pair<[nil, AST::Node>, Symbol>>] The receiver-message pairs to look for.
    def initialize(receiver_messages:)
      super()
      @message_receivers = receiver_messages.each_with_object({}) do |(receiver, message), t|
        (t[message] ||= []) << receiver
      end
    end

    # @param root_node [Parser::AST:Node]
    # @yieldparam send_node [Parser::AST:Node]
    # @yieldparam method_name [nil, String] the surrounding method's name.
    def find_calls(root_node, &block)
      @callback = block
      process root_node
    ensure
      @callback = nil
    end

    # @param root_node (see #find_calls)
    # @yieldparam (see #find_calls)
    # @return [Array<block return values excluding nils>]
    def collect_calls(root_node)
      results = []
      find_calls root_node do |send_node, method_name|
        result = yield send_node, method_name
        results << result if result
      end
      results
    end

    def on_def(node)
      @method_name = node.children[0]
      handler_missing node
    ensure
      @method_name = nil
    end

    def on_send(send_node)
      receiver = send_node.children[0]
      message  = send_node.children[1]
      valid_receivers = @message_receivers[message]
      # use `any?` because `include?` checks type equality, but the receiver is a Parser::AST::Node != AST::Node.
      if valid_receivers && valid_receivers.any? { |r| r == receiver }
        @callback.call(send_node, @method_name)
      end
      # always invoke handler_missing to get nested translations in children
      handler_missing send_node
      nil
    end

    def handler_missing(node)
      node.children.each { |child| process(child) if child.is_a?(::Parser::AST::Node) }
      nil
    end
  end
end

Version data entries

6 entries across 6 versions & 1 rubygems

Version Path
i18n-tasks-0.9.19 lib/i18n/tasks/scanners/ruby_ast_call_finder.rb
i18n-tasks-0.9.18 lib/i18n/tasks/scanners/ruby_ast_call_finder.rb
i18n-tasks-0.9.17 lib/i18n/tasks/scanners/ruby_ast_call_finder.rb
i18n-tasks-0.9.16 lib/i18n/tasks/scanners/ruby_ast_call_finder.rb
i18n-tasks-0.9.15 lib/i18n/tasks/scanners/ruby_ast_call_finder.rb
i18n-tasks-0.9.14 lib/i18n/tasks/scanners/ruby_ast_call_finder.rb