Sha256: e9a2fc07c9169b4425dc2dd49dd20761d5b45ac12bab3637faf2724c21de45e8

Contents?: true

Size: 1.42 KB

Versions: 2

Compression:

Stored size: 1.42 KB

Contents

# frozen_string_literal: true

require "prism"
require "rbs/inline"

module RbsActionmailer
  class Parser
    # @rbs! type t = RBS::Inline::AST::Declarations::ClassDecl | RBS::Inline::AST::Declarations::ModuleDecl

    # @rbs klass_name: String
    def self.parse(klass_name) #: t?
      parser = new
      parser.parse(klass_name)
    end

    # @rbs klass_name: String
    def parse(klass_name) #: t?
      decls = load(klass_name)
      return unless decls

      names = klass_name.split("::").map(&:to_sym)
      dig(decls, *names)
    end

    private

    # @rbs klass_name: String
    def load(klass_name) #: Array[RBS::Inline::AST::Declarations::t]?
      filename, = Object.const_source_location(klass_name) #: String?
      return unless filename && File.exist?(filename)

      parse_result = Prism.parse(File.read(filename))
      _, decls, = RBS::Inline::Parser.parse(parse_result, opt_in: false)
      decls
    end

    # @rbs decls: Array[RBS::Inline::AST::Declarations::t | RBS::Inline::AST::Members::t]
    # @rbs name: Symbol
    # @rbs *remains: Symbol
    def dig(decls, name, *remains) #: t?
      decls.each do |decl|
        case decl
        when RBS::Inline::AST::Declarations::ClassDecl, RBS::Inline::AST::Declarations::ModuleDecl
          if decl.node.name == name
            return decl if remains.empty?

            return dig(decl.members, *remains)
          end
        end
      end

      nil
    end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
rbs_actionmailer-1.1.0 lib/rbs_actionmailer/parser.rb
rbs_actionmailer-1.0.0 lib/rbs_actionmailer/parser.rb