Class: Solargraph::ComplexType

Inherits:
Object
  • Object
show all
Defined in:
lib/solargraph/complex_type.rb,
lib/solargraph/complex_type/unique_type.rb,
lib/solargraph/complex_type/type_methods.rb

Overview

A container for type data based on YARD type tags.

Defined Under Namespace

Modules: TypeMethods Classes: UniqueType

Constant Summary collapse

GENERIC_TAG_NAME =
'generic'.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(types = [UniqueType::UNDEFINED]) ⇒ ComplexType

Returns a new instance of ComplexType.

Parameters:



15
16
17
18
19
# File 'lib/solargraph/complex_type.rb', line 15

def initialize types = [UniqueType::UNDEFINED]
  # @todo @items here should not need an annotation
  # @type [Array<UniqueType>]
  @items = types.flat_map(&:items).uniq(&:to_s)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object?

Parameters:

  • name (Symbol)

Returns:

  • (Object, nil)


113
114
115
116
117
# File 'lib/solargraph/complex_type.rb', line 113

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

Instance Attribute Details

#itemsObject (readonly)

Returns the value of attribute items.



179
180
181
# File 'lib/solargraph/complex_type.rb', line 179

def items
  @items
end

Class Method Details

.parse(*strings, partial: false) ⇒ Array<UniqueType>

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.

Parse type strings into a ComplexType.

Examples:

ComplexType.parse 'String', 'Foo', 'nil' #=> [String, Foo, nil]
TODO:

Need ability to use a literal true as a type below

Parameters:

  • partial (Boolean) (defaults to: false)

    True if the string is part of a another type

Returns:

Parameters:

  • *strings (Array<String>)

    The type definitions to parse

Returns:



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/solargraph/complex_type.rb', line 227

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
    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.new(base[0..-2].strip)
          # @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.new(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.new(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

.try_parse(*strings) ⇒ ComplexType

Parameters:

  • strings (Array<String>)

Returns:



311
312
313
314
315
316
# File 'lib/solargraph/complex_type.rb', line 311

def try_parse *strings
  parse *strings
rescue ComplexTypeError => e
  Solargraph.logger.info "Error parsing complex type: #{e.message}"
  ComplexType::UNDEFINED
end

Instance Method Details

#[](index) ⇒ UniqueType

Parameters:

  • index (Integer)

Returns:



91
92
93
# File 'lib/solargraph/complex_type.rb', line 91

def [](index)
  @items[index]
end

#all?(&block) ⇒ Boolean

Returns:

  • (Boolean)


129
130
131
# File 'lib/solargraph/complex_type.rb', line 129

def all? &block
  @items.all? &block
end

#all_paramsArray<ComplexType>

Returns:



175
176
177
# File 'lib/solargraph/complex_type.rb', line 175

def all_params
  @items.first.all_params || []
end

#any?(&block) ⇒ Boolean

Returns:

  • (Boolean)


133
134
135
# File 'lib/solargraph/complex_type.rb', line 133

def any? &block
  @items.compact.any? &block
end

#each {|| ... } ⇒ Enumerable<UniqueType>

Yield Parameters:

Returns:



63
64
65
# File 'lib/solargraph/complex_type.rb', line 63

def each &block
  @items.each &block
end

#each_unique_typeEnumerator<UniqueType>

This method returns an undefined value.

Returns:

Yield Parameters:



71
72
73
74
75
76
77
# File 'lib/solargraph/complex_type.rb', line 71

def each_unique_type &block
  return enum_for(__method__) unless block_given?

  @items.each do |item|
    item.each_unique_type &block
  end
end

#firstUniqueType

Returns:



44
45
46
# File 'lib/solargraph/complex_type.rb', line 44

def first
  @items.first
end

#generic?Boolean

Returns:

  • (Boolean)


141
142
143
# File 'lib/solargraph/complex_type.rb', line 141

def generic?
  any?(&:generic?)
end

#lengthInteger

Returns:

  • (Integer)


80
81
82
# File 'lib/solargraph/complex_type.rb', line 80

def length
  @items.length
end

#map {|| ... } ⇒ Array

Yield Parameters:

Returns:

  • (Array)


57
58
59
# File 'lib/solargraph/complex_type.rb', line 57

def map &block
  @items.map &block
end

#namespaceString

Returns:

  • (String)


101
102
103
104
# File 'lib/solargraph/complex_type.rb', line 101

def namespace
  # cache this attr for high frequency call
  @namespace ||= method_missing(:namespace).to_s
end

#namespacesArray<String>

Returns:

  • (Array<String>)


107
108
109
# File 'lib/solargraph/complex_type.rb', line 107

def namespaces
  @items.map(&:namespace)
end

#nullable?Boolean

Returns:

  • (Boolean)


170
171
172
# File 'lib/solargraph/complex_type.rb', line 170

def nullable?
  @items.any?(&:nil_type?)
end

#qualify(api_map, context = '') ⇒ ComplexType

Parameters:

  • api_map (ApiMap)
  • context (String) (defaults to: '')

Returns:



24
25
26
27
28
29
30
31
# File 'lib/solargraph/complex_type.rb', line 24

def qualify api_map, context = ''
  red = reduce_object
  types = red.items.map do |t|
    next t if ['Boolean', 'nil', 'void', 'undefined'].include?(t.name)
    t.qualify api_map, context
  end
  ComplexType.new(types).reduce_object
end

#resolve_generics(definitions, context_type) ⇒ ComplexType

Parameters:

Returns:



156
157
158
159
# File 'lib/solargraph/complex_type.rb', line 156

def resolve_generics definitions, context_type
  result = @items.map { |i| i.resolve_generics(definitions, context_type) }
  ComplexType.parse(*result.map(&:tag))
end

#resolve_generics_from_context(generics_to_resolve, context_type, resolved_generic_values: {}) ⇒ self

Parameters:

  • generics_to_resolve (Enumerable<String>)

    ]

  • context_type (UniqueType, nil)
  • resolved_generic_values (Hash{String => ComplexType}) (defaults to: {})

    Added to as types are encountered or resolved

Returns:

  • (self)


37
38
39
40
41
# File 'lib/solargraph/complex_type.rb', line 37

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

#respond_to_missing?(name, include_private = false) ⇒ Boolean

Parameters:

  • name (Symbol)
  • include_private (Boolean) (defaults to: false)

Returns:

  • (Boolean)


121
122
123
# File 'lib/solargraph/complex_type.rb', line 121

def respond_to_missing?(name, include_private = false)
  TypeMethods.public_instance_methods.include?(name) || super
end

#select(&block) ⇒ Array<UniqueType>

Returns:



96
97
98
# File 'lib/solargraph/complex_type.rb', line 96

def select &block
  @items.select &block
end

#self_to(dst) ⇒ ComplexType

Parameters:

  • dst (String)

Returns:



163
164
165
166
167
168
# File 'lib/solargraph/complex_type.rb', line 163

def self_to dst
  return self unless selfy?
  red = reduce_class(dst)
  result = @items.map { |i| i.self_to red }
  ComplexType.parse(*result.map(&:tag))
end

#selfy?Boolean

Returns:

  • (Boolean)


137
138
139
# File 'lib/solargraph/complex_type.rb', line 137

def selfy?
  @items.any?(&:selfy?)
end

#to_aArray<UniqueType>

Returns:



85
86
87
# File 'lib/solargraph/complex_type.rb', line 85

def to_a
  @items
end

#to_rbsString

Returns:

  • (String)


49
50
51
52
53
# File 'lib/solargraph/complex_type.rb', line 49

def to_rbs
  ((@items.length > 1 ? '(' : '') +
   @items.map(&:to_rbs).join(' | ') +
   (@items.length > 1 ? ')' : ''))
end

#to_sObject



125
126
127
# File 'lib/solargraph/complex_type.rb', line 125

def to_s
  map(&:tag).join(', ')
end

#transform(new_name = nil) {|t| ... } ⇒ ComplexType

Parameters:

  • new_name (String, nil) (defaults to: nil)

Yield Parameters:

Yield Returns:

Returns:



149
150
151
# File 'lib/solargraph/complex_type.rb', line 149

def transform(new_name = nil, &transform_type)
  ComplexType.new(map { |ut| ut.transform(new_name, &transform_type) })
end