solargraph 0.58.3 → 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 +41 -38
- data/.github/workflows/rspec.yml +45 -13
- data/.github/workflows/typecheck.yml +2 -2
- data/.gitignore +0 -1
- data/.rubocop_todo.yml +27 -49
- data/CHANGELOG.md +1 -10
- data/README.md +3 -3
- data/Rakefile +1 -0
- data/lib/solargraph/api_map/cache.rb +3 -3
- data/lib/solargraph/api_map/constants.rb +13 -3
- data/lib/solargraph/api_map/index.rb +22 -11
- data/lib/solargraph/api_map/source_to_yard.rb +13 -1
- data/lib/solargraph/api_map/store.rb +11 -8
- data/lib/solargraph/api_map.rb +105 -50
- data/lib/solargraph/bench.rb +45 -45
- data/lib/solargraph/complex_type/conformance.rb +176 -0
- data/lib/solargraph/complex_type/type_methods.rb +16 -2
- data/lib/solargraph/complex_type/unique_type.rb +170 -20
- data/lib/solargraph/complex_type.rb +119 -14
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +3 -1
- data/lib/solargraph/convention/data_definition.rb +4 -1
- data/lib/solargraph/convention/gemfile.rb +15 -15
- data/lib/solargraph/convention/gemspec.rb +23 -23
- data/lib/solargraph/convention/rakefile.rb +17 -17
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +1 -0
- data/lib/solargraph/convention/struct_definition.rb +5 -1
- data/lib/solargraph/convention.rb +78 -78
- data/lib/solargraph/converters/dd.rb +17 -17
- data/lib/solargraph/converters/dl.rb +15 -15
- data/lib/solargraph/converters/dt.rb +15 -15
- data/lib/solargraph/converters/misc.rb +1 -1
- data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
- data/lib/solargraph/diagnostics/rubocop.rb +1 -0
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +2 -0
- data/lib/solargraph/diagnostics/type_check.rb +1 -0
- data/lib/solargraph/diagnostics/update_errors.rb +41 -41
- data/lib/solargraph/doc_map.rb +134 -373
- data/lib/solargraph/equality.rb +1 -1
- data/lib/solargraph/gem_pins.rb +14 -15
- data/lib/solargraph/language_server/error_codes.rb +20 -20
- data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
- data/lib/solargraph/language_server/host/dispatch.rb +1 -0
- data/lib/solargraph/language_server/host/message_worker.rb +2 -1
- data/lib/solargraph/language_server/host/sources.rb +1 -0
- data/lib/solargraph/language_server/host.rb +6 -1
- data/lib/solargraph/language_server/message/base.rb +97 -97
- data/lib/solargraph/language_server/message/client/register_capability.rb +15 -15
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +60 -60
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -7
- data/lib/solargraph/language_server/message/extended/document.rb +1 -0
- data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
- data/lib/solargraph/language_server/message/extended/download_core.rb +19 -19
- data/lib/solargraph/language_server/message/extended/search.rb +20 -20
- data/lib/solargraph/language_server/message/initialize.rb +191 -191
- data/lib/solargraph/language_server/message/text_document/completion.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/document_highlight.rb +16 -16
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -11
- data/lib/solargraph/language_server/message/text_document/references.rb +16 -16
- data/lib/solargraph/language_server/message/text_document/rename.rb +19 -19
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -0
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +2 -0
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +35 -35
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +40 -40
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +26 -26
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -0
- data/lib/solargraph/language_server/message.rb +94 -94
- data/lib/solargraph/language_server/request.rb +27 -27
- data/lib/solargraph/language_server/transport/data_reader.rb +74 -74
- data/lib/solargraph/language_server/uri_helpers.rb +49 -49
- data/lib/solargraph/library.rb +59 -13
- data/lib/solargraph/location.rb +9 -4
- data/lib/solargraph/logging.rb +21 -1
- data/lib/solargraph/page.rb +92 -92
- data/lib/solargraph/parser/comment_ripper.rb +7 -0
- data/lib/solargraph/parser/flow_sensitive_typing.rb +330 -102
- data/lib/solargraph/parser/node_processor/base.rb +32 -2
- data/lib/solargraph/parser/node_processor.rb +7 -6
- data/lib/solargraph/parser/parser_gem/class_methods.rb +28 -10
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +31 -6
- data/lib/solargraph/parser/parser_gem/node_methods.rb +27 -7
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +2 -0
- data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -11
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +7 -0
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +37 -37
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +3 -2
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +2 -2
- data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +12 -7
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
- data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +5 -1
- data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
- data/lib/solargraph/parser/parser_gem.rb +12 -12
- data/lib/solargraph/parser/region.rb +9 -3
- data/lib/solargraph/parser/snippet.rb +1 -1
- data/lib/solargraph/parser.rb +23 -23
- data/lib/solargraph/pin/base.rb +53 -21
- data/lib/solargraph/pin/base_variable.rb +312 -20
- data/lib/solargraph/pin/block.rb +26 -4
- data/lib/solargraph/pin/breakable.rb +5 -1
- data/lib/solargraph/pin/callable.rb +50 -3
- data/lib/solargraph/pin/closure.rb +2 -6
- data/lib/solargraph/pin/common.rb +20 -5
- data/lib/solargraph/pin/compound_statement.rb +55 -0
- data/lib/solargraph/pin/constant.rb +45 -45
- data/lib/solargraph/pin/conversions.rb +2 -1
- data/lib/solargraph/pin/delegated_method.rb +15 -4
- data/lib/solargraph/pin/documenting.rb +1 -0
- data/lib/solargraph/pin/instance_variable.rb +5 -1
- data/lib/solargraph/pin/keyword.rb +0 -4
- data/lib/solargraph/pin/local_variable.rb +13 -57
- data/lib/solargraph/pin/method.rb +90 -42
- data/lib/solargraph/pin/method_alias.rb +8 -0
- data/lib/solargraph/pin/namespace.rb +7 -1
- data/lib/solargraph/pin/parameter.rb +76 -13
- data/lib/solargraph/pin/proxy_type.rb +2 -1
- data/lib/solargraph/pin/reference/override.rb +1 -1
- data/lib/solargraph/pin/reference/superclass.rb +2 -0
- data/lib/solargraph/pin/reference.rb +2 -0
- data/lib/solargraph/pin/search.rb +1 -0
- data/lib/solargraph/pin/signature.rb +8 -0
- data/lib/solargraph/pin/symbol.rb +1 -1
- data/lib/solargraph/pin/until.rb +1 -1
- data/lib/solargraph/pin/while.rb +1 -1
- data/lib/solargraph/pin.rb +2 -0
- data/lib/solargraph/pin_cache.rb +477 -57
- data/lib/solargraph/position.rb +12 -26
- data/lib/solargraph/range.rb +6 -6
- data/lib/solargraph/rbs_map/conversions.rb +33 -10
- data/lib/solargraph/rbs_map/core_fills.rb +84 -84
- data/lib/solargraph/rbs_map/core_map.rb +24 -17
- data/lib/solargraph/rbs_map/stdlib_map.rb +34 -5
- data/lib/solargraph/rbs_map.rb +74 -20
- data/lib/solargraph/server_methods.rb +16 -16
- data/lib/solargraph/shell.rb +73 -39
- data/lib/solargraph/source/chain/array.rb +37 -37
- data/lib/solargraph/source/chain/call.rb +52 -17
- data/lib/solargraph/source/chain/class_variable.rb +13 -13
- data/lib/solargraph/source/chain/constant.rb +2 -0
- data/lib/solargraph/source/chain/global_variable.rb +13 -13
- data/lib/solargraph/source/chain/hash.rb +1 -0
- data/lib/solargraph/source/chain/if.rb +1 -0
- data/lib/solargraph/source/chain/instance_variable.rb +22 -1
- data/lib/solargraph/source/chain/link.rb +109 -109
- data/lib/solargraph/source/chain/literal.rb +5 -0
- data/lib/solargraph/source/chain/or.rb +9 -1
- data/lib/solargraph/source/chain/q_call.rb +11 -11
- data/lib/solargraph/source/chain/variable.rb +13 -13
- data/lib/solargraph/source/chain/z_super.rb +30 -30
- data/lib/solargraph/source/chain.rb +25 -22
- data/lib/solargraph/source/change.rb +9 -2
- data/lib/solargraph/source/cursor.rb +7 -1
- data/lib/solargraph/source/source_chainer.rb +13 -3
- data/lib/solargraph/source/updater.rb +4 -0
- data/lib/solargraph/source.rb +33 -7
- data/lib/solargraph/source_map/clip.rb +13 -2
- data/lib/solargraph/source_map/data.rb +4 -1
- data/lib/solargraph/source_map/mapper.rb +24 -1
- data/lib/solargraph/source_map.rb +14 -6
- data/lib/solargraph/type_checker/problem.rb +3 -1
- data/lib/solargraph/type_checker/rules.rb +75 -2
- data/lib/solargraph/type_checker.rb +111 -30
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +3 -1
- data/lib/solargraph/workspace/gemspecs.rb +367 -0
- data/lib/solargraph/workspace/require_paths.rb +1 -0
- data/lib/solargraph/workspace.rb +158 -16
- data/lib/solargraph/yard_map/helpers.rb +2 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +5 -1
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
- data/lib/solargraph/yard_map/mapper.rb +5 -0
- data/lib/solargraph/yard_tags.rb +20 -20
- data/lib/solargraph/yardoc.rb +33 -23
- data/lib/solargraph.rb +24 -3
- data/rbs/fills/rubygems/0/dependency.rbs +193 -0
- data/rbs/fills/tuple/tuple.rbs +28 -0
- data/rbs/shims/ast/0/node.rbs +1 -1
- data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
- data/solargraph.gemspec +2 -1
- metadata +12 -7
- 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/lib/solargraph/pin/base.rb
CHANGED
|
@@ -41,7 +41,7 @@ module Solargraph
|
|
|
41
41
|
# @param type_location [Solargraph::Location, nil]
|
|
42
42
|
# @param closure [Solargraph::Pin::Closure, nil]
|
|
43
43
|
# @param name [String]
|
|
44
|
-
# @param comments [String]
|
|
44
|
+
# @param comments [String, nil]
|
|
45
45
|
# @param source [Symbol, nil]
|
|
46
46
|
# @param docstring [YARD::Docstring, nil]
|
|
47
47
|
# @param directives [::Array<YARD::Tags::Directive>, nil]
|
|
@@ -57,6 +57,9 @@ module Solargraph
|
|
|
57
57
|
@docstring = docstring
|
|
58
58
|
@directives = directives
|
|
59
59
|
@combine_priority = combine_priority
|
|
60
|
+
# @type [ComplexType, ComplexType::UniqueType, nil]
|
|
61
|
+
@binder = nil
|
|
62
|
+
|
|
60
63
|
|
|
61
64
|
assert_source_provided
|
|
62
65
|
assert_location_provided
|
|
@@ -72,7 +75,6 @@ module Solargraph
|
|
|
72
75
|
# @return [Pin::Closure, nil]
|
|
73
76
|
def closure
|
|
74
77
|
Solargraph.assert_or_log(:closure, "Closure not set on #{self.class} #{name.inspect} from #{source.inspect}") unless @closure
|
|
75
|
-
# @type [Pin::Closure, nil]
|
|
76
78
|
@closure
|
|
77
79
|
end
|
|
78
80
|
|
|
@@ -81,7 +83,6 @@ module Solargraph
|
|
|
81
83
|
#
|
|
82
84
|
# @return [self]
|
|
83
85
|
def combine_with(other, attrs={})
|
|
84
|
-
raise "tried to combine #{other.class} with #{self.class}" unless other.class == self.class
|
|
85
86
|
priority_choice = choose_priority(other)
|
|
86
87
|
return priority_choice unless priority_choice.nil?
|
|
87
88
|
|
|
@@ -92,7 +93,7 @@ module Solargraph
|
|
|
92
93
|
location: location,
|
|
93
94
|
type_location: type_location,
|
|
94
95
|
name: combined_name,
|
|
95
|
-
closure:
|
|
96
|
+
closure: combine_closure(other),
|
|
96
97
|
comments: choose_longer(other, :comments),
|
|
97
98
|
source: :combined,
|
|
98
99
|
docstring: choose(other, :docstring),
|
|
@@ -140,14 +141,22 @@ module Solargraph
|
|
|
140
141
|
end
|
|
141
142
|
|
|
142
143
|
# @param other [self]
|
|
144
|
+
#
|
|
143
145
|
# @return [::Array<YARD::Tags::Directive>, nil]
|
|
144
146
|
def combine_directives(other)
|
|
145
147
|
return self.directives if other.directives.empty?
|
|
146
148
|
return other.directives if directives.empty?
|
|
147
|
-
|
|
149
|
+
(directives + other.directives).uniq
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# @param other [self]
|
|
153
|
+
# @return [Pin::Closure, nil]
|
|
154
|
+
def combine_closure(other)
|
|
155
|
+
choose_pin_attr_with_same_name(other, :closure)
|
|
148
156
|
end
|
|
149
157
|
|
|
150
158
|
# @param other [self]
|
|
159
|
+
# @sg-ignore @type should override probed type
|
|
151
160
|
# @return [String]
|
|
152
161
|
def combine_name(other)
|
|
153
162
|
if needs_consistent_name? || other.needs_consistent_name?
|
|
@@ -170,6 +179,9 @@ module Solargraph
|
|
|
170
179
|
# Same with @directives, @macros, @maybe_directives, which
|
|
171
180
|
# regenerate docstring
|
|
172
181
|
@deprecated = nil
|
|
182
|
+
@context = nil
|
|
183
|
+
@binder = nil
|
|
184
|
+
@path = nil
|
|
173
185
|
reset_conversions
|
|
174
186
|
end
|
|
175
187
|
|
|
@@ -189,6 +201,10 @@ module Solargraph
|
|
|
189
201
|
other.return_type
|
|
190
202
|
elsif other.return_type.undefined?
|
|
191
203
|
return_type
|
|
204
|
+
elsif return_type.erased_version_of?(other.return_type)
|
|
205
|
+
other.return_type
|
|
206
|
+
elsif other.return_type.erased_version_of?(return_type)
|
|
207
|
+
return_type
|
|
192
208
|
elsif dodgy_return_type_source? && !other.dodgy_return_type_source?
|
|
193
209
|
other.return_type
|
|
194
210
|
elsif other.dodgy_return_type_source? && !dodgy_return_type_source?
|
|
@@ -203,9 +219,12 @@ module Solargraph
|
|
|
203
219
|
end
|
|
204
220
|
end
|
|
205
221
|
|
|
222
|
+
# @sg-ignore need boolish support for ? methods
|
|
206
223
|
def dodgy_return_type_source?
|
|
207
224
|
# uses a lot of 'Object' instead of 'self'
|
|
208
|
-
location&.filename&.include?('core_ext/object/')
|
|
225
|
+
location&.filename&.include?('core_ext/object/') ||
|
|
226
|
+
# ditto
|
|
227
|
+
location&.filename&.include?('stdlib/date/0/date.rbs')
|
|
209
228
|
end
|
|
210
229
|
|
|
211
230
|
# when choices are arbitrary, make sure the choice is consistent
|
|
@@ -213,11 +232,13 @@ module Solargraph
|
|
|
213
232
|
# @param other [Pin::Base]
|
|
214
233
|
# @param attr [::Symbol]
|
|
215
234
|
#
|
|
216
|
-
# @
|
|
235
|
+
# @sg-ignore
|
|
236
|
+
# @return [undefined, nil]
|
|
217
237
|
def choose(other, attr)
|
|
218
238
|
results = [self, other].map(&attr).compact
|
|
219
239
|
# true and false are different classes and can't be sorted
|
|
220
240
|
return true if results.any? { |r| r == true || r == false }
|
|
241
|
+
return results.first if results.any? { |r| r.is_a? AST::Node }
|
|
221
242
|
results.min
|
|
222
243
|
rescue
|
|
223
244
|
STDERR.puts("Problem handling #{attr} for \n#{self.inspect}\n and \n#{other.inspect}\n\n#{self.send(attr).inspect} vs #{other.send(attr).inspect}")
|
|
@@ -250,6 +271,7 @@ module Solargraph
|
|
|
250
271
|
end
|
|
251
272
|
end
|
|
252
273
|
|
|
274
|
+
# @sg-ignore need boolish support for ? methods
|
|
253
275
|
def rbs_location?
|
|
254
276
|
type_location&.rbs?
|
|
255
277
|
end
|
|
@@ -309,7 +331,11 @@ module Solargraph
|
|
|
309
331
|
# @sg-ignore
|
|
310
332
|
# @return [undefined]
|
|
311
333
|
def assert_same(other, attr)
|
|
312
|
-
|
|
334
|
+
if other.nil?
|
|
335
|
+
Solargraph.assert_or_log("combine_with_#{attr}_nil".to_sym,
|
|
336
|
+
"Other was passed in nil in assert_same on #{self}")
|
|
337
|
+
return send(attr)
|
|
338
|
+
end
|
|
313
339
|
val1 = send(attr)
|
|
314
340
|
val2 = other.send(attr)
|
|
315
341
|
return val1 if val1 == val2
|
|
@@ -358,8 +384,11 @@ module Solargraph
|
|
|
358
384
|
[
|
|
359
385
|
# maximize number of gates, as types in other combined pins may
|
|
360
386
|
# depend on those gates
|
|
387
|
+
|
|
388
|
+
# @sg-ignore Need better handling of #compact
|
|
361
389
|
closure.gates.length,
|
|
362
390
|
# use basename so that results don't vary system to system
|
|
391
|
+
# @sg-ignore Need better handling of #compact
|
|
363
392
|
File.basename(closure.best_location.to_s)
|
|
364
393
|
]
|
|
365
394
|
end
|
|
@@ -376,7 +405,7 @@ module Solargraph
|
|
|
376
405
|
end
|
|
377
406
|
|
|
378
407
|
# @param generics_to_resolve [Enumerable<String>]
|
|
379
|
-
# @param return_type_context [ComplexType, nil]
|
|
408
|
+
# @param return_type_context [ComplexType, ComplexType::UniqueType, nil]
|
|
380
409
|
# @param context [ComplexType]
|
|
381
410
|
# @param resolved_generic_values [Hash{String => ComplexType}]
|
|
382
411
|
# @return [self]
|
|
@@ -418,6 +447,7 @@ module Solargraph
|
|
|
418
447
|
# @return [String, nil]
|
|
419
448
|
def filename
|
|
420
449
|
return nil if location.nil?
|
|
450
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
421
451
|
location.filename
|
|
422
452
|
end
|
|
423
453
|
|
|
@@ -453,11 +483,16 @@ module Solargraph
|
|
|
453
483
|
# @return [Boolean]
|
|
454
484
|
def nearly? other
|
|
455
485
|
self.class == other.class &&
|
|
486
|
+
# @sg-ignore Translate to something flow sensitive typing understands
|
|
456
487
|
name == other.name &&
|
|
488
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
457
489
|
(closure == other.closure || (closure && closure.nearly?(other.closure))) &&
|
|
490
|
+
# @sg-ignore Translate to something flow sensitive typing understands
|
|
458
491
|
(comments == other.comments ||
|
|
492
|
+
# @sg-ignore Translate to something flow sensitive typing understands
|
|
459
493
|
(((maybe_directives? == false && other.maybe_directives? == false) || compare_directives(directives, other.directives)) &&
|
|
460
|
-
|
|
494
|
+
# @sg-ignore Translate to something flow sensitive typing understands
|
|
495
|
+
compare_docstring_tags(docstring, other.docstring))
|
|
461
496
|
)
|
|
462
497
|
end
|
|
463
498
|
|
|
@@ -484,6 +519,7 @@ module Solargraph
|
|
|
484
519
|
@docstring ||= Solargraph::Source.parse_docstring('').to_docstring
|
|
485
520
|
end
|
|
486
521
|
|
|
522
|
+
# @sg-ignore parse_comments will always set @directives
|
|
487
523
|
# @return [::Array<YARD::Tags::Directive>]
|
|
488
524
|
def directives
|
|
489
525
|
parse_comments unless @directives
|
|
@@ -520,7 +556,7 @@ module Solargraph
|
|
|
520
556
|
# provided ApiMap.
|
|
521
557
|
#
|
|
522
558
|
# @param api_map [ApiMap]
|
|
523
|
-
# @return [ComplexType]
|
|
559
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
524
560
|
def typify api_map
|
|
525
561
|
return_type.qualify(api_map, *(closure&.gates || ['']))
|
|
526
562
|
end
|
|
@@ -528,16 +564,16 @@ module Solargraph
|
|
|
528
564
|
# Infer the pin's return type via static code analysis.
|
|
529
565
|
#
|
|
530
566
|
# @param api_map [ApiMap]
|
|
531
|
-
# @return [ComplexType]
|
|
567
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
532
568
|
def probe api_map
|
|
533
569
|
typify api_map
|
|
534
570
|
end
|
|
535
571
|
|
|
536
572
|
# @deprecated Use #typify and/or #probe instead
|
|
537
573
|
# @param api_map [ApiMap]
|
|
538
|
-
# @return [ComplexType]
|
|
574
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
539
575
|
def infer api_map
|
|
540
|
-
Solargraph
|
|
576
|
+
Solargraph.assert_or_log(:pin_infer, 'WARNING: Pin #infer methods are deprecated. Use #typify or #probe instead.')
|
|
541
577
|
type = typify(api_map)
|
|
542
578
|
return type unless type.undefined?
|
|
543
579
|
probe api_map
|
|
@@ -568,7 +604,7 @@ module Solargraph
|
|
|
568
604
|
# the return type and the #proxied? setting, the proxy should be a clone
|
|
569
605
|
# of the original.
|
|
570
606
|
#
|
|
571
|
-
# @param return_type [ComplexType]
|
|
607
|
+
# @param return_type [ComplexType, ComplexType::UniqueType, nil]
|
|
572
608
|
# @return [self]
|
|
573
609
|
def proxy return_type
|
|
574
610
|
result = dup
|
|
@@ -618,7 +654,7 @@ module Solargraph
|
|
|
618
654
|
|
|
619
655
|
# @return [String]
|
|
620
656
|
def inner_desc
|
|
621
|
-
closure_info = closure&.
|
|
657
|
+
closure_info = closure&.name.inspect
|
|
622
658
|
binder_info = binder&.desc
|
|
623
659
|
"name=#{name.inspect} return_type=#{type_desc}, context=#{context.rooted_tags}, closure=#{closure_info}, binder=#{binder_info}"
|
|
624
660
|
end
|
|
@@ -646,10 +682,6 @@ module Solargraph
|
|
|
646
682
|
end
|
|
647
683
|
end
|
|
648
684
|
|
|
649
|
-
# @return [void]
|
|
650
|
-
def reset_generated!
|
|
651
|
-
end
|
|
652
|
-
|
|
653
685
|
protected
|
|
654
686
|
|
|
655
687
|
# @return [Boolean]
|
|
@@ -658,7 +690,7 @@ module Solargraph
|
|
|
658
690
|
# @return [Boolean]
|
|
659
691
|
attr_writer :proxied
|
|
660
692
|
|
|
661
|
-
# @return [ComplexType]
|
|
693
|
+
# @return [ComplexType, ComplexType::UniqueType, nil]
|
|
662
694
|
attr_writer :return_type
|
|
663
695
|
|
|
664
696
|
attr_writer :docstring
|
|
@@ -6,31 +6,139 @@ module Solargraph
|
|
|
6
6
|
# include Solargraph::Source::NodeMethods
|
|
7
7
|
include Solargraph::Parser::NodeMethods
|
|
8
8
|
|
|
9
|
-
# @return [Parser::AST::Node
|
|
10
|
-
attr_reader :
|
|
9
|
+
# @return [Array<Parser::AST::Node>]
|
|
10
|
+
attr_reader :assignments
|
|
11
11
|
|
|
12
12
|
attr_accessor :mass_assignment
|
|
13
13
|
|
|
14
|
+
# @return [Range, nil]
|
|
15
|
+
attr_reader :presence
|
|
16
|
+
|
|
14
17
|
# @param return_type [ComplexType, nil]
|
|
18
|
+
# @param assignment [Parser::AST::Node, nil] First assignment
|
|
19
|
+
# that was made to this variable
|
|
20
|
+
# @param assignments [Array<Parser::AST::Node>] Possible
|
|
21
|
+
# assignments that may have been made to this variable
|
|
15
22
|
# @param mass_assignment [::Array(Parser::AST::Node, Integer), nil]
|
|
16
|
-
# @param assignment [Parser::AST::Node, nil]
|
|
17
|
-
|
|
23
|
+
# @param assignment [Parser::AST::Node, nil] First assignment
|
|
24
|
+
# that was made to this variable
|
|
25
|
+
# @param assignments [Array<Parser::AST::Node>] Possible
|
|
26
|
+
# assignments that may have been made to this variable
|
|
27
|
+
# @param exclude_return_type [ComplexType, nil] Ensure any
|
|
28
|
+
# return type returned will never include any of these unique
|
|
29
|
+
# types in the unique types of its complex type.
|
|
30
|
+
#
|
|
31
|
+
# Example: If a return type is 'Float | Integer | nil' and the
|
|
32
|
+
# exclude_return_type is 'Integer', the resulting return
|
|
33
|
+
# type will be 'Float | nil' because Integer is excluded.
|
|
34
|
+
# @param intersection_return_type [ComplexType, nil] Ensure each unique
|
|
35
|
+
# return type is compatible with at least one element of this
|
|
36
|
+
# complex type. If a ComplexType used as a return type is an
|
|
37
|
+
# union type - we can return any of these - these are
|
|
38
|
+
# intersection types - everything we return needs to meet at least
|
|
39
|
+
# one of these unique types.
|
|
40
|
+
#
|
|
41
|
+
# Example: If a return type is 'Numeric | nil' and the
|
|
42
|
+
# intersection_return_type is 'Float | nil', the resulting return
|
|
43
|
+
# type will be 'Float | nil' because Float is compatible
|
|
44
|
+
# with Numeric and nil is compatible with nil.
|
|
45
|
+
# @see https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types
|
|
46
|
+
# @see https://en.wikipedia.org/wiki/Intersection_type#TypeScript_example
|
|
47
|
+
# @param presence [Range, nil]
|
|
48
|
+
# @param presence_certain [Boolean]
|
|
49
|
+
def initialize assignment: nil, assignments: [], mass_assignment: nil,
|
|
50
|
+
presence: nil, presence_certain: false, return_type: nil,
|
|
51
|
+
intersection_return_type: nil, exclude_return_type: nil,
|
|
52
|
+
**splat
|
|
18
53
|
super(**splat)
|
|
19
|
-
@
|
|
54
|
+
@assignments = (assignment.nil? ? [] : [assignment]) + assignments
|
|
20
55
|
# @type [nil, ::Array(Parser::AST::Node, Integer)]
|
|
21
|
-
@mass_assignment =
|
|
56
|
+
@mass_assignment = mass_assignment
|
|
22
57
|
@return_type = return_type
|
|
58
|
+
@intersection_return_type = intersection_return_type
|
|
59
|
+
@exclude_return_type = exclude_return_type
|
|
60
|
+
@presence = presence
|
|
61
|
+
@presence_certain = presence_certain
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @param presence [Range]
|
|
65
|
+
# @param exclude_return_type [ComplexType, nil]
|
|
66
|
+
# @param intersection_return_type [ComplexType, nil]
|
|
67
|
+
# @param source [::Symbol]
|
|
68
|
+
#
|
|
69
|
+
# @return [self]
|
|
70
|
+
def downcast presence:, exclude_return_type: nil, intersection_return_type: nil,
|
|
71
|
+
source: self.source
|
|
72
|
+
result = dup
|
|
73
|
+
result.exclude_return_type = exclude_return_type
|
|
74
|
+
result.intersection_return_type = intersection_return_type
|
|
75
|
+
result.source = source
|
|
76
|
+
result.presence = presence
|
|
77
|
+
result.reset_generated!
|
|
78
|
+
result
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def reset_generated!
|
|
82
|
+
@assignment = nil
|
|
83
|
+
super
|
|
23
84
|
end
|
|
24
85
|
|
|
25
86
|
def combine_with(other, attrs={})
|
|
87
|
+
new_assignments = combine_assignments(other)
|
|
26
88
|
new_attrs = attrs.merge({
|
|
27
|
-
|
|
28
|
-
|
|
89
|
+
# default values don't exist in RBS parameters; it just
|
|
90
|
+
# tells you if the arg is optional or not. Prefer a
|
|
91
|
+
# provided value if we have one here since we can't rely on
|
|
92
|
+
# it from RBS so we can infer from it and typecheck on it.
|
|
93
|
+
assignment: choose(other, :assignment),
|
|
94
|
+
assignments: new_assignments,
|
|
95
|
+
mass_assignment: combine_mass_assignment(other),
|
|
29
96
|
return_type: combine_return_type(other),
|
|
97
|
+
intersection_return_type: combine_types(other, :intersection_return_type),
|
|
98
|
+
exclude_return_type: combine_types(other, :exclude_return_type),
|
|
99
|
+
presence: combine_presence(other),
|
|
100
|
+
presence_certain: combine_presence_certain(other)
|
|
30
101
|
})
|
|
31
102
|
super(other, new_attrs)
|
|
32
103
|
end
|
|
33
104
|
|
|
105
|
+
# @param other [self]
|
|
106
|
+
#
|
|
107
|
+
# @return [Array(AST::Node, Integer), nil]
|
|
108
|
+
def combine_mass_assignment(other)
|
|
109
|
+
# @todo pick first non-nil arbitrarily - we don't yet support
|
|
110
|
+
# mass assignment merging
|
|
111
|
+
mass_assignment || other.mass_assignment
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# If a certain pin is being combined with an uncertain pin, we
|
|
115
|
+
# end up with a certain result
|
|
116
|
+
#
|
|
117
|
+
# @param other [self]
|
|
118
|
+
#
|
|
119
|
+
# @return [Boolean]
|
|
120
|
+
def combine_presence_certain(other)
|
|
121
|
+
presence_certain? || other.presence_certain?
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# @return [Parser::AST::Node, nil]
|
|
125
|
+
def assignment
|
|
126
|
+
@assignment ||= assignments.last
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# @param other [self]
|
|
130
|
+
#
|
|
131
|
+
# @return [::Array<Parser::AST::Node>]
|
|
132
|
+
def combine_assignments(other)
|
|
133
|
+
(other.assignments + assignments).uniq
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def inner_desc
|
|
137
|
+
super + ", presence=#{presence.inspect}, assignments=#{assignments}, " \
|
|
138
|
+
"intersection_return_type=#{intersection_return_type&.rooted_tags.inspect}, " \
|
|
139
|
+
"exclude_return_type=#{exclude_return_type&.rooted_tags.inspect}"
|
|
140
|
+
end
|
|
141
|
+
|
|
34
142
|
def completion_item_kind
|
|
35
143
|
Solargraph::LanguageServer::CompletionItemKinds::VARIABLE
|
|
36
144
|
end
|
|
@@ -40,10 +148,6 @@ module Solargraph
|
|
|
40
148
|
Solargraph::LanguageServer::SymbolKinds::VARIABLE
|
|
41
149
|
end
|
|
42
150
|
|
|
43
|
-
def return_type
|
|
44
|
-
@return_type ||= generate_complex_type
|
|
45
|
-
end
|
|
46
|
-
|
|
47
151
|
def nil_assignment?
|
|
48
152
|
# this will always be false - should it be return_type ==
|
|
49
153
|
# ComplexType::NIL or somesuch?
|
|
@@ -67,10 +171,12 @@ module Solargraph
|
|
|
67
171
|
rng = Range.from_node(node)
|
|
68
172
|
next if rng.nil?
|
|
69
173
|
pos = rng.ending
|
|
174
|
+
# @sg-ignore Need to add nil check here
|
|
70
175
|
clip = api_map.clip_at(location.filename, pos)
|
|
71
176
|
# Use the return node for inference. The clip might infer from the
|
|
72
177
|
# first node in a method call instead of the entire call.
|
|
73
178
|
chain = Parser.chain(node, nil, nil)
|
|
179
|
+
# @sg-ignore Need to add nil check here
|
|
74
180
|
result = chain.infer(api_map, closure, clip.locals).self_to_type(closure.context)
|
|
75
181
|
types.push result unless result.undefined?
|
|
76
182
|
end
|
|
@@ -79,13 +185,15 @@ module Solargraph
|
|
|
79
185
|
end
|
|
80
186
|
|
|
81
187
|
# @param api_map [ApiMap]
|
|
82
|
-
# @return [ComplexType]
|
|
188
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
83
189
|
def probe api_map
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
end
|
|
190
|
+
assignment_types = assignments.flat_map { |node| return_types_from_node(node, api_map) }
|
|
191
|
+
type_from_assignment = ComplexType.new(assignment_types.flat_map(&:items).uniq) unless assignment_types.empty?
|
|
192
|
+
return adjust_type api_map, type_from_assignment unless type_from_assignment.nil?
|
|
88
193
|
|
|
194
|
+
# @todo should handle merging types from mass assignments as
|
|
195
|
+
# well so that we can do better flow sensitive typing with
|
|
196
|
+
# multiple assignments
|
|
89
197
|
unless @mass_assignment.nil?
|
|
90
198
|
mass_node, index = @mass_assignment
|
|
91
199
|
types = return_types_from_node(mass_node, api_map)
|
|
@@ -96,7 +204,10 @@ module Solargraph
|
|
|
96
204
|
type.all_params.first
|
|
97
205
|
end
|
|
98
206
|
end.compact!
|
|
99
|
-
|
|
207
|
+
|
|
208
|
+
return ComplexType::UNDEFINED if types.empty?
|
|
209
|
+
|
|
210
|
+
return adjust_type api_map, ComplexType.new(types.uniq).qualify(api_map, *gates)
|
|
100
211
|
end
|
|
101
212
|
|
|
102
213
|
ComplexType::UNDEFINED
|
|
@@ -113,13 +224,194 @@ module Solargraph
|
|
|
113
224
|
"#{super} = #{assignment&.type.inspect}"
|
|
114
225
|
end
|
|
115
226
|
|
|
227
|
+
# @return [ComplexType, nil]
|
|
228
|
+
def return_type
|
|
229
|
+
generate_complex_type || @return_type || intersection_return_type || ComplexType::UNDEFINED
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def typify api_map
|
|
233
|
+
raw_return_type = super
|
|
234
|
+
|
|
235
|
+
adjust_type(api_map, raw_return_type)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# @sg-ignore need boolish support for ? methods
|
|
239
|
+
def presence_certain?
|
|
240
|
+
exclude_return_type || intersection_return_type
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# @param other_loc [Location]
|
|
244
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
245
|
+
def starts_at?(other_loc)
|
|
246
|
+
location&.filename == other_loc.filename &&
|
|
247
|
+
presence &&
|
|
248
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
249
|
+
presence.start == other_loc.range.start
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# Narrow the presence range to the intersection of both.
|
|
253
|
+
#
|
|
254
|
+
# @param other [self]
|
|
255
|
+
#
|
|
256
|
+
# @return [Range, nil]
|
|
257
|
+
def combine_presence(other)
|
|
258
|
+
return presence || other.presence if presence.nil? || other.presence.nil?
|
|
259
|
+
|
|
260
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
261
|
+
Range.new([presence.start, other.presence.start].max, [presence.ending, other.presence.ending].min)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# @param other [self]
|
|
265
|
+
# @return [Pin::Closure, nil]
|
|
266
|
+
def combine_closure(other)
|
|
267
|
+
return closure if self.closure == other.closure
|
|
268
|
+
|
|
269
|
+
# choose first defined, as that establishes the scope of the variable
|
|
270
|
+
if closure.nil? || other.closure.nil?
|
|
271
|
+
Solargraph.assert_or_log(:varible_closure_missing) do
|
|
272
|
+
"One of the local variables being combined is missing a closure: " \
|
|
273
|
+
"#{self.inspect} vs #{other.inspect}"
|
|
274
|
+
end
|
|
275
|
+
return closure || other.closure
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
279
|
+
if closure.location.nil? || other.closure.location.nil?
|
|
280
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
281
|
+
return closure.location.nil? ? other.closure : closure
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# if filenames are different, this will just pick one
|
|
285
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
286
|
+
return closure if closure.location <= other.closure.location
|
|
287
|
+
|
|
288
|
+
other.closure
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# @param other_closure [Pin::Closure]
|
|
292
|
+
# @param other_loc [Location]
|
|
293
|
+
def visible_at?(other_closure, other_loc)
|
|
294
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
295
|
+
location.filename == other_loc.filename &&
|
|
296
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
297
|
+
(!presence || presence.include?(other_loc.range.start)) &&
|
|
298
|
+
visible_in_closure?(other_closure)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def presence_certain?
|
|
302
|
+
@presence_certain
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
protected
|
|
306
|
+
|
|
307
|
+
attr_accessor :exclude_return_type, :intersection_return_type
|
|
308
|
+
|
|
309
|
+
# @return [Range]
|
|
310
|
+
attr_writer :presence
|
|
311
|
+
|
|
116
312
|
private
|
|
117
313
|
|
|
118
|
-
# @
|
|
314
|
+
# @param api_map [ApiMap]
|
|
315
|
+
# @param raw_return_type [ComplexType, ComplexType::UniqueType]
|
|
316
|
+
#
|
|
317
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
318
|
+
def adjust_type(api_map, raw_return_type)
|
|
319
|
+
qualified_exclude = exclude_return_type&.qualify(api_map, *(closure&.gates || ['']))
|
|
320
|
+
minus_exclusions = raw_return_type.exclude qualified_exclude, api_map
|
|
321
|
+
qualified_intersection = intersection_return_type&.qualify(api_map, *(closure&.gates || ['']))
|
|
322
|
+
minus_exclusions.intersect_with qualified_intersection, api_map
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# @param other [self]
|
|
326
|
+
# @return [Pin::Closure, nil]
|
|
327
|
+
def combine_closure(other)
|
|
328
|
+
return closure if self.closure == other.closure
|
|
329
|
+
|
|
330
|
+
# choose first defined, as that establishes the scope of the variable
|
|
331
|
+
if closure.nil? || other.closure.nil?
|
|
332
|
+
Solargraph.assert_or_log(:varible_closure_missing) do
|
|
333
|
+
"One of the local variables being combined is missing a closure: " \
|
|
334
|
+
"#{self.inspect} vs #{other.inspect}"
|
|
335
|
+
end
|
|
336
|
+
return closure || other.closure
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
# @sg-ignore Need to add nil check here
|
|
340
|
+
if closure.location.nil? || other.closure.location.nil?
|
|
341
|
+
# @sg-ignore Need to add nil check here
|
|
342
|
+
return closure.location.nil? ? other.closure : closure
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# if filenames are different, this will just pick one
|
|
346
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
347
|
+
return closure if closure.location <= other.closure.location
|
|
348
|
+
|
|
349
|
+
other.closure
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# See if this variable is visible within 'viewing_closure'
|
|
353
|
+
#
|
|
354
|
+
# @param viewing_closure [Pin::Closure]
|
|
355
|
+
# @return [Boolean]
|
|
356
|
+
def visible_in_closure? viewing_closure
|
|
357
|
+
return false if closure.nil?
|
|
358
|
+
|
|
359
|
+
# if we're declared at top level, we can't be seen from within
|
|
360
|
+
# methods declared tere
|
|
361
|
+
|
|
362
|
+
# @sg-ignore Need to add nil check here
|
|
363
|
+
return false if viewing_closure.is_a?(Pin::Method) && closure.context.tags == 'Class<>'
|
|
364
|
+
|
|
365
|
+
# @sg-ignore Need to add nil check here
|
|
366
|
+
return true if viewing_closure.binder.namespace == closure.binder.namespace
|
|
367
|
+
|
|
368
|
+
# @sg-ignore Need to add nil check here
|
|
369
|
+
return true if viewing_closure.return_type == closure.context
|
|
370
|
+
|
|
371
|
+
# classes and modules can't see local variables declared
|
|
372
|
+
# in their parent closure, so stop here
|
|
373
|
+
return false if scope == :instance && viewing_closure.is_a?(Pin::Namespace)
|
|
374
|
+
|
|
375
|
+
parent_of_viewing_closure = viewing_closure.closure
|
|
376
|
+
|
|
377
|
+
return false if parent_of_viewing_closure.nil?
|
|
378
|
+
|
|
379
|
+
visible_in_closure?(parent_of_viewing_closure)
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
# @param other [self]
|
|
383
|
+
# @return [ComplexType, nil]
|
|
384
|
+
def combine_return_type(other)
|
|
385
|
+
combine_types(other, :return_type)
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
# @param other [self]
|
|
389
|
+
# @param attr [::Symbol]
|
|
390
|
+
#
|
|
391
|
+
# @return [ComplexType, nil]
|
|
392
|
+
def combine_types(other, attr)
|
|
393
|
+
# @type [ComplexType, nil]
|
|
394
|
+
type1 = send(attr)
|
|
395
|
+
# @type [ComplexType, nil]
|
|
396
|
+
type2 = other.send(attr)
|
|
397
|
+
if type1 && type2
|
|
398
|
+
types = (type1.items + type2.items).uniq
|
|
399
|
+
ComplexType.new(types)
|
|
400
|
+
else
|
|
401
|
+
type1 || type2
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
# @return [::Symbol]
|
|
406
|
+
def scope
|
|
407
|
+
:instance
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
# @return [ComplexType, nil]
|
|
119
411
|
def generate_complex_type
|
|
120
412
|
tag = docstring.tag(:type)
|
|
121
413
|
return ComplexType.try_parse(*tag.types) unless tag.nil? || tag.types.nil? || tag.types.empty?
|
|
122
|
-
|
|
414
|
+
nil
|
|
123
415
|
end
|
|
124
416
|
end
|
|
125
417
|
end
|