solargraph 0.54.4 → 0.56.2
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 +62 -0
- data/README.md +13 -3
- data/lib/solargraph/api_map/index.rb +24 -16
- data/lib/solargraph/api_map/store.rb +48 -23
- data/lib/solargraph/api_map.rb +175 -77
- data/lib/solargraph/bench.rb +17 -1
- data/lib/solargraph/complex_type/type_methods.rb +6 -1
- data/lib/solargraph/complex_type/unique_type.rb +98 -9
- data/lib/solargraph/complex_type.rb +35 -6
- data/lib/solargraph/convention/base.rb +3 -3
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +60 -0
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +89 -0
- data/lib/solargraph/convention/data_definition.rb +104 -0
- data/lib/solargraph/convention/gemspec.rb +2 -1
- 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 +141 -0
- data/lib/solargraph/convention.rb +5 -3
- data/lib/solargraph/doc_map.rb +277 -57
- data/lib/solargraph/gem_pins.rb +53 -37
- data/lib/solargraph/language_server/host/message_worker.rb +10 -7
- data/lib/solargraph/language_server/host.rb +12 -2
- 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/library.rb +45 -17
- data/lib/solargraph/location.rb +21 -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 +14 -0
- data/lib/solargraph/parser/node_processor/base.rb +9 -4
- data/lib/solargraph/parser/node_processor.rb +21 -8
- data/lib/solargraph/parser/parser_gem/class_methods.rb +16 -14
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +10 -10
- data/lib/solargraph/parser/parser_gem/node_methods.rb +4 -2
- 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 +2 -1
- 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 +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +4 -1
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +42 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +3 -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 +3 -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 +14 -0
- data/lib/solargraph/parser/region.rb +1 -1
- data/lib/solargraph/parser.rb +1 -0
- data/lib/solargraph/pin/base.rb +316 -28
- data/lib/solargraph/pin/base_variable.rb +16 -9
- data/lib/solargraph/pin/block.rb +2 -0
- data/lib/solargraph/pin/breakable.rb +9 -0
- data/lib/solargraph/pin/callable.rb +74 -3
- 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 +169 -43
- data/lib/solargraph/pin/namespace.rb +17 -9
- data/lib/solargraph/pin/parameter.rb +60 -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 +9 -0
- data/lib/solargraph/range.rb +9 -0
- data/lib/solargraph/rbs_map/conversions.rb +221 -67
- 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 -17
- data/lib/solargraph/shell.rb +17 -18
- data/lib/solargraph/source/chain/array.rb +11 -7
- 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 +53 -23
- data/lib/solargraph/source/chain/constant.rb +1 -1
- data/lib/solargraph/source/chain/hash.rb +4 -3
- data/lib/solargraph/source/chain/head.rb +1 -1
- data/lib/solargraph/source/chain/if.rb +1 -1
- data/lib/solargraph/source/chain/link.rb +2 -0
- data/lib/solargraph/source/chain/literal.rb +22 -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 +78 -48
- data/lib/solargraph/source/source_chainer.rb +2 -2
- data/lib/solargraph/source_map/clip.rb +3 -1
- 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 +35 -8
- 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 +1 -1
- data/lib/solargraph/workspace.rb +23 -5
- data/lib/solargraph/yard_map/helpers.rb +29 -1
- data/lib/solargraph/yard_map/mapper/to_constant.rb +7 -5
- data/lib/solargraph/yard_map/mapper/to_method.rb +53 -18
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +9 -7
- data/lib/solargraph/yard_map/mapper.rb +4 -3
- data/lib/solargraph/yard_map/to_method.rb +4 -2
- data/lib/solargraph/yardoc.rb +7 -8
- data/lib/solargraph.rb +32 -1
- data/rbs/fills/tuple.rbs +150 -0
- data/rbs_collection.yaml +19 -0
- data/solargraph.gemspec +2 -1
- metadata +37 -9
- data/lib/solargraph/cache.rb +0 -77
data/lib/solargraph/api_map.rb
CHANGED
@@ -66,7 +66,7 @@ module Solargraph
|
|
66
66
|
@source_map_hash = {}
|
67
67
|
implicit.clear
|
68
68
|
cache.clear
|
69
|
-
store.update
|
69
|
+
store.update @@core_map.pins, pins
|
70
70
|
self
|
71
71
|
end
|
72
72
|
|
@@ -85,24 +85,23 @@ module Solargraph
|
|
85
85
|
# @param bench [Bench]
|
86
86
|
# @return [self]
|
87
87
|
def catalog bench
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
@source_map_hash = bench.source_maps.map { |s| [s.filename, s] }.to_h
|
92
|
-
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 || []
|
93
91
|
implicit.clear
|
94
92
|
source_map_hash.each_value do |map|
|
95
93
|
implicit.merge map.environ
|
96
94
|
end
|
97
95
|
unresolved_requires = (bench.external_requires + implicit.requires + bench.workspace.config.required).to_a.compact.uniq
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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
|
102
103
|
end
|
103
|
-
store.update
|
104
|
-
@cache.clear if need_to_uncache
|
105
|
-
|
104
|
+
@cache.clear if store.update(@@core_map.pins, @doc_map.pins, implicit.pins, iced_pins, live_pins)
|
106
105
|
@missing_docs = [] # @todo Implement missing docs
|
107
106
|
self
|
108
107
|
end
|
@@ -111,7 +110,11 @@ module Solargraph
|
|
111
110
|
# that this overload of 'protected' will typecheck @sg-ignore
|
112
111
|
# @sg-ignore
|
113
112
|
protected def equality_fields
|
114
|
-
[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([], [])
|
115
118
|
end
|
116
119
|
|
117
120
|
# @return [::Array<Gem::Specification>]
|
@@ -119,6 +122,16 @@ module Solargraph
|
|
119
122
|
@doc_map&.uncached_gemspecs || []
|
120
123
|
end
|
121
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
|
+
|
122
135
|
# @return [Array<Pin::Base>]
|
123
136
|
def core_pins
|
124
137
|
@@core_map.pins
|
@@ -173,6 +186,18 @@ module Solargraph
|
|
173
186
|
api_map
|
174
187
|
end
|
175
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
|
+
|
176
201
|
# Create an ApiMap with a workspace in the specified directory and cache
|
177
202
|
# any missing gems.
|
178
203
|
#
|
@@ -183,15 +208,14 @@ module Solargraph
|
|
183
208
|
# @param directory [String]
|
184
209
|
# @param out [IO] The output stream for messages
|
185
210
|
# @return [ApiMap]
|
186
|
-
def self.load_with_cache directory, out
|
211
|
+
def self.load_with_cache directory, out
|
187
212
|
api_map = load(directory)
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
out.puts "Caching gem #{gemspec.name} #{gemspec.version}"
|
192
|
-
pins = GemPins.build(gemspec)
|
193
|
-
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
|
194
216
|
end
|
217
|
+
|
218
|
+
api_map.cache_all!(out)
|
195
219
|
load(directory)
|
196
220
|
end
|
197
221
|
|
@@ -269,15 +293,19 @@ module Solargraph
|
|
269
293
|
# Should not be prefixed with '::'.
|
270
294
|
# @return [String, nil] fully qualified tag
|
271
295
|
def qualify tag, context_tag = ''
|
272
|
-
return tag if ['self', nil].include?(tag)
|
296
|
+
return tag if ['Boolean', 'self', nil].include?(tag)
|
273
297
|
|
274
|
-
context_type = ComplexType.
|
298
|
+
context_type = ComplexType.try_parse(context_tag).force_rooted
|
275
299
|
return unless context_type
|
276
300
|
|
277
301
|
type = ComplexType.try_parse(tag)
|
278
302
|
return unless type
|
303
|
+
return tag if type.literal?
|
279
304
|
|
280
|
-
|
305
|
+
context_type = ComplexType.try_parse(context_tag)
|
306
|
+
return unless context_type
|
307
|
+
|
308
|
+
fqns = qualify_namespace(type.rooted_namespace, context_type.rooted_namespace)
|
281
309
|
return unless fqns
|
282
310
|
|
283
311
|
fqns + type.substring
|
@@ -324,6 +352,11 @@ module Solargraph
|
|
324
352
|
result
|
325
353
|
end
|
326
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
|
+
|
327
360
|
# Get an array of class variable pins for a namespace.
|
328
361
|
#
|
329
362
|
# @param namespace [String] A fully qualified namespace
|
@@ -355,6 +388,11 @@ module Solargraph
|
|
355
388
|
# @param deep [Boolean] True to include superclasses, mixins, etc.
|
356
389
|
# @return [Array<Solargraph::Pin::Method>]
|
357
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
|
358
396
|
rooted_type = ComplexType.try_parse(rooted_tag)
|
359
397
|
fqns = rooted_type.namespace
|
360
398
|
namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
|
@@ -381,18 +419,36 @@ module Solargraph
|
|
381
419
|
init_pin = get_method_stack(rooted_tag, 'initialize').first
|
382
420
|
next pin unless init_pin
|
383
421
|
|
384
|
-
type = ComplexType
|
385
|
-
Pin::Method.new(
|
422
|
+
type = ComplexType::SELF
|
423
|
+
new_pin = Pin::Method.new(
|
386
424
|
name: 'new',
|
387
425
|
scope: :class,
|
388
426
|
location: init_pin.location,
|
389
|
-
parameters: init_pin.parameters,
|
390
|
-
signatures: init_pin.signatures.map { |sig| sig.proxy(type) },
|
391
427
|
return_type: type,
|
392
428
|
comments: init_pin.comments,
|
393
|
-
closure: init_pin.closure
|
394
|
-
|
395
|
-
|
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
|
396
452
|
end
|
397
453
|
end
|
398
454
|
result.concat inner_get_methods('Kernel', :instance, [:public], deep, skip) if visibility.include?(:private)
|
@@ -431,7 +487,7 @@ module Solargraph
|
|
431
487
|
result = Set.new
|
432
488
|
complex_type.each do |type|
|
433
489
|
if type.duck_type?
|
434
|
-
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)
|
435
491
|
result.merge get_methods('Object')
|
436
492
|
else
|
437
493
|
unless type.nil? || type.name == 'void'
|
@@ -500,13 +556,8 @@ module Solargraph
|
|
500
556
|
.select { |path| path.downcase.include?(query.downcase) }
|
501
557
|
end
|
502
558
|
|
503
|
-
#
|
504
|
-
#
|
505
|
-
# @example
|
506
|
-
# api_map.document('String#split')
|
507
|
-
#
|
508
|
-
# @todo This method is likely superfluous. Calling get_path_pins directly
|
509
|
-
# should be sufficient.
|
559
|
+
# @deprecated This method is likely superfluous. Calling #get_path_pins
|
560
|
+
# directly should be sufficient.
|
510
561
|
#
|
511
562
|
# @param path [String] The path to find
|
512
563
|
# @return [Enumerable<Pin::Base>]
|
@@ -600,6 +651,19 @@ module Solargraph
|
|
600
651
|
store.get_includes(host_ns).map { |inc_tag| ComplexType.parse(inc_tag).name }.include?(module_ns)
|
601
652
|
end
|
602
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
|
+
|
603
667
|
private
|
604
668
|
|
605
669
|
# A hash of source maps with filename keys.
|
@@ -648,29 +712,20 @@ module Solargraph
|
|
648
712
|
if scope == :instance
|
649
713
|
store.get_includes(fqns).reverse.each do |include_tag|
|
650
714
|
rooted_include_tag = qualify(include_tag, rooted_tag)
|
651
|
-
|
652
|
-
# relative to the generics passed to the include. e.g.,
|
653
|
-
# Foo<String> might include Enumerable<String>
|
654
|
-
#
|
655
|
-
# @todo perform the same translation in the other areas
|
656
|
-
# here after adding a spec and handling things correctly
|
657
|
-
# in ApiMap::Store and RbsMap::Conversions
|
658
|
-
resolved_include_type = ComplexType.parse(rooted_include_tag).force_rooted.resolve_generics(namespace_pin, rooted_type)
|
659
|
-
methods = inner_get_methods(resolved_include_type.tag, scope, visibility, deep, skip, true)
|
660
|
-
result.concat methods
|
715
|
+
result.concat inner_get_methods_from_reference(rooted_include_tag, namespace_pin, rooted_type, scope, visibility, deep, skip, true)
|
661
716
|
end
|
662
|
-
|
663
|
-
unless
|
664
|
-
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)
|
665
720
|
end
|
666
721
|
else
|
667
722
|
store.get_extends(fqns).reverse.each do |em|
|
668
723
|
fqem = qualify(em, fqns)
|
669
724
|
result.concat inner_get_methods(fqem, :instance, visibility, deep, skip, true) unless fqem.nil?
|
670
725
|
end
|
671
|
-
|
672
|
-
unless
|
673
|
-
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)
|
674
729
|
end
|
675
730
|
unless no_core || fqns.empty?
|
676
731
|
type = get_namespace_type(fqns)
|
@@ -686,6 +741,41 @@ module Solargraph
|
|
686
741
|
result
|
687
742
|
end
|
688
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
|
+
|
689
779
|
# @param fqns [String]
|
690
780
|
# @param visibility [Array<Symbol>]
|
691
781
|
# @param skip [Set<String>]
|
@@ -721,15 +811,19 @@ module Solargraph
|
|
721
811
|
qualify namespace, context.split('::')[0..-2].join('::')
|
722
812
|
end
|
723
813
|
|
724
|
-
# @param
|
814
|
+
# @param fq_tag [String]
|
725
815
|
# @return [String, nil]
|
726
|
-
def qualify_superclass
|
727
|
-
|
728
|
-
|
729
|
-
|
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('::')
|
730
824
|
last = parts.pop
|
731
|
-
parts.pop if last ==
|
732
|
-
qualify(
|
825
|
+
parts.pop if last == sup_ns
|
826
|
+
qualify(sup_tag, parts.join('::'))
|
733
827
|
end
|
734
828
|
|
735
829
|
# @param name [String] Namespace to fully qualify
|
@@ -802,40 +896,44 @@ module Solargraph
|
|
802
896
|
result + nil_pins
|
803
897
|
end
|
804
898
|
|
805
|
-
# @param pins [Enumerable<Pin::Base>]
|
806
|
-
# @param visibility [Enumerable<Symbol>]
|
807
|
-
# @return [Array<Pin::Base>]
|
808
|
-
def resolve_method_aliases pins, visibility = [:public, :private, :protected]
|
809
|
-
pins.map do |pin|
|
810
|
-
resolved = resolve_method_alias(pin)
|
811
|
-
next pin if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
|
812
|
-
resolved
|
813
|
-
end.compact
|
814
|
-
end
|
815
|
-
|
816
899
|
# @param pin [Pin::MethodAlias, Pin::Base]
|
817
900
|
# @return [Pin::Method]
|
818
901
|
def resolve_method_alias pin
|
819
902
|
return pin unless pin.is_a?(Pin::MethodAlias)
|
820
903
|
return nil if @method_alias_stack.include?(pin.path)
|
821
904
|
@method_alias_stack.push pin.path
|
822
|
-
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
|
823
906
|
@method_alias_stack.pop
|
824
907
|
return nil if origin.nil?
|
825
908
|
args = {
|
826
909
|
location: pin.location,
|
910
|
+
type_location: origin.type_location,
|
827
911
|
closure: pin.closure,
|
828
912
|
name: pin.name,
|
829
913
|
comments: origin.comments,
|
830
914
|
scope: origin.scope,
|
831
915
|
# context: pin.context,
|
832
916
|
visibility: origin.visibility,
|
833
|
-
signatures: origin.signatures,
|
917
|
+
signatures: origin.signatures.map(&:clone).freeze,
|
834
918
|
attribute: origin.attribute?,
|
835
|
-
generics: origin.generics,
|
919
|
+
generics: origin.generics.clone,
|
836
920
|
return_type: origin.return_type,
|
921
|
+
source: :resolve_method_alias
|
837
922
|
}
|
838
|
-
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
|
839
937
|
end
|
840
938
|
|
841
939
|
include Logging
|
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,
|
@@ -171,7 +172,11 @@ module Solargraph
|
|
171
172
|
elsif fixed_parameters?
|
172
173
|
"(#{subtypes_str})"
|
173
174
|
else
|
174
|
-
|
175
|
+
if name == 'Hash'
|
176
|
+
"<#{key_types_str}, #{subtypes_str}>"
|
177
|
+
else
|
178
|
+
"<#{key_types_str}#{subtypes_str}>"
|
179
|
+
end
|
175
180
|
end
|
176
181
|
end
|
177
182
|
|
@@ -27,7 +27,7 @@ module Solargraph
|
|
27
27
|
# @return [UniqueType]
|
28
28
|
def self.parse name, substring = '', make_rooted: nil
|
29
29
|
if name.start_with?(':::')
|
30
|
-
raise "Illegal prefix: #{name}"
|
30
|
+
raise ComplexTypeError, "Illegal prefix: #{name}"
|
31
31
|
end
|
32
32
|
if name.start_with?('::')
|
33
33
|
name = name[2..-1]
|
@@ -48,13 +48,20 @@ module Solargraph
|
|
48
48
|
subs = ComplexType.parse(substring[1..-2], partial: true)
|
49
49
|
parameters_type = PARAMETERS_TYPE_BY_STARTING_TAG.fetch(substring[0])
|
50
50
|
if parameters_type == :hash
|
51
|
-
raise ComplexTypeError, "Bad hash type" unless !subs.is_a?(ComplexType) and subs.length == 2 and !subs[0].is_a?(UniqueType) and !subs[1].is_a?(UniqueType)
|
51
|
+
raise ComplexTypeError, "Bad hash type: name=#{name}, substring=#{substring}" unless !subs.is_a?(ComplexType) and subs.length == 2 and !subs[0].is_a?(UniqueType) and !subs[1].is_a?(UniqueType)
|
52
52
|
# @todo should be able to resolve map; both types have it
|
53
53
|
# with same return type
|
54
54
|
# @sg-ignore
|
55
55
|
key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
|
56
56
|
# @sg-ignore
|
57
57
|
subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
|
58
|
+
elsif parameters_type == :list && name == 'Hash'
|
59
|
+
# Treat Hash<A, B> as Hash{A => B}
|
60
|
+
if subs.length != 2
|
61
|
+
raise ComplexTypeError, "Bad hash type: name=#{name}, substring=#{substring} - must have exactly two parameters"
|
62
|
+
end
|
63
|
+
key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
|
64
|
+
subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
|
58
65
|
else
|
59
66
|
subtypes.concat subs
|
60
67
|
end
|
@@ -73,19 +80,63 @@ module Solargraph
|
|
73
80
|
end
|
74
81
|
raise "Please remove leading :: and set rooted instead - #{name.inspect}" if name.start_with?('::')
|
75
82
|
@name = name
|
76
|
-
@
|
77
|
-
|
83
|
+
@parameters_type = parameters_type
|
84
|
+
if implicit_union?
|
85
|
+
@key_types = key_types.uniq
|
86
|
+
@subtypes = subtypes.uniq
|
87
|
+
else
|
88
|
+
@key_types = key_types
|
89
|
+
@subtypes = subtypes
|
90
|
+
end
|
78
91
|
@rooted = rooted
|
79
92
|
@all_params = []
|
80
|
-
@all_params.concat key_types
|
81
|
-
@all_params.concat subtypes
|
82
|
-
|
93
|
+
@all_params.concat @key_types
|
94
|
+
@all_params.concat @subtypes
|
95
|
+
end
|
96
|
+
|
97
|
+
def implicit_union?
|
98
|
+
# @todo use api_map to establish number of generics in type;
|
99
|
+
# if only one is allowed but multiple are passed in, treat
|
100
|
+
# those as implicit unions
|
101
|
+
['Hash', 'Array', 'Set', '_ToAry', 'Enumerable', '_Each'].include?(name) && parameters_type != :fixed
|
83
102
|
end
|
84
103
|
|
85
104
|
def to_s
|
86
105
|
tag
|
87
106
|
end
|
88
107
|
|
108
|
+
def simplify_literals
|
109
|
+
transform do |t|
|
110
|
+
next t unless t.literal?
|
111
|
+
t.recreate(new_name: t.non_literal_name)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def literal?
|
116
|
+
non_literal_name != name
|
117
|
+
end
|
118
|
+
|
119
|
+
def non_literal_name
|
120
|
+
@non_literal_name ||= determine_non_literal_name
|
121
|
+
end
|
122
|
+
|
123
|
+
def determine_non_literal_name
|
124
|
+
# https://github.com/ruby/rbs/blob/master/docs/syntax.md
|
125
|
+
#
|
126
|
+
# _literal_ ::= _string-literal_
|
127
|
+
# | _symbol-literal_
|
128
|
+
# | _integer-literal_
|
129
|
+
# | `true`
|
130
|
+
# | `false`
|
131
|
+
return name if name.empty?
|
132
|
+
return 'NilClass' if name == 'nil'
|
133
|
+
return 'Boolean' if ['true', 'false'].include?(name)
|
134
|
+
return 'Symbol' if name[0] == ':'
|
135
|
+
return 'String' if ['"', "'"].include?(name[0])
|
136
|
+
return 'Integer' if name.match?(/^-?\d+$/)
|
137
|
+
name
|
138
|
+
end
|
139
|
+
|
89
140
|
def eql?(other)
|
90
141
|
self.class == other.class &&
|
91
142
|
@name == other.name &&
|
@@ -113,6 +164,8 @@ module Solargraph
|
|
113
164
|
def rbs_name
|
114
165
|
if name == 'undefined'
|
115
166
|
'untyped'
|
167
|
+
elsif literal?
|
168
|
+
name
|
116
169
|
else
|
117
170
|
rooted_name
|
118
171
|
end
|
@@ -183,6 +236,23 @@ module Solargraph
|
|
183
236
|
name == GENERIC_TAG_NAME || all_params.any?(&:generic?)
|
184
237
|
end
|
185
238
|
|
239
|
+
# @param api_map [ApiMap] The ApiMap that performs qualification
|
240
|
+
# @param atype [ComplexType] type which may be assigned to this type
|
241
|
+
def can_assign?(api_map, atype)
|
242
|
+
logger.debug { "UniqueType#can_assign?(self=#{rooted_tags.inspect}, atype=#{atype.rooted_tags.inspect})" }
|
243
|
+
downcasted_atype = atype.downcast_to_literal_if_possible
|
244
|
+
out = downcasted_atype.all? do |autype|
|
245
|
+
autype.name == name || api_map.super_and_sub?(name, autype.name)
|
246
|
+
end
|
247
|
+
logger.debug { "UniqueType#can_assign?(self=#{rooted_tags.inspect}, atype=#{atype.rooted_tags.inspect}) => #{out}" }
|
248
|
+
out
|
249
|
+
end
|
250
|
+
|
251
|
+
# @return [UniqueType]
|
252
|
+
def downcast_to_literal_if_possible
|
253
|
+
SINGLE_SUBTYPE.fetch(rooted_tag, self)
|
254
|
+
end
|
255
|
+
|
186
256
|
# @param generics_to_resolve [Enumerable<String>]
|
187
257
|
# @param context_type [UniqueType, nil]
|
188
258
|
# @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
|
@@ -243,7 +313,8 @@ module Solargraph
|
|
243
313
|
|
244
314
|
transform(name) do |t|
|
245
315
|
if t.name == GENERIC_TAG_NAME
|
246
|
-
|
316
|
+
generic_name = t.subtypes.first&.name
|
317
|
+
idx = definitions.generics.index(generic_name)
|
247
318
|
next t if idx.nil?
|
248
319
|
if context_type.parameters_type == :hash
|
249
320
|
if idx == 0
|
@@ -253,8 +324,14 @@ module Solargraph
|
|
253
324
|
else
|
254
325
|
next ComplexType::UNDEFINED
|
255
326
|
end
|
327
|
+
elsif context_type.all?(&:implicit_union?)
|
328
|
+
if idx == 0 && !context_type.all_params.empty?
|
329
|
+
ComplexType.new(context_type.all_params)
|
330
|
+
else
|
331
|
+
ComplexType::UNDEFINED
|
332
|
+
end
|
256
333
|
else
|
257
|
-
context_type.all_params[idx] || ComplexType::UNDEFINED
|
334
|
+
context_type.all_params[idx] || definitions.generic_defaults[generic_name] || ComplexType::UNDEFINED
|
258
335
|
end
|
259
336
|
else
|
260
337
|
t
|
@@ -381,6 +458,18 @@ module Solargraph
|
|
381
458
|
|
382
459
|
UNDEFINED = UniqueType.new('undefined', rooted: false)
|
383
460
|
BOOLEAN = UniqueType.new('Boolean', rooted: true)
|
461
|
+
TRUE = UniqueType.new('true', rooted: true)
|
462
|
+
FALSE = UniqueType.new('false', rooted: true)
|
463
|
+
NIL = UniqueType.new('nil', rooted: true)
|
464
|
+
# @type [Hash{String => UniqueType}]
|
465
|
+
SINGLE_SUBTYPE = {
|
466
|
+
'::TrueClass' => UniqueType::TRUE,
|
467
|
+
'::FalseClass' => UniqueType::FALSE,
|
468
|
+
'::NilClass' => UniqueType::NIL
|
469
|
+
}.freeze
|
470
|
+
|
471
|
+
|
472
|
+
include Logging
|
384
473
|
end
|
385
474
|
end
|
386
475
|
end
|