solargraph 0.54.2 → 0.54.5

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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/lib/solargraph/api_map/cache.rb +10 -1
  4. data/lib/solargraph/api_map/index.rb +167 -0
  5. data/lib/solargraph/api_map/store.rb +68 -121
  6. data/lib/solargraph/api_map.rb +20 -13
  7. data/lib/solargraph/bench.rb +17 -1
  8. data/lib/solargraph/complex_type/unique_type.rb +21 -1
  9. data/lib/solargraph/complex_type.rb +13 -12
  10. data/lib/solargraph/convention.rb +1 -0
  11. data/lib/solargraph/doc_map.rb +1 -0
  12. data/lib/solargraph/equality.rb +33 -0
  13. data/lib/solargraph/language_server/host/message_worker.rb +3 -0
  14. data/lib/solargraph/language_server/host.rb +2 -1
  15. data/lib/solargraph/language_server/message/base.rb +1 -1
  16. data/lib/solargraph/language_server/message/initialize.rb +3 -1
  17. data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -0
  18. data/lib/solargraph/library.rb +7 -7
  19. data/lib/solargraph/location.rb +7 -0
  20. data/lib/solargraph/parser/node_methods.rb +1 -1
  21. data/lib/solargraph/parser/node_processor.rb +1 -0
  22. data/lib/solargraph/parser/parser_gem/class_methods.rb +2 -6
  23. data/lib/solargraph/parser/parser_gem/node_chainer.rb +7 -13
  24. data/lib/solargraph/parser/parser_gem/node_methods.rb +2 -2
  25. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -2
  26. data/lib/solargraph/pin/base.rb +27 -16
  27. data/lib/solargraph/pin/base_variable.rb +3 -2
  28. data/lib/solargraph/pin/callable.rb +3 -3
  29. data/lib/solargraph/pin/method.rb +6 -0
  30. data/lib/solargraph/pin/namespace.rb +1 -1
  31. data/lib/solargraph/pin/parameter.rb +2 -1
  32. data/lib/solargraph/position.rb +7 -0
  33. data/lib/solargraph/range.rb +7 -0
  34. data/lib/solargraph/rbs_map/conversions.rb +1 -1
  35. data/lib/solargraph/rbs_map.rb +1 -0
  36. data/lib/solargraph/shell.rb +2 -0
  37. data/lib/solargraph/source/chain/array.rb +1 -1
  38. data/lib/solargraph/source/chain/call.rb +9 -4
  39. data/lib/solargraph/source/chain/hash.rb +5 -0
  40. data/lib/solargraph/source/chain/if.rb +5 -0
  41. data/lib/solargraph/source/chain/link.rb +17 -5
  42. data/lib/solargraph/source/chain/literal.rb +5 -0
  43. data/lib/solargraph/source/chain.rb +33 -19
  44. data/lib/solargraph/source/cursor.rb +0 -11
  45. data/lib/solargraph/source.rb +2 -1
  46. data/lib/solargraph/source_map/clip.rb +1 -1
  47. data/lib/solargraph/type_checker.rb +8 -8
  48. data/lib/solargraph/version.rb +1 -1
  49. data/lib/solargraph/workspace/config.rb +7 -3
  50. data/lib/solargraph/workspace.rb +1 -1
  51. data/lib/solargraph/yard_map/mapper/to_constant.rb +1 -0
  52. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  53. data/lib/solargraph/yard_map/mapper.rb +1 -0
  54. data/lib/solargraph/yardoc.rb +1 -1
  55. data/lib/solargraph.rb +1 -0
  56. data/solargraph.gemspec +1 -1
  57. metadata +11 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 17844968917df55d45751cbe82fa1f59e72f4dbfe7ecce04f73dbccbc1ec2aeb
4
- data.tar.gz: 1b86c653e3b5c145f1b0aa9c614f136bd6d75c305aeac680f0cfe992ca4ff3dc
3
+ metadata.gz: 155e6f0e4fc44166c0d4b3c1ba6691ff1d1629d229adf8d37f6d3fe4b5fc0c77
4
+ data.tar.gz: c33c4dab114c6a70b3c0dfbee6a5ccdc379cf284af3d34dae8a30473dbcdc517
5
5
  SHA512:
6
- metadata.gz: 44d428aa78d2d82bcfb97b650acd72aaf904666702a59e13a87f1a4c4c8bb2fa171afe6f502fb7327a67f12854a3953fccee1fde95f75fc5cf4b4f8742683e8e
7
- data.tar.gz: ce37d473c9e3b8decd9c97c868fb66ef8441e27aeb10b557abf345bba1ad9c96c8dc5657127ea9680dfa60f59da7663f25ccffed412d5683b272ea3dbf823f76
6
+ metadata.gz: 267350435fa9592fc49dc2c5b05f9f9157b576025ea4ed9abe3ebc58e4344d7412805ace58920585105fbb81eaa2bad246416c5456ce66656f22c8639054002d
7
+ data.tar.gz: 7a3860337657dc869e7a96f8b95509867ece49db13e89523e09c1567490b427ed41f5fc57c87e5d8477bfe3857cbe97512bd811598adbb53f4a2f617e724c44c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## 0.54.5 - May 17, 2025
2
+ - Repair unknown encoding errors (#936, #935)
3
+ - Index arbitrary pinsets (#937)
4
+ - Separate YARD cache from doc map cache (#938)
5
+
6
+ ## 0.54.4 - May 14, 2025
7
+ - Delete files from Library hash (#932)
8
+ - Clip#define returns variable pins (#934, #933)
9
+
10
+ ## 0.54.3 - May 13, 2025
11
+ - Improve inspect()/desc()/to_s() methods for better debugging output (#913)
12
+ - Fix generic resolution in Hash types (#906)
13
+ - Stop parsing RBS type parameter constraints as the type name (#918)
14
+ - Fix pin inference stack (#922)
15
+ - Refactor pin equality for performance (#925)
16
+ - Improve ApiMap catalog speed by preserving static pin indexes (#930)
17
+ - Update jaro_winkler dependency (#931)
18
+
1
19
  ## 0.54.2 - April 28, 2025
2
20
  - Resolve generics correctly on mixin inclusion (#898)
3
21
  - Pick correct String#split overload (#905)
@@ -8,7 +8,7 @@ module Solargraph
8
8
  @methods = {}
9
9
  # @type [Hash{(String, Array<String>) => Array<Pin::Base>}]
10
10
  @constants = {}
11
- # @type [Hash{(String, String) => String}]
11
+ # @type [Hash{String => String}]
12
12
  @qualified_namespaces = {}
13
13
  # @type [Hash{String => Pin::Method}]
14
14
  @receiver_definitions = {}
@@ -16,6 +16,15 @@ module Solargraph
16
16
  @clips = {}
17
17
  end
18
18
 
19
+ def to_s
20
+ self.class.to_s
21
+ end
22
+
23
+ # avoid enormous dump
24
+ def inspect
25
+ to_s
26
+ end
27
+
19
28
  # @param fqns [String]
20
29
  # @param scope [Symbol]
21
30
  # @param visibility [Array<Symbol>]
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class ApiMap
5
+ class Index
6
+ # @param pins [Array<Pin::Base>]
7
+ def initialize pins = []
8
+ catalog pins
9
+ end
10
+
11
+ # @return [Array<Pin::Base>]
12
+ def pins
13
+ @pins ||= []
14
+ end
15
+
16
+ # @return [Hash{String => Array<Pin::Namespace>}]
17
+ def namespace_hash
18
+ @namespace_hash ||= Hash.new { |h, k| h[k] = [] }
19
+ end
20
+
21
+ # @return [Hash{String => Array<Pin::Base>}]
22
+ def pin_class_hash
23
+ @pin_class_hash ||= Hash.new { |h, k| h[k] = [] }
24
+ end
25
+
26
+ # @return [Hash{String => Array<Pin::Base>}]
27
+ def path_pin_hash
28
+ @path_pin_hash ||= Hash.new { |h, k| h[k] = [] }
29
+ end
30
+
31
+ # @generic T
32
+ # @param klass [Class<generic<T>>]
33
+ # @return [Set<generic<T>>]
34
+ def pins_by_class klass
35
+ # @type [Set<Solargraph::Pin::Base>]
36
+ s = Set.new
37
+ @pin_select_cache[klass] ||= pin_class_hash.each_with_object(s) { |(key, o), n| n.merge(o) if key <= klass }
38
+ end
39
+
40
+ # @return [Hash{String => Array<Pin::Reference::Include>}]
41
+ def include_references
42
+ @include_references ||= Hash.new { |h, k| h[k] = [] }
43
+ end
44
+
45
+ # @return [Hash{String => Array<Pin::Reference::Extend>}]
46
+ def extend_references
47
+ @extend_references ||= Hash.new { |h, k| h[k] = [] }
48
+ end
49
+
50
+ # @return [Hash{String => Array<Pin::Reference::Prepend>}]
51
+ def prepend_references
52
+ @prepend_references ||= Hash.new { |h, k| h[k] = [] }
53
+ end
54
+
55
+ # @return [Hash{String => Array<Pin::Reference::Superclass>}]
56
+ def superclass_references
57
+ @superclass_references ||= Hash.new { |h, k| h[k] = [] }
58
+ end
59
+
60
+ # @param pins [Array<Pin::Base>]
61
+ def merge pins
62
+ deep_clone.catalog pins
63
+ end
64
+
65
+ protected
66
+
67
+ attr_writer :pins, :pin_select_cache, :namespace_hash, :pin_class_hash, :path_pin_hash, :include_references,
68
+ :extend_references, :prepend_references, :superclass_references
69
+
70
+ def deep_clone
71
+ Index.allocate.tap do |copy|
72
+ copy.pin_select_cache = {}
73
+ copy.pins = pins.clone
74
+ %i[
75
+ namespace_hash pin_class_hash path_pin_hash include_references extend_references prepend_references
76
+ superclass_references
77
+ ].each do |sym|
78
+ copy.send("#{sym}=", send(sym).clone)
79
+ copy.send(sym)&.transform_values!(&:clone)
80
+ end
81
+ end
82
+ end
83
+
84
+ # @param new_pins [Array<Pin::Base>]
85
+ def catalog new_pins
86
+ @pin_select_cache = {}
87
+ pins.concat new_pins
88
+ set = new_pins.to_set
89
+ set.classify(&:class)
90
+ .map { |k, v| pin_class_hash[k].concat v.to_a }
91
+ set.classify(&:namespace)
92
+ .map { |k, v| namespace_hash[k].concat v.to_a }
93
+ set.classify(&:path)
94
+ .map { |k, v| path_pin_hash[k].concat v.to_a }
95
+ @namespaces = path_pin_hash.keys.compact.to_set
96
+ map_references Pin::Reference::Include, include_references
97
+ map_references Pin::Reference::Prepend, prepend_references
98
+ map_references Pin::Reference::Extend, extend_references
99
+ map_references Pin::Reference::Superclass, superclass_references
100
+ map_overrides
101
+ self
102
+ end
103
+
104
+ # @param klass [Class<Pin::Reference>]
105
+ # @param hash [Hash{String => Array<Pin::Reference>}]
106
+ # @return [void]
107
+ def map_references klass, hash
108
+ pins_by_class(klass).each do |pin|
109
+ store_parametric_reference(hash, pin)
110
+ end
111
+ end
112
+
113
+ # Add references to a map
114
+ #
115
+ # @param hash [Hash{String => Array<Pin::Reference>}]
116
+ # @param reference_pin [Pin::Reference]
117
+ #
118
+ # @return [void]
119
+ def store_parametric_reference(hash, reference_pin)
120
+ referenced_ns = reference_pin.name
121
+ referenced_tag_params = reference_pin.generic_values
122
+ referenced_tag = referenced_ns +
123
+ if referenced_tag_params && referenced_tag_params.length > 0
124
+ "<" + referenced_tag_params.join(', ') + ">"
125
+ else
126
+ ''
127
+ end
128
+ referencing_ns = reference_pin.namespace
129
+ hash[referencing_ns].push referenced_tag
130
+ end
131
+
132
+ # @return [void]
133
+ def map_overrides
134
+ pins_by_class(Pin::Reference::Override).each do |ovr|
135
+ pin = path_pin_hash[ovr.name].first
136
+ next if pin.nil?
137
+ new_pin = if pin.path.end_with?('#initialize')
138
+ path_pin_hash[pin.path.sub(/#initialize/, '.new')].first
139
+ end
140
+ (ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
141
+ pin.docstring.delete_tags tag
142
+ new_pin.docstring.delete_tags tag if new_pin
143
+ end
144
+ ovr.tags.each do |tag|
145
+ pin.docstring.add_tag(tag)
146
+ redefine_return_type pin, tag
147
+ if new_pin
148
+ new_pin.docstring.add_tag(tag)
149
+ redefine_return_type new_pin, tag
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ # @param pin [Pin::Method]
156
+ # @param tag [YARD::Tags::Tag]
157
+ # @return [void]
158
+ def redefine_return_type pin, tag
159
+ return unless pin && tag.tag_name == 'return'
160
+ pin.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
161
+ pin.signatures.each do |sig|
162
+ sig.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
@@ -1,19 +1,50 @@
1
1
  # frozen_string_literal: true
2
2
 
3
-
4
3
  module Solargraph
5
4
  class ApiMap
6
5
  # Queryable collection of Pins representing a Workspace, gems and the Ruby
7
6
  # core.
8
7
  #
9
8
  class Store
9
+ # @param pinsets [Array<Enumerable<Pin::Base>>]
10
+ def initialize *pinsets
11
+ catalog pinsets
12
+ end
13
+
10
14
  # @return [Array<Solargraph::Pin::Base>]
11
- attr_reader :pins
15
+ def pins
16
+ index.pins
17
+ end
18
+
19
+ # @param pinsets [Array<Enumerable<Pin::Base>>]
20
+ # @return [Boolean] True if the index was updated
21
+ def update *pinsets
22
+ return catalog(pinsets) if pinsets.length != @pinsets.length
23
+
24
+ changed = pinsets.find_index.with_index { |pinset, idx| @pinsets[idx] != pinset }
25
+ return false unless changed
26
+
27
+ # @todo Fix this map
28
+ @fqns_pins_map = nil
29
+ return catalog(pinsets) if changed == 0
30
+
31
+ pinsets[changed..].each_with_index do |pins, idx|
32
+ @pinsets[changed + idx] = pins
33
+ @indexes[changed + idx] = if pins.empty?
34
+ @indexes[changed + idx - 1]
35
+ else
36
+ @indexes[changed + idx - 1].merge(pins)
37
+ end
38
+ end
39
+ true
40
+ end
12
41
 
13
- # @param pins [Enumerable<Solargraph::Pin::Base>]
14
- def initialize pins = []
15
- @pins = pins
16
- index
42
+ def to_s
43
+ self.class.to_s
44
+ end
45
+
46
+ def inspect
47
+ to_s
17
48
  end
18
49
 
19
50
  # @param fqns [String]
@@ -66,11 +97,7 @@ module Solargraph
66
97
  # @param path [String]
67
98
  # @return [Array<Solargraph::Pin::Base>]
68
99
  def get_path_pins path
69
- path_pin_hash[path] || []
70
- end
71
-
72
- def cacheable_pins
73
- @cacheable_pins ||= pins_by_class(Pin::Namespace) + pins_by_class(Pin::Constant) + pins_by_class(Pin::Method) + pins_by_class(Pin::Reference)
100
+ index.path_pin_hash[path]
74
101
  end
75
102
 
76
103
  # @param fqns [String]
@@ -101,10 +128,10 @@ module Solargraph
101
128
 
102
129
  # @return [Set<String>]
103
130
  def namespaces
104
- @namespaces ||= Set.new
131
+ index.namespaces
105
132
  end
106
133
 
107
- # @return [Enumerable<Solargraph::Pin::Base>]
134
+ # @return [Enumerable<Solargraph::Pin::Namespace>]
108
135
  def namespace_pins
109
136
  pins_by_class(Solargraph::Pin::Namespace)
110
137
  end
@@ -143,18 +170,11 @@ module Solargraph
143
170
  pins_by_class(Pin::Block)
144
171
  end
145
172
 
146
- def inspect
147
- # Avoid insane dumps in specs
148
- to_s
149
- end
150
-
151
173
  # @generic T
152
- # @param klass [Class<T>]
153
- # @return [Set<T>]
174
+ # @param klass [Class<generic<T>>]
175
+ # @return [Set<generic<T>>]
154
176
  def pins_by_class klass
155
- # @type [Set<Solargraph::Pin::Base>]
156
- s = Set.new
157
- @pin_select_cache[klass] ||= @pin_class_hash.each_with_object(s) { |(key, o), n| n.merge(o) if key <= klass }
177
+ index.pins_by_class klass
158
178
  end
159
179
 
160
180
  # @param fqns [String]
@@ -174,6 +194,23 @@ module Solargraph
174
194
 
175
195
  private
176
196
 
197
+ def index
198
+ @indexes.last
199
+ end
200
+
201
+ def catalog pinsets
202
+ @pinsets = pinsets
203
+ @indexes = []
204
+ pinsets.each do |pins|
205
+ if @indexes.last && pins.empty?
206
+ @indexes.push @indexes.last
207
+ else
208
+ @indexes.push(@indexes.last&.merge(pins) || Solargraph::ApiMap::Index.new(pins))
209
+ end
210
+ end
211
+ true
212
+ end
213
+
177
214
  # @return [Hash{::Array(String, String) => ::Array<Pin::Namespace>}]
178
215
  def fqns_pins_map
179
216
  @fqns_pins_map ||= Hash.new do |h, (base, name)|
@@ -184,129 +221,39 @@ module Solargraph
184
221
 
185
222
  # @return [Enumerable<Solargraph::Pin::Symbol>]
186
223
  def symbols
187
- pins_by_class(Pin::Symbol)
224
+ index.pins_by_class(Pin::Symbol)
188
225
  end
189
226
 
190
227
  # @return [Hash{String => Array<String>}]
191
228
  def superclass_references
192
- @superclass_references ||= {}
229
+ index.superclass_references
193
230
  end
194
231
 
195
232
  # @return [Hash{String => Array<String>}]
196
233
  def include_references
197
- @include_references ||= {}
234
+ index.include_references
198
235
  end
199
236
 
200
237
  # @return [Hash{String => Array<String>}]
201
238
  def prepend_references
202
- @prepend_references ||= {}
239
+ index.prepend_references
203
240
  end
204
241
 
205
242
  # @return [Hash{String => Array<String>}]
206
243
  def extend_references
207
- @extend_references ||= {}
244
+ index.extend_references
208
245
  end
209
246
 
210
247
  # @param name [String]
211
248
  # @return [Enumerable<Solargraph::Pin::Base>]
212
249
  def namespace_children name
213
- namespace_map[name] || []
214
- end
215
-
216
- # @return [Hash{String => Enumerable<Pin::Base>}
217
- def namespace_map
218
- @namespace_map ||= {}
250
+ return [] unless index.namespace_hash.key?(name)
251
+ index.namespace_hash[name]
219
252
  end
220
253
 
221
254
  # @return [Enumerable<Pin::InstanceVariable>]
222
255
  def all_instance_variables
223
- pins_by_class(Pin::InstanceVariable)
224
- end
225
-
226
- # @return [Hash{String => Array<Pin::Base>}]
227
- def path_pin_hash
228
- @path_pin_hash ||= {}
229
- end
230
-
231
- # Add references to a map
232
- #
233
- # @param h [Hash{String => Pin:Base}]
234
- # @param reference_pin [Pin::Reference]
235
- #
236
- # @return [void]
237
- def store_parametric_reference(h, reference_pin)
238
- referenced_ns = reference_pin.name
239
- referenced_tag_params = reference_pin.generic_values
240
- referenced_tag = referenced_ns +
241
- if referenced_tag_params && referenced_tag_params.length > 0
242
- "<" + referenced_tag_params.join(', ') + ">"
243
- else
244
- ''
245
- end
246
- referencing_ns = reference_pin.namespace
247
- h[referencing_ns] ||= []
248
- h[referencing_ns].push referenced_tag
249
- end
250
-
251
- # @return [void]
252
- def index
253
- set = pins.to_set
254
- @pin_class_hash = set.classify(&:class).transform_values(&:to_a)
255
- # @type [Hash{Class => ::Array<Solargraph::Pin::Base>}]
256
- @pin_select_cache = {}
257
- @namespace_map = set.classify(&:namespace)
258
- @path_pin_hash = set.classify(&:path)
259
- @namespaces = @path_pin_hash.keys.compact.to_set
260
- pins_by_class(Pin::Reference::Include).each do |pin|
261
- store_parametric_reference(include_references, pin)
262
- end
263
- # @todo move the rest of these reference pins over to use
264
- # generic types, adding rbs_map/conversions.rb code to
265
- # populate type parameters and adding related specs ensuring
266
- # the generics get resolved, along with any api_map.rb
267
- # changes needed in
268
- pins_by_class(Pin::Reference::Prepend).each do |pin|
269
- prepend_references[pin.namespace] ||= []
270
- prepend_references[pin.namespace].push pin.name
271
- end
272
- pins_by_class(Pin::Reference::Extend).each do |pin|
273
- extend_references[pin.namespace] ||= []
274
- extend_references[pin.namespace].push pin.name
275
- end
276
- pins_by_class(Pin::Reference::Superclass).each do |pin|
277
- superclass_references[pin.namespace] ||= []
278
- superclass_references[pin.namespace].push pin.name
279
- end
280
- pins_by_class(Pin::Reference::Override).each do |ovr|
281
- pin = get_path_pins(ovr.name).first
282
- next if pin.nil?
283
- new_pin = if pin.path.end_with?('#initialize')
284
- get_path_pins(pin.path.sub(/#initialize/, '.new')).first
285
- end
286
- (ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
287
- pin.docstring.delete_tags tag
288
- new_pin.docstring.delete_tags tag if new_pin
289
- end
290
- ovr.tags.each do |tag|
291
- pin.docstring.add_tag(tag)
292
- redefine_return_type pin, tag
293
- if new_pin
294
- new_pin.docstring.add_tag(tag)
295
- redefine_return_type new_pin, tag
296
- end
297
- end
298
- end
299
- end
300
-
301
- # @param pin [Pin::Base]
302
- # @param tag [String]
303
- # @return [void]
304
- def redefine_return_type pin, tag
305
- return unless pin && tag.tag_name == 'return'
306
- pin.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
307
- pin.signatures.each do |sig|
308
- sig.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
309
- end
256
+ index.pins_by_class(Pin::InstanceVariable)
310
257
  end
311
258
  end
312
259
  end
@@ -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
- @store = Store.new(@@core_map.pins + pins)
69
+ store.update @@core_map.pins, pins
60
70
  self
61
71
  end
62
72
 
@@ -75,10 +85,9 @@ module Solargraph
75
85
  # @param bench [Bench]
76
86
  # @return [self]
77
87
  def catalog bench
78
- old_api_hash = @source_map_hash&.values&.map(&:api_hash)
79
- need_to_uncache = (old_api_hash != bench.source_maps.map(&:api_hash))
80
- @source_map_hash = bench.source_maps.map { |s| [s.filename, s] }.to_h
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
@@ -87,11 +96,8 @@ module Solargraph
87
96
  if @unresolved_requires != unresolved_requires || @doc_map&.uncached_gemspecs&.any?
88
97
  @doc_map = DocMap.new(unresolved_requires, [], bench.workspace.rbs_collection_path) # @todo Implement gem preferences
89
98
  @unresolved_requires = unresolved_requires
90
- need_to_uncache = true
91
99
  end
92
- @store = Store.new(@@core_map.pins + @doc_map.pins + implicit.pins + pins)
93
- @cache.clear if need_to_uncache
94
-
100
+ @cache.clear if store.update(@@core_map.pins, @doc_map.pins, implicit.pins, iced_pins, live_pins)
95
101
  @missing_docs = [] # @todo Implement missing docs
96
102
  self
97
103
  end
@@ -100,7 +106,7 @@ module Solargraph
100
106
  # that this overload of 'protected' will typecheck @sg-ignore
101
107
  # @sg-ignore
102
108
  protected def equality_fields
103
- [self.class, @source_map_hash, implicit, @doc_map, @unresolved_requires, @missing_docs]
109
+ [self.class, @source_map_hash, implicit, @doc_map, @unresolved_requires]
104
110
  end
105
111
 
106
112
  # @return [::Array<Gem::Specification>]
@@ -186,7 +192,7 @@ module Solargraph
186
192
 
187
193
  # @return [Array<Solargraph::Pin::Base>]
188
194
  def pins
189
- store.pins
195
+ store.pins.clone.freeze
190
196
  end
191
197
 
192
198
  # An array of pins based on Ruby keywords (`if`, `end`, etc.).
@@ -349,6 +355,7 @@ module Solargraph
349
355
  namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
350
356
  cached = cache.get_methods(rooted_tag, scope, visibility, deep)
351
357
  return cached.clone unless cached.nil?
358
+ # @type [Array<Solargraph::Pin::Method>]
352
359
  result = []
353
360
  skip = Set.new
354
361
  if rooted_tag == ''
@@ -775,8 +782,8 @@ module Solargraph
775
782
 
776
783
  # Sort an array of pins to put nil or undefined variables last.
777
784
  #
778
- # @param pins [Enumerable<Solargraph::Pin::Base>]
779
- # @return [Enumerable<Solargraph::Pin::Base>]
785
+ # @param pins [Enumerable<Pin::BaseVariable>]
786
+ # @return [Enumerable<Pin::BaseVariable>]
780
787
  def prefer_non_nil_variables pins
781
788
  result = []
782
789
  nil_pins = []
@@ -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
@@ -7,9 +7,15 @@ module Solargraph
7
7
  #
8
8
  class UniqueType
9
9
  include TypeMethods
10
+ include Equality
10
11
 
11
12
  attr_reader :all_params, :subtypes, :key_types
12
13
 
14
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
15
+ protected def equality_fields
16
+ [@name, @all_params, @subtypes, @key_types]
17
+ end
18
+
13
19
  # Create a UniqueType with the specified name and an optional substring.
14
20
  # The substring is the parameter section of a parametrized type, e.g.,
15
21
  # for the type `Array<String>`, the name is `Array` and the substring is
@@ -112,6 +118,10 @@ module Solargraph
112
118
  end
113
119
  end
114
120
 
121
+ def desc
122
+ rooted_tags
123
+ end
124
+
115
125
  # @return [String]
116
126
  def to_rbs
117
127
  if duck_type?
@@ -235,7 +245,17 @@ module Solargraph
235
245
  if t.name == GENERIC_TAG_NAME
236
246
  idx = definitions.generics.index(t.subtypes.first&.name)
237
247
  next t if idx.nil?
238
- context_type.all_params[idx] || ComplexType::UNDEFINED
248
+ if context_type.parameters_type == :hash
249
+ if idx == 0
250
+ next ComplexType.new(context_type.key_types)
251
+ elsif idx == 1
252
+ next ComplexType.new(context_type.subtypes)
253
+ else
254
+ next ComplexType::UNDEFINED
255
+ end
256
+ else
257
+ context_type.all_params[idx] || ComplexType::UNDEFINED
258
+ end
239
259
  else
240
260
  t
241
261
  end