solargraph 0.53.4 → 0.54.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +41 -0
- data/lib/solargraph/api_map/cache.rb +2 -12
- data/lib/solargraph/api_map/store.rb +14 -5
- data/lib/solargraph/api_map.rb +67 -24
- data/lib/solargraph/complex_type/type_methods.rb +70 -39
- data/lib/solargraph/complex_type/unique_type.rb +187 -73
- data/lib/solargraph/complex_type.rb +105 -40
- data/lib/solargraph/doc_map.rb +19 -3
- data/lib/solargraph/gem_pins.rb +9 -1
- data/lib/solargraph/language_server/host/dispatch.rb +8 -1
- data/lib/solargraph/language_server/host/message_worker.rb +29 -3
- data/lib/solargraph/language_server/host/sources.rb +1 -61
- data/lib/solargraph/language_server/host.rb +21 -68
- data/lib/solargraph/language_server/message/base.rb +1 -1
- data/lib/solargraph/language_server/message/initialize.rb +14 -0
- data/lib/solargraph/language_server/message/text_document/definition.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -0
- data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +3 -3
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
- data/lib/solargraph/language_server/progress.rb +135 -0
- data/lib/solargraph/language_server.rb +1 -0
- data/lib/solargraph/library.rb +144 -113
- data/lib/solargraph/location.rb +14 -1
- data/lib/solargraph/parser/node_processor/base.rb +3 -2
- data/lib/solargraph/parser/node_processor.rb +1 -0
- data/lib/solargraph/parser/parser_gem/class_methods.rb +3 -7
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +13 -7
- data/lib/solargraph/parser/parser_gem/node_methods.rb +1 -5
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +23 -19
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -2
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +53 -0
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +6 -4
- data/lib/solargraph/parser/parser_gem/node_processors.rb +2 -0
- data/lib/solargraph/parser.rb +2 -5
- data/lib/solargraph/pin/base.rb +15 -1
- data/lib/solargraph/pin/base_variable.rb +35 -6
- data/lib/solargraph/pin/block.rb +48 -11
- data/lib/solargraph/pin/callable.rb +147 -0
- data/lib/solargraph/pin/closure.rb +8 -3
- data/lib/solargraph/pin/common.rb +2 -6
- data/lib/solargraph/pin/conversions.rb +3 -2
- data/lib/solargraph/pin/delegated_method.rb +5 -1
- data/lib/solargraph/pin/documenting.rb +2 -0
- data/lib/solargraph/pin/instance_variable.rb +2 -2
- data/lib/solargraph/pin/method.rb +54 -32
- data/lib/solargraph/pin/namespace.rb +4 -4
- data/lib/solargraph/pin/parameter.rb +14 -39
- data/lib/solargraph/pin/proxy_type.rb +1 -1
- data/lib/solargraph/pin/signature.rb +3 -129
- data/lib/solargraph/pin.rb +4 -1
- data/lib/solargraph/range.rb +2 -4
- data/lib/solargraph/rbs_map/conversions.rb +79 -42
- data/lib/solargraph/rbs_map/core_fills.rb +6 -6
- data/lib/solargraph/rbs_map.rb +11 -3
- data/lib/solargraph/shell.rb +35 -15
- data/lib/solargraph/source/chain/array.rb +6 -5
- data/lib/solargraph/source/chain/block_symbol.rb +1 -1
- data/lib/solargraph/source/chain/block_variable.rb +1 -1
- data/lib/solargraph/source/chain/call.rb +78 -50
- data/lib/solargraph/source/chain/link.rb +9 -0
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain.rb +60 -16
- data/lib/solargraph/source/cursor.rb +13 -2
- data/lib/solargraph/source/updater.rb +1 -0
- data/lib/solargraph/source.rb +102 -129
- data/lib/solargraph/source_map/clip.rb +4 -4
- data/lib/solargraph/source_map/data.rb +30 -0
- data/lib/solargraph/source_map/mapper.rb +3 -2
- data/lib/solargraph/source_map.rb +37 -15
- data/lib/solargraph/type_checker/rules.rb +6 -1
- data/lib/solargraph/type_checker.rb +50 -25
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +3 -5
- data/lib/solargraph/workspace/config.rb +2 -1
- data/lib/solargraph/workspace.rb +13 -0
- metadata +6 -3
- data/lib/solargraph/language_server/host/cataloger.rb +0 -57
@@ -17,49 +17,87 @@ module Solargraph
|
|
17
17
|
#
|
18
18
|
# @param name [String] The name of the type
|
19
19
|
# @param substring [String] The substring of the type
|
20
|
-
|
20
|
+
# @param make_rooted [Boolean, nil]
|
21
|
+
# @return [UniqueType]
|
22
|
+
def self.parse name, substring = '', make_rooted: nil
|
23
|
+
if name.start_with?(':::')
|
24
|
+
raise "Illegal prefix: #{name}"
|
25
|
+
end
|
21
26
|
if name.start_with?('::')
|
22
|
-
|
23
|
-
|
27
|
+
name = name[2..-1]
|
28
|
+
rooted = true
|
29
|
+
elsif !can_root_name?(name)
|
30
|
+
rooted = true
|
24
31
|
else
|
25
|
-
|
26
|
-
@rooted = false
|
32
|
+
rooted = false
|
27
33
|
end
|
28
|
-
|
29
|
-
|
30
|
-
# @type [Array<ComplexType>]
|
31
|
-
@key_types = []
|
34
|
+
rooted = make_rooted unless make_rooted.nil?
|
35
|
+
|
32
36
|
# @type [Array<ComplexType>]
|
33
|
-
|
37
|
+
key_types = []
|
34
38
|
# @type [Array<ComplexType>]
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
@subtypes.concat subs[1].map { |u| ComplexType.new([u]) }
|
52
|
-
else
|
53
|
-
@subtypes.concat subs
|
39
|
+
subtypes = []
|
40
|
+
parameters_type = nil
|
41
|
+
unless substring.empty?
|
42
|
+
subs = ComplexType.parse(substring[1..-2], partial: true)
|
43
|
+
parameters_type = PARAMETERS_TYPE_BY_STARTING_TAG.fetch(substring[0])
|
44
|
+
if parameters_type == :hash
|
45
|
+
raise ComplexTypeError, "Bad hash type" unless !subs.is_a?(ComplexType) and subs.length == 2 and !subs[0].is_a?(UniqueType) and !subs[1].is_a?(UniqueType)
|
46
|
+
# @todo should be able to resolve map; both types have it
|
47
|
+
# with same return type
|
48
|
+
# @sg-ignore
|
49
|
+
key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
|
50
|
+
# @sg-ignore
|
51
|
+
subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
|
52
|
+
else
|
53
|
+
subtypes.concat subs
|
54
|
+
end
|
54
55
|
end
|
55
|
-
|
56
|
-
|
56
|
+
new(name, key_types, subtypes, rooted: rooted, parameters_type: parameters_type)
|
57
|
+
end
|
58
|
+
|
59
|
+
# @param name [String]
|
60
|
+
# @param key_types [Array<ComplexType>]
|
61
|
+
# @param subtypes [Array<ComplexType>]
|
62
|
+
# @param rooted [Boolean]
|
63
|
+
# @param parameters_type [Symbol, nil]
|
64
|
+
def initialize(name, key_types = [], subtypes = [], rooted:, parameters_type: nil)
|
65
|
+
if parameters_type.nil?
|
66
|
+
raise "You must supply parameters_type if you provide parameters" unless key_types.empty? && subtypes.empty?
|
67
|
+
end
|
68
|
+
raise "Please remove leading :: and set rooted instead - #{name.inspect}" if name.start_with?('::')
|
69
|
+
@name = name
|
70
|
+
@key_types = key_types
|
71
|
+
@subtypes = subtypes
|
72
|
+
@rooted = rooted
|
73
|
+
@all_params = []
|
74
|
+
@all_params.concat key_types
|
75
|
+
@all_params.concat subtypes
|
76
|
+
@parameters_type = parameters_type
|
57
77
|
end
|
58
78
|
|
59
79
|
def to_s
|
60
80
|
tag
|
61
81
|
end
|
62
82
|
|
83
|
+
def eql?(other)
|
84
|
+
self.class == other.class &&
|
85
|
+
@name == other.name &&
|
86
|
+
@key_types == other.key_types &&
|
87
|
+
@subtypes == other.subtypes &&
|
88
|
+
@rooted == other.rooted? &&
|
89
|
+
@all_params == other.all_params &&
|
90
|
+
@parameters_type == other.parameters_type
|
91
|
+
end
|
92
|
+
|
93
|
+
def ==(other)
|
94
|
+
eql?(other)
|
95
|
+
end
|
96
|
+
|
97
|
+
def hash
|
98
|
+
[self.class, @name, @key_types, @sub_types, @rooted, @all_params, @parameters_type].hash
|
99
|
+
end
|
100
|
+
|
63
101
|
# @return [Array<UniqueType>]
|
64
102
|
def items
|
65
103
|
[self]
|
@@ -76,11 +114,25 @@ module Solargraph
|
|
76
114
|
|
77
115
|
# @return [String]
|
78
116
|
def to_rbs
|
79
|
-
if
|
117
|
+
if duck_type?
|
118
|
+
'untyped'
|
119
|
+
elsif name == 'Boolean'
|
120
|
+
'bool'
|
121
|
+
elsif name.downcase == 'nil'
|
122
|
+
'nil'
|
123
|
+
elsif name == GENERIC_TAG_NAME
|
124
|
+
all_params.first.name
|
125
|
+
elsif ['Class', 'Module'].include?(name)
|
126
|
+
rbs_name
|
127
|
+
elsif ['Tuple', 'Array'].include?(name) && fixed_parameters?
|
80
128
|
# tuples don't have a name; they're just [foo, bar, baz].
|
81
129
|
if substring == '()'
|
82
130
|
# but there are no zero element tuples, so we go with an array
|
83
|
-
|
131
|
+
if rooted?
|
132
|
+
'::Array[]'
|
133
|
+
else
|
134
|
+
'Array[]'
|
135
|
+
end
|
84
136
|
else
|
85
137
|
# already generated surrounded by []
|
86
138
|
parameters_as_rbs
|
@@ -90,16 +142,37 @@ module Solargraph
|
|
90
142
|
end
|
91
143
|
end
|
92
144
|
|
145
|
+
# @return [Boolean]
|
146
|
+
def parameters?
|
147
|
+
!all_params.empty?
|
148
|
+
end
|
149
|
+
|
150
|
+
# @param types [Array<UniqueType, ComplexType>]
|
151
|
+
# @return [String]
|
152
|
+
def rbs_union(types)
|
153
|
+
if types.length == 1
|
154
|
+
types.first.to_rbs
|
155
|
+
else
|
156
|
+
"(#{types.map(&:to_rbs).join(' | ')})"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
93
160
|
# @return [String]
|
94
161
|
def parameters_as_rbs
|
95
|
-
|
162
|
+
return '' unless parameters?
|
163
|
+
|
164
|
+
return "[#{all_params.map(&:to_rbs).join(', ')}]" if key_types.empty?
|
165
|
+
|
166
|
+
# handle, e.g., Hash[K, V] case
|
167
|
+
key_types_str = rbs_union(key_types)
|
168
|
+
subtypes_str = rbs_union(subtypes)
|
169
|
+
"[#{key_types_str}, #{subtypes_str}]"
|
96
170
|
end
|
97
171
|
|
98
172
|
def generic?
|
99
173
|
name == GENERIC_TAG_NAME || all_params.any?(&:generic?)
|
100
174
|
end
|
101
175
|
|
102
|
-
|
103
176
|
# @param generics_to_resolve [Enumerable<String>]
|
104
177
|
# @param context_type [UniqueType, nil]
|
105
178
|
# @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
|
@@ -182,39 +255,35 @@ module Solargraph
|
|
182
255
|
end
|
183
256
|
|
184
257
|
# @param new_name [String, nil]
|
258
|
+
# @param make_rooted [Boolean, nil]
|
185
259
|
# @param new_key_types [Array<UniqueType>, nil]
|
260
|
+
# @param rooted [Boolean, nil]
|
186
261
|
# @param new_subtypes [Array<UniqueType>, nil]
|
187
262
|
# @return [self]
|
188
|
-
def recreate(new_name: nil, new_key_types: nil, new_subtypes: nil)
|
263
|
+
def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil)
|
264
|
+
raise "Please remove leading :: and set rooted instead - #{new_name}" if new_name&.start_with?('::')
|
265
|
+
|
189
266
|
new_name ||= name
|
190
267
|
new_key_types ||= @key_types
|
191
268
|
new_subtypes ||= @subtypes
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
# Array<(String), Integer> is not ambiguous if we accept
|
211
|
-
# (String) as a tuple type, but not currently understood
|
212
|
-
# by Solargraph.
|
213
|
-
UniqueType.new(new_name, "<(#{new_subtypes.join(', ')})>")
|
214
|
-
elsif fixed_parameters?
|
215
|
-
UniqueType.new(new_name, "(#{new_subtypes.join(', ')})")
|
216
|
-
else
|
217
|
-
UniqueType.new(new_name, "<#{new_subtypes.join(', ')}>")
|
269
|
+
make_rooted = @rooted if make_rooted.nil?
|
270
|
+
UniqueType.new(new_name, new_key_types, new_subtypes, rooted: make_rooted, parameters_type: parameters_type)
|
271
|
+
end
|
272
|
+
|
273
|
+
# @return [String]
|
274
|
+
def rooted_tags
|
275
|
+
rooted_tag
|
276
|
+
end
|
277
|
+
|
278
|
+
# @return [String]
|
279
|
+
def tags
|
280
|
+
tag
|
281
|
+
end
|
282
|
+
|
283
|
+
# @return [self]
|
284
|
+
def force_rooted
|
285
|
+
transform do |t|
|
286
|
+
t.recreate(make_rooted: true)
|
218
287
|
end
|
219
288
|
end
|
220
289
|
|
@@ -225,19 +294,35 @@ module Solargraph
|
|
225
294
|
# @yieldreturn [self]
|
226
295
|
# @return [self]
|
227
296
|
def transform(new_name = nil, &transform_type)
|
228
|
-
|
229
|
-
|
230
|
-
|
297
|
+
raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}" if new_name&.start_with?('::')
|
298
|
+
if name == ComplexType::GENERIC_TAG_NAME
|
299
|
+
# doesn't make sense to manipulate the name of the generic
|
300
|
+
new_key_types = @key_types
|
301
|
+
new_subtypes = @subtypes
|
302
|
+
else
|
303
|
+
new_key_types = @key_types.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
|
304
|
+
new_subtypes = @subtypes.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
|
305
|
+
end
|
306
|
+
new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes, make_rooted: @rooted)
|
231
307
|
yield new_type
|
232
308
|
end
|
233
309
|
|
234
|
-
#
|
235
|
-
#
|
236
|
-
# @
|
237
|
-
|
310
|
+
# Generate a ComplexType that fully qualifies this type's namespaces.
|
311
|
+
#
|
312
|
+
# @param api_map [ApiMap] The ApiMap that performs qualification
|
313
|
+
# @param context [String] The namespace from which to resolve names
|
314
|
+
# @return [self, ComplexType, UniqueType] The generated ComplexType
|
315
|
+
def qualify api_map, context = ''
|
238
316
|
transform do |t|
|
239
|
-
next t if t.name
|
240
|
-
t.
|
317
|
+
next t if t.name == GENERIC_TAG_NAME
|
318
|
+
next t if t.duck_type? || t.void? || t.undefined?
|
319
|
+
recon = (t.rooted? ? '' : context)
|
320
|
+
fqns = api_map.qualify(t.name, recon)
|
321
|
+
if fqns.nil?
|
322
|
+
next UniqueType::BOOLEAN if t.tag == 'Boolean'
|
323
|
+
next UniqueType::UNDEFINED
|
324
|
+
end
|
325
|
+
t.recreate(new_name: fqns, make_rooted: true)
|
241
326
|
end
|
242
327
|
end
|
243
328
|
|
@@ -245,8 +330,37 @@ module Solargraph
|
|
245
330
|
@name == 'self' || @key_types.any?(&:selfy?) || @subtypes.any?(&:selfy?)
|
246
331
|
end
|
247
332
|
|
248
|
-
|
249
|
-
|
333
|
+
# @param dst [ComplexType]
|
334
|
+
# @return [self]
|
335
|
+
def self_to_type dst
|
336
|
+
object_type_dst = dst.reduce_class_type
|
337
|
+
transform do |t|
|
338
|
+
next t if t.name != 'self'
|
339
|
+
object_type_dst
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
def all_rooted?
|
344
|
+
return true if name == GENERIC_TAG_NAME
|
345
|
+
rooted? && all_params.all?(&:rooted?)
|
346
|
+
end
|
347
|
+
|
348
|
+
def rooted?
|
349
|
+
!can_root_name? || @rooted
|
350
|
+
end
|
351
|
+
|
352
|
+
def can_root_name?(name_to_check = name)
|
353
|
+
self.class.can_root_name?(name_to_check)
|
354
|
+
end
|
355
|
+
|
356
|
+
# @param name [String]
|
357
|
+
def self.can_root_name?(name)
|
358
|
+
# name is not lowercase
|
359
|
+
!name.empty? && name != name.downcase
|
360
|
+
end
|
361
|
+
|
362
|
+
UNDEFINED = UniqueType.new('undefined', rooted: false)
|
363
|
+
BOOLEAN = UniqueType.new('Boolean', rooted: true)
|
250
364
|
end
|
251
365
|
end
|
252
366
|
end
|
@@ -11,20 +11,34 @@ module Solargraph
|
|
11
11
|
autoload :TypeMethods, 'solargraph/complex_type/type_methods'
|
12
12
|
autoload :UniqueType, 'solargraph/complex_type/unique_type'
|
13
13
|
|
14
|
-
# @param types [Array<
|
14
|
+
# @param types [Array<UniqueType, ComplexType>]
|
15
15
|
def initialize types = [UniqueType::UNDEFINED]
|
16
16
|
# @todo @items here should not need an annotation
|
17
17
|
# @type [Array<UniqueType>]
|
18
18
|
@items = types.flat_map(&:items).uniq(&:to_s)
|
19
19
|
end
|
20
20
|
|
21
|
+
def eql?(other)
|
22
|
+
self.class == other.class &&
|
23
|
+
@items == other.items
|
24
|
+
end
|
25
|
+
|
26
|
+
def ==(other)
|
27
|
+
self.eql?(other)
|
28
|
+
end
|
29
|
+
|
30
|
+
def hash
|
31
|
+
[self.class, @items].hash
|
32
|
+
end
|
33
|
+
|
21
34
|
# @param api_map [ApiMap]
|
22
35
|
# @param context [String]
|
23
36
|
# @return [ComplexType]
|
24
37
|
def qualify api_map, context = ''
|
25
38
|
red = reduce_object
|
26
39
|
types = red.items.map do |t|
|
27
|
-
next t if ['
|
40
|
+
next t if ['nil', 'void', 'undefined'].include?(t.name)
|
41
|
+
next t if ['::Boolean'].include?(t.rooted_name)
|
28
42
|
t.qualify api_map, context
|
29
43
|
end
|
30
44
|
ComplexType.new(types).reduce_object
|
@@ -52,6 +66,16 @@ module Solargraph
|
|
52
66
|
(@items.length > 1 ? ')' : ''))
|
53
67
|
end
|
54
68
|
|
69
|
+
# @param dst [ComplexType]
|
70
|
+
# @return [ComplexType]
|
71
|
+
def self_to_type dst
|
72
|
+
object_type_dst = dst.reduce_class_type
|
73
|
+
transform do |t|
|
74
|
+
next t if t.name != 'self'
|
75
|
+
object_type_dst
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
55
79
|
# @yieldparam [UniqueType]
|
56
80
|
# @return [Array]
|
57
81
|
def map &block
|
@@ -86,6 +110,10 @@ module Solargraph
|
|
86
110
|
@items
|
87
111
|
end
|
88
112
|
|
113
|
+
def tags
|
114
|
+
@items.map(&:tag).join(', ')
|
115
|
+
end
|
116
|
+
|
89
117
|
# @param index [Integer]
|
90
118
|
# @return [UniqueType]
|
91
119
|
def [](index)
|
@@ -126,6 +154,10 @@ module Solargraph
|
|
126
154
|
map(&:tag).join(', ')
|
127
155
|
end
|
128
156
|
|
157
|
+
def rooted_tags
|
158
|
+
map(&:rooted_tag).join(', ')
|
159
|
+
end
|
160
|
+
|
129
161
|
def all? &block
|
130
162
|
@items.all? &block
|
131
163
|
end
|
@@ -147,24 +179,23 @@ module Solargraph
|
|
147
179
|
# @yieldreturn [UniqueType]
|
148
180
|
# @return [ComplexType]
|
149
181
|
def transform(new_name = nil, &transform_type)
|
182
|
+
raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}" if new_name&.start_with?('::')
|
150
183
|
ComplexType.new(map { |ut| ut.transform(new_name, &transform_type) })
|
151
184
|
end
|
152
185
|
|
186
|
+
# @return [self]
|
187
|
+
def force_rooted
|
188
|
+
transform do |t|
|
189
|
+
t.recreate(make_rooted: true)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
153
193
|
# @param definitions [Pin::Namespace, Pin::Method]
|
154
194
|
# @param context_type [ComplexType]
|
155
195
|
# @return [ComplexType]
|
156
196
|
def resolve_generics definitions, context_type
|
157
197
|
result = @items.map { |i| i.resolve_generics(definitions, context_type) }
|
158
|
-
ComplexType.
|
159
|
-
end
|
160
|
-
|
161
|
-
# @param dst [String]
|
162
|
-
# @return [ComplexType]
|
163
|
-
def self_to dst
|
164
|
-
return self unless selfy?
|
165
|
-
red = reduce_class(dst)
|
166
|
-
result = @items.map { |i| i.self_to red }
|
167
|
-
ComplexType.parse(*result.map(&:tag))
|
198
|
+
ComplexType.new(result)
|
168
199
|
end
|
169
200
|
|
170
201
|
def nullable?
|
@@ -176,35 +207,49 @@ module Solargraph
|
|
176
207
|
@items.first.all_params || []
|
177
208
|
end
|
178
209
|
|
210
|
+
# @return [ComplexType]
|
211
|
+
def reduce_class_type
|
212
|
+
new_items = items.flat_map do |type|
|
213
|
+
next type unless ['Module', 'Class'].include?(type.name)
|
214
|
+
|
215
|
+
type.all_params
|
216
|
+
end
|
217
|
+
ComplexType.new(new_items)
|
218
|
+
end
|
219
|
+
|
220
|
+
# every type and subtype in this union have been resolved to be
|
221
|
+
# fully qualified
|
222
|
+
def all_rooted?
|
223
|
+
all?(&:all_rooted?)
|
224
|
+
end
|
225
|
+
|
226
|
+
# every top-level type has resolved to be fully qualified; see
|
227
|
+
# #all_rooted? to check their subtypes as well
|
228
|
+
def rooted?
|
229
|
+
all?(&:rooted?)
|
230
|
+
end
|
231
|
+
|
179
232
|
attr_reader :items
|
180
233
|
|
234
|
+
def rooted?
|
235
|
+
@items.all?(&:rooted?)
|
236
|
+
end
|
237
|
+
|
181
238
|
protected
|
182
239
|
|
183
240
|
# @return [ComplexType]
|
184
241
|
def reduce_object
|
185
|
-
|
186
|
-
|
242
|
+
new_items = items.flat_map do |ut|
|
243
|
+
next [ut] if ut.name != 'Object' || ut.subtypes.empty?
|
244
|
+
ut.subtypes
|
245
|
+
end
|
246
|
+
ComplexType.new(new_items)
|
187
247
|
end
|
188
248
|
|
189
249
|
def bottom?
|
190
250
|
@items.all?(&:bot?)
|
191
251
|
end
|
192
252
|
|
193
|
-
private
|
194
|
-
|
195
|
-
# @todo This is a quick and dirty hack that forces `self` keywords
|
196
|
-
# to reference an instance of their class and never the class itself.
|
197
|
-
# This behavior may change depending on which result is expected
|
198
|
-
# from YARD conventions. See https://github.com/lsegal/yard/issues/1257
|
199
|
-
# @param dst [String]
|
200
|
-
# @return [String]
|
201
|
-
def reduce_class dst
|
202
|
-
while dst =~ /^(Class|Module)\<(.*?)\>$/
|
203
|
-
dst = dst.sub(/^(Class|Module)\</, '').sub(/\>$/, '')
|
204
|
-
end
|
205
|
-
dst
|
206
|
-
end
|
207
|
-
|
208
253
|
class << self
|
209
254
|
# Parse type strings into a ComplexType.
|
210
255
|
#
|
@@ -220,10 +265,15 @@ module Solargraph
|
|
220
265
|
#
|
221
266
|
# @param *strings [Array<String>] The type definitions to parse
|
222
267
|
# @return [ComplexType]
|
223
|
-
# @overload parse(*strings, partial: false)
|
224
|
-
# @todo Need ability to use a literal true as a type below
|
225
|
-
# @param partial [Boolean] True if the string is part of a another type
|
226
|
-
# @return [Array<UniqueType>]
|
268
|
+
# # @overload parse(*strings, partial: false)
|
269
|
+
# # @todo Need ability to use a literal true as a type below
|
270
|
+
# # @param partial [Boolean] True if the string is part of a another type
|
271
|
+
# # @return [Array<UniqueType>]
|
272
|
+
# @sg-ignore
|
273
|
+
# @todo To be able to select the right signature above,
|
274
|
+
# Chain::Call needs to know the decl type (:arg, :optarg,
|
275
|
+
# :kwarg, etc) of the arguments given, instead of just having
|
276
|
+
# an array of Chains as the arguments.
|
227
277
|
def parse *strings, partial: false
|
228
278
|
# @type [Hash{Array<String> => ComplexType}]
|
229
279
|
@cache ||= {}
|
@@ -250,7 +300,7 @@ module Solargraph
|
|
250
300
|
elsif base.end_with?('=')
|
251
301
|
raise ComplexTypeError, "Invalid hash thing" unless key_types.nil?
|
252
302
|
# types.push ComplexType.new([UniqueType.new(base[0..-2].strip)])
|
253
|
-
types.push UniqueType.
|
303
|
+
types.push UniqueType.parse(base[0..-2].strip, subtype_string)
|
254
304
|
# @todo this should either expand key_type's type
|
255
305
|
# automatically or complain about not being
|
256
306
|
# compatible with key_type's type in type checking
|
@@ -281,7 +331,7 @@ module Solargraph
|
|
281
331
|
next
|
282
332
|
elsif char == ',' && point_stack == 0 && curly_stack == 0 && paren_stack == 0
|
283
333
|
# types.push ComplexType.new([UniqueType.new(base.strip, subtype_string.strip)])
|
284
|
-
types.push UniqueType.
|
334
|
+
types.push UniqueType.parse(base.strip, subtype_string.strip)
|
285
335
|
base.clear
|
286
336
|
subtype_string.clear
|
287
337
|
next
|
@@ -294,7 +344,7 @@ module Solargraph
|
|
294
344
|
end
|
295
345
|
raise ComplexTypeError, "Unclosed subtype in #{type_string}" if point_stack != 0 || curly_stack != 0 || paren_stack != 0
|
296
346
|
# types.push ComplexType.new([UniqueType.new(base, subtype_string)])
|
297
|
-
types.push UniqueType.
|
347
|
+
types.push UniqueType.parse(base.strip, subtype_string.strip)
|
298
348
|
end
|
299
349
|
unless key_types.nil?
|
300
350
|
raise ComplexTypeError, "Invalid use of key/value parameters" unless partial
|
@@ -311,18 +361,33 @@ module Solargraph
|
|
311
361
|
def try_parse *strings
|
312
362
|
parse *strings
|
313
363
|
rescue ComplexTypeError => e
|
314
|
-
Solargraph.logger.info "Error parsing complex type
|
364
|
+
Solargraph.logger.info "Error parsing complex type `#{strings.join(', ')}`: #{e.message}"
|
315
365
|
ComplexType::UNDEFINED
|
316
366
|
end
|
317
367
|
end
|
318
368
|
|
319
369
|
VOID = ComplexType.parse('void')
|
320
370
|
UNDEFINED = ComplexType.parse('undefined')
|
321
|
-
SYMBOL = ComplexType.parse('Symbol')
|
322
|
-
ROOT = ComplexType.parse('Class<>')
|
371
|
+
SYMBOL = ComplexType.parse('::Symbol')
|
372
|
+
ROOT = ComplexType.parse('::Class<>')
|
323
373
|
NIL = ComplexType.parse('nil')
|
324
374
|
SELF = ComplexType.parse('self')
|
325
|
-
BOOLEAN = ComplexType.parse('Boolean')
|
375
|
+
BOOLEAN = ComplexType.parse('::Boolean')
|
326
376
|
BOT = ComplexType.parse('bot')
|
377
|
+
|
378
|
+
private
|
379
|
+
|
380
|
+
# @todo This is a quick and dirty hack that forces `self` keywords
|
381
|
+
# to reference an instance of their class and never the class itself.
|
382
|
+
# This behavior may change depending on which result is expected
|
383
|
+
# from YARD conventions. See https://github.com/lsegal/yard/issues/1257
|
384
|
+
# @param dst [String]
|
385
|
+
# @return [String]
|
386
|
+
def reduce_class dst
|
387
|
+
while dst =~ /^(Class|Module)\<(.*?)\>$/
|
388
|
+
dst = dst.sub(/^(Class|Module)\</, '').sub(/\>$/, '')
|
389
|
+
end
|
390
|
+
dst
|
391
|
+
end
|
327
392
|
end
|
328
393
|
end
|
data/lib/solargraph/doc_map.rb
CHANGED
@@ -18,9 +18,11 @@ module Solargraph
|
|
18
18
|
|
19
19
|
# @param requires [Array<String>]
|
20
20
|
# @param preferences [Array<Gem::Specification>]
|
21
|
-
|
21
|
+
# @param rbs_path [String, Pathname, nil]
|
22
|
+
def initialize(requires, preferences, rbs_path = nil)
|
22
23
|
@requires = requires.compact
|
23
24
|
@preferences = preferences.compact
|
25
|
+
@rbs_path = rbs_path
|
24
26
|
generate
|
25
27
|
end
|
26
28
|
|
@@ -39,6 +41,7 @@ module Solargraph
|
|
39
41
|
@gems_in_memory ||= {}
|
40
42
|
end
|
41
43
|
|
44
|
+
# @return [Set<Gem::Specification>]
|
42
45
|
def dependencies
|
43
46
|
@dependencies ||= (gemspecs.flat_map { |spec| fetch_dependencies(spec) } - gemspecs).to_set
|
44
47
|
end
|
@@ -57,6 +60,7 @@ module Solargraph
|
|
57
60
|
end
|
58
61
|
end
|
59
62
|
dependencies.each { |dep| try_cache dep }
|
63
|
+
@uncached_gemspecs.uniq!
|
60
64
|
end
|
61
65
|
|
62
66
|
# @return [Hash{String => Gem::Specification, nil}]
|
@@ -75,7 +79,8 @@ module Solargraph
|
|
75
79
|
return if try_gem_in_memory(gemspec)
|
76
80
|
cache_file = File.join('gems', "#{gemspec.name}-#{gemspec.version}.ser")
|
77
81
|
if Cache.exist?(cache_file)
|
78
|
-
|
82
|
+
cached = Cache.load(cache_file)
|
83
|
+
gempins = update_from_collection(gemspec, cached)
|
79
84
|
self.class.gems_in_memory[gemspec] = gempins
|
80
85
|
@pins.concat gempins
|
81
86
|
else
|
@@ -93,7 +98,7 @@ module Solargraph
|
|
93
98
|
@pins.concat map.pins
|
94
99
|
else
|
95
100
|
# @todo Temporarily ignoring unresolved `require 'set'`
|
96
|
-
Solargraph.logger.
|
101
|
+
Solargraph.logger.debug "Require path #{path} could not be resolved" unless path == 'set'
|
97
102
|
end
|
98
103
|
end
|
99
104
|
|
@@ -107,6 +112,17 @@ module Solargraph
|
|
107
112
|
true
|
108
113
|
end
|
109
114
|
|
115
|
+
def update_from_collection gemspec, gempins
|
116
|
+
return gempins unless @rbs_path && File.directory?(@rbs_path)
|
117
|
+
return gempins if RbsMap.new(gemspec.name, gemspec.version).resolved?
|
118
|
+
|
119
|
+
rbs_map = RbsMap.new(gemspec.name, gemspec.version, directories: [@rbs_path])
|
120
|
+
return gempins unless rbs_map.resolved?
|
121
|
+
|
122
|
+
Solargraph.logger.info "Updating #{gemspec.name} #{gemspec.version} from collection"
|
123
|
+
GemPins.combine(gempins, rbs_map)
|
124
|
+
end
|
125
|
+
|
110
126
|
# @param path [String]
|
111
127
|
# @return [Gem::Specification, nil]
|
112
128
|
def resolve_path_to_gemspec path
|
data/lib/solargraph/gem_pins.rb
CHANGED
@@ -16,13 +16,21 @@ module Solargraph
|
|
16
16
|
def self.build(gemspec)
|
17
17
|
yard_pins = build_yard_pins(gemspec)
|
18
18
|
rbs_map = RbsMap.from_gemspec(gemspec)
|
19
|
+
combine yard_pins, rbs_map
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param yard_pins [Array<Pin::Base>]
|
23
|
+
# @param rbs_map [RbsMap]
|
24
|
+
# @return [Array<Pin::Base>]
|
25
|
+
def self.combine(yard_pins, rbs_map)
|
19
26
|
in_yard = Set.new
|
20
27
|
combined = yard_pins.map do |yard|
|
21
28
|
in_yard.add yard.path
|
22
29
|
next yard unless yard.is_a?(Pin::Method)
|
30
|
+
|
23
31
|
rbs = rbs_map.path_pin(yard.path, Pin::Method)
|
24
32
|
next yard unless rbs
|
25
|
-
|
33
|
+
|
26
34
|
# @sg-ignore
|
27
35
|
yard.class.new(
|
28
36
|
location: yard.location,
|