solargraph 0.54.0 → 0.55.0
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 +58 -0
- data/lib/solargraph/api_map/cache.rb +10 -1
- data/lib/solargraph/api_map/index.rb +167 -0
- data/lib/solargraph/api_map/store.rb +75 -122
- data/lib/solargraph/api_map.rb +109 -41
- data/lib/solargraph/bench.rb +17 -1
- data/lib/solargraph/complex_type/type_methods.rb +17 -11
- data/lib/solargraph/complex_type/unique_type.rb +181 -17
- data/lib/solargraph/complex_type.rb +103 -24
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +51 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +100 -0
- data/lib/solargraph/convention/struct_definition.rb +101 -0
- data/lib/solargraph/convention.rb +2 -0
- data/lib/solargraph/doc_map.rb +43 -18
- data/lib/solargraph/equality.rb +33 -0
- data/lib/solargraph/language_server/host/message_worker.rb +51 -5
- data/lib/solargraph/language_server/host.rb +13 -11
- data/lib/solargraph/language_server/message/base.rb +19 -12
- data/lib/solargraph/language_server/message/initialize.rb +3 -1
- data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
- 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 +4 -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 +19 -2
- data/lib/solargraph/library.rb +31 -41
- data/lib/solargraph/location.rb +29 -1
- data/lib/solargraph/parser/comment_ripper.rb +11 -6
- data/lib/solargraph/parser/flow_sensitive_typing.rb +226 -0
- data/lib/solargraph/parser/node_methods.rb +15 -1
- data/lib/solargraph/parser/parser_gem/class_methods.rb +11 -6
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +10 -10
- data/lib/solargraph/parser/parser_gem/node_methods.rb +6 -4
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +21 -0
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +23 -19
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +21 -1
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +21 -0
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +8 -2
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +26 -5
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +41 -0
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +28 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +28 -0
- data/lib/solargraph/parser/parser_gem/node_processors.rb +10 -0
- data/lib/solargraph/parser.rb +3 -5
- data/lib/solargraph/pin/base.rb +47 -17
- data/lib/solargraph/pin/base_variable.rb +11 -4
- data/lib/solargraph/pin/block.rb +8 -26
- data/lib/solargraph/pin/breakable.rb +9 -0
- 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/instance_variable.rb +2 -2
- data/lib/solargraph/pin/local_variable.rb +7 -1
- data/lib/solargraph/pin/method.rb +76 -48
- data/lib/solargraph/pin/namespace.rb +14 -11
- data/lib/solargraph/pin/parameter.rb +24 -17
- data/lib/solargraph/pin/proxy_type.rb +13 -7
- data/lib/solargraph/pin/signature.rb +3 -129
- data/lib/solargraph/pin/until.rb +18 -0
- data/lib/solargraph/pin/while.rb +18 -0
- data/lib/solargraph/pin.rb +7 -1
- data/lib/solargraph/position.rb +7 -0
- data/lib/solargraph/range.rb +9 -4
- data/lib/solargraph/rbs_map/conversions.rb +84 -45
- data/lib/solargraph/rbs_map/core_fills.rb +16 -9
- data/lib/solargraph/rbs_map.rb +1 -0
- data/lib/solargraph/shell.rb +19 -2
- data/lib/solargraph/source/chain/array.rb +10 -8
- 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 +125 -61
- data/lib/solargraph/source/chain/constant.rb +1 -1
- data/lib/solargraph/source/chain/hash.rb +8 -2
- data/lib/solargraph/source/chain/if.rb +5 -0
- data/lib/solargraph/source/chain/link.rb +28 -5
- data/lib/solargraph/source/chain/literal.rb +27 -2
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain/z_super.rb +1 -1
- data/lib/solargraph/source/chain.rb +131 -63
- data/lib/solargraph/source/cursor.rb +3 -2
- data/lib/solargraph/source/source_chainer.rb +2 -2
- data/lib/solargraph/source.rb +104 -86
- data/lib/solargraph/source_map/clip.rb +8 -6
- data/lib/solargraph/source_map/data.rb +30 -0
- data/lib/solargraph/source_map.rb +28 -16
- data/lib/solargraph/type_checker/checks.rb +4 -0
- data/lib/solargraph/type_checker/rules.rb +6 -1
- data/lib/solargraph/type_checker.rb +48 -21
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +3 -5
- data/lib/solargraph/workspace/config.rb +7 -3
- data/lib/solargraph/workspace.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_constant.rb +1 -0
- data/lib/solargraph/yard_map/mapper/to_method.rb +42 -15
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
- data/lib/solargraph/yard_map/mapper.rb +1 -0
- data/lib/solargraph/yardoc.rb +1 -1
- data/lib/solargraph.rb +1 -0
- data/solargraph.gemspec +5 -5
- metadata +41 -25
|
@@ -3,10 +3,20 @@
|
|
|
3
3
|
module Solargraph
|
|
4
4
|
class Source
|
|
5
5
|
class Chain
|
|
6
|
-
|
|
6
|
+
#
|
|
7
|
+
# Handles both method calls and local variable references by
|
|
8
|
+
# first looking for a variable with the name 'word', then
|
|
9
|
+
# proceeding to method signature resolution if not found.
|
|
10
|
+
#
|
|
11
|
+
class Call < Chain::Link
|
|
12
|
+
include Solargraph::Parser::NodeMethods
|
|
13
|
+
|
|
7
14
|
# @return [String]
|
|
8
15
|
attr_reader :word
|
|
9
16
|
|
|
17
|
+
# @return [Location]
|
|
18
|
+
attr_reader :location
|
|
19
|
+
|
|
10
20
|
# @return [::Array<Chain>]
|
|
11
21
|
attr_reader :arguments
|
|
12
22
|
|
|
@@ -14,47 +24,55 @@ module Solargraph
|
|
|
14
24
|
attr_reader :block
|
|
15
25
|
|
|
16
26
|
# @param word [String]
|
|
27
|
+
# @param location [Location, nil]
|
|
17
28
|
# @param arguments [::Array<Chain>]
|
|
18
29
|
# @param block [Chain, nil]
|
|
19
|
-
def initialize word, arguments = [], block = nil
|
|
30
|
+
def initialize word, location = nil, arguments = [], block = nil
|
|
20
31
|
@word = word
|
|
32
|
+
@location = location
|
|
21
33
|
@arguments = arguments
|
|
22
34
|
@block = block
|
|
23
35
|
fix_block_pass
|
|
24
36
|
end
|
|
25
37
|
|
|
38
|
+
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
39
|
+
protected def equality_fields
|
|
40
|
+
super + [arguments, block]
|
|
41
|
+
end
|
|
42
|
+
|
|
26
43
|
def with_block?
|
|
27
44
|
!!@block
|
|
28
45
|
end
|
|
29
46
|
|
|
30
47
|
# @param api_map [ApiMap]
|
|
31
|
-
# @param name_pin [Pin::
|
|
48
|
+
# @param name_pin [Pin::Closure] name_pin.binder should give us the type of the object on which 'word' will be invoked
|
|
32
49
|
# @param locals [::Array<Pin::LocalVariable>]
|
|
33
50
|
def resolve api_map, name_pin, locals
|
|
34
51
|
return super_pins(api_map, name_pin) if word == 'super'
|
|
35
52
|
return yield_pins(api_map, name_pin) if word == 'yield'
|
|
36
53
|
found = if head?
|
|
37
|
-
locals
|
|
54
|
+
api_map.visible_pins(locals, word, name_pin, location)
|
|
38
55
|
else
|
|
39
56
|
[]
|
|
40
57
|
end
|
|
41
|
-
return inferred_pins(found, api_map, name_pin
|
|
42
|
-
# @param [ComplexType::UniqueType]
|
|
58
|
+
return inferred_pins(found, api_map, name_pin, locals) unless found.empty?
|
|
43
59
|
pins = name_pin.binder.each_unique_type.flat_map do |context|
|
|
44
|
-
|
|
60
|
+
ns_tag = context.namespace == '' ? '' : context.namespace_type.tag
|
|
61
|
+
stack = api_map.get_method_stack(ns_tag, word, scope: context.scope)
|
|
62
|
+
[stack.first].compact
|
|
45
63
|
end
|
|
46
64
|
return [] if pins.empty?
|
|
47
|
-
inferred_pins(pins, api_map, name_pin
|
|
65
|
+
inferred_pins(pins, api_map, name_pin, locals)
|
|
48
66
|
end
|
|
49
67
|
|
|
50
68
|
private
|
|
51
69
|
|
|
52
70
|
# @param pins [::Enumerable<Pin::Method>]
|
|
53
71
|
# @param api_map [ApiMap]
|
|
54
|
-
# @param
|
|
55
|
-
# @param locals [::Array<Pin::LocalVariable>]
|
|
72
|
+
# @param name_pin [Pin::Base]
|
|
73
|
+
# @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
|
|
56
74
|
# @return [::Array<Pin::Base>]
|
|
57
|
-
def inferred_pins pins, api_map,
|
|
75
|
+
def inferred_pins pins, api_map, name_pin, locals
|
|
58
76
|
result = pins.map do |p|
|
|
59
77
|
next p unless p.is_a?(Pin::Method)
|
|
60
78
|
overloads = p.signatures
|
|
@@ -65,10 +83,11 @@ module Solargraph
|
|
|
65
83
|
# use it. If we didn't pass a block, the logic below will
|
|
66
84
|
# reject it regardless
|
|
67
85
|
|
|
68
|
-
|
|
86
|
+
with_block, without_block = overloads.partition(&:block?)
|
|
87
|
+
sorted_overloads = with_block + without_block
|
|
69
88
|
new_signature_pin = nil
|
|
70
89
|
sorted_overloads.each do |ol|
|
|
71
|
-
next unless arity_matches?(arguments,
|
|
90
|
+
next unless ol.arity_matches?(arguments, with_block?)
|
|
72
91
|
match = true
|
|
73
92
|
|
|
74
93
|
atypes = []
|
|
@@ -78,10 +97,9 @@ module Solargraph
|
|
|
78
97
|
match = ol.parameters.any?(&:restarg?)
|
|
79
98
|
break
|
|
80
99
|
end
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
unless param.return_type.undefined? || atype.name == param.return_type.name || api_map.super_and_sub?(param.return_type.name, atype.name) || param.return_type.generic?
|
|
100
|
+
|
|
101
|
+
atype = atypes[idx] ||= arg.infer(api_map, Pin::ProxyType.anonymous(name_pin.context), locals)
|
|
102
|
+
unless param.compatible_arg?(atype, api_map) || param.restarg?
|
|
85
103
|
match = false
|
|
86
104
|
break
|
|
87
105
|
end
|
|
@@ -89,11 +107,36 @@ module Solargraph
|
|
|
89
107
|
if match
|
|
90
108
|
if ol.block && with_block?
|
|
91
109
|
block_atypes = ol.block.parameters.map(&:return_type)
|
|
92
|
-
|
|
110
|
+
if block.links.map(&:class) == [BlockSymbol]
|
|
111
|
+
# like the bar in foo(&:bar)
|
|
112
|
+
blocktype = block_symbol_call_type(api_map, name_pin.context, block_atypes, locals)
|
|
113
|
+
else
|
|
114
|
+
blocktype = block_call_type(api_map, name_pin, locals)
|
|
115
|
+
end
|
|
93
116
|
end
|
|
94
117
|
new_signature_pin = ol.resolve_generics_from_context_until_complete(ol.generics, atypes, nil, nil, blocktype)
|
|
95
118
|
new_return_type = new_signature_pin.return_type
|
|
96
|
-
|
|
119
|
+
if head?
|
|
120
|
+
# If we're at the head of the chain, we called a
|
|
121
|
+
# method somewhere that marked itself as returning
|
|
122
|
+
# self. Given we didn't invoke this on an object,
|
|
123
|
+
# this must be a method in this same class - so we
|
|
124
|
+
# use our own self type
|
|
125
|
+
self_type = name_pin.context
|
|
126
|
+
else
|
|
127
|
+
# if we're past the head in the chain, whatever the
|
|
128
|
+
# type of the lhs side is what 'self' will be in its
|
|
129
|
+
# declaration - we can't just use the type of the
|
|
130
|
+
# method pin, as this might be a subclass of the
|
|
131
|
+
# place where the method is defined
|
|
132
|
+
self_type = name_pin.binder
|
|
133
|
+
end
|
|
134
|
+
# This same logic applies to the YARD work done by
|
|
135
|
+
# 'with_params()'.
|
|
136
|
+
#
|
|
137
|
+
# qualify(), however, happens in the namespace where
|
|
138
|
+
# the docs were written - from the method pin.
|
|
139
|
+
type = with_params(new_return_type.self_to_type(self_type), self_type).qualify(api_map, p.namespace) if new_return_type.defined?
|
|
97
140
|
type ||= ComplexType::UNDEFINED
|
|
98
141
|
end
|
|
99
142
|
break if type.defined?
|
|
@@ -101,20 +144,22 @@ module Solargraph
|
|
|
101
144
|
p = p.with_single_signature(new_signature_pin) unless new_signature_pin.nil?
|
|
102
145
|
next p.proxy(type) if type.defined?
|
|
103
146
|
if !p.macros.empty?
|
|
104
|
-
result = process_macro(p, api_map, context, locals)
|
|
147
|
+
result = process_macro(p, api_map, name_pin.context, locals)
|
|
105
148
|
next result unless result.return_type.undefined?
|
|
106
149
|
elsif !p.directives.empty?
|
|
107
|
-
result = process_directive(p, api_map, context, locals)
|
|
150
|
+
result = process_directive(p, api_map, name_pin.context, locals)
|
|
108
151
|
next result unless result.return_type.undefined?
|
|
109
152
|
end
|
|
110
153
|
p
|
|
111
154
|
end
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
155
|
+
logger.debug { "Call#inferred_pins(name_pin.binder=#{name_pin.binder}, word=#{word}, pins=#{pins.map(&:desc)}, name_pin=#{name_pin}) - result=#{result}" }
|
|
156
|
+
out = result.map do |pin|
|
|
157
|
+
if pin.path == 'Class#new' && name_pin.binder.tag != 'Class'
|
|
158
|
+
reduced_context = name_pin.binder.reduce_class_type
|
|
159
|
+
pin.proxy(reduced_context)
|
|
115
160
|
else
|
|
116
161
|
next pin if pin.return_type.undefined?
|
|
117
|
-
selfy = pin.return_type.
|
|
162
|
+
selfy = pin.return_type.self_to_type(name_pin.binder)
|
|
118
163
|
selfy == pin.return_type ? pin : pin.proxy(selfy)
|
|
119
164
|
end
|
|
120
165
|
end
|
|
@@ -123,7 +168,7 @@ module Solargraph
|
|
|
123
168
|
# @param pin [Pin::Base]
|
|
124
169
|
# @param api_map [ApiMap]
|
|
125
170
|
# @param context [ComplexType]
|
|
126
|
-
# @param locals [
|
|
171
|
+
# @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
|
|
127
172
|
# @return [Pin::Base]
|
|
128
173
|
def process_macro pin, api_map, context, locals
|
|
129
174
|
pin.macros.each do |macro|
|
|
@@ -142,7 +187,7 @@ module Solargraph
|
|
|
142
187
|
# @param pin [Pin::Method]
|
|
143
188
|
# @param api_map [ApiMap]
|
|
144
189
|
# @param context [ComplexType]
|
|
145
|
-
# @param locals [
|
|
190
|
+
# @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
|
|
146
191
|
# @return [Pin::ProxyType]
|
|
147
192
|
def process_directive pin, api_map, context, locals
|
|
148
193
|
pin.directives.each do |dir|
|
|
@@ -158,7 +203,7 @@ module Solargraph
|
|
|
158
203
|
# @param macro [YARD::Tags::MacroDirective]
|
|
159
204
|
# @param api_map [ApiMap]
|
|
160
205
|
# @param context [ComplexType]
|
|
161
|
-
# @param locals [
|
|
206
|
+
# @param locals [::Array<Pin::LocalVariable, Pin::Parameter>]
|
|
162
207
|
# @return [Pin::ProxyType]
|
|
163
208
|
def inner_process_macro pin, macro, api_map, context, locals
|
|
164
209
|
vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
|
|
@@ -192,24 +237,24 @@ module Solargraph
|
|
|
192
237
|
nil
|
|
193
238
|
end
|
|
194
239
|
|
|
195
|
-
# @param
|
|
196
|
-
# @
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
return false if argcount < parcount && !(argcount == parcount - 1 && parameters.last.restarg?)
|
|
205
|
-
true
|
|
240
|
+
# @param name_pin [Pin::Base]
|
|
241
|
+
# @return [Pin::Method, nil]
|
|
242
|
+
def find_method_pin(name_pin)
|
|
243
|
+
method_pin = name_pin
|
|
244
|
+
until method_pin.is_a?(Pin::Method)
|
|
245
|
+
method_pin = method_pin.closure
|
|
246
|
+
return if method_pin.nil?
|
|
247
|
+
end
|
|
248
|
+
method_pin
|
|
206
249
|
end
|
|
207
250
|
|
|
208
251
|
# @param api_map [ApiMap]
|
|
209
252
|
# @param name_pin [Pin::Base]
|
|
210
253
|
# @return [::Array<Pin::Base>]
|
|
211
254
|
def super_pins api_map, name_pin
|
|
212
|
-
|
|
255
|
+
method_pin = find_method_pin(name_pin)
|
|
256
|
+
return [] if method_pin.nil?
|
|
257
|
+
pins = api_map.get_method_stack(method_pin.namespace, method_pin.name, scope: method_pin.context.scope)
|
|
213
258
|
pins.reject{|p| p.path == name_pin.path}
|
|
214
259
|
end
|
|
215
260
|
|
|
@@ -217,10 +262,13 @@ module Solargraph
|
|
|
217
262
|
# @param name_pin [Pin::Base]
|
|
218
263
|
# @return [::Array<Pin::Base>]
|
|
219
264
|
def yield_pins api_map, name_pin
|
|
220
|
-
method_pin =
|
|
221
|
-
return []
|
|
265
|
+
method_pin = find_method_pin(name_pin)
|
|
266
|
+
return [] unless method_pin
|
|
222
267
|
|
|
223
|
-
method_pin.signatures.map(&:block).compact
|
|
268
|
+
method_pin.signatures.map(&:block).compact.map do |signature_pin|
|
|
269
|
+
return_type = signature_pin.return_type.qualify(api_map, name_pin.namespace)
|
|
270
|
+
signature_pin.proxy(return_type)
|
|
271
|
+
end
|
|
224
272
|
end
|
|
225
273
|
|
|
226
274
|
# @param type [ComplexType]
|
|
@@ -228,7 +276,7 @@ module Solargraph
|
|
|
228
276
|
# @return [ComplexType]
|
|
229
277
|
def with_params type, context
|
|
230
278
|
return type unless type.to_s.include?('$')
|
|
231
|
-
ComplexType.try_parse(type.to_s.gsub('$', context.value_types.map(&:
|
|
279
|
+
ComplexType.try_parse(type.to_s.gsub('$', context.value_types.map(&:rooted_tag).join(', ')).gsub('<>', ''))
|
|
232
280
|
end
|
|
233
281
|
|
|
234
282
|
# @return [void]
|
|
@@ -242,25 +290,41 @@ module Solargraph
|
|
|
242
290
|
# @param block_parameter_types [::Array<ComplexType>]
|
|
243
291
|
# @param locals [::Array<Pin::LocalVariable>]
|
|
244
292
|
# @return [ComplexType, nil]
|
|
245
|
-
def
|
|
293
|
+
def block_symbol_call_type(api_map, context, block_parameter_types, locals)
|
|
294
|
+
# Ruby's shorthand for sending the passed in method name
|
|
295
|
+
# to the first yield parameter with no arguments
|
|
296
|
+
block_symbol_name = block.links.first.word
|
|
297
|
+
block_symbol_call_path = "#{block_parameter_types.first}##{block_symbol_name}"
|
|
298
|
+
callee = api_map.get_path_pins(block_symbol_call_path).first
|
|
299
|
+
return_type = callee&.return_type
|
|
300
|
+
# @todo: Figure out why we get unresolved generics at
|
|
301
|
+
# this point and need to assume method return types
|
|
302
|
+
# based on the generic type
|
|
303
|
+
return_type ||= api_map.get_path_pins("#{context.subtypes.first}##{block.links.first.word}").first&.return_type
|
|
304
|
+
return_type || ComplexType::UNDEFINED
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# @param api_map [ApiMap]
|
|
308
|
+
# @return [Pin::Block, nil]
|
|
309
|
+
def find_block_pin(api_map)
|
|
310
|
+
node_location = Solargraph::Location.from_node(block.node)
|
|
311
|
+
return if node_location.nil?
|
|
312
|
+
block_pins = api_map.get_block_pins
|
|
313
|
+
block_pins.find { |pin| pin.location.contain?(node_location) }
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# @param api_map [ApiMap]
|
|
317
|
+
# @param name_pin [Pin::Base]
|
|
318
|
+
# @param block_parameter_types [::Array<ComplexType>]
|
|
319
|
+
# @param locals [::Array<Pin::LocalVariable>]
|
|
320
|
+
# @return [ComplexType, nil]
|
|
321
|
+
def block_call_type(api_map, name_pin, locals)
|
|
246
322
|
return nil unless with_block?
|
|
247
323
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
block_symbol_name = block.links.first.word
|
|
253
|
-
block_symbol_call_path = "#{block_parameter_types.first}##{block_symbol_name}"
|
|
254
|
-
callee = api_map.get_path_pins(block_symbol_call_path).first
|
|
255
|
-
return_type = callee&.return_type
|
|
256
|
-
# @todo: Figure out why we get unresolved generics at
|
|
257
|
-
# this point and need to assume method return types
|
|
258
|
-
# based on the generic type
|
|
259
|
-
return_type ||= api_map.get_path_pins("#{context.subtypes.first}##{block.links.first.word}").first&.return_type
|
|
260
|
-
return_type || ComplexType::UNDEFINED
|
|
261
|
-
else
|
|
262
|
-
block.infer(api_map, Pin::ProxyType.anonymous(context), locals)
|
|
263
|
-
end
|
|
324
|
+
block_context_pin = name_pin
|
|
325
|
+
block_pin = find_block_pin(api_map)
|
|
326
|
+
block_context_pin = block_pin.closure if block_pin
|
|
327
|
+
block.infer(api_map, block_context_pin, locals)
|
|
264
328
|
end
|
|
265
329
|
end
|
|
266
330
|
end
|
|
@@ -5,12 +5,18 @@ module Solargraph
|
|
|
5
5
|
class Chain
|
|
6
6
|
class Hash < Literal
|
|
7
7
|
# @param type [String]
|
|
8
|
+
# @param node [Parser::AST::Node]
|
|
8
9
|
# @param splatted [Boolean]
|
|
9
|
-
def initialize type, splatted = false
|
|
10
|
-
super(type)
|
|
10
|
+
def initialize type, node, splatted = false
|
|
11
|
+
super(type, node)
|
|
11
12
|
@splatted = splatted
|
|
12
13
|
end
|
|
13
14
|
|
|
15
|
+
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
16
|
+
protected def equality_fields
|
|
17
|
+
super + [@splatted]
|
|
18
|
+
end
|
|
19
|
+
|
|
14
20
|
def word
|
|
15
21
|
@word ||= "<#{@type}>"
|
|
16
22
|
end
|
|
@@ -13,6 +13,11 @@ module Solargraph
|
|
|
13
13
|
@links = links
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
17
|
+
protected def equality_fields
|
|
18
|
+
super + [@links]
|
|
19
|
+
end
|
|
20
|
+
|
|
16
21
|
def resolve api_map, name_pin, locals
|
|
17
22
|
types = @links.map { |link| link.infer(api_map, name_pin, locals) }
|
|
18
23
|
[Solargraph::Pin::ProxyType.anonymous(Solargraph::ComplexType.try_parse(types.map(&:tag).uniq.join(', ')))]
|
|
@@ -4,6 +4,8 @@ module Solargraph
|
|
|
4
4
|
class Source
|
|
5
5
|
class Chain
|
|
6
6
|
class Link
|
|
7
|
+
include Equality
|
|
8
|
+
|
|
7
9
|
# @return [String]
|
|
8
10
|
attr_reader :word
|
|
9
11
|
|
|
@@ -15,6 +17,11 @@ module Solargraph
|
|
|
15
17
|
@word = word
|
|
16
18
|
end
|
|
17
19
|
|
|
20
|
+
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
21
|
+
protected def equality_fields
|
|
22
|
+
[self.class, word]
|
|
23
|
+
end
|
|
24
|
+
|
|
18
25
|
def undefined?
|
|
19
26
|
word == '<undefined>'
|
|
20
27
|
end
|
|
@@ -31,18 +38,23 @@ module Solargraph
|
|
|
31
38
|
[]
|
|
32
39
|
end
|
|
33
40
|
|
|
41
|
+
# debugging description of contents; not for machine use
|
|
42
|
+
def desc
|
|
43
|
+
word
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def to_s
|
|
47
|
+
desc
|
|
48
|
+
end
|
|
49
|
+
|
|
34
50
|
def inspect
|
|
35
|
-
"
|
|
51
|
+
"#<#{self.class} - `#{self.desc}`>"
|
|
36
52
|
end
|
|
37
53
|
|
|
38
54
|
def head?
|
|
39
55
|
@head ||= false
|
|
40
56
|
end
|
|
41
57
|
|
|
42
|
-
def == other
|
|
43
|
-
self.class == other.class and word == other.word
|
|
44
|
-
end
|
|
45
|
-
|
|
46
58
|
# Make a copy of this link marked as the head of a chain
|
|
47
59
|
#
|
|
48
60
|
# @return [self]
|
|
@@ -61,6 +73,17 @@ module Solargraph
|
|
|
61
73
|
false
|
|
62
74
|
end
|
|
63
75
|
|
|
76
|
+
# debugging description of contents; not for machine use
|
|
77
|
+
def desc
|
|
78
|
+
word
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def inspect
|
|
82
|
+
"#<#{self.class} - `#{self.desc}`>"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
include Logging
|
|
86
|
+
|
|
64
87
|
protected
|
|
65
88
|
|
|
66
89
|
# Mark whether this link is the head of a chain
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'parser'
|
|
4
|
+
|
|
3
5
|
module Solargraph
|
|
4
6
|
class Source
|
|
5
7
|
class Chain
|
|
@@ -8,14 +10,37 @@ module Solargraph
|
|
|
8
10
|
@word ||= "<#{@type}>"
|
|
9
11
|
end
|
|
10
12
|
|
|
13
|
+
attr_reader :value
|
|
14
|
+
|
|
11
15
|
# @param type [String]
|
|
12
|
-
|
|
16
|
+
# @param node [Parser::AST::Node, Object]
|
|
17
|
+
def initialize type, node
|
|
18
|
+
if node.is_a?(::Parser::AST::Node)
|
|
19
|
+
if node.type == :true
|
|
20
|
+
@value = true
|
|
21
|
+
elsif node.type == :false
|
|
22
|
+
@value = false
|
|
23
|
+
elsif [:int, :sym].include?(node.type)
|
|
24
|
+
@value = node.children.first
|
|
25
|
+
end
|
|
26
|
+
end
|
|
13
27
|
@type = type
|
|
28
|
+
@literal_type = ComplexType.try_parse(@value.inspect)
|
|
14
29
|
@complex_type = ComplexType.try_parse(type)
|
|
15
30
|
end
|
|
16
31
|
|
|
32
|
+
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
33
|
+
protected def equality_fields
|
|
34
|
+
super + [@value, @type, @literal_type, @complex_type]
|
|
35
|
+
end
|
|
36
|
+
|
|
17
37
|
def resolve api_map, name_pin, locals
|
|
18
|
-
|
|
38
|
+
if api_map.super_and_sub?(@complex_type.name, @literal_type.name)
|
|
39
|
+
[Pin::ProxyType.anonymous(@literal_type)]
|
|
40
|
+
else
|
|
41
|
+
# we don't support this value as a literal type
|
|
42
|
+
[Pin::ProxyType.anonymous(@complex_type)]
|
|
43
|
+
end
|
|
19
44
|
end
|
|
20
45
|
end
|
|
21
46
|
end
|
|
@@ -15,7 +15,7 @@ module Solargraph
|
|
|
15
15
|
|
|
16
16
|
def resolve api_map, name_pin, locals
|
|
17
17
|
types = @links.map { |link| link.infer(api_map, name_pin, locals) }
|
|
18
|
-
[Solargraph::Pin::ProxyType.anonymous(Solargraph::ComplexType.
|
|
18
|
+
[Solargraph::Pin::ProxyType.anonymous(Solargraph::ComplexType.new(types.uniq))]
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
end
|
|
@@ -15,7 +15,7 @@ module Solargraph
|
|
|
15
15
|
# @param with_block [Boolean] True if the chain is inside a block
|
|
16
16
|
# @param head [Boolean] True if the call is the start of its chain
|
|
17
17
|
def initialize word, with_block = false
|
|
18
|
-
super(word, [], with_block)
|
|
18
|
+
super(word, nil, [], with_block)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
# @param api_map [ApiMap]
|