class Solargraph::ComplexType
A container for type data based on YARD type tags.
Constants
- BOOLEAN
- BOT
- GENERIC_TAG_NAME
- NIL
- ROOT
- SELF
- SYMBOL
- UNDEFINED
- VOID
Attributes
Public Class Methods
Source
# File lib/solargraph/complex_type.rb, line 16 def initialize types = [UniqueType::UNDEFINED] # @todo @items here should not need an annotation # @type [Array<UniqueType>] items = types.flat_map(&:items).uniq(&:to_s) if items.any? { |i| i.name == 'false' } && items.any? { |i| i.name == 'true' } items.delete_if { |i| i.name == 'false' || i.name == 'true' } items.unshift(ComplexType::BOOLEAN) end items = [UniqueType::UNDEFINED] if items.any?(&:undefined?) @items = items end
@param types [Array<UniqueType, ComplexType>]
Source
# File lib/solargraph/complex_type.rb, line 327 def parse *strings, partial: false # @type [Hash{Array<String> => ComplexType}] @cache ||= {} unless partial cached = @cache[strings] return cached unless cached.nil? end types = [] key_types = nil strings.each do |type_string| point_stack = 0 curly_stack = 0 paren_stack = 0 base = String.new subtype_string = String.new # @param char [String] type_string&.each_char do |char| if char == '=' #raise ComplexTypeError, "Invalid = in type #{type_string}" unless curly_stack > 0 elsif char == '<' point_stack += 1 elsif char == '>' if subtype_string.end_with?('=') && curly_stack > 0 subtype_string += char elsif base.end_with?('=') raise ComplexTypeError, "Invalid hash thing" unless key_types.nil? # types.push ComplexType.new([UniqueType.new(base[0..-2].strip)]) types.push UniqueType.parse(base[0..-2].strip, subtype_string) # @todo this should either expand key_type's type # automatically or complain about not being # compatible with key_type's type in type checking key_types = types types = [] base.clear subtype_string.clear next else raise ComplexTypeError, "Invalid close in type #{type_string}" if point_stack == 0 point_stack -= 1 subtype_string += char end next elsif char == '{' curly_stack += 1 elsif char == '}' curly_stack -= 1 subtype_string += char raise ComplexTypeError, "Invalid close in type #{type_string}" if curly_stack < 0 next elsif char == '(' paren_stack += 1 elsif char == ')' paren_stack -= 1 subtype_string += char raise ComplexTypeError, "Invalid close in type #{type_string}" if paren_stack < 0 next elsif char == ',' && point_stack == 0 && curly_stack == 0 && paren_stack == 0 # types.push ComplexType.new([UniqueType.new(base.strip, subtype_string.strip)]) types.push UniqueType.parse(base.strip, subtype_string.strip) base.clear subtype_string.clear next end if point_stack == 0 && curly_stack == 0 && paren_stack == 0 base.concat char else subtype_string.concat char end end raise ComplexTypeError, "Unclosed subtype in #{type_string}" if point_stack != 0 || curly_stack != 0 || paren_stack != 0 # types.push ComplexType.new([UniqueType.new(base, subtype_string)]) types.push UniqueType.parse(base.strip, subtype_string.strip) end unless key_types.nil? raise ComplexTypeError, "Invalid use of key/value parameters" unless partial return key_types if types.empty? return [key_types, types] end result = partial ? types : ComplexType.new(types) @cache[strings] = result unless partial result end
Parse type strings into a ComplexType.
@example
ComplexType.parse 'String', 'Foo', 'nil' #=> [String, Foo, nil]
@note
The `partial` parameter is used to indicate that the method is receiving a string that will be used inside another ComplexType. It returns arrays of ComplexTypes instead of a single cohesive one. Consumers should not need to use this parameter; it should only be used internally.
@param strings [Array<String>] The type definitions to parse @return [ComplexType] # @overload parse(*strings, partial: false) # @todo Need ability to use a literal true as a type below # @param partial [Boolean] True if the string is part of a another type # @return [Array<UniqueType>] @todo To be able to select the right signature above,
Chain::Call needs to know the decl type (:arg, :optarg, :kwarg, etc) of the arguments given, instead of just having an array of Chains as the arguments.
Source
# File lib/solargraph/complex_type.rb, line 412 def try_parse *strings parse *strings rescue ComplexTypeError => e Solargraph.logger.info "Error parsing complex type `#{strings.join(', ')}`: #{e.message}" ComplexType::UNDEFINED end
@param strings [Array<String>] @return [ComplexType]
Public Instance Methods
Source
# File lib/solargraph/complex_type.rb, line 135 def [](index) @items[index] end
@param index [Integer] @return [UniqueType]
Source
# File lib/solargraph/complex_type.rb, line 203 def all? &block @items.all? &block end
@yieldparam [UniqueType]
Source
# File lib/solargraph/complex_type.rb, line 256 def all_params @items.first.all_params || [] end
@return [Array<ComplexType>]
Source
# File lib/solargraph/complex_type.rb, line 273 def all_rooted? all?(&:all_rooted?) end
every type and subtype in this union have been resolved to be fully qualified
Source
# File lib/solargraph/complex_type.rb, line 210 def any? &block @items.compact.any? &block end
@yieldparam [UniqueType] @yieldreturn [Boolean] @return [Boolean]
Source
# File lib/solargraph/complex_type.rb, line 104 def can_assign?(api_map, atype) any? { |ut| ut.can_assign?(api_map, atype) } end
Source
# File lib/solargraph/complex_type.rb, line 193 def desc rooted_tags end
@return [String]
Source
# File lib/solargraph/complex_type.rb, line 188 def downcast_to_literal_if_possible ComplexType.new(items.map(&:downcast_to_literal_if_possible)) end
@return [ComplexType]
Source
# File lib/solargraph/complex_type.rb, line 86 def each &block @items.each &block end
@yieldparam [UniqueType] @return [Enumerable<UniqueType>]
Source
# File lib/solargraph/complex_type.rb, line 94 def each_unique_type &block return enum_for(__method__) unless block_given? @items.each do |item| item.each_unique_type &block end end
@yieldparam [UniqueType] @return [void] @overload each_unique_type()
@return [Enumerator<UniqueType>]
Source
# File lib/solargraph/complex_type.rb, line 57 def first @items.first end
@return [UniqueType]
Source
# File lib/solargraph/complex_type.rb, line 237 def force_rooted transform do |t| t.recreate(make_rooted: true) end end
@return [self]
Source
# File lib/solargraph/complex_type.rb, line 218 def generic? any?(&:generic?) end
Source
# File lib/solargraph/complex_type.rb, line 124 def length @items.length end
@return [Integer]
Source
# File lib/solargraph/complex_type.rb, line 183 def literal? @items.any?(&:literal?) end
Source
# File lib/solargraph/complex_type.rb, line 80 def map &block @items.map &block end
@yieldparam [UniqueType] @return [Array<UniqueType>]
Source
# File lib/solargraph/complex_type.rb, line 157 def method_missing name, *args, &block return if @items.first.nil? return @items.first.send(name, *args, &block) if respond_to_missing?(name) super end
@param name [Symbol] @return [Object, nil]
Source
# File lib/solargraph/complex_type.rb, line 145 def namespace # cache this attr for high frequency call @namespace ||= method_missing(:namespace).to_s end
@return [String]
Source
# File lib/solargraph/complex_type.rb, line 151 def namespaces @items.map(&:namespace) end
@return [Array<String>]
Source
# File lib/solargraph/complex_type.rb, line 251 def nullable? @items.any?(&:nil_type?) end
Source
# File lib/solargraph/complex_type.rb, line 36 def qualify api_map, *gates red = reduce_object types = red.items.map do |t| next t if ['nil', 'void', 'undefined'].include?(t.name) next t if ['::Boolean'].include?(t.rooted_name) t.qualify api_map, *gates end ComplexType.new(types).reduce_object end
@param api_map [ApiMap] @param context [String] @return [ComplexType]
Source
# File lib/solargraph/complex_type.rb, line 114 def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil) ComplexType.new(map do |ut| ut.recreate(new_name: new_name, make_rooted: make_rooted, new_key_types: new_key_types, new_subtypes: new_subtypes) end) end
@param new_name [String, nil] @param make_rooted [Boolean, nil] @param new_key_types [Array<ComplexType>, nil] @param rooted [Boolean, nil] @param new_subtypes [Array<ComplexType>, nil] @return [self]
Source
# File lib/solargraph/complex_type.rb, line 261 def reduce_class_type new_items = items.flat_map do |type| next type unless ['Module', 'Class'].include?(type.name) next type if type.all_params.empty? type.all_params end ComplexType.new(new_items) end
@return [ComplexType]
Source
# File lib/solargraph/complex_type.rb, line 246 def resolve_generics definitions, context_type result = @items.map { |i| i.resolve_generics(definitions, context_type) } ComplexType.new(result) end
@param definitions [Pin::Namespace, Pin::Method] @param context_type [ComplexType] @return [ComplexType]
Source
# File lib/solargraph/complex_type.rb, line 50 def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {} return self unless generic? ComplexType.new(@items.map { |i| i.resolve_generics_from_context(generics_to_resolve, context_type, resolved_generic_values: resolved_generic_values) }) end
@param generics_to_resolve [Enumerable<String>]] @param context_type [UniqueType, nil] @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved @return [self]
Source
# File lib/solargraph/complex_type.rb, line 165 def respond_to_missing?(name, include_private = false) TypeMethods.public_instance_methods.include?(name) || super end
@param name [Symbol] @param include_private [Boolean]
Source
# File lib/solargraph/complex_type.rb, line 279 def rooted? all?(&:rooted?) end
every top-level type has resolved to be fully qualified; see all_rooted? to check their subtypes as well
Source
# File lib/solargraph/complex_type.rb, line 140 def select &block @items.select &block end
@return [Array<UniqueType>]
Source
# File lib/solargraph/complex_type.rb, line 70 def self_to_type dst object_type_dst = dst.reduce_class_type transform do |t| next t if t.name != 'self' object_type_dst end end
@param dst [ComplexType] @return [ComplexType]
Source
# File lib/solargraph/complex_type.rb, line 214 def selfy? @items.any?(&:selfy?) end
Source
# File lib/solargraph/complex_type.rb, line 223 def simplify_literals ComplexType.new(map(&:simplify_literals)) end
@return [self]
Source
# File lib/solargraph/complex_type.rb, line 129 def to_a @items end
@return [Array<UniqueType>]
Source
# File lib/solargraph/complex_type.rb, line 62 def to_rbs ((@items.length > 1 ? '(' : '') + @items.map(&:to_rbs).join(' | ') + (@items.length > 1 ? ')' : '')) end
@return [String]
Source
# File lib/solargraph/complex_type.rb, line 231 def transform(new_name = nil, &transform_type) raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}" if new_name&.start_with?('::') ComplexType.new(map { |ut| ut.transform(new_name, &transform_type) }) end
@param new_name [String, nil] @yieldparam t [UniqueType] @yieldreturn [UniqueType] @return [ComplexType]
Protected Instance Methods
Source
# File lib/solargraph/complex_type.rb, line 300 def bottom? @items.all?(&:bot?) end
Source
# File lib/solargraph/complex_type.rb, line 29 def equality_fields [self.class, items] end
@sg-ignore Fix “Not enough arguments to Module#protected”
Source
# File lib/solargraph/complex_type.rb, line 292 def reduce_object new_items = items.flat_map do |ut| next [ut] if ut.name != 'Object' || ut.subtypes.empty? ut.subtypes end ComplexType.new(new_items) end
@return [ComplexType]
Private Instance Methods
Source
# File lib/solargraph/complex_type.rb, line 437 def reduce_class dst while dst =~ /^(Class|Module)\<(.*?)\>$/ dst = dst.sub(/^(Class|Module)\</, '').sub(/\>$/, '') end dst end
@todo This is a quick and dirty hack that forces ‘self` keywords
to reference an instance of their class and never the class itself. This behavior may change depending on which result is expected from YARD conventions. See https://github.com/lsegal/yard/issues/1257
@param dst [String] @return [String]