Class: Solargraph::ComplexType
- Inherits:
-
Object
- Object
- Solargraph::ComplexType
show all
- Includes:
- Equality
- 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
-
#[](index) ⇒ UniqueType
-
#all? {|| ... } ⇒ Boolean
-
#all_params ⇒ Array<ComplexType>
-
#all_rooted? ⇒ Boolean
every type and subtype in this union have been resolved to be fully qualified.
-
#any? {|| ... } ⇒ Boolean
-
#can_assign?(api_map, atype) ⇒ Boolean
-
#desc ⇒ String
-
#downcast_to_literal_if_possible ⇒ ComplexType
-
#each {|| ... } ⇒ Enumerable<UniqueType>
-
#each_unique_type ⇒ Enumerator<UniqueType>
-
#first ⇒ UniqueType
-
#force_rooted ⇒ self
-
#generic? ⇒ Boolean
-
#initialize(types = [UniqueType::UNDEFINED]) ⇒ ComplexType
constructor
A new instance of ComplexType.
-
#length ⇒ Integer
-
#literal? ⇒ Boolean
-
#map {|| ... } ⇒ Array<UniqueType>
-
#method_missing(name, *args, &block) ⇒ Object?
-
#namespace ⇒ String
-
#namespaces ⇒ Array<String>
-
#nullable? ⇒ Boolean
-
#qualify(api_map, *gates) ⇒ ComplexType
-
#recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil) ⇒ self
-
#reduce_class_type ⇒ ComplexType
-
#resolve_generics(definitions, context_type) ⇒ ComplexType
-
#resolve_generics_from_context(generics_to_resolve, context_type, resolved_generic_values: {}) ⇒ self
-
#respond_to_missing?(name, include_private = false) ⇒ Boolean
-
#rooted? ⇒ Boolean
every top-level type has resolved to be fully qualified; see #all_rooted? to check their subtypes as well.
-
#rooted_tags ⇒ String
-
#select(&block) ⇒ Array<UniqueType>
-
#self_to_type(dst) ⇒ ComplexType
-
#selfy? ⇒ Boolean
-
#simple_tags ⇒ String
-
#simplify_literals ⇒ self
-
#tags ⇒ String
-
#to_a ⇒ Array<UniqueType>
-
#to_rbs ⇒ String
-
#to_s ⇒ Object
-
#transform(new_name = nil) {|t| ... } ⇒ ComplexType
Methods included from Equality
#==, #eql?, #freeze, #hash
Constructor Details
#initialize(types = [UniqueType::UNDEFINED]) ⇒ ComplexType
Returns a new instance of ComplexType.
16
17
18
19
20
21
22
23
24
25
26
|
# File 'lib/solargraph/complex_type.rb', line 16
def initialize types = [UniqueType::UNDEFINED]
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
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object?
157
158
159
160
161
|
# 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
|
Instance Attribute Details
#items ⇒ Object
Returns the value of attribute items.
283
284
285
|
# File 'lib/solargraph/complex_type.rb', line 283
def items
@items
end
|
Class Method Details
.parse(*strings, partial: false) ⇒ ComplexType
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.
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.
@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]
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
|
# File 'lib/solargraph/complex_type.rb', line 327
def parse *strings, partial: false
@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 == '='
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 UniqueType.parse(base[0..-2].strip, subtype_string)
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 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 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
|
.try_parse(*strings) ⇒ ComplexType
412
413
414
415
416
417
|
# 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
|
Instance Method Details
135
136
137
|
# File 'lib/solargraph/complex_type.rb', line 135
def [](index)
@items[index]
end
|
#all? {|| ... } ⇒ Boolean
203
204
205
|
# File 'lib/solargraph/complex_type.rb', line 203
def all? &block
@items.all? &block
end
|
256
257
258
|
# File 'lib/solargraph/complex_type.rb', line 256
def all_params
@items.first.all_params || []
end
|
#all_rooted? ⇒ Boolean
every type and subtype in this union have been resolved to be
fully qualified
273
274
275
|
# File 'lib/solargraph/complex_type.rb', line 273
def all_rooted?
all?(&:all_rooted?)
end
|
#any? {|| ... } ⇒ Boolean
210
211
212
|
# File 'lib/solargraph/complex_type.rb', line 210
def any? &block
@items.compact.any? &block
end
|
#can_assign?(api_map, atype) ⇒ Boolean
104
105
106
|
# File 'lib/solargraph/complex_type.rb', line 104
def can_assign?(api_map, atype)
any? { |ut| ut.can_assign?(api_map, atype) }
end
|
#desc ⇒ String
193
194
195
|
# File 'lib/solargraph/complex_type.rb', line 193
def desc
rooted_tags
end
|
#downcast_to_literal_if_possible ⇒ ComplexType
188
189
190
|
# File 'lib/solargraph/complex_type.rb', line 188
def downcast_to_literal_if_possible
ComplexType.new(items.map(&:downcast_to_literal_if_possible))
end
|
#each {|| ... } ⇒ Enumerable<UniqueType>
86
87
88
|
# File 'lib/solargraph/complex_type.rb', line 86
def each &block
@items.each &block
end
|
#each_unique_type ⇒ Enumerator<UniqueType>
This method returns an undefined value.
94
95
96
97
98
99
100
|
# 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
|
57
58
59
|
# File 'lib/solargraph/complex_type.rb', line 57
def first
@items.first
end
|
#force_rooted ⇒ self
237
238
239
240
241
|
# File 'lib/solargraph/complex_type.rb', line 237
def force_rooted
transform do |t|
t.recreate(make_rooted: true)
end
end
|
#generic? ⇒ Boolean
218
219
220
|
# File 'lib/solargraph/complex_type.rb', line 218
def generic?
any?(&:generic?)
end
|
#length ⇒ Integer
124
125
126
|
# File 'lib/solargraph/complex_type.rb', line 124
def length
@items.length
end
|
#literal? ⇒ Boolean
183
184
185
|
# File 'lib/solargraph/complex_type.rb', line 183
def literal?
@items.any?(&:literal?)
end
|
#map {|| ... } ⇒ Array<UniqueType>
80
81
82
|
# File 'lib/solargraph/complex_type.rb', line 80
def map &block
@items.map &block
end
|
#namespace ⇒ String
145
146
147
148
|
# File 'lib/solargraph/complex_type.rb', line 145
def namespace
@namespace ||= method_missing(:namespace).to_s
end
|
#namespaces ⇒ Array<String>
151
152
153
|
# File 'lib/solargraph/complex_type.rb', line 151
def namespaces
@items.map(&:namespace)
end
|
#nullable? ⇒ Boolean
251
252
253
|
# File 'lib/solargraph/complex_type.rb', line 251
def nullable?
@items.any?(&:nil_type?)
end
|
#qualify(api_map, *gates) ⇒ ComplexType
36
37
38
39
40
41
42
43
44
|
# 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
|
#recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil) ⇒ self
114
115
116
117
118
119
120
121
|
# 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
|
261
262
263
264
265
266
267
268
269
|
# 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
|
#resolve_generics(definitions, context_type) ⇒ ComplexType
246
247
248
249
|
# 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
|
#resolve_generics_from_context(generics_to_resolve, context_type, resolved_generic_values: {}) ⇒ self
50
51
52
53
54
|
# 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
|
#respond_to_missing?(name, include_private = false) ⇒ Boolean
165
166
167
|
# File 'lib/solargraph/complex_type.rb', line 165
def respond_to_missing?(name, include_private = false)
TypeMethods.public_instance_methods.include?(name) || super
end
|
#rooted? ⇒ Boolean
every top-level type has resolved to be fully qualified; see
#all_rooted? to check their subtypes as well
279
280
281
|
# File 'lib/solargraph/complex_type.rb', line 279
def rooted?
all?(&:rooted?)
end
|
198
199
200
|
# File 'lib/solargraph/complex_type.rb', line 198
def rooted_tags
map(&:rooted_tag).join(', ')
end
|
#select(&block) ⇒ Array<UniqueType>
140
141
142
|
# File 'lib/solargraph/complex_type.rb', line 140
def select &block
@items.select &block
end
|
70
71
72
73
74
75
76
|
# 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
|
#selfy? ⇒ Boolean
214
215
216
|
# File 'lib/solargraph/complex_type.rb', line 214
def selfy?
@items.any?(&:selfy?)
end
|
179
180
181
|
# File 'lib/solargraph/complex_type.rb', line 179
def simple_tags
simplify_literals.tags
end
|
#simplify_literals ⇒ self
223
224
225
|
# File 'lib/solargraph/complex_type.rb', line 223
def simplify_literals
ComplexType.new(map(&:simplify_literals))
end
|
174
175
176
|
# File 'lib/solargraph/complex_type.rb', line 174
def tags
map(&:tag).join(', ')
end
|
129
130
131
|
# File 'lib/solargraph/complex_type.rb', line 129
def to_a
@items
end
|
#to_rbs ⇒ String
62
63
64
65
66
|
# File 'lib/solargraph/complex_type.rb', line 62
def to_rbs
((@items.length > 1 ? '(' : '') +
@items.map(&:to_rbs).join(' | ') +
(@items.length > 1 ? ')' : ''))
end
|
#to_s ⇒ Object
169
170
171
|
# File 'lib/solargraph/complex_type.rb', line 169
def to_s
map(&:tag).join(', ')
end
|
231
232
233
234
|
# 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
|