solargraph 0.60.4 → 0.62.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/linting.yml +24 -2
- data/.github/workflows/plugins.yml +19 -1
- data/.github/workflows/rspec.yml +17 -2
- data/.github/workflows/typecheck.yml +6 -0
- data/CHANGELOG.md +54 -0
- data/Gemfile +0 -3
- data/lib/solargraph/api_map/index.rb +28 -4
- data/lib/solargraph/api_map/store.rb +19 -0
- data/lib/solargraph/api_map.rb +91 -80
- data/lib/solargraph/cache_dir.rb +58 -0
- data/lib/solargraph/collection/base.rb +50 -0
- data/lib/solargraph/collection/core.rb +17 -0
- data/lib/solargraph/collection/gem.rb +59 -0
- data/lib/solargraph/collection/stdlib.rb +25 -0
- data/lib/solargraph/collection.rb +30 -0
- data/lib/solargraph/complex_type/unique_type.rb +13 -0
- data/lib/solargraph/complex_type.rb +23 -3
- data/lib/solargraph/convention.rb +5 -7
- data/lib/solargraph/diagnostics/require_not_found.rb +0 -4
- data/lib/solargraph/diagnostics/type_check.rb +0 -1
- data/lib/solargraph/external.rb +187 -0
- data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
- data/lib/solargraph/language_server/host/dispatch.rb +4 -2
- data/lib/solargraph/language_server/host.rb +10 -2
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +10 -3
- data/lib/solargraph/language_server/message/text_document/definition.rb +5 -2
- data/lib/solargraph/language_server/message/text_document/hover.rb +1 -2
- data/lib/solargraph/library.rb +26 -53
- data/lib/solargraph/metagem.rb +80 -0
- data/lib/solargraph/parser/node_processor/base.rb +6 -0
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +22 -3
- data/lib/solargraph/parser/parser_gem/node_methods.rb +29 -6
- data/lib/solargraph/parser/parser_gem/node_processors/class_definition/class_assignment_node.rb +98 -0
- data/lib/solargraph/parser/parser_gem/node_processors/class_definition.rb +54 -0
- data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/data_definition/data_assignment_node.rb +65 -0
- data/lib/solargraph/parser/parser_gem/node_processors/data_definition/data_definition_node.rb +97 -0
- data/lib/solargraph/parser/parser_gem/node_processors/data_definition.rb +110 -0
- data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +2 -0
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +185 -0
- data/lib/solargraph/parser/parser_gem/node_processors/struct_definition/struct_assignment_node.rb +66 -0
- data/lib/solargraph/parser/parser_gem/node_processors/struct_definition/struct_definition_node.rb +108 -0
- data/lib/solargraph/parser/parser_gem/node_processors/struct_definition.rb +170 -0
- data/lib/solargraph/parser/parser_gem/node_processors.rb +33 -29
- data/lib/solargraph/pin/base.rb +25 -1
- data/lib/solargraph/pin/base_variable.rb +31 -1
- data/lib/solargraph/pin/callable.rb +11 -2
- data/lib/solargraph/pin/closure.rb +17 -0
- data/lib/solargraph/pin/delegated_method.rb +5 -0
- data/lib/solargraph/pin/duck_method.rb +36 -16
- data/lib/solargraph/pin/factory_parameter.rb +84 -0
- data/lib/solargraph/pin/instance_variable.rb +45 -0
- data/lib/solargraph/pin/method.rb +10 -0
- data/lib/solargraph/pin/method_alias.rb +4 -0
- data/lib/solargraph/pin/parameter.rb +1 -1
- data/lib/solargraph/pin/reference/included_mixin.rb +22 -0
- data/lib/solargraph/pin/reference.rb +1 -0
- data/lib/solargraph/pin.rb +1 -0
- data/lib/solargraph/plugin/active_support.rb +100 -0
- data/lib/solargraph/plugin/addon.rb +16 -0
- data/lib/solargraph/plugin/base.rb +25 -0
- data/lib/solargraph/plugin/panel.rb +37 -0
- data/lib/solargraph/plugin.rb +26 -0
- data/lib/solargraph/rbs_collection.rb +119 -0
- data/lib/solargraph/rbs_map/base.rb +31 -0
- data/lib/solargraph/rbs_map/conversions.rb +109 -48
- data/lib/solargraph/rbs_map/{core_map.rb → core.rb} +18 -39
- data/lib/solargraph/rbs_map/core_fills.rb +1 -1
- data/lib/solargraph/rbs_map/gem.rb +16 -0
- data/lib/solargraph/rbs_map/helpers.rb +61 -0
- data/lib/solargraph/rbs_map/path.rb +19 -0
- data/lib/solargraph/rbs_map/stdlib.rb +24 -0
- data/lib/solargraph/rbs_map.rb +7 -198
- data/lib/solargraph/rbs_translator.rb +105 -70
- data/lib/solargraph/repo.rb +177 -0
- data/lib/solargraph/shell.rb +49 -99
- data/lib/solargraph/source/chain/call.rb +58 -14
- data/lib/solargraph/source/chain/literal.rb +17 -17
- data/lib/solargraph/source/chain/parameter.rb +79 -0
- data/lib/solargraph/source/chain.rb +8 -0
- data/lib/solargraph/source/node_map.rb +27 -0
- data/lib/solargraph/source/source_chainer.rb +40 -44
- data/lib/solargraph/source.rb +17 -0
- data/lib/solargraph/source_map/call.rb +18 -0
- data/lib/solargraph/source_map/clip.rb +5 -3
- data/lib/solargraph/source_map/mapper.rb +6 -2
- data/lib/solargraph/source_map.rb +28 -9
- data/lib/solargraph/type_checker/rules.rb +3 -2
- data/lib/solargraph/type_checker.rb +4 -1
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace.rb +0 -1
- data/lib/solargraph/yard_map/cache.rb +1 -1
- data/lib/solargraph/yard_map/directives/attribute_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/domain_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/method_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/override_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/parse_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/scope_directive.rb +178 -0
- data/lib/solargraph/yard_map/directives/visibility_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives.rb +5 -2
- data/lib/solargraph/yard_map/helpers.rb +1 -1
- data/lib/solargraph/yard_map/macro.rb +85 -6
- data/lib/solargraph/yard_map/mapper/to_constant.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -1
- data/lib/solargraph/yard_map/mapper.rb +2 -2
- data/lib/solargraph/yard_map.rb +1 -1
- data/lib/solargraph/yardoc.rb +43 -60
- data/lib/solargraph.rb +8 -3
- data/rbs/fills/boolean/0/boolean.rbs +12 -0
- data/solargraph.gemspec +2 -2
- metadata +41 -18
- data/lib/solargraph/convention/active_support_concern.rb +0 -111
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +0 -61
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +0 -93
- data/lib/solargraph/convention/data_definition.rb +0 -108
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +0 -62
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +0 -103
- data/lib/solargraph/convention/struct_definition.rb +0 -168
- data/lib/solargraph/doc_map.rb +0 -439
- data/lib/solargraph/gem_pins.rb +0 -87
- data/lib/solargraph/pin_cache.rb +0 -248
- data/lib/solargraph/rbs_map/stdlib_map.rb +0 -71
- data/lib/solargraph/workspace/gemspecs.rb +0 -373
|
@@ -370,6 +370,13 @@ module Solargraph
|
|
|
370
370
|
@explicit
|
|
371
371
|
end
|
|
372
372
|
|
|
373
|
+
# False for method pins synthesized from a class-body statement rather than parsed from a def.
|
|
374
|
+
#
|
|
375
|
+
# @return [Boolean]
|
|
376
|
+
def body?
|
|
377
|
+
!attribute?
|
|
378
|
+
end
|
|
379
|
+
|
|
373
380
|
def attribute?
|
|
374
381
|
@attribute
|
|
375
382
|
end
|
|
@@ -387,6 +394,9 @@ module Solargraph
|
|
|
387
394
|
|
|
388
395
|
def probe api_map
|
|
389
396
|
attribute? ? infer_from_iv(api_map) : infer_from_return_nodes(api_map)
|
|
397
|
+
rescue FileNotFoundError
|
|
398
|
+
# @todo Necessary for pins from source maps that are not part of the workspace
|
|
399
|
+
ComplexType::UNDEFINED
|
|
390
400
|
end
|
|
391
401
|
|
|
392
402
|
# @return [::Array<Pin::Signature>]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Pin
|
|
5
|
+
class Reference
|
|
6
|
+
# A mixin that a module's +self.included+ hook applies to every class
|
|
7
|
+
# that includes the module, e.g. +base.extend ClassMethods+. The closure
|
|
8
|
+
# is the hooking module and the name is the mixed-in module.
|
|
9
|
+
class IncludedMixin < Reference
|
|
10
|
+
# @return [::Symbol] :include, :prepend or :extend
|
|
11
|
+
attr_reader :keyword
|
|
12
|
+
|
|
13
|
+
# @param keyword [::Symbol] :include, :prepend or :extend
|
|
14
|
+
# @param splat [Hash{Symbol => Object}]
|
|
15
|
+
def initialize keyword:, **splat
|
|
16
|
+
super(**splat)
|
|
17
|
+
@keyword = keyword
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -8,6 +8,7 @@ module Solargraph
|
|
|
8
8
|
autoload :Include, 'solargraph/pin/reference/include'
|
|
9
9
|
autoload :Prepend, 'solargraph/pin/reference/prepend'
|
|
10
10
|
autoload :Extend, 'solargraph/pin/reference/extend'
|
|
11
|
+
autoload :IncludedMixin, 'solargraph/pin/reference/included_mixin'
|
|
11
12
|
autoload :Override, 'solargraph/pin/reference/override'
|
|
12
13
|
autoload :TypeAlias, 'solargraph/pin/reference/type_alias'
|
|
13
14
|
|
data/lib/solargraph/pin.rb
CHANGED
|
@@ -38,6 +38,7 @@ module Solargraph
|
|
|
38
38
|
autoload :Until, 'solargraph/pin/until'
|
|
39
39
|
autoload :While, 'solargraph/pin/while'
|
|
40
40
|
autoload :Callable, 'solargraph/pin/callable'
|
|
41
|
+
autoload :FactoryParameter, 'solargraph/pin/factory_parameter'
|
|
41
42
|
autoload :CompoundStatement,
|
|
42
43
|
'solargraph/pin/compound_statement'
|
|
43
44
|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Plugin
|
|
5
|
+
class ActiveSupport < Base
|
|
6
|
+
ATTRIBUTE_NAME = /\A[_A-Za-z]\w*\z/
|
|
7
|
+
|
|
8
|
+
def addon
|
|
9
|
+
return EMPTY_ADDON unless gem_names.include?('activesupport')
|
|
10
|
+
|
|
11
|
+
Addon.new(pins: classmethod_pins + attribute_pins)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def classmethod_pins
|
|
17
|
+
pins_by_class(Pin::Reference::Include).map do |inc|
|
|
18
|
+
Pin::Reference::Extend.new(name: "#{inc.name}::ClassMethods", closure: inc.closure)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def attribute_pins
|
|
23
|
+
source_maps.flat_map { |map| map.calls(:class_attribute, :mattr_accessor, :cattr_accessor, :mattr_reader, :cattr_reader, :mattr_writer, :cattr_writer, :config_accessor) }
|
|
24
|
+
.select { |call| call.closure.is_a?(Pin::Namespace) }
|
|
25
|
+
.flat_map { |call| generate_call_pins(call) }
|
|
26
|
+
.compact
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @param call [SourceMap::Call]
|
|
30
|
+
def generate_call_pins call
|
|
31
|
+
options = option_hash(call.chain.links.last.arguments.last)
|
|
32
|
+
method_names = call.chain.links.last.arguments.select(&:literal?).map { |arg| arg.links.last.value }.compact
|
|
33
|
+
.grep(ATTRIBUTE_NAME)
|
|
34
|
+
case call.chain.links.last.word
|
|
35
|
+
when 'class_attribute'
|
|
36
|
+
class_suffixes = ['', '=']
|
|
37
|
+
class_suffixes.push '?' if options[:instance_predicate]
|
|
38
|
+
instance_suffixes = []
|
|
39
|
+
instance_suffixes.push '' if options[:instance_accessor] && options[:instance_reader]
|
|
40
|
+
instance_suffixes.push '=' if options[:instance_accessor] && options[:instance_writer]
|
|
41
|
+
instance_suffixes.push '?' if options[:instance_accessor] && options[:instance_predicate]
|
|
42
|
+
method_names.flat_map { |name| method_pins(name, class_suffixes, instance_suffixes, call) }
|
|
43
|
+
when 'mattr_accessor', 'cattr_accessor', 'config_accessor'
|
|
44
|
+
class_suffixes = ['', '=']
|
|
45
|
+
instance_suffixes = []
|
|
46
|
+
instance_suffixes.push '' if options[:instance_accessor] && options[:instance_reader]
|
|
47
|
+
instance_suffixes.push '=' if options[:instance_accessor] && options[:instance_writer]
|
|
48
|
+
method_names.flat_map { |name| method_pins(name, class_suffixes, instance_suffixes, call) }
|
|
49
|
+
when 'mattr_reader', 'cattr_reader'
|
|
50
|
+
class_suffixes = ['']
|
|
51
|
+
instance_suffixes = []
|
|
52
|
+
instance_suffixes.push '' if options[:instance_accessor] && options[:instance_reader]
|
|
53
|
+
method_names.flat_map { |name| method_pins(name, class_suffixes, instance_suffixes, call) }
|
|
54
|
+
when 'mattr_writer', 'cattr_writer'
|
|
55
|
+
class_suffixes = ['=']
|
|
56
|
+
instance_suffixes = []
|
|
57
|
+
instance_suffixes.push '=' if options[:instance_accessor] && options[:instance_writer]
|
|
58
|
+
method_names.flat_map { |name| method_pins(name, class_suffixes, instance_suffixes, call) }
|
|
59
|
+
else
|
|
60
|
+
[]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def option_hash args
|
|
65
|
+
defaults = {
|
|
66
|
+
instance_reader: true,
|
|
67
|
+
instance_writer: true,
|
|
68
|
+
instance_accessor: true,
|
|
69
|
+
instance_predicate: true
|
|
70
|
+
}
|
|
71
|
+
kwargs = Parser::ParserGem::NodeMethods.convert_hash(args.node)
|
|
72
|
+
.select { |_, val| val.literal? }
|
|
73
|
+
.transform_values { |val| val.links.last.value }
|
|
74
|
+
return defaults unless kwargs.is_a?(Hash)
|
|
75
|
+
defaults.merge(kwargs)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# @param call [SourceMap::Call]
|
|
79
|
+
# @param name [String]
|
|
80
|
+
# @param class_suffixes [Array<String>]
|
|
81
|
+
# @param instance_suffixes [Array<String>]
|
|
82
|
+
def method_pins name, class_suffixes, instance_suffixes, call
|
|
83
|
+
comments = call.source_map.source.comments_for(call.chain.node)
|
|
84
|
+
location = Solargraph::Location.new(call.closure.filename, Solargraph::Range.from_node(call.chain.node))
|
|
85
|
+
class_suffixes.map do |sfx|
|
|
86
|
+
Pin::Method.new(name: "#{name}#{sfx}", closure: call.closure, scope: :class, attribute: true, location: location, comments: comments).tap do |pin|
|
|
87
|
+
next unless sfx == '='
|
|
88
|
+
pin.parameters.push Pin::Parameter.new(name: 'value', closure: pin)
|
|
89
|
+
end
|
|
90
|
+
end +
|
|
91
|
+
instance_suffixes.map do |sfx|
|
|
92
|
+
Pin::Method.new(name: "#{name}#{sfx}", closure: call.closure, scope: :instance, attribute: true, location: location, comments: comments).tap do |pin|
|
|
93
|
+
next unless sfx == '='
|
|
94
|
+
pin.parameters.push Pin::Parameter.new(name: 'value', closure: pin)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Plugin
|
|
5
|
+
class Addon
|
|
6
|
+
attr_reader :gem_names, :pins
|
|
7
|
+
|
|
8
|
+
# @param gem_names [Array<String>]
|
|
9
|
+
# @param pins [Array<Pin::Base>]
|
|
10
|
+
def initialize gem_names: [], pins: []
|
|
11
|
+
@gem_names = gem_names
|
|
12
|
+
@pins = pins
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'forwardable'
|
|
4
|
+
|
|
5
|
+
module Solargraph
|
|
6
|
+
module Plugin
|
|
7
|
+
class Base
|
|
8
|
+
extend Forwardable
|
|
9
|
+
|
|
10
|
+
attr_reader :panel
|
|
11
|
+
|
|
12
|
+
def_delegators :@panel, :pins, :pins_by_class, :pins_by_path, :gem_names, :source_maps
|
|
13
|
+
|
|
14
|
+
# @param panel [Panel]
|
|
15
|
+
def initialize panel
|
|
16
|
+
@panel = panel
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @return [Addon]
|
|
20
|
+
def addon
|
|
21
|
+
EMPTY_ADDON
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Plugin
|
|
5
|
+
class Panel
|
|
6
|
+
attr_reader :source_maps, :live_map, :gem_names
|
|
7
|
+
|
|
8
|
+
def initialize source_maps: [], live_map: nil, gem_names: []
|
|
9
|
+
@source_maps = source_maps
|
|
10
|
+
@live_map = live_map
|
|
11
|
+
@gem_names = gem_names
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def pins
|
|
15
|
+
@pins ||= source_maps.flat_map(&:pins)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def pins_by_class klass
|
|
19
|
+
pin_class_hash[klass] || []
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def pins_by_path path
|
|
23
|
+
pin_path_hash[path] || []
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def pin_class_hash
|
|
29
|
+
@pin_class_hash ||= pins.to_set.classify(&:class)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def pin_path_hash
|
|
33
|
+
@pin_path_hash ||= pins.to_set.classify(&:path)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Plugin
|
|
5
|
+
autoload :Addon, 'solargraph/plugin/addon'
|
|
6
|
+
autoload :Base, 'solargraph/plugin/base'
|
|
7
|
+
autoload :Panel, 'solargraph/plugin/panel'
|
|
8
|
+
autoload :ActiveSupport, 'solargraph/plugin/active_support'
|
|
9
|
+
|
|
10
|
+
EMPTY_ADDON = Addon.new.freeze
|
|
11
|
+
|
|
12
|
+
def self.registry
|
|
13
|
+
@registry ||= Set.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.register klass
|
|
17
|
+
registry.add klass
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.unregister klass
|
|
21
|
+
registry.delete klass
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
Plugin.register ActiveSupport
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
# The RBS collection declared by a project's rbs_collection.lock.yaml.
|
|
5
|
+
#
|
|
6
|
+
class RbsCollection
|
|
7
|
+
attr_reader :lockfile
|
|
8
|
+
|
|
9
|
+
def initialize lockfile
|
|
10
|
+
@lockfile = File.expand_path(lockfile) if lockfile
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# @param metagem [Metagem]
|
|
14
|
+
# @return [Array<Pin::Base>]
|
|
15
|
+
def load metagem
|
|
16
|
+
key = best_key(metagem)
|
|
17
|
+
return [] unless key
|
|
18
|
+
mem_cache[key] ||= RbsMap::Path.pins(gem_path_map[key])
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def gem_keys
|
|
22
|
+
gem_path_map.keys
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# The names of the stdlib signature sets declared by the collection.
|
|
26
|
+
#
|
|
27
|
+
# +rbs collection install+ resolves these to the signatures which ship
|
|
28
|
+
# with the rbs gem instead of copying them into the collection directory,
|
|
29
|
+
# so they can never be located by a gem name/version lookup.
|
|
30
|
+
#
|
|
31
|
+
# @return [Array<String>]
|
|
32
|
+
def stdlib_names
|
|
33
|
+
@stdlib_names ||= raw_data[:gems].select { |gem| gem.dig(:source, :type).to_s == 'stdlib' }
|
|
34
|
+
.map { |gem| gem[:name].to_s }.uniq
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def gem_path_map
|
|
40
|
+
@gem_path_map ||= raw_data[:gems].to_h { |gem| ["#{gem[:name]}-#{gem[:version]}", gem_source_path(gem)] }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# The versions available in the collection for each gem name.
|
|
44
|
+
#
|
|
45
|
+
# @return [Hash{String => Array<String>}]
|
|
46
|
+
def versions_by_name
|
|
47
|
+
@versions_by_name ||= raw_data[:gems].group_by { |gem| gem[:name].to_s }
|
|
48
|
+
.transform_values { |gems| gems.map { |gem| gem[:version].to_s } }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def best_key metagem
|
|
52
|
+
key = "#{metagem.name}-#{metagem.version}"
|
|
53
|
+
return key if gem_path_map.key?(key)
|
|
54
|
+
|
|
55
|
+
full_key = "#{metagem.name}-#{metagem.version}."
|
|
56
|
+
zero_key = "#{metagem.name}-0"
|
|
57
|
+
found = gem_path_map.find { |key, _| full_key.start_with?("#{key}.") } ||
|
|
58
|
+
gem_path_map.find { |key, _| key == zero_key }
|
|
59
|
+
found&.first || closest_key(metagem)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Signature collections version their directories independently from the
|
|
63
|
+
# gems they describe. gem_rbs_collection, for example, provides
|
|
64
|
+
# +actionpack/6.0+ for every Rails 6 and 7 release and +devise/4.9+ for
|
|
65
|
+
# Devise 4 and 5. When no directory matches a gem's version, fall back to
|
|
66
|
+
# the closest version the collection provides for that gem, preferring the
|
|
67
|
+
# highest one that does not exceed the gem's version.
|
|
68
|
+
#
|
|
69
|
+
# @param metagem [Metagem]
|
|
70
|
+
# @return [String, nil]
|
|
71
|
+
def closest_key metagem
|
|
72
|
+
versions = versions_by_name[metagem.name.to_s]
|
|
73
|
+
return nil if versions.nil? || versions.empty?
|
|
74
|
+
return "#{metagem.name}-#{versions.first}" if versions.size == 1
|
|
75
|
+
parsed = versions.map { |version| [version, parse_version(version)] }
|
|
76
|
+
usable = parsed.compact
|
|
77
|
+
gem_version = parse_version(metagem.version)
|
|
78
|
+
chosen = if gem_version
|
|
79
|
+
usable.reject { |_, parsed_version| parsed_version > gem_version }.max_by { |_, parsed_version| parsed_version }
|
|
80
|
+
end
|
|
81
|
+
chosen ||= usable.min_by { |_, parsed_version| parsed_version }
|
|
82
|
+
chosen ||= parsed.first
|
|
83
|
+
"#{metagem.name}-#{chosen[0]}"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# @param value [Object]
|
|
87
|
+
# @return [Gem::Version, nil]
|
|
88
|
+
def parse_version value
|
|
89
|
+
Gem::Version.new value.to_s
|
|
90
|
+
rescue ArgumentError
|
|
91
|
+
nil
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# @param gem_hash [Hash]
|
|
95
|
+
def gem_source_path gem_hash
|
|
96
|
+
root_path = gem_hash.dig(:source, :path) || raw_data[:path]
|
|
97
|
+
return unless root_path
|
|
98
|
+
gem_path = File.join(root_path, gem_hash[:name], gem_hash[:version])
|
|
99
|
+
File.expand_path(gem_path, File.dirname(lockfile))
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def gem_rbs_collection_path
|
|
103
|
+
@gem_rbs_collection_path ||= File.expand_path(raw_data[:path]) if raw_data[:path]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# @return [Hash]
|
|
107
|
+
def raw_data
|
|
108
|
+
@raw_data ||= if lockfile && File.file?(lockfile)
|
|
109
|
+
YAML.load_file(lockfile, symbolize_names: true)
|
|
110
|
+
else
|
|
111
|
+
{ gems: [] }
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def mem_cache
|
|
116
|
+
@mem_cache ||= {}
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module RbsMap
|
|
5
|
+
class Base
|
|
6
|
+
def pins
|
|
7
|
+
@pins ||= RbsMap::Conversions.new(loader: loader).pins
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# @return [RBS::Repository]
|
|
11
|
+
def repository
|
|
12
|
+
@repository ||= RBS::Repository.new(no_stdlib: true)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @return [RBS::EnvironmentLoader]
|
|
16
|
+
def loader
|
|
17
|
+
@loader ||= RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @param path [String]
|
|
21
|
+
# @return [Array<Pin::Base>]
|
|
22
|
+
def path_pins path
|
|
23
|
+
pins.select { |p| p.path == path }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.pins(...)
|
|
27
|
+
new(...).pins
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|