# frozen_string_literal: true module Yardcheck class Typedef class Parser include Concord.new(:namespace, :types), Adamantium def parse Typedef.parse(types.map(&method(:parse_type)).flatten.compact) end def parse_type(type) parsed = parse_yard_type(type) return [parsed] if parsed.is_a?(Invalid) parsed.map do |parsed_type| resolve_yard_type(parsed_type) end end def parse_yard_type(type) YARD::Tags::TypesExplainer::Parser.parse(type) rescue SyntaxError => error Invalid.new(type, error.message) end def resolve_yard_type(yard_type) case yard_type when YARD::Tags::TypesExplainer::CollectionType Collection.new( *resolve_type(yard_type.name), yard_type.types.flat_map(&method(:resolve_yard_type)) ) when YARD::Tags::TypesExplainer::Type types = resolve_type(yard_type.name) case types when :undefined then Undefined.new when :ducktype then Ducktype.parse(yard_type.name) else types.map { |type| Literal.new(type) } end else fail "wtf! #{yard_type}" end end def resolve_type(name) case name when 'nil' then [Const.new(NilClass)] when 'true' then [Const.new(TrueClass)] when 'false' then [Const.new(FalseClass)] when 'self' then [namespace_const] when 'undefined', 'void' then :undefined when 'Boolean', 'Bool' then [Const.new(TrueClass), Const.new(FalseClass)] when Ducktype::PATTERN then :ducktype else [tag_const(name)] end end def tag_const(name) Const.resolve(name, namespace_constant) end def namespace_const Const.resolve(namespace) end def namespace_constant namespace_const.constant end memoize :namespace_constant class Invalid include Concord.new(:type, :error) def signature type end end # Invalid end # Parser end # Typedef end # Yardcheck