solargraph 0.60.4 → 0.61.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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/plugins.yml +1 -1
  3. data/.github/workflows/rspec.yml +3 -1
  4. data/CHANGELOG.md +16 -0
  5. data/Gemfile +0 -3
  6. data/lib/solargraph/api_map/index.rb +15 -2
  7. data/lib/solargraph/api_map/store.rb +13 -0
  8. data/lib/solargraph/api_map.rb +60 -81
  9. data/lib/solargraph/cache_dir.rb +58 -0
  10. data/lib/solargraph/collection/base.rb +50 -0
  11. data/lib/solargraph/collection/core.rb +17 -0
  12. data/lib/solargraph/collection/gem.rb +57 -0
  13. data/lib/solargraph/collection/rbs.rb +49 -0
  14. data/lib/solargraph/collection/stdlib.rb +25 -0
  15. data/lib/solargraph/collection.rb +31 -0
  16. data/lib/solargraph/convention.rb +5 -3
  17. data/lib/solargraph/diagnostics/require_not_found.rb +0 -4
  18. data/lib/solargraph/external.rb +159 -0
  19. data/lib/solargraph/language_server/message/text_document/definition.rb +4 -1
  20. data/lib/solargraph/language_server/message/text_document/hover.rb +1 -2
  21. data/lib/solargraph/library.rb +11 -24
  22. data/lib/solargraph/metagem.rb +80 -0
  23. data/lib/solargraph/parser/parser_gem/node_chainer.rb +22 -3
  24. data/lib/solargraph/pin/closure.rb +17 -0
  25. data/lib/solargraph/pin/factory_parameter.rb +84 -0
  26. data/lib/solargraph/pin.rb +1 -0
  27. data/lib/solargraph/rbs_map/base.rb +31 -0
  28. data/lib/solargraph/rbs_map/conversions.rb +3 -1
  29. data/lib/solargraph/rbs_map/{core_map.rb → core.rb} +18 -39
  30. data/lib/solargraph/rbs_map/core_fills.rb +1 -1
  31. data/lib/solargraph/rbs_map/gem.rb +13 -0
  32. data/lib/solargraph/rbs_map/helpers.rb +60 -0
  33. data/lib/solargraph/rbs_map/path.rb +19 -0
  34. data/lib/solargraph/rbs_map/stdlib.rb +24 -0
  35. data/lib/solargraph/rbs_map.rb +7 -198
  36. data/lib/solargraph/repo.rb +177 -0
  37. data/lib/solargraph/shell.rb +49 -99
  38. data/lib/solargraph/source/chain/call.rb +29 -4
  39. data/lib/solargraph/source/chain/literal.rb +17 -17
  40. data/lib/solargraph/source/chain/parameter.rb +79 -0
  41. data/lib/solargraph/source/chain.rb +8 -0
  42. data/lib/solargraph/source/source_chainer.rb +40 -44
  43. data/lib/solargraph/source_map/clip.rb +5 -3
  44. data/lib/solargraph/source_map/mapper.rb +6 -2
  45. data/lib/solargraph/source_map.rb +10 -5
  46. data/lib/solargraph/type_checker/rules.rb +2 -1
  47. data/lib/solargraph/version.rb +1 -1
  48. data/lib/solargraph/workspace.rb +0 -1
  49. data/lib/solargraph/yard_map/cache.rb +1 -1
  50. data/lib/solargraph/yard_map/directives/attribute_directive.rb +1 -1
  51. data/lib/solargraph/yard_map/directives/domain_directive.rb +1 -1
  52. data/lib/solargraph/yard_map/directives/method_directive.rb +1 -1
  53. data/lib/solargraph/yard_map/directives/override_directive.rb +1 -1
  54. data/lib/solargraph/yard_map/directives/parse_directive.rb +1 -1
  55. data/lib/solargraph/yard_map/directives/scope_directive.rb +178 -0
  56. data/lib/solargraph/yard_map/directives/visibility_directive.rb +1 -1
  57. data/lib/solargraph/yard_map/directives.rb +5 -2
  58. data/lib/solargraph/yard_map/helpers.rb +1 -1
  59. data/lib/solargraph/yard_map/macro.rb +34 -5
  60. data/lib/solargraph/yard_map/mapper/to_constant.rb +1 -1
  61. data/lib/solargraph/yard_map/mapper/to_method.rb +1 -1
  62. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -1
  63. data/lib/solargraph/yard_map/mapper.rb +2 -2
  64. data/lib/solargraph/yard_map.rb +1 -1
  65. data/lib/solargraph/yardoc.rb +43 -60
  66. data/lib/solargraph.rb +6 -3
  67. data/solargraph.gemspec +1 -1
  68. metadata +22 -9
  69. data/lib/solargraph/doc_map.rb +0 -439
  70. data/lib/solargraph/gem_pins.rb +0 -87
  71. data/lib/solargraph/pin_cache.rb +0 -248
  72. data/lib/solargraph/rbs_map/stdlib_map.rb +0 -71
  73. data/lib/solargraph/workspace/gemspecs.rb +0 -373
@@ -1,439 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'pathname'
4
- require 'benchmark'
5
- require 'open3'
6
-
7
- module Solargraph
8
- # A collection of pins generated from required gems.
9
- #
10
- class DocMap
11
- include Logging
12
-
13
- # @return [Array<String>]
14
- attr_reader :requires
15
- alias required requires
16
-
17
- # @return [Array<Gem::Specification>]
18
- attr_reader :preferences
19
-
20
- # @return [Array<Pin::Base>]
21
- attr_reader :pins
22
-
23
- # @return [Array<Gem::Specification>]
24
- def uncached_gemspecs
25
- uncached_yard_gemspecs.concat(uncached_rbs_collection_gemspecs)
26
- .sort
27
- .uniq { |gemspec| "#{gemspec.name}:#{gemspec.version}" }
28
- end
29
-
30
- # @return [Array<Gem::Specification>]
31
- attr_reader :uncached_yard_gemspecs
32
-
33
- # @return [Array<Gem::Specification>]
34
- attr_reader :uncached_rbs_collection_gemspecs
35
-
36
- # @return [String, nil]
37
- attr_reader :rbs_collection_path
38
-
39
- # @return [String, nil]
40
- attr_reader :rbs_collection_config_path
41
-
42
- # @return [Workspace, nil]
43
- attr_reader :workspace
44
-
45
- # @return [Environ]
46
- attr_reader :environ
47
-
48
- # @param requires [Array<String>]
49
- # @param workspace [Workspace, nil]
50
- # @param [Object] out
51
- def initialize requires, workspace, out: $stderr
52
- @requires = requires.compact
53
- @workspace = workspace
54
- @rbs_collection_path = workspace&.rbs_collection_path
55
- @rbs_collection_config_path = workspace&.rbs_collection_config_path
56
- @environ = Convention.for_global(self)
57
- @requires.concat @environ.requires if @environ
58
- load_serialized_gem_pins
59
- pins.concat @environ.pins
60
- @out = out
61
- end
62
-
63
- # @param out [IO, StringIO, nil]
64
- # @return [void]
65
- # @param [Boolean] rebuild
66
- def cache_all! out, rebuild: false
67
- # if we log at debug level:
68
- if logger.info?
69
- gem_desc = uncached_gemspecs.map { |gemspec| "#{gemspec.name}:#{gemspec.version}" }.join(', ')
70
- logger.info "Caching pins for gems: #{gem_desc}" unless uncached_gemspecs.empty?
71
- end
72
- logger.debug { "Caching for YARD: #{uncached_yard_gemspecs.map(&:name)}" }
73
- logger.debug { "Caching for RBS collection: #{uncached_rbs_collection_gemspecs.map(&:name)}" }
74
- load_serialized_gem_pins
75
- uncached_gemspecs.each do |gemspec|
76
- cache(gemspec, rebuild: rebuild, out: out)
77
- end
78
- load_serialized_gem_pins
79
- @uncached_rbs_collection_gemspecs = []
80
- @uncached_yard_gemspecs = []
81
- end
82
-
83
- # @param gemspec [Gem::Specification]
84
- # @param out [IO, StringIO, nil]
85
- # @return [void]
86
- def cache_yard_pins gemspec, out
87
- pins = GemPins.build_yard_pins(yard_plugins, gemspec)
88
- PinCache.serialize_yard_gem(gemspec, pins)
89
- logger.info { "Cached #{pins.length} YARD pins for gem #{gemspec.name}:#{gemspec.version}" } unless pins.empty?
90
- end
91
-
92
- # @param gemspec [Gem::Specification]
93
- # @param out [IO, StringIO, nil]
94
- # @return [void]
95
- def cache_rbs_collection_pins gemspec, out
96
- rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path)
97
- pins = rbs_map.pins
98
- rbs_version_cache_key = rbs_map.cache_key
99
- # cache pins even if result is zero, so we don't retry building pins
100
- pins ||= []
101
- PinCache.serialize_rbs_collection_gem(gemspec, rbs_version_cache_key, pins)
102
- logger.info { "Cached #{pins.length} RBS collection pins for gem #{gemspec.name} #{gemspec.version} with cache_key #{rbs_version_cache_key.inspect}" unless pins.empty? }
103
- end
104
-
105
- # @param gemspec [Gem::Specification]
106
- # @param rebuild [Boolean] whether to rebuild the pins even if they are cached
107
- # @param out [IO, StringIO, nil] output stream for logging
108
- # @return [void]
109
- def cache gemspec, rebuild: false, out: nil
110
- build_yard = uncached_yard_gemspecs.include?(gemspec) || rebuild
111
- build_rbs_collection = uncached_rbs_collection_gemspecs.include?(gemspec) || rebuild
112
- if build_yard || build_rbs_collection
113
- type = []
114
- type << 'YARD' if build_yard
115
- type << 'RBS collection' if build_rbs_collection
116
- out&.puts("Caching #{type.join(' and ')} pins for gem #{gemspec.name}:#{gemspec.version}")
117
- end
118
- cache_yard_pins(gemspec, out) if build_yard
119
- cache_rbs_collection_pins(gemspec, out) if build_rbs_collection
120
- end
121
-
122
- # @return [Array<Gem::Specification>]
123
- def gemspecs
124
- @gemspecs ||= required_gems_map.values.compact.flatten
125
- end
126
-
127
- # @return [Array<String>]
128
- def unresolved_requires
129
- @unresolved_requires ||= required_gems_map.select { |_, gemspecs| gemspecs.nil? }.keys
130
- end
131
-
132
- # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
133
- def self.all_yard_gems_in_memory
134
- @all_yard_gems_in_memory ||= {}
135
- end
136
-
137
- # @return [Hash{String => Hash{Array(String, String) => Array<Pin::Base>}}] stored by RBS collection path
138
- def self.all_rbs_collection_gems_in_memory
139
- @all_rbs_collection_gems_in_memory ||= {}
140
- end
141
-
142
- # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
143
- def yard_pins_in_memory
144
- self.class.all_yard_gems_in_memory
145
- end
146
-
147
- # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
148
- def rbs_collection_pins_in_memory
149
- # @sg-ignore rbs_collection_path is String | nil but used as hash key
150
- self.class.all_rbs_collection_gems_in_memory[rbs_collection_path] ||= {}
151
- end
152
-
153
- # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
154
- def self.all_combined_pins_in_memory
155
- @all_combined_pins_in_memory ||= {}
156
- end
157
-
158
- # @todo this should also include an index by the hash of the RBS collection
159
- # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
160
- def combined_pins_in_memory
161
- self.class.all_combined_pins_in_memory
162
- end
163
-
164
- # @return [Array<String>]
165
- def yard_plugins
166
- @environ.yard_plugins
167
- end
168
-
169
- # @return [Set<Gem::Specification>]
170
- def dependencies
171
- @dependencies ||= (gemspecs.flat_map { |spec| fetch_dependencies(spec) } - gemspecs).to_set
172
- end
173
-
174
- private
175
-
176
- # @return [void]
177
- def load_serialized_gem_pins
178
- @pins = []
179
- @uncached_yard_gemspecs = []
180
- @uncached_rbs_collection_gemspecs = []
181
- with_gemspecs, without_gemspecs = required_gems_map.partition { |_, v| v }
182
- # @type [Array<String>]
183
- paths = without_gemspecs.to_h.keys
184
- # @type [Array<Gem::Specification>]
185
- gemspecs = with_gemspecs.to_h.values.flatten.compact + dependencies.to_a
186
-
187
- paths.each do |path|
188
- deserialize_stdlib_rbs_map path
189
- end
190
-
191
- logger.debug { 'DocMap#load_serialized_gem_pins: Combining pins...' }
192
- time = Benchmark.measure do
193
- gemspecs.each do |gemspec|
194
- pins = deserialize_combined_pin_cache gemspec
195
- @pins.concat pins if pins
196
- end
197
- end
198
- logger.info { "DocMap#load_serialized_gem_pins: Loaded and processed serialized pins together in #{time.real} seconds" }
199
- @uncached_yard_gemspecs.uniq!
200
- @uncached_rbs_collection_gemspecs.uniq!
201
- nil
202
- end
203
-
204
- # @return [Hash{String => Array<Gem::Specification>}]
205
- def required_gems_map
206
- @required_gems_map ||= requires.to_h { |path| [path, resolve_path_to_gemspecs(path)] }
207
- end
208
-
209
- # @return [Hash{String => Gem::Specification}]
210
- def preference_map
211
- @preference_map ||= preferences.to_h { |gemspec| [gemspec.name, gemspec] }
212
- end
213
-
214
- # @param gemspec [Gem::Specification]
215
- # @return [Array<Pin::Base>, nil]
216
- def deserialize_yard_pin_cache gemspec
217
- if yard_pins_in_memory.key?([gemspec.name, gemspec.version])
218
- return yard_pins_in_memory[[gemspec.name, gemspec.version]]
219
- end
220
-
221
- cached = PinCache.deserialize_yard_gem(gemspec)
222
- if cached
223
- logger.info { "Loaded #{cached.length} cached YARD pins from #{gemspec.name}:#{gemspec.version}" }
224
- yard_pins_in_memory[[gemspec.name, gemspec.version]] = cached
225
- cached
226
- else
227
- logger.debug "No YARD pin cache for #{gemspec.name}:#{gemspec.version}"
228
- @uncached_yard_gemspecs.push gemspec
229
- nil
230
- end
231
- end
232
-
233
- # @param gemspec [Gem::Specification]
234
- # @return [void]
235
- def deserialize_combined_pin_cache gemspec
236
- unless combined_pins_in_memory[[gemspec.name, gemspec.version]].nil?
237
- return combined_pins_in_memory[[gemspec.name, gemspec.version]]
238
- end
239
-
240
- rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path)
241
- rbs_version_cache_key = rbs_map.cache_key
242
-
243
- cached = PinCache.deserialize_combined_gem(gemspec, rbs_version_cache_key)
244
- if cached
245
- logger.info { "Loaded #{cached.length} cached YARD pins from #{gemspec.name}:#{gemspec.version}" }
246
- combined_pins_in_memory[[gemspec.name, gemspec.version]] = cached
247
- return combined_pins_in_memory[[gemspec.name, gemspec.version]]
248
- end
249
-
250
- rbs_collection_pins = deserialize_rbs_collection_cache gemspec, rbs_version_cache_key
251
-
252
- yard_pins = deserialize_yard_pin_cache gemspec
253
-
254
- if !rbs_collection_pins.nil? && !yard_pins.nil?
255
- logger.debug { "Combining pins for #{gemspec.name}:#{gemspec.version}" }
256
- combined_pins = GemPins.combine(yard_pins, rbs_collection_pins)
257
- PinCache.serialize_combined_gem(gemspec, rbs_version_cache_key, combined_pins)
258
- combined_pins_in_memory[[gemspec.name, gemspec.version]] = combined_pins
259
- logger.info { "Generated #{combined_pins_in_memory[[gemspec.name, gemspec.version]].length} combined pins for #{gemspec.name} #{gemspec.version}" }
260
- return combined_pins
261
- end
262
-
263
- if !yard_pins.nil?
264
- logger.debug { "Using only YARD pins for #{gemspec.name}:#{gemspec.version}" }
265
- combined_pins_in_memory[[gemspec.name, gemspec.version]] = yard_pins
266
- combined_pins_in_memory[[gemspec.name, gemspec.version]]
267
- elsif !rbs_collection_pins.nil?
268
- logger.debug { "Using only RBS collection pins for #{gemspec.name}:#{gemspec.version}" }
269
- combined_pins_in_memory[[gemspec.name, gemspec.version]] = rbs_collection_pins
270
- combined_pins_in_memory[[gemspec.name, gemspec.version]]
271
- else
272
- logger.debug { "Pins not yet cached for #{gemspec.name}:#{gemspec.version}" }
273
- nil
274
- end
275
- end
276
-
277
- # @param path [String] require path that might be in the RBS stdlib collection
278
- # @return [void]
279
- def deserialize_stdlib_rbs_map path
280
- map = RbsMap::StdlibMap.load(path)
281
- if map.resolved?
282
- logger.debug { "Loading stdlib pins for #{path}" }
283
- @pins.concat map.pins
284
- logger.debug { "Loaded #{map.pins.length} stdlib pins for #{path}" }
285
- map.pins
286
- else
287
- # @todo Temporarily ignoring unresolved `require 'set'`
288
- logger.debug { "Require path #{path} could not be resolved in RBS" } unless path == 'set'
289
- nil
290
- end
291
- end
292
-
293
- # @param gemspec [Gem::Specification]
294
- # @param rbs_version_cache_key [String]
295
- # @return [Array<Pin::Base>, nil]
296
- def deserialize_rbs_collection_cache gemspec, rbs_version_cache_key
297
- return if rbs_collection_pins_in_memory.key?([gemspec, rbs_version_cache_key])
298
- cached = PinCache.deserialize_rbs_collection_gem(gemspec, rbs_version_cache_key)
299
- if cached
300
- logger.info { "Loaded #{cached.length} pins from RBS collection cache for #{gemspec.name}:#{gemspec.version}" } unless cached.empty?
301
- rbs_collection_pins_in_memory[[gemspec, rbs_version_cache_key]] = cached
302
- cached
303
- else
304
- logger.debug "No RBS collection pin cache for #{gemspec.name} #{gemspec.version}"
305
- @uncached_rbs_collection_gemspecs.push gemspec
306
- nil
307
- end
308
- end
309
-
310
- # @param path [String]
311
- # @return [::Array<Gem::Specification>, nil]
312
- def resolve_path_to_gemspecs path
313
- return nil if path.empty?
314
- return gemspecs_required_from_bundler if path == 'bundler/require'
315
-
316
- # @type [Gem::Specification, nil]
317
- gemspec = Gem::Specification.find_by_path(path)
318
- if gemspec.nil?
319
- gem_name_guess = path.split('/').first
320
- return nil if gem_name_guess.to_s.empty?
321
- begin
322
- # this can happen when the gem is included via a local path in
323
- # a Gemfile; Gem doesn't try to index the paths in that case.
324
- #
325
- # See if we can make a good guess:
326
- gemspec = Gem::Specification.find_by_name(gem_name_guess)
327
- rescue Gem::MissingSpecError
328
- logger.debug { "Require path #{path} could not be resolved to a gem via find_by_path or guess of #{gem_name_guess}" }
329
- []
330
- end
331
- end
332
- return nil if gemspec.nil?
333
- [gemspec_or_preference(gemspec)]
334
- end
335
-
336
- # @param gemspec [Gem::Specification]
337
- # @return [Gem::Specification]
338
- def gemspec_or_preference gemspec
339
- # :nocov: dormant feature
340
- return gemspec unless preference_map.key?(gemspec.name)
341
- return gemspec if gemspec.version == preference_map[gemspec.name].version
342
-
343
- change_gemspec_version gemspec, preference_map[gemspec.name].version
344
- # :nocov:
345
- end
346
-
347
- # @param gemspec [Gem::Specification]
348
- # @param version [Gem::Version, String]
349
- # @return [Gem::Specification]
350
- def change_gemspec_version gemspec, version
351
- Gem::Specification.find_by_name(gemspec.name, "= #{version}")
352
- rescue Gem::MissingSpecError
353
- Solargraph.logger.info "Gem #{gemspec.name} version #{version} not found. Using #{gemspec.version} instead"
354
- gemspec
355
- end
356
-
357
- # @param gemspec [Gem::Specification]
358
- # @return [Array<Gem::Specification>]
359
- def fetch_dependencies gemspec
360
- # @param spec [Gem::Dependency]
361
- # @param deps [Set<Gem::Specification>]
362
- only_runtime_dependencies(gemspec).each_with_object(Set.new) do |spec, deps|
363
- Solargraph.logger.info "Adding #{spec.name} dependency for #{gemspec.name}"
364
- dep = Gem.loaded_specs[spec.name]
365
- # @todo is next line necessary?
366
- dep ||= Gem::Specification.find_by_name(spec.name, spec.requirement)
367
- deps.merge fetch_dependencies(dep) if deps.add?(dep)
368
- rescue Gem::MissingSpecError
369
- Solargraph.logger.warn "Gem dependency #{spec.name} for #{gemspec.name} not found in RubyGems."
370
- end.to_a
371
- end
372
-
373
- # @param gemspec [Gem::Specification]
374
- # @return [Array<Gem::Dependency>]
375
- def only_runtime_dependencies gemspec
376
- gemspec.dependencies - gemspec.development_dependencies
377
- end
378
-
379
- def inspect
380
- self.class.inspect
381
- end
382
-
383
- # @return [Array<Gem::Specification>, nil]
384
- def gemspecs_required_from_bundler
385
- # @todo Handle projects with custom Bundler/Gemfile setups
386
- return unless workspace&.gemfile?
387
-
388
- # @sg-ignore workspace is checked for nil above
389
- if workspace.gemfile? && Bundler.definition&.lockfile&.to_s&.start_with?(workspace.directory) # rubocop:disable Style/SafeNavigationChainLength
390
- # Find only the gems bundler is now using
391
- Bundler.definition.locked_gems.specs.flat_map do |lazy_spec|
392
- logger.info "Handling #{lazy_spec.name}:#{lazy_spec.version}"
393
- [Gem::Specification.find_by_name(lazy_spec.name, lazy_spec.version)]
394
- rescue Gem::MissingSpecError => e
395
- logger.info("Could not find #{lazy_spec.name}:#{lazy_spec.version} with find_by_name, falling back to guess")
396
- # can happen in local filesystem references
397
- specs = resolve_path_to_gemspecs lazy_spec.name
398
- logger.warn "Gem #{lazy_spec.name} #{lazy_spec.version} from bundle not found: #{e}" if specs.nil?
399
- next specs
400
- end.compact
401
- else
402
- logger.info 'Fetching gemspecs required from Bundler (bundler/require)'
403
- gemspecs_required_from_external_bundle
404
- end
405
- end
406
-
407
- # @return [Array<Gem::Specification>]
408
- def gemspecs_required_from_external_bundle
409
- logger.info 'Fetching gemspecs required from external bundle'
410
- return [] unless workspace&.directory
411
-
412
- Solargraph.with_clean_env do
413
- cmd = [
414
- 'ruby', '-e',
415
- # @sg-ignore return above ensures workspace.directory is not nil
416
- "require 'bundler'; require 'json'; Dir.chdir('#{workspace.directory}') { puts Bundler.definition.locked_gems.specs.map { |spec| [spec.name, spec.version] }.to_h.to_json }"
417
- ]
418
- o, e, s = Open3.capture3(*cmd)
419
- if s.success?
420
- Solargraph.logger.debug "External bundle: #{o}"
421
- hash = o && !o.empty? ? JSON.parse(o.split("\n").last) : {}
422
- hash.flat_map do |name, version|
423
- Gem::Specification.find_by_name(name, version)
424
- rescue Gem::MissingSpecError => e
425
- logger.info("Could not find #{name}:#{version} with find_by_name, falling back to guess")
426
- # can happen in local filesystem references
427
- specs = resolve_path_to_gemspecs name
428
- logger.warn "Gem #{name} #{version} from bundle not found: #{e}" if specs.nil?
429
- next specs
430
- end.compact
431
- else
432
- # @sg-ignore return above ensures workspace.directory is not nil
433
- Solargraph.logger.warn "Failed to load gems from bundle at #{workspace.directory}: #{e}"
434
- []
435
- end
436
- end
437
- end
438
- end
439
- end
@@ -1,87 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rbs'
4
-
5
- module Solargraph
6
- # A utility for building gem pins from a combination of YARD and RBS
7
- # documentation.
8
- #
9
- module GemPins
10
- class << self
11
- include Logging
12
- end
13
-
14
- # @param pins [Array<Pin::Method>]
15
- # @return [Pin::Method, nil]
16
- def self.combine_method_pins(*pins)
17
- # @type [Pin::Method, nil]
18
- combined_pin = nil
19
- # @param memo [Pin::Method, nil]
20
- # @param pin [Pin::Method]
21
- out = pins.reduce(combined_pin) do |memo, pin|
22
- next pin if memo.nil?
23
- if memo == pin && memo.source != :combined
24
- # @todo we should track down situations where we are handled
25
- # the same pin from the same source here and eliminate them -
26
- # this is an efficiency workaround for now
27
- next memo
28
- end
29
- memo.combine_with(pin)
30
- end
31
- logger.debug { "GemPins.combine_method_pins(pins.length=#{pins.length}, pins=#{pins}) => #{out.inspect}" }
32
- out
33
- end
34
-
35
- # @param yard_plugins [Array<String>] The names of YARD plugins to use.
36
- # @param gemspec [Gem::Specification]
37
- # @return [Array<Pin::Base>]
38
- def self.build_yard_pins yard_plugins, gemspec
39
- Yardoc.cache(yard_plugins, gemspec) unless Yardoc.cached?(gemspec)
40
- return [] unless Yardoc.cached?(gemspec)
41
- yardoc = Yardoc.load!(gemspec)
42
- YardMap::Mapper.new(yardoc, gemspec).map
43
- end
44
-
45
- # @param yard_pins [Array<Pin::Base>]
46
- # @param rbs_pins [Array<Pin::Base>]
47
- #
48
- # @return [Array<Pin::Base>]
49
- def self.combine yard_pins, rbs_pins
50
- in_yard = Set.new
51
- rbs_api_map = Solargraph::ApiMap.new(pins: rbs_pins)
52
- combined = yard_pins.map do |yard_pin|
53
- in_yard.add yard_pin.path
54
- rbs_pin = rbs_api_map.get_path_pins(yard_pin.path).filter { |pin| pin.is_a? Pin::Method }.first
55
- next yard_pin unless rbs_pin && yard_pin.instance_of?(Pin::Method)
56
-
57
- unless rbs_pin
58
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
59
- logger.debug { "GemPins.combine: No rbs pin for #{yard_pin.path} - using YARD's '#{yard_pin.inspect} (return_type=#{yard_pin.return_type}; signatures=#{yard_pin.signatures})" }
60
- next yard_pin
61
- end
62
-
63
- out = combine_method_pins(rbs_pin, yard_pin)
64
- logger.debug { "GemPins.combine: Combining yard.path=#{yard_pin.path} - rbs=#{rbs_pin.inspect} with yard=#{yard_pin.inspect} into #{out}" }
65
- out
66
- end
67
- in_rbs_only = rbs_pins.select do |pin|
68
- pin.path.nil? || !in_yard.include?(pin.path)
69
- end
70
- out = combined + in_rbs_only
71
- logger.debug { "GemPins#combine: Returning #{out.length} combined pins" }
72
- out
73
- end
74
-
75
- class << self
76
- private
77
-
78
- # Select the first defined type.
79
- #
80
- # @param choices [Array<ComplexType>]
81
- # @return [ComplexType]
82
- def best_return_type *choices
83
- choices.find(&:defined?) || choices.first || ComplexType::UNDEFINED
84
- end
85
- end
86
- end
87
- end