solargraph 0.58.1 → 0.59.0.dev.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/.envrc +3 -0
- data/.github/workflows/linting.yml +4 -5
- data/.github/workflows/plugins.yml +40 -36
- data/.github/workflows/rspec.yml +45 -13
- data/.github/workflows/typecheck.yml +2 -2
- data/.rubocop_todo.yml +27 -49
- data/README.md +3 -3
- data/Rakefile +1 -0
- data/lib/solargraph/api_map/cache.rb +110 -110
- data/lib/solargraph/api_map/constants.rb +289 -279
- data/lib/solargraph/api_map/index.rb +204 -193
- data/lib/solargraph/api_map/source_to_yard.rb +109 -97
- data/lib/solargraph/api_map/store.rb +387 -384
- data/lib/solargraph/api_map.rb +1000 -945
- data/lib/solargraph/complex_type/conformance.rb +176 -0
- data/lib/solargraph/complex_type/type_methods.rb +242 -228
- data/lib/solargraph/complex_type/unique_type.rb +632 -482
- data/lib/solargraph/complex_type.rb +549 -444
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +93 -91
- data/lib/solargraph/convention/data_definition.rb +108 -105
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +62 -61
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +103 -102
- data/lib/solargraph/convention/struct_definition.rb +168 -164
- data/lib/solargraph/diagnostics/require_not_found.rb +54 -53
- data/lib/solargraph/diagnostics/rubocop.rb +119 -118
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +70 -68
- data/lib/solargraph/diagnostics/type_check.rb +56 -55
- data/lib/solargraph/doc_map.rb +200 -439
- data/lib/solargraph/equality.rb +34 -34
- data/lib/solargraph/gem_pins.rb +97 -98
- data/lib/solargraph/language_server/host/dispatch.rb +131 -130
- data/lib/solargraph/language_server/host/message_worker.rb +113 -112
- data/lib/solargraph/language_server/host/sources.rb +100 -99
- data/lib/solargraph/language_server/host.rb +883 -878
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +109 -114
- data/lib/solargraph/language_server/message/extended/document.rb +24 -23
- data/lib/solargraph/language_server/message/text_document/completion.rb +58 -56
- data/lib/solargraph/language_server/message/text_document/definition.rb +42 -40
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +28 -26
- data/lib/solargraph/language_server/message/text_document/formatting.rb +150 -148
- data/lib/solargraph/language_server/message/text_document/hover.rb +60 -58
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +25 -24
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +27 -25
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +25 -23
- data/lib/solargraph/library.rb +729 -683
- data/lib/solargraph/location.rb +87 -82
- data/lib/solargraph/logging.rb +57 -37
- data/lib/solargraph/parser/comment_ripper.rb +76 -69
- data/lib/solargraph/parser/flow_sensitive_typing.rb +483 -255
- data/lib/solargraph/parser/node_processor/base.rb +122 -92
- data/lib/solargraph/parser/node_processor.rb +63 -62
- data/lib/solargraph/parser/parser_gem/class_methods.rb +167 -149
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +191 -166
- data/lib/solargraph/parser/parser_gem/node_methods.rb +506 -486
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -22
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +61 -59
- data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +24 -15
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +46 -46
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +60 -53
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +53 -23
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +41 -40
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +30 -29
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +61 -59
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -98
- data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -17
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +39 -38
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +53 -52
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +296 -291
- data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +33 -29
- data/lib/solargraph/parser/parser_gem/node_processors.rb +74 -70
- data/lib/solargraph/parser/region.rb +75 -69
- data/lib/solargraph/parser/snippet.rb +17 -17
- data/lib/solargraph/pin/base.rb +761 -729
- data/lib/solargraph/pin/base_variable.rb +418 -126
- data/lib/solargraph/pin/block.rb +126 -104
- data/lib/solargraph/pin/breakable.rb +13 -9
- data/lib/solargraph/pin/callable.rb +278 -231
- data/lib/solargraph/pin/closure.rb +68 -72
- data/lib/solargraph/pin/common.rb +94 -79
- data/lib/solargraph/pin/compound_statement.rb +55 -0
- data/lib/solargraph/pin/conversions.rb +124 -123
- data/lib/solargraph/pin/delegated_method.rb +131 -120
- data/lib/solargraph/pin/documenting.rb +115 -114
- data/lib/solargraph/pin/instance_variable.rb +38 -34
- data/lib/solargraph/pin/keyword.rb +16 -20
- data/lib/solargraph/pin/local_variable.rb +31 -75
- data/lib/solargraph/pin/method.rb +720 -672
- data/lib/solargraph/pin/method_alias.rb +42 -34
- data/lib/solargraph/pin/namespace.rb +121 -115
- data/lib/solargraph/pin/parameter.rb +338 -275
- data/lib/solargraph/pin/proxy_type.rb +40 -39
- data/lib/solargraph/pin/reference/override.rb +47 -47
- data/lib/solargraph/pin/reference/superclass.rb +17 -15
- data/lib/solargraph/pin/reference.rb +41 -39
- data/lib/solargraph/pin/search.rb +62 -61
- data/lib/solargraph/pin/signature.rb +69 -61
- data/lib/solargraph/pin/symbol.rb +53 -53
- data/lib/solargraph/pin/until.rb +18 -18
- data/lib/solargraph/pin/while.rb +18 -18
- data/lib/solargraph/pin.rb +46 -44
- data/lib/solargraph/pin_cache.rb +665 -245
- data/lib/solargraph/position.rb +118 -119
- data/lib/solargraph/range.rb +112 -112
- data/lib/solargraph/rbs_map/conversions.rb +846 -823
- data/lib/solargraph/rbs_map/core_map.rb +65 -58
- data/lib/solargraph/rbs_map/stdlib_map.rb +72 -43
- data/lib/solargraph/rbs_map.rb +217 -163
- data/lib/solargraph/shell.rb +397 -352
- data/lib/solargraph/source/chain/call.rb +372 -337
- data/lib/solargraph/source/chain/constant.rb +28 -26
- data/lib/solargraph/source/chain/hash.rb +35 -34
- data/lib/solargraph/source/chain/if.rb +29 -28
- data/lib/solargraph/source/chain/instance_variable.rb +34 -13
- data/lib/solargraph/source/chain/literal.rb +53 -48
- data/lib/solargraph/source/chain/or.rb +31 -23
- data/lib/solargraph/source/chain.rb +294 -291
- data/lib/solargraph/source/change.rb +89 -82
- data/lib/solargraph/source/cursor.rb +172 -166
- data/lib/solargraph/source/source_chainer.rb +204 -194
- data/lib/solargraph/source/updater.rb +59 -55
- data/lib/solargraph/source.rb +524 -498
- data/lib/solargraph/source_map/clip.rb +237 -226
- data/lib/solargraph/source_map/data.rb +37 -34
- data/lib/solargraph/source_map/mapper.rb +282 -259
- data/lib/solargraph/source_map.rb +220 -212
- data/lib/solargraph/type_checker/problem.rb +34 -32
- data/lib/solargraph/type_checker/rules.rb +157 -84
- data/lib/solargraph/type_checker.rb +895 -814
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +257 -255
- data/lib/solargraph/workspace/gemspecs.rb +367 -0
- data/lib/solargraph/workspace/require_paths.rb +98 -97
- data/lib/solargraph/workspace.rb +362 -220
- data/lib/solargraph/yard_map/helpers.rb +45 -44
- data/lib/solargraph/yard_map/mapper/to_method.rb +134 -130
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +32 -31
- data/lib/solargraph/yard_map/mapper.rb +84 -79
- data/lib/solargraph/yardoc.rb +97 -87
- data/lib/solargraph.rb +126 -105
- data/rbs/fills/rubygems/0/dependency.rbs +193 -0
- data/rbs/fills/tuple/tuple.rbs +28 -0
- data/rbs/shims/ast/0/node.rbs +5 -0
- data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
- data/rbs_collection.yaml +1 -1
- data/solargraph.gemspec +2 -1
- metadata +22 -17
- data/lib/solargraph/type_checker/checks.rb +0 -124
- data/lib/solargraph/type_checker/param_def.rb +0 -37
- data/lib/solargraph/yard_map/to_method.rb +0 -89
- data/sig/shims/ast/0/node.rbs +0 -5
- /data/{sig → rbs}/shims/ast/2.4/.rbs_meta.yaml +0 -0
- /data/{sig → rbs}/shims/ast/2.4/ast.rbs +0 -0
- /data/{sig → rbs}/shims/parser/3.2.0.1/builders/default.rbs +0 -0
- /data/{sig → rbs}/shims/parser/3.2.0.1/manifest.yaml +0 -0
- /data/{sig → rbs}/shims/parser/3.2.0.1/parser.rbs +0 -0
- /data/{sig → rbs}/shims/parser/3.2.0.1/polyfill.rbs +0 -0
- /data/{sig → rbs}/shims/thor/1.2.0.1/.rbs_meta.yaml +0 -0
- /data/{sig → rbs}/shims/thor/1.2.0.1/manifest.yaml +0 -0
- /data/{sig → rbs}/shims/thor/1.2.0.1/thor.rbs +0 -0
|
@@ -1,291 +1,294 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# HACK: Fix autoload issue
|
|
4
|
-
require 'solargraph/source/chain/link'
|
|
5
|
-
|
|
6
|
-
module Solargraph
|
|
7
|
-
class Source
|
|
8
|
-
#
|
|
9
|
-
# Represents an expression as a single call chain at the parse
|
|
10
|
-
# tree level, made up of constants, variables, and method calls,
|
|
11
|
-
# each represented as a Link object.
|
|
12
|
-
#
|
|
13
|
-
# Computes Pins and/or ComplexTypes representing the interpreted
|
|
14
|
-
# expression.
|
|
15
|
-
#
|
|
16
|
-
class Chain
|
|
17
|
-
include Equality
|
|
18
|
-
include Logging
|
|
19
|
-
|
|
20
|
-
autoload :Link, 'solargraph/source/chain/link'
|
|
21
|
-
autoload :Call, 'solargraph/source/chain/call'
|
|
22
|
-
autoload :QCall, 'solargraph/source/chain/q_call'
|
|
23
|
-
autoload :Variable, 'solargraph/source/chain/variable'
|
|
24
|
-
autoload :ClassVariable, 'solargraph/source/chain/class_variable'
|
|
25
|
-
autoload :Constant, 'solargraph/source/chain/constant'
|
|
26
|
-
autoload :InstanceVariable, 'solargraph/source/chain/instance_variable'
|
|
27
|
-
autoload :GlobalVariable, 'solargraph/source/chain/global_variable'
|
|
28
|
-
autoload :Literal, 'solargraph/source/chain/literal'
|
|
29
|
-
autoload :Head, 'solargraph/source/chain/head'
|
|
30
|
-
autoload :If, 'solargraph/source/chain/if'
|
|
31
|
-
autoload :Or, 'solargraph/source/chain/or'
|
|
32
|
-
autoload :BlockVariable, 'solargraph/source/chain/block_variable'
|
|
33
|
-
autoload :BlockSymbol, 'solargraph/source/chain/block_symbol'
|
|
34
|
-
autoload :ZSuper, 'solargraph/source/chain/z_super'
|
|
35
|
-
autoload :Hash, 'solargraph/source/chain/hash'
|
|
36
|
-
autoload :Array, 'solargraph/source/chain/array'
|
|
37
|
-
|
|
38
|
-
@@inference_stack = []
|
|
39
|
-
@@inference_depth = 0
|
|
40
|
-
@@inference_invalidation_key = nil
|
|
41
|
-
@@inference_cache = {}
|
|
42
|
-
|
|
43
|
-
UNDEFINED_CALL = Chain::Call.new('<undefined>', nil)
|
|
44
|
-
UNDEFINED_CONSTANT = Chain::Constant.new('<undefined>')
|
|
45
|
-
|
|
46
|
-
# @return [::Array<Source::Chain::Link>]
|
|
47
|
-
attr_reader :links
|
|
48
|
-
|
|
49
|
-
attr_reader :node
|
|
50
|
-
|
|
51
|
-
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
52
|
-
protected def equality_fields
|
|
53
|
-
[links, node]
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# @param node [Parser::AST::Node, nil]
|
|
57
|
-
# @param links [::Array<Chain::Link>]
|
|
58
|
-
# @param splat [Boolean]
|
|
59
|
-
def initialize links, node = nil, splat = false
|
|
60
|
-
@links = links.clone
|
|
61
|
-
@links.push UNDEFINED_CALL if @links.empty?
|
|
62
|
-
head = true
|
|
63
|
-
@links.map! do |link|
|
|
64
|
-
result = (head ? link.clone_head : link.clone_body)
|
|
65
|
-
head = false
|
|
66
|
-
result
|
|
67
|
-
end
|
|
68
|
-
@node = node
|
|
69
|
-
@splat = splat
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# @return [Chain]
|
|
73
|
-
def base
|
|
74
|
-
@
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
# :class scoped
|
|
93
|
-
#
|
|
94
|
-
#
|
|
95
|
-
#
|
|
96
|
-
#
|
|
97
|
-
#
|
|
98
|
-
#
|
|
99
|
-
# 'a
|
|
100
|
-
#
|
|
101
|
-
#
|
|
102
|
-
#
|
|
103
|
-
#
|
|
104
|
-
#
|
|
105
|
-
#
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
#
|
|
111
|
-
#
|
|
112
|
-
#
|
|
113
|
-
#
|
|
114
|
-
#
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
#
|
|
126
|
-
#
|
|
127
|
-
#
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
# @param
|
|
138
|
-
# @
|
|
139
|
-
# @
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
# @
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
# @param
|
|
215
|
-
# @
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
# @
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
@@inference_depth
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
@@inference_stack.
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
ComplexType
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# HACK: Fix autoload issue
|
|
4
|
+
require 'solargraph/source/chain/link'
|
|
5
|
+
|
|
6
|
+
module Solargraph
|
|
7
|
+
class Source
|
|
8
|
+
#
|
|
9
|
+
# Represents an expression as a single call chain at the parse
|
|
10
|
+
# tree level, made up of constants, variables, and method calls,
|
|
11
|
+
# each represented as a Link object.
|
|
12
|
+
#
|
|
13
|
+
# Computes Pins and/or ComplexTypes representing the interpreted
|
|
14
|
+
# expression.
|
|
15
|
+
#
|
|
16
|
+
class Chain
|
|
17
|
+
include Equality
|
|
18
|
+
include Logging
|
|
19
|
+
|
|
20
|
+
autoload :Link, 'solargraph/source/chain/link'
|
|
21
|
+
autoload :Call, 'solargraph/source/chain/call'
|
|
22
|
+
autoload :QCall, 'solargraph/source/chain/q_call'
|
|
23
|
+
autoload :Variable, 'solargraph/source/chain/variable'
|
|
24
|
+
autoload :ClassVariable, 'solargraph/source/chain/class_variable'
|
|
25
|
+
autoload :Constant, 'solargraph/source/chain/constant'
|
|
26
|
+
autoload :InstanceVariable, 'solargraph/source/chain/instance_variable'
|
|
27
|
+
autoload :GlobalVariable, 'solargraph/source/chain/global_variable'
|
|
28
|
+
autoload :Literal, 'solargraph/source/chain/literal'
|
|
29
|
+
autoload :Head, 'solargraph/source/chain/head'
|
|
30
|
+
autoload :If, 'solargraph/source/chain/if'
|
|
31
|
+
autoload :Or, 'solargraph/source/chain/or'
|
|
32
|
+
autoload :BlockVariable, 'solargraph/source/chain/block_variable'
|
|
33
|
+
autoload :BlockSymbol, 'solargraph/source/chain/block_symbol'
|
|
34
|
+
autoload :ZSuper, 'solargraph/source/chain/z_super'
|
|
35
|
+
autoload :Hash, 'solargraph/source/chain/hash'
|
|
36
|
+
autoload :Array, 'solargraph/source/chain/array'
|
|
37
|
+
|
|
38
|
+
@@inference_stack = []
|
|
39
|
+
@@inference_depth = 0
|
|
40
|
+
@@inference_invalidation_key = nil
|
|
41
|
+
@@inference_cache = {}
|
|
42
|
+
|
|
43
|
+
UNDEFINED_CALL = Chain::Call.new('<undefined>', nil)
|
|
44
|
+
UNDEFINED_CONSTANT = Chain::Constant.new('<undefined>')
|
|
45
|
+
|
|
46
|
+
# @return [::Array<Source::Chain::Link>]
|
|
47
|
+
attr_reader :links
|
|
48
|
+
|
|
49
|
+
attr_reader :node
|
|
50
|
+
|
|
51
|
+
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
52
|
+
protected def equality_fields
|
|
53
|
+
[links, node]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @param node [Parser::AST::Node, nil]
|
|
57
|
+
# @param links [::Array<Chain::Link>]
|
|
58
|
+
# @param splat [Boolean]
|
|
59
|
+
def initialize links, node = nil, splat = false
|
|
60
|
+
@links = links.clone
|
|
61
|
+
@links.push UNDEFINED_CALL if @links.empty?
|
|
62
|
+
head = true
|
|
63
|
+
@links.map! do |link|
|
|
64
|
+
result = (head ? link.clone_head : link.clone_body)
|
|
65
|
+
head = false
|
|
66
|
+
result
|
|
67
|
+
end
|
|
68
|
+
@node = node
|
|
69
|
+
@splat = splat
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# @return [Chain]
|
|
73
|
+
def base
|
|
74
|
+
# @sg-ignore Need to add nil check here
|
|
75
|
+
@base ||= Chain.new(links[0..-2])
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Determine potential Pins returned by this chain of words
|
|
79
|
+
#
|
|
80
|
+
# @param api_map [ApiMap]
|
|
81
|
+
#
|
|
82
|
+
# @param name_pin [Pin::Base] A pin representing the closure in
|
|
83
|
+
# which expression is evaluated (e.g., a Method pin, or a
|
|
84
|
+
# Module or Class pin if not run within a method - both in
|
|
85
|
+
# terms of the closure around the chain, as well as the self
|
|
86
|
+
# type used for any method calls in head position.
|
|
87
|
+
#
|
|
88
|
+
# Requirements for name_pin:
|
|
89
|
+
#
|
|
90
|
+
# * name_pin.context: This should be a type representing the
|
|
91
|
+
# namespace where we can look up non-local variables. If
|
|
92
|
+
# it is a Class<X>, we will look up :class scoped
|
|
93
|
+
# instance variables.
|
|
94
|
+
#
|
|
95
|
+
# * name_pin.binder: Used for method call lookups only
|
|
96
|
+
# (Chain::Call links). For method calls as the first
|
|
97
|
+
# element in the chain, 'name_pin.binder' should be the
|
|
98
|
+
# same as name_pin.context above. For method calls later
|
|
99
|
+
# in the chain, it changes. (e.g., for 'b' in a.b.c, it
|
|
100
|
+
# should represent the type of 'a').
|
|
101
|
+
#
|
|
102
|
+
# @param locals [::Array<Pin::LocalVariable>] Any local
|
|
103
|
+
# variables / method parameters etc visible by the statement
|
|
104
|
+
#
|
|
105
|
+
# @return [::Array<Pin::Base>] Pins representing possible return
|
|
106
|
+
# types of this method.
|
|
107
|
+
def define api_map, name_pin, locals
|
|
108
|
+
return [] if undefined?
|
|
109
|
+
|
|
110
|
+
# working_pin is the surrounding closure pin for the link
|
|
111
|
+
# being processed, whose #binder method will provide the LHS /
|
|
112
|
+
# 'self type' of the next link (same as the #return_type method
|
|
113
|
+
# --the type of the result so far).
|
|
114
|
+
#
|
|
115
|
+
# @todo ProxyType uses 'type' for the binder, but '
|
|
116
|
+
working_pin = name_pin
|
|
117
|
+
# @sg-ignore Need to add nil check here
|
|
118
|
+
links[0..-2].each do |link|
|
|
119
|
+
pins = link.resolve(api_map, working_pin, locals)
|
|
120
|
+
type = infer_from_definitions(pins, working_pin, api_map, locals)
|
|
121
|
+
if type.undefined?
|
|
122
|
+
logger.debug { "Chain#define(links=#{links.map(&:desc)}, name_pin=#{name_pin.inspect}, locals=#{locals}) => [] - undefined type from #{link.desc}" }
|
|
123
|
+
return []
|
|
124
|
+
end
|
|
125
|
+
# We continue to use the context from the head pin, in case
|
|
126
|
+
# we need it to, for instance, provide context for a block
|
|
127
|
+
# evaluation. However, we use the last link's return type
|
|
128
|
+
# for the binder, as this is chaining off of it, and the
|
|
129
|
+
# binder is now the lhs of the rhs we are evaluating.
|
|
130
|
+
working_pin = Pin::ProxyType.anonymous(name_pin.context, binder: type, closure: name_pin, source: :chain)
|
|
131
|
+
logger.debug { "Chain#define(links=#{links.map(&:desc)}, name_pin=#{name_pin.inspect}, locals=#{locals}) - after processing #{link.desc}, new working_pin=#{working_pin} with binder #{working_pin.binder}" }
|
|
132
|
+
end
|
|
133
|
+
links.last.last_context = working_pin
|
|
134
|
+
links.last.resolve(api_map, working_pin, locals)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# @param api_map [ApiMap]
|
|
138
|
+
# @param name_pin [Pin::Base] The pin for the closure in which this code runs
|
|
139
|
+
# @param locals [::Array<Pin::LocalVariable>]
|
|
140
|
+
# @return [ComplexType]
|
|
141
|
+
# @sg-ignore
|
|
142
|
+
def infer api_map, name_pin, locals
|
|
143
|
+
# includes binder as it is mutable in Pin::Block
|
|
144
|
+
cache_key = [node, node&.location, links, name_pin&.return_type, name_pin&.binder, locals]
|
|
145
|
+
if @@inference_invalidation_key == api_map.hash
|
|
146
|
+
cached = @@inference_cache[cache_key]
|
|
147
|
+
return cached if cached
|
|
148
|
+
else
|
|
149
|
+
@@inference_invalidation_key = api_map.hash
|
|
150
|
+
@@inference_cache = {}
|
|
151
|
+
end
|
|
152
|
+
out = infer_uncached(api_map, name_pin, locals).downcast_to_literal_if_possible
|
|
153
|
+
logger.debug { "Chain#infer() - caching result - cache_key_hash=#{cache_key.hash}, links.map(&:hash)=#{links.map(&:hash)}, links=#{links}, cache_key.map(&:hash) = #{cache_key.map(&:hash)}, cache_key=#{cache_key}" }
|
|
154
|
+
@@inference_cache[cache_key] = out
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# @param api_map [ApiMap]
|
|
158
|
+
# @param name_pin [Pin::Base]
|
|
159
|
+
# @param locals [::Array<Pin::LocalVariable>]
|
|
160
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
161
|
+
def infer_uncached api_map, name_pin, locals
|
|
162
|
+
pins = define(api_map, name_pin, locals)
|
|
163
|
+
if pins.empty?
|
|
164
|
+
logger.debug { "Chain#infer_uncached(links=#{links.map(&:desc)}, locals=#{locals.map(&:desc)}) => undefined - no pins" }
|
|
165
|
+
return ComplexType::UNDEFINED
|
|
166
|
+
end
|
|
167
|
+
type = infer_from_definitions(pins, links.last.last_context, api_map, locals)
|
|
168
|
+
out = maybe_nil(type)
|
|
169
|
+
logger.debug { "Chain#infer_uncached(links=#{self.links.map(&:desc)}, locals=#{locals.map(&:desc)}, name_pin=#{name_pin}, name_pin.closure=#{name_pin.closure.inspect}, name_pin.binder=#{name_pin.binder}) => #{out.rooted_tags.inspect}" }
|
|
170
|
+
out
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# @return [Boolean]
|
|
174
|
+
def literal?
|
|
175
|
+
links.last.is_a?(Chain::Literal)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def undefined?
|
|
179
|
+
links.any?(&:undefined?)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def defined?
|
|
183
|
+
!undefined?
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# @return [Boolean]
|
|
187
|
+
def constant?
|
|
188
|
+
links.last.is_a?(Chain::Constant)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def splat?
|
|
192
|
+
@splat
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def nullable?
|
|
196
|
+
links.any?(&:nullable?)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
include Logging
|
|
200
|
+
|
|
201
|
+
# @return [String]
|
|
202
|
+
def desc
|
|
203
|
+
links.map(&:desc).to_s
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def to_s
|
|
207
|
+
desc
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
include Logging
|
|
211
|
+
|
|
212
|
+
private
|
|
213
|
+
|
|
214
|
+
# @param pins [::Array<Pin::Base>]
|
|
215
|
+
# @param name_pin [Pin::Base]
|
|
216
|
+
# @param api_map [ApiMap]
|
|
217
|
+
# @param locals [::Enumerable<Pin::LocalVariable>]
|
|
218
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
219
|
+
def infer_from_definitions pins, name_pin, api_map, locals
|
|
220
|
+
# @type [::Array<ComplexType, ComplexType::UniqueType>]
|
|
221
|
+
types = []
|
|
222
|
+
unresolved_pins = []
|
|
223
|
+
# @todo this param tag shouldn't be needed to probe the type
|
|
224
|
+
# @todo ...but given it is needed, typecheck should complain that it is needed
|
|
225
|
+
# @param pin [Pin::Base]
|
|
226
|
+
pins.each do |pin|
|
|
227
|
+
# Avoid infinite recursion
|
|
228
|
+
next if @@inference_stack.include?(pin)
|
|
229
|
+
|
|
230
|
+
@@inference_stack.push pin
|
|
231
|
+
type = pin.typify(api_map)
|
|
232
|
+
@@inference_stack.pop
|
|
233
|
+
if type.defined?
|
|
234
|
+
if type.generic?
|
|
235
|
+
# @todo even at strong, no typechecking complaint
|
|
236
|
+
# happens when a [Pin::Base,nil] is passed into a method
|
|
237
|
+
# that accepts only [Pin::Namespace] as an argument
|
|
238
|
+
# @sg-ignore Need to add nil check here
|
|
239
|
+
type = type.resolve_generics(pin.closure, name_pin.binder)
|
|
240
|
+
end
|
|
241
|
+
types << type
|
|
242
|
+
else
|
|
243
|
+
unresolved_pins << pin
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# Limit method inference recursion
|
|
248
|
+
if @@inference_depth >= 10 && pins.first.is_a?(Pin::Method)
|
|
249
|
+
return ComplexType::UNDEFINED
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
@@inference_depth += 1
|
|
253
|
+
# @param pin [Pin::Base]
|
|
254
|
+
unresolved_pins.each do |pin|
|
|
255
|
+
# Avoid infinite recursion
|
|
256
|
+
if @@inference_stack.include?(pin.identity)
|
|
257
|
+
next
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
@@inference_stack.push(pin.identity)
|
|
261
|
+
type = pin.probe(api_map)
|
|
262
|
+
@@inference_stack.pop
|
|
263
|
+
types.push type if type
|
|
264
|
+
end
|
|
265
|
+
@@inference_depth -= 1
|
|
266
|
+
|
|
267
|
+
type = if types.empty?
|
|
268
|
+
ComplexType::UNDEFINED
|
|
269
|
+
elsif types.length > 1
|
|
270
|
+
# Move nil to the end by convention
|
|
271
|
+
|
|
272
|
+
# @param a [ComplexType::UniqueType]
|
|
273
|
+
sorted = types.flat_map(&:items).sort { |a, _| a.tag == 'nil' ? 1 : 0 }
|
|
274
|
+
ComplexType.new(sorted.uniq)
|
|
275
|
+
else
|
|
276
|
+
ComplexType.new(types)
|
|
277
|
+
end
|
|
278
|
+
if name_pin.nil? || name_pin.context.undefined?
|
|
279
|
+
# up to downstream to resolve self type
|
|
280
|
+
return type
|
|
281
|
+
end
|
|
282
|
+
type.self_to_type(name_pin.context)
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
# @param type [ComplexType, ComplexType::UniqueType]
|
|
286
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
287
|
+
def maybe_nil type
|
|
288
|
+
return type if type.undefined? || type.void? || type.nullable?
|
|
289
|
+
return type unless nullable?
|
|
290
|
+
ComplexType.new(type.items + [ComplexType::NIL])
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|