solargraph 0.54.1 → 0.56.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/.github/workflows/plugins.yml +2 -0
- data/.github/workflows/typecheck.yml +3 -1
- data/.gitignore +2 -0
- data/CHANGELOG.md +70 -0
- data/README.md +13 -3
- data/lib/solargraph/api_map/cache.rb +10 -1
- data/lib/solargraph/api_map/index.rb +175 -0
- data/lib/solargraph/api_map/store.rb +79 -126
- data/lib/solargraph/api_map.rb +247 -93
- data/lib/solargraph/bench.rb +17 -1
- data/lib/solargraph/complex_type/type_methods.rb +13 -1
- data/lib/solargraph/complex_type/unique_type.rb +118 -9
- data/lib/solargraph/complex_type.rb +48 -18
- data/lib/solargraph/convention/base.rb +3 -3
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +60 -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 +5 -3
- data/lib/solargraph/doc_map.rb +274 -56
- data/lib/solargraph/equality.rb +33 -0
- data/lib/solargraph/gem_pins.rb +53 -37
- data/lib/solargraph/language_server/host/message_worker.rb +31 -11
- data/lib/solargraph/language_server/host.rb +24 -13
- data/lib/solargraph/language_server/message/base.rb +19 -12
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
- data/lib/solargraph/language_server/message/extended/document.rb +5 -2
- data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
- 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/formatting.rb +4 -0
- data/lib/solargraph/library.rb +13 -11
- data/lib/solargraph/location.rb +28 -0
- data/lib/solargraph/logging.rb +1 -0
- data/lib/solargraph/parser/comment_ripper.rb +12 -6
- data/lib/solargraph/parser/flow_sensitive_typing.rb +227 -0
- data/lib/solargraph/parser/node_methods.rb +15 -1
- data/lib/solargraph/parser/node_processor.rb +3 -1
- data/lib/solargraph/parser/parser_gem/class_methods.rb +16 -14
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +17 -23
- data/lib/solargraph/parser/parser_gem/node_methods.rb +5 -3
- data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +21 -0
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +23 -2
- data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +21 -0
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +4 -3
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +29 -6
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +41 -0
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -3
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +28 -16
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
- data/lib/solargraph/parser/parser_gem/node_processors.rb +10 -0
- data/lib/solargraph/parser/region.rb +1 -1
- data/lib/solargraph/parser.rb +1 -0
- data/lib/solargraph/pin/base.rb +326 -43
- data/lib/solargraph/pin/base_variable.rb +18 -10
- data/lib/solargraph/pin/block.rb +3 -3
- data/lib/solargraph/pin/breakable.rb +9 -0
- data/lib/solargraph/pin/callable.rb +77 -6
- data/lib/solargraph/pin/closure.rb +18 -1
- data/lib/solargraph/pin/common.rb +5 -0
- data/lib/solargraph/pin/delegated_method.rb +20 -1
- data/lib/solargraph/pin/documenting.rb +16 -0
- data/lib/solargraph/pin/keyword.rb +7 -2
- data/lib/solargraph/pin/local_variable.rb +15 -6
- data/lib/solargraph/pin/method.rb +172 -42
- data/lib/solargraph/pin/namespace.rb +17 -9
- data/lib/solargraph/pin/parameter.rb +61 -11
- data/lib/solargraph/pin/proxy_type.rb +12 -6
- data/lib/solargraph/pin/reference/override.rb +10 -6
- data/lib/solargraph/pin/reference/require.rb +2 -2
- data/lib/solargraph/pin/signature.rb +42 -0
- data/lib/solargraph/pin/singleton.rb +1 -1
- data/lib/solargraph/pin/symbol.rb +3 -2
- data/lib/solargraph/pin/until.rb +18 -0
- data/lib/solargraph/pin/while.rb +18 -0
- data/lib/solargraph/pin.rb +4 -1
- data/lib/solargraph/pin_cache.rb +185 -0
- data/lib/solargraph/position.rb +16 -0
- data/lib/solargraph/range.rb +16 -0
- data/lib/solargraph/rbs_map/conversions.rb +199 -66
- data/lib/solargraph/rbs_map/core_fills.rb +32 -16
- data/lib/solargraph/rbs_map/core_map.rb +34 -11
- data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
- data/lib/solargraph/rbs_map.rb +74 -16
- data/lib/solargraph/shell.rb +19 -18
- data/lib/solargraph/source/chain/array.rb +12 -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 +62 -25
- data/lib/solargraph/source/chain/constant.rb +1 -1
- data/lib/solargraph/source/chain/hash.rb +9 -3
- data/lib/solargraph/source/chain/head.rb +1 -1
- data/lib/solargraph/source/chain/if.rb +6 -1
- data/lib/solargraph/source/chain/link.rb +19 -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 +106 -62
- data/lib/solargraph/source/cursor.rb +1 -11
- data/lib/solargraph/source/source_chainer.rb +2 -2
- data/lib/solargraph/source.rb +2 -1
- data/lib/solargraph/source_map/clip.rb +4 -2
- data/lib/solargraph/source_map/mapper.rb +9 -5
- data/lib/solargraph/source_map.rb +0 -17
- data/lib/solargraph/type_checker/checks.rb +4 -0
- data/lib/solargraph/type_checker.rb +41 -14
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/_method.erb +10 -10
- data/lib/solargraph/views/_namespace.erb +3 -3
- data/lib/solargraph/views/document.erb +10 -10
- data/lib/solargraph/workspace/config.rb +7 -3
- data/lib/solargraph/workspace.rb +16 -6
- data/lib/solargraph/yard_map/mapper/to_constant.rb +5 -2
- data/lib/solargraph/yard_map/mapper/to_method.rb +55 -15
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +5 -2
- data/lib/solargraph/yard_map/mapper.rb +5 -3
- data/lib/solargraph/yard_map/to_method.rb +4 -2
- data/lib/solargraph/yardoc.rb +6 -9
- data/lib/solargraph.rb +20 -1
- data/rbs/fills/tuple.rbs +150 -0
- data/rbs_collection.yaml +19 -0
- data/solargraph.gemspec +6 -5
- metadata +56 -29
- data/lib/solargraph/cache.rb +0 -77
data/lib/solargraph/api_map.rb
CHANGED
|
@@ -12,6 +12,7 @@ module Solargraph
|
|
|
12
12
|
autoload :Cache, 'solargraph/api_map/cache'
|
|
13
13
|
autoload :SourceToYard, 'solargraph/api_map/source_to_yard'
|
|
14
14
|
autoload :Store, 'solargraph/api_map/store'
|
|
15
|
+
autoload :Index, 'solargraph/api_map/index'
|
|
15
16
|
|
|
16
17
|
# @return [Array<String>]
|
|
17
18
|
attr_reader :unresolved_requires
|
|
@@ -48,6 +49,15 @@ module Solargraph
|
|
|
48
49
|
equality_fields.hash
|
|
49
50
|
end
|
|
50
51
|
|
|
52
|
+
def to_s
|
|
53
|
+
self.class.to_s
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# avoid enormous dump
|
|
57
|
+
def inspect
|
|
58
|
+
to_s
|
|
59
|
+
end
|
|
60
|
+
|
|
51
61
|
# @param pins [Array<Pin::Base>]
|
|
52
62
|
# @return [self]
|
|
53
63
|
def index pins
|
|
@@ -56,7 +66,7 @@ module Solargraph
|
|
|
56
66
|
@source_map_hash = {}
|
|
57
67
|
implicit.clear
|
|
58
68
|
cache.clear
|
|
59
|
-
|
|
69
|
+
store.update @@core_map.pins, pins
|
|
60
70
|
self
|
|
61
71
|
end
|
|
62
72
|
|
|
@@ -75,29 +85,36 @@ module Solargraph
|
|
|
75
85
|
# @param bench [Bench]
|
|
76
86
|
# @return [self]
|
|
77
87
|
def catalog bench
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
pins = bench.source_maps.flat_map(&:pins).flatten
|
|
88
|
+
@source_map_hash = bench.source_map_hash
|
|
89
|
+
iced_pins = bench.icebox.flat_map(&:pins)
|
|
90
|
+
live_pins = bench.live_map&.pins || []
|
|
82
91
|
implicit.clear
|
|
83
92
|
source_map_hash.each_value do |map|
|
|
84
93
|
implicit.merge map.environ
|
|
85
94
|
end
|
|
86
95
|
unresolved_requires = (bench.external_requires + implicit.requires + bench.workspace.config.required).to_a.compact.uniq
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
96
|
+
recreate_docmap = @unresolved_requires != unresolved_requires ||
|
|
97
|
+
@doc_map&.uncached_yard_gemspecs&.any? ||
|
|
98
|
+
@doc_map&.uncached_rbs_collection_gemspecs&.any? ||
|
|
99
|
+
@doc_map&.rbs_collection_path != bench.workspace.rbs_collection_path
|
|
100
|
+
if recreate_docmap
|
|
101
|
+
@doc_map = DocMap.new(unresolved_requires, [], bench.workspace) # @todo Implement gem preferences
|
|
102
|
+
@unresolved_requires = @doc_map.unresolved_requires
|
|
91
103
|
end
|
|
92
|
-
@
|
|
93
|
-
@cache.clear if need_to_uncache
|
|
94
|
-
|
|
104
|
+
@cache.clear if store.update(@@core_map.pins, @doc_map.pins, implicit.pins, iced_pins, live_pins)
|
|
95
105
|
@missing_docs = [] # @todo Implement missing docs
|
|
96
106
|
self
|
|
97
107
|
end
|
|
98
108
|
|
|
109
|
+
# @todo need to model type def statement in chains as a symbol so
|
|
110
|
+
# that this overload of 'protected' will typecheck @sg-ignore
|
|
111
|
+
# @sg-ignore
|
|
99
112
|
protected def equality_fields
|
|
100
|
-
[self.class, @source_map_hash, implicit, @doc_map, @unresolved_requires
|
|
113
|
+
[self.class, @source_map_hash, implicit, @doc_map, @unresolved_requires]
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def doc_map
|
|
117
|
+
@doc_map ||= DocMap.new([], [])
|
|
101
118
|
end
|
|
102
119
|
|
|
103
120
|
# @return [::Array<Gem::Specification>]
|
|
@@ -105,6 +122,16 @@ module Solargraph
|
|
|
105
122
|
@doc_map&.uncached_gemspecs || []
|
|
106
123
|
end
|
|
107
124
|
|
|
125
|
+
# @return [::Array<Gem::Specification>]
|
|
126
|
+
def uncached_rbs_collection_gemspecs
|
|
127
|
+
@doc_map.uncached_rbs_collection_gemspecs
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# @return [::Array<Gem::Specification>]
|
|
131
|
+
def uncached_yard_gemspecs
|
|
132
|
+
@doc_map.uncached_yard_gemspecs
|
|
133
|
+
end
|
|
134
|
+
|
|
108
135
|
# @return [Array<Pin::Base>]
|
|
109
136
|
def core_pins
|
|
110
137
|
@@core_map.pins
|
|
@@ -159,6 +186,18 @@ module Solargraph
|
|
|
159
186
|
api_map
|
|
160
187
|
end
|
|
161
188
|
|
|
189
|
+
def cache_all!(out)
|
|
190
|
+
@doc_map.cache_all!(out)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def cache_gem(gemspec, rebuild: false, out: nil)
|
|
194
|
+
@doc_map.cache(gemspec, rebuild: rebuild, out: out)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
class << self
|
|
198
|
+
include Logging
|
|
199
|
+
end
|
|
200
|
+
|
|
162
201
|
# Create an ApiMap with a workspace in the specified directory and cache
|
|
163
202
|
# any missing gems.
|
|
164
203
|
#
|
|
@@ -169,21 +208,20 @@ module Solargraph
|
|
|
169
208
|
# @param directory [String]
|
|
170
209
|
# @param out [IO] The output stream for messages
|
|
171
210
|
# @return [ApiMap]
|
|
172
|
-
def self.load_with_cache directory, out
|
|
211
|
+
def self.load_with_cache directory, out
|
|
173
212
|
api_map = load(directory)
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
out.puts "Caching gem #{gemspec.name} #{gemspec.version}"
|
|
178
|
-
pins = GemPins.build(gemspec)
|
|
179
|
-
Solargraph::Cache.save('gems', "#{gemspec.name}-#{gemspec.version}.ser", pins)
|
|
213
|
+
if api_map.uncached_gemspecs.empty?
|
|
214
|
+
logger.info { "All gems cached for #{directory}" }
|
|
215
|
+
return api_map
|
|
180
216
|
end
|
|
217
|
+
|
|
218
|
+
api_map.cache_all!(out)
|
|
181
219
|
load(directory)
|
|
182
220
|
end
|
|
183
221
|
|
|
184
222
|
# @return [Array<Solargraph::Pin::Base>]
|
|
185
223
|
def pins
|
|
186
|
-
store.pins
|
|
224
|
+
store.pins.clone.freeze
|
|
187
225
|
end
|
|
188
226
|
|
|
189
227
|
# An array of pins based on Ruby keywords (`if`, `end`, etc.).
|
|
@@ -255,15 +293,19 @@ module Solargraph
|
|
|
255
293
|
# Should not be prefixed with '::'.
|
|
256
294
|
# @return [String, nil] fully qualified tag
|
|
257
295
|
def qualify tag, context_tag = ''
|
|
258
|
-
return tag if ['self', nil].include?(tag)
|
|
296
|
+
return tag if ['Boolean', 'self', nil].include?(tag)
|
|
259
297
|
|
|
260
|
-
context_type = ComplexType.
|
|
298
|
+
context_type = ComplexType.try_parse(context_tag).force_rooted
|
|
261
299
|
return unless context_type
|
|
262
300
|
|
|
263
301
|
type = ComplexType.try_parse(tag)
|
|
264
302
|
return unless type
|
|
303
|
+
return tag if type.literal?
|
|
304
|
+
|
|
305
|
+
context_type = ComplexType.try_parse(context_tag)
|
|
306
|
+
return unless context_type
|
|
265
307
|
|
|
266
|
-
fqns = qualify_namespace(type.rooted_namespace, context_type.
|
|
308
|
+
fqns = qualify_namespace(type.rooted_namespace, context_type.rooted_namespace)
|
|
267
309
|
return unless fqns
|
|
268
310
|
|
|
269
311
|
fqns + type.substring
|
|
@@ -310,6 +352,11 @@ module Solargraph
|
|
|
310
352
|
result
|
|
311
353
|
end
|
|
312
354
|
|
|
355
|
+
# @see Solargraph::Parser::FlowSensitiveTyping#visible_pins
|
|
356
|
+
def visible_pins(*args, **kwargs, &blk)
|
|
357
|
+
Solargraph::Parser::FlowSensitiveTyping.visible_pins(*args, **kwargs, &blk)
|
|
358
|
+
end
|
|
359
|
+
|
|
313
360
|
# Get an array of class variable pins for a namespace.
|
|
314
361
|
#
|
|
315
362
|
# @param namespace [String] A fully qualified namespace
|
|
@@ -341,8 +388,17 @@ module Solargraph
|
|
|
341
388
|
# @param deep [Boolean] True to include superclasses, mixins, etc.
|
|
342
389
|
# @return [Array<Solargraph::Pin::Method>]
|
|
343
390
|
def get_methods rooted_tag, scope: :instance, visibility: [:public], deep: true
|
|
391
|
+
if rooted_tag.start_with? 'Array('
|
|
392
|
+
# Array() are really tuples - use our fill, as the RBS repo
|
|
393
|
+
# does not give us definitions for it
|
|
394
|
+
rooted_tag = "Solargraph::Fills::Tuple(#{rooted_tag[6..-2]})"
|
|
395
|
+
end
|
|
396
|
+
rooted_type = ComplexType.try_parse(rooted_tag)
|
|
397
|
+
fqns = rooted_type.namespace
|
|
398
|
+
namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
|
|
344
399
|
cached = cache.get_methods(rooted_tag, scope, visibility, deep)
|
|
345
400
|
return cached.clone unless cached.nil?
|
|
401
|
+
# @type [Array<Solargraph::Pin::Method>]
|
|
346
402
|
result = []
|
|
347
403
|
skip = Set.new
|
|
348
404
|
if rooted_tag == ''
|
|
@@ -363,26 +419,47 @@ module Solargraph
|
|
|
363
419
|
init_pin = get_method_stack(rooted_tag, 'initialize').first
|
|
364
420
|
next pin unless init_pin
|
|
365
421
|
|
|
366
|
-
type = ComplexType
|
|
367
|
-
Pin::Method.new(
|
|
422
|
+
type = ComplexType::SELF
|
|
423
|
+
new_pin = Pin::Method.new(
|
|
368
424
|
name: 'new',
|
|
369
425
|
scope: :class,
|
|
370
426
|
location: init_pin.location,
|
|
371
|
-
parameters: init_pin.parameters,
|
|
372
|
-
signatures: init_pin.signatures.map { |sig| sig.proxy(type) },
|
|
373
427
|
return_type: type,
|
|
374
428
|
comments: init_pin.comments,
|
|
375
|
-
closure: init_pin.closure
|
|
376
|
-
|
|
377
|
-
|
|
429
|
+
closure: init_pin.closure,
|
|
430
|
+
source: init_pin.source,
|
|
431
|
+
type_location: init_pin.type_location,
|
|
432
|
+
)
|
|
433
|
+
new_pin.parameters = init_pin.parameters.map do |init_param|
|
|
434
|
+
param = init_param.clone
|
|
435
|
+
param.closure = new_pin
|
|
436
|
+
param.reset_generated!
|
|
437
|
+
param
|
|
438
|
+
end.freeze
|
|
439
|
+
new_pin.signatures = init_pin.signatures.map do |init_sig|
|
|
440
|
+
sig = init_sig.proxy(type)
|
|
441
|
+
sig.parameters = init_sig.parameters.map do |param|
|
|
442
|
+
param = param.clone
|
|
443
|
+
param.closure = new_pin
|
|
444
|
+
param.reset_generated!
|
|
445
|
+
param
|
|
446
|
+
end.freeze
|
|
447
|
+
sig.closure = new_pin
|
|
448
|
+
sig.reset_generated!
|
|
449
|
+
sig
|
|
450
|
+
end.freeze
|
|
451
|
+
new_pin
|
|
378
452
|
end
|
|
379
453
|
end
|
|
380
454
|
result.concat inner_get_methods('Kernel', :instance, [:public], deep, skip) if visibility.include?(:private)
|
|
381
455
|
result.concat inner_get_methods('Module', scope, visibility, deep, skip) if scope == :module
|
|
382
456
|
end
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
457
|
+
result = resolve_method_aliases(result, visibility)
|
|
458
|
+
if namespace_pin && rooted_tag != rooted_type.name
|
|
459
|
+
result = result.map { |method_pin| method_pin.resolve_generics(namespace_pin, rooted_type) }
|
|
460
|
+
end
|
|
461
|
+
cache.set_methods(rooted_tag, scope, visibility, deep, result)
|
|
462
|
+
result
|
|
386
463
|
end
|
|
387
464
|
|
|
388
465
|
# Get an array of method pins for a complex type.
|
|
@@ -410,7 +487,7 @@ module Solargraph
|
|
|
410
487
|
result = Set.new
|
|
411
488
|
complex_type.each do |type|
|
|
412
489
|
if type.duck_type?
|
|
413
|
-
result.add Pin::DuckMethod.new(name: type.to_s[1..-1])
|
|
490
|
+
result.add Pin::DuckMethod.new(name: type.to_s[1..-1], source: :api_map)
|
|
414
491
|
result.merge get_methods('Object')
|
|
415
492
|
else
|
|
416
493
|
unless type.nil? || type.name == 'void'
|
|
@@ -438,8 +515,13 @@ module Solargraph
|
|
|
438
515
|
# @param name [String] Method name to look up
|
|
439
516
|
# @param scope [Symbol] :instance or :class
|
|
440
517
|
# @return [Array<Solargraph::Pin::Method>]
|
|
441
|
-
def get_method_stack rooted_tag, name, scope: :instance
|
|
442
|
-
|
|
518
|
+
def get_method_stack rooted_tag, name, scope: :instance, visibility: [:private, :protected, :public], preserve_generics: false
|
|
519
|
+
rooted_type = ComplexType.parse(rooted_tag)
|
|
520
|
+
fqns = rooted_type.namespace
|
|
521
|
+
namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
|
|
522
|
+
methods = get_methods(rooted_tag, scope: scope, visibility: visibility).select { |p| p.name == name }
|
|
523
|
+
methods = erase_generics(namespace_pin, rooted_type, methods) unless preserve_generics
|
|
524
|
+
methods
|
|
443
525
|
end
|
|
444
526
|
|
|
445
527
|
# Get an array of all suggestions that match the specified path.
|
|
@@ -474,13 +556,8 @@ module Solargraph
|
|
|
474
556
|
.select { |path| path.downcase.include?(query.downcase) }
|
|
475
557
|
end
|
|
476
558
|
|
|
477
|
-
#
|
|
478
|
-
#
|
|
479
|
-
# @example
|
|
480
|
-
# api_map.document('String#split')
|
|
481
|
-
#
|
|
482
|
-
# @todo This method is likely superfluous. Calling get_path_pins directly
|
|
483
|
-
# should be sufficient.
|
|
559
|
+
# @deprecated This method is likely superfluous. Calling #get_path_pins
|
|
560
|
+
# directly should be sufficient.
|
|
484
561
|
#
|
|
485
562
|
# @param path [String] The path to find
|
|
486
563
|
# @return [Enumerable<Pin::Base>]
|
|
@@ -574,6 +651,19 @@ module Solargraph
|
|
|
574
651
|
store.get_includes(host_ns).map { |inc_tag| ComplexType.parse(inc_tag).name }.include?(module_ns)
|
|
575
652
|
end
|
|
576
653
|
|
|
654
|
+
# @param pins [Enumerable<Pin::Base>]
|
|
655
|
+
# @param visibility [Enumerable<Symbol>]
|
|
656
|
+
# @return [Array<Pin::Base>]
|
|
657
|
+
def resolve_method_aliases pins, visibility = [:public, :private, :protected]
|
|
658
|
+
with_resolved_aliases = pins.map do |pin|
|
|
659
|
+
resolved = resolve_method_alias(pin)
|
|
660
|
+
next nil if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
|
|
661
|
+
resolved
|
|
662
|
+
end.compact
|
|
663
|
+
logger.debug { "ApiMap#resolve_method_aliases(pins=#{pins.map(&:name)}, visibility=#{visibility}) => #{with_resolved_aliases.map(&:name)}" }
|
|
664
|
+
GemPins.combine_method_pins_by_path(with_resolved_aliases)
|
|
665
|
+
end
|
|
666
|
+
|
|
577
667
|
private
|
|
578
668
|
|
|
579
669
|
# A hash of source maps with filename keys.
|
|
@@ -601,6 +691,7 @@ module Solargraph
|
|
|
601
691
|
rooted_type = ComplexType.parse(rooted_tag).force_rooted
|
|
602
692
|
fqns = rooted_type.namespace
|
|
603
693
|
fqns_generic_params = rooted_type.all_params
|
|
694
|
+
namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
|
|
604
695
|
return [] if no_core && fqns =~ /^(Object|BasicObject|Class|Module)$/
|
|
605
696
|
reqstr = "#{fqns}|#{scope}|#{visibility.sort}|#{deep}"
|
|
606
697
|
return [] if skip.include?(reqstr)
|
|
@@ -615,43 +706,26 @@ module Solargraph
|
|
|
615
706
|
# Store#get_methods doesn't know about full tags, just
|
|
616
707
|
# namespaces; resolving the generics in the method pins is this
|
|
617
708
|
# class' responsibility
|
|
618
|
-
|
|
619
|
-
namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
|
|
620
|
-
methods = if namespace_pin && rooted_tag != fqns
|
|
621
|
-
methods = raw_methods.map do |method_pin|
|
|
622
|
-
method_pin.resolve_generics(namespace_pin, rooted_type)
|
|
623
|
-
end
|
|
624
|
-
else
|
|
625
|
-
raw_methods
|
|
626
|
-
end
|
|
709
|
+
methods = store.get_methods(fqns, scope: scope, visibility: visibility).sort{ |a, b| a.name <=> b.name }
|
|
627
710
|
result.concat methods
|
|
628
711
|
if deep
|
|
629
712
|
if scope == :instance
|
|
630
713
|
store.get_includes(fqns).reverse.each do |include_tag|
|
|
631
714
|
rooted_include_tag = qualify(include_tag, rooted_tag)
|
|
632
|
-
|
|
633
|
-
# relative to the generics passed to the include. e.g.,
|
|
634
|
-
# Foo<String> might include Enumerable<String>
|
|
635
|
-
#
|
|
636
|
-
# @todo perform the same translation in the other areas
|
|
637
|
-
# here after adding a spec and handling things correctly
|
|
638
|
-
# in ApiMap::Store and RbsMap::Conversions
|
|
639
|
-
resolved_include_type = ComplexType.parse(rooted_include_tag).force_rooted.resolve_generics(namespace_pin, rooted_type)
|
|
640
|
-
methods = inner_get_methods(resolved_include_type.tag, scope, visibility, deep, skip, true)
|
|
641
|
-
result.concat methods
|
|
715
|
+
result.concat inner_get_methods_from_reference(rooted_include_tag, namespace_pin, rooted_type, scope, visibility, deep, skip, true)
|
|
642
716
|
end
|
|
643
|
-
|
|
644
|
-
unless
|
|
645
|
-
result.concat
|
|
717
|
+
rooted_sc_tag = qualify_superclass(rooted_tag)
|
|
718
|
+
unless rooted_sc_tag.nil?
|
|
719
|
+
result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope, visibility, true, skip, no_core)
|
|
646
720
|
end
|
|
647
721
|
else
|
|
648
722
|
store.get_extends(fqns).reverse.each do |em|
|
|
649
723
|
fqem = qualify(em, fqns)
|
|
650
724
|
result.concat inner_get_methods(fqem, :instance, visibility, deep, skip, true) unless fqem.nil?
|
|
651
725
|
end
|
|
652
|
-
|
|
653
|
-
unless
|
|
654
|
-
result.concat
|
|
726
|
+
rooted_sc_tag = qualify_superclass(rooted_tag)
|
|
727
|
+
unless rooted_sc_tag.nil?
|
|
728
|
+
result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope, visibility, true, skip, true)
|
|
655
729
|
end
|
|
656
730
|
unless no_core || fqns.empty?
|
|
657
731
|
type = get_namespace_type(fqns)
|
|
@@ -667,6 +741,41 @@ module Solargraph
|
|
|
667
741
|
result
|
|
668
742
|
end
|
|
669
743
|
|
|
744
|
+
# @param fq_reference_tag [String] A fully qualified whose method should be pulled in
|
|
745
|
+
# @param namespace_pin [Pin::Base] Namespace pin for the rooted_type
|
|
746
|
+
# parameter - used to pull generics information
|
|
747
|
+
# @param type [ComplexType] The type which is having its
|
|
748
|
+
# methods supplemented from fq_reference_tag
|
|
749
|
+
# @param scope [Symbol] :class or :instance
|
|
750
|
+
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
|
751
|
+
# @param deep [Boolean]
|
|
752
|
+
# @param skip [Set<String>]
|
|
753
|
+
# @param no_core [Boolean] Skip core classes if true
|
|
754
|
+
# @return [Array<Pin::Base>]
|
|
755
|
+
def inner_get_methods_from_reference(fq_reference_tag, namespace_pin, type, scope, visibility, deep, skip, no_core)
|
|
756
|
+
# logger.debug { "ApiMap#add_methods_from_reference(type=#{type}) starting" }
|
|
757
|
+
|
|
758
|
+
# Ensure the types returned by the methods in the referenced
|
|
759
|
+
# type are relative to the generic values passed in the
|
|
760
|
+
# reference. e.g., Foo<String> might include Enumerable<String>
|
|
761
|
+
#
|
|
762
|
+
# @todo perform the same translation in the other areas
|
|
763
|
+
# here after adding a spec and handling things correctly
|
|
764
|
+
# in ApiMap::Store and RbsMap::Conversions for each
|
|
765
|
+
resolved_reference_type = ComplexType.parse(fq_reference_tag).force_rooted.resolve_generics(namespace_pin, type)
|
|
766
|
+
# @todo Can inner_get_methods be cached? Lots of lookups of base types going on.
|
|
767
|
+
methods = inner_get_methods(resolved_reference_type.tag, scope, visibility, deep, skip, no_core)
|
|
768
|
+
if namespace_pin && !resolved_reference_type.all_params.empty?
|
|
769
|
+
reference_pin = store.get_path_pins(resolved_reference_type.name).select { |p| p.is_a?(Pin::Namespace) }.first
|
|
770
|
+
# logger.debug { "ApiMap#add_methods_from_reference(type=#{type}) - resolving generics with #{reference_pin.generics}, #{resolved_reference_type.rooted_tags}" }
|
|
771
|
+
methods = methods.map do |method_pin|
|
|
772
|
+
method_pin.resolve_generics(reference_pin, resolved_reference_type)
|
|
773
|
+
end
|
|
774
|
+
end
|
|
775
|
+
# logger.debug { "ApiMap#add_methods_from_reference(type=#{type}) - resolved_reference_type: #{resolved_reference_type} for type=#{type}: #{methods.map(&:name)}" }
|
|
776
|
+
methods
|
|
777
|
+
end
|
|
778
|
+
|
|
670
779
|
# @param fqns [String]
|
|
671
780
|
# @param visibility [Array<Symbol>]
|
|
672
781
|
# @param skip [Set<String>]
|
|
@@ -702,15 +811,19 @@ module Solargraph
|
|
|
702
811
|
qualify namespace, context.split('::')[0..-2].join('::')
|
|
703
812
|
end
|
|
704
813
|
|
|
705
|
-
# @param
|
|
814
|
+
# @param fq_tag [String]
|
|
706
815
|
# @return [String, nil]
|
|
707
|
-
def qualify_superclass
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
816
|
+
def qualify_superclass fq_sub_tag
|
|
817
|
+
fq_sub_type = ComplexType.try_parse(fq_sub_tag)
|
|
818
|
+
fq_sub_ns = fq_sub_type.name
|
|
819
|
+
sup_tag = store.get_superclass(fq_sub_tag)
|
|
820
|
+
sup_type = ComplexType.try_parse(sup_tag)
|
|
821
|
+
sup_ns = sup_type.name
|
|
822
|
+
return nil if sup_tag.nil?
|
|
823
|
+
parts = fq_sub_ns.split('::')
|
|
711
824
|
last = parts.pop
|
|
712
|
-
parts.pop if last ==
|
|
713
|
-
qualify(
|
|
825
|
+
parts.pop if last == sup_ns
|
|
826
|
+
qualify(sup_tag, parts.join('::'))
|
|
714
827
|
end
|
|
715
828
|
|
|
716
829
|
# @param name [String] Namespace to fully qualify
|
|
@@ -768,8 +881,8 @@ module Solargraph
|
|
|
768
881
|
|
|
769
882
|
# Sort an array of pins to put nil or undefined variables last.
|
|
770
883
|
#
|
|
771
|
-
# @param pins [Enumerable<
|
|
772
|
-
# @return [Enumerable<
|
|
884
|
+
# @param pins [Enumerable<Pin::BaseVariable>]
|
|
885
|
+
# @return [Enumerable<Pin::BaseVariable>]
|
|
773
886
|
def prefer_non_nil_variables pins
|
|
774
887
|
result = []
|
|
775
888
|
nil_pins = []
|
|
@@ -783,37 +896,78 @@ module Solargraph
|
|
|
783
896
|
result + nil_pins
|
|
784
897
|
end
|
|
785
898
|
|
|
786
|
-
# @param pins [Enumerable<Pin::Base>]
|
|
787
|
-
# @param visibility [Enumerable<Symbol>]
|
|
788
|
-
# @return [Array<Pin::Base>]
|
|
789
|
-
def resolve_method_aliases pins, visibility = [:public, :private, :protected]
|
|
790
|
-
pins.map do |pin|
|
|
791
|
-
resolved = resolve_method_alias(pin)
|
|
792
|
-
next pin if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
|
|
793
|
-
resolved
|
|
794
|
-
end.compact
|
|
795
|
-
end
|
|
796
|
-
|
|
797
899
|
# @param pin [Pin::MethodAlias, Pin::Base]
|
|
798
900
|
# @return [Pin::Method]
|
|
799
901
|
def resolve_method_alias pin
|
|
800
902
|
return pin unless pin.is_a?(Pin::MethodAlias)
|
|
801
903
|
return nil if @method_alias_stack.include?(pin.path)
|
|
802
904
|
@method_alias_stack.push pin.path
|
|
803
|
-
origin = get_method_stack(pin.full_context.tag, pin.original, scope: pin.scope).first
|
|
905
|
+
origin = get_method_stack(pin.full_context.tag, pin.original, scope: pin.scope, preserve_generics: true).first
|
|
804
906
|
@method_alias_stack.pop
|
|
805
907
|
return nil if origin.nil?
|
|
806
908
|
args = {
|
|
807
909
|
location: pin.location,
|
|
910
|
+
type_location: origin.type_location,
|
|
808
911
|
closure: pin.closure,
|
|
809
912
|
name: pin.name,
|
|
810
913
|
comments: origin.comments,
|
|
811
914
|
scope: origin.scope,
|
|
915
|
+
# context: pin.context,
|
|
812
916
|
visibility: origin.visibility,
|
|
813
|
-
signatures: origin.signatures,
|
|
814
|
-
attribute: origin.attribute
|
|
917
|
+
signatures: origin.signatures.map(&:clone).freeze,
|
|
918
|
+
attribute: origin.attribute?,
|
|
919
|
+
generics: origin.generics.clone,
|
|
920
|
+
return_type: origin.return_type,
|
|
921
|
+
source: :resolve_method_alias
|
|
815
922
|
}
|
|
816
|
-
Pin::Method.new **args
|
|
923
|
+
out = Pin::Method.new **args
|
|
924
|
+
out.signatures.each do |sig|
|
|
925
|
+
sig.parameters = sig.parameters.map(&:clone).freeze
|
|
926
|
+
sig.source = :resolve_method_alias
|
|
927
|
+
sig.parameters.each do |param|
|
|
928
|
+
param.closure = out
|
|
929
|
+
param.source = :resolve_method_alias
|
|
930
|
+
param.reset_generated!
|
|
931
|
+
end
|
|
932
|
+
sig.closure = out
|
|
933
|
+
sig.reset_generated!
|
|
934
|
+
end
|
|
935
|
+
logger.debug { "ApiMap#resolve_method_alias(pin=#{pin}) - returning #{out} from #{origin}" }
|
|
936
|
+
out
|
|
937
|
+
end
|
|
938
|
+
|
|
939
|
+
include Logging
|
|
940
|
+
|
|
941
|
+
private
|
|
942
|
+
|
|
943
|
+
# @param namespace_pin [Pin::Namespace]
|
|
944
|
+
# @param rooted_type [ComplexType]
|
|
945
|
+
# @param pins [Enumerable<Pin::Base>]
|
|
946
|
+
# @return [Array<Pin::Base>]
|
|
947
|
+
def erase_generics(namespace_pin, rooted_type, pins)
|
|
948
|
+
return pins unless should_erase_generics_when_done?(namespace_pin, rooted_type)
|
|
949
|
+
|
|
950
|
+
logger.debug("Erasing generics on namespace_pin=#{namespace_pin} / rooted_type=#{rooted_type}")
|
|
951
|
+
pins.map do |method_pin|
|
|
952
|
+
method_pin.erase_generics(namespace_pin.generics)
|
|
953
|
+
end
|
|
954
|
+
end
|
|
955
|
+
|
|
956
|
+
# @param namespace_pin [Pin::Namespace]
|
|
957
|
+
# @param rooted_type [ComplexType]
|
|
958
|
+
def should_erase_generics_when_done?(namespace_pin, rooted_type)
|
|
959
|
+
has_generics?(namespace_pin) && !can_resolve_generics?(namespace_pin, rooted_type)
|
|
960
|
+
end
|
|
961
|
+
|
|
962
|
+
# @param namespace_pin [Pin::Namespace]
|
|
963
|
+
def has_generics?(namespace_pin)
|
|
964
|
+
namespace_pin && !namespace_pin.generics.empty?
|
|
965
|
+
end
|
|
966
|
+
|
|
967
|
+
# @param namespace_pin [Pin::Namespace]
|
|
968
|
+
# @param rooted_type [ComplexType]
|
|
969
|
+
def can_resolve_generics?(namespace_pin, rooted_type)
|
|
970
|
+
has_generics?(namespace_pin) && !rooted_type.all_params.empty?
|
|
817
971
|
end
|
|
818
972
|
end
|
|
819
973
|
end
|
data/lib/solargraph/bench.rb
CHANGED
|
@@ -11,18 +11,34 @@ module Solargraph
|
|
|
11
11
|
# @return [Workspace]
|
|
12
12
|
attr_reader :workspace
|
|
13
13
|
|
|
14
|
+
# @return [SourceMap]
|
|
15
|
+
attr_reader :live_map
|
|
16
|
+
|
|
14
17
|
# @return [Set<String>]
|
|
15
18
|
attr_reader :external_requires
|
|
16
19
|
|
|
17
20
|
# @param source_maps [Array<SourceMap>, Set<SourceMap>]
|
|
18
21
|
# @param workspace [Workspace]
|
|
22
|
+
# @param live_map [SourceMap, nil]
|
|
19
23
|
# @param external_requires [Array<String>, Set<String>]
|
|
20
|
-
def initialize source_maps: [], workspace: Workspace.new, external_requires: []
|
|
24
|
+
def initialize source_maps: [], workspace: Workspace.new, live_map: nil, external_requires: []
|
|
21
25
|
@source_maps = source_maps.to_set
|
|
22
26
|
@workspace = workspace
|
|
27
|
+
@live_map = live_map
|
|
23
28
|
@external_requires = external_requires.reject { |path| workspace.would_require?(path) }
|
|
24
29
|
.compact
|
|
25
30
|
.to_set
|
|
26
31
|
end
|
|
32
|
+
|
|
33
|
+
# @return [Hash{String => SourceMap}]
|
|
34
|
+
def source_map_hash
|
|
35
|
+
# @todo Work around #to_h bug in current Ruby head (3.5) with #map#to_h
|
|
36
|
+
@source_map_hash ||= source_maps.map { |s| [s.filename, s] }
|
|
37
|
+
.to_h
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def icebox
|
|
41
|
+
@icebox ||= (source_maps - [live_map])
|
|
42
|
+
end
|
|
27
43
|
end
|
|
28
44
|
end
|
|
@@ -88,6 +88,7 @@ module Solargraph
|
|
|
88
88
|
# @return [Symbol, nil]
|
|
89
89
|
attr_reader :parameters_type
|
|
90
90
|
|
|
91
|
+
# @type [Hash{String => Symbol}]
|
|
91
92
|
PARAMETERS_TYPE_BY_STARTING_TAG = {
|
|
92
93
|
'{' => :hash,
|
|
93
94
|
'(' => :fixed,
|
|
@@ -129,6 +130,13 @@ module Solargraph
|
|
|
129
130
|
end.call
|
|
130
131
|
end
|
|
131
132
|
|
|
133
|
+
def namespace_type
|
|
134
|
+
return ComplexType.parse('::Object') if duck_type?
|
|
135
|
+
return ComplexType.parse('::NilClass') if nil_type?
|
|
136
|
+
return subtypes.first if (name == 'Class' || name == 'Module') && !subtypes.empty?
|
|
137
|
+
self
|
|
138
|
+
end
|
|
139
|
+
|
|
132
140
|
# @return [String]
|
|
133
141
|
def rooted_namespace
|
|
134
142
|
return namespace unless rooted? && can_root_name?(namespace)
|
|
@@ -164,7 +172,11 @@ module Solargraph
|
|
|
164
172
|
elsif fixed_parameters?
|
|
165
173
|
"(#{subtypes_str})"
|
|
166
174
|
else
|
|
167
|
-
|
|
175
|
+
if name == 'Hash'
|
|
176
|
+
"<#{key_types_str}, #{subtypes_str}>"
|
|
177
|
+
else
|
|
178
|
+
"<#{key_types_str}#{subtypes_str}>"
|
|
179
|
+
end
|
|
168
180
|
end
|
|
169
181
|
end
|
|
170
182
|
|