solargraph 0.53.3 → 0.54.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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -0
  3. data/lib/solargraph/api_map/cache.rb +2 -12
  4. data/lib/solargraph/api_map/store.rb +11 -6
  5. data/lib/solargraph/api_map.rb +80 -26
  6. data/lib/solargraph/complex_type/type_methods.rb +62 -30
  7. data/lib/solargraph/complex_type/unique_type.rb +117 -66
  8. data/lib/solargraph/complex_type.rb +41 -25
  9. data/lib/solargraph/doc_map.rb +19 -3
  10. data/lib/solargraph/gem_pins.rb +9 -1
  11. data/lib/solargraph/language_server/host/dispatch.rb +8 -1
  12. data/lib/solargraph/language_server/host/sources.rb +1 -61
  13. data/lib/solargraph/language_server/host.rb +39 -68
  14. data/lib/solargraph/language_server/message/base.rb +1 -1
  15. data/lib/solargraph/language_server/message/initialize.rb +14 -0
  16. data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -0
  17. data/lib/solargraph/language_server/progress.rb +118 -0
  18. data/lib/solargraph/language_server.rb +1 -0
  19. data/lib/solargraph/library.rb +136 -96
  20. data/lib/solargraph/parser/node_processor/base.rb +3 -2
  21. data/lib/solargraph/parser/node_processor.rb +1 -0
  22. data/lib/solargraph/parser/parser_gem/class_methods.rb +3 -7
  23. data/lib/solargraph/parser/parser_gem/node_methods.rb +0 -4
  24. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +47 -0
  25. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +5 -3
  26. data/lib/solargraph/parser/parser_gem/node_processors.rb +2 -0
  27. data/lib/solargraph/pin/base_variable.rb +34 -5
  28. data/lib/solargraph/pin/block.rb +62 -7
  29. data/lib/solargraph/pin/delegated_method.rb +5 -1
  30. data/lib/solargraph/pin/documenting.rb +2 -0
  31. data/lib/solargraph/pin/method.rb +4 -2
  32. data/lib/solargraph/pin/parameter.rb +5 -28
  33. data/lib/solargraph/rbs_map/conversions.rb +12 -6
  34. data/lib/solargraph/rbs_map/core_fills.rb +4 -1
  35. data/lib/solargraph/rbs_map.rb +11 -3
  36. data/lib/solargraph/shell.rb +18 -13
  37. data/lib/solargraph/source/chain.rb +20 -0
  38. data/lib/solargraph/source/updater.rb +1 -0
  39. data/lib/solargraph/source.rb +0 -44
  40. data/lib/solargraph/source_map/clip.rb +1 -0
  41. data/lib/solargraph/source_map/mapper.rb +3 -2
  42. data/lib/solargraph/source_map.rb +10 -0
  43. data/lib/solargraph/type_checker.rb +44 -18
  44. data/lib/solargraph/version.rb +1 -1
  45. data/lib/solargraph/workspace/config.rb +2 -1
  46. data/lib/solargraph/workspace.rb +13 -0
  47. data/lib/solargraph/yard_map/mapper/to_method.rb +5 -2
  48. metadata +4 -3
  49. data/lib/solargraph/language_server/host/cataloger.rb +0 -57
@@ -268,6 +268,7 @@ module Solargraph
268
268
  base = base.base
269
269
  end
270
270
  closest = found.typify(api_map) if found
271
+ # @todo remove the internal_or_core? check at a higher-than-strict level
271
272
  if !found || found.is_a?(Pin::BaseVariable) || (closest.defined? && internal_or_core?(found))
272
273
  unless closest.generic? || ignored_pins.include?(found)
273
274
  result.push Problem.new(location, "Unresolved call to #{missing.links.last.word}")
@@ -290,13 +291,19 @@ module Solargraph
290
291
  result = []
291
292
  base = chain
292
293
  until base.links.length == 1 && base.undefined?
294
+ last_base_link = base.links.last
295
+ break unless last_base_link.is_a?(Solargraph::Source::Chain::Call)
296
+
297
+ arguments = last_base_link.arguments
298
+
293
299
  pins = base.define(api_map, block_pin, locals)
294
300
 
295
- if pins.first.is_a?(Pin::DelegatedMethod) && !pins.first.resolvable?(api_map)
301
+ first_pin = pins.first
302
+ if first_pin.is_a?(Pin::DelegatedMethod) && !first_pin.resolvable?(api_map)
296
303
  # Do nothing, as we can't find the actual method implementation
297
- elsif pins.first.is_a?(Pin::Method)
304
+ elsif first_pin.is_a?(Pin::Method)
298
305
  # @type [Pin::Method]
299
- pin = pins.first
306
+ pin = first_pin
300
307
  ap = if base.links.last.is_a?(Solargraph::Source::Chain::ZSuper)
301
308
  arity_problems_for(pin, fake_args_for(block_pin), location)
302
309
  elsif pin.path == 'Class#new'
@@ -306,9 +313,9 @@ module Solargraph
306
313
  base.base.infer(api_map, block_pin, locals).namespace
307
314
  end
308
315
  init = api_map.get_method_stack(fqns, 'initialize').first
309
- init ? arity_problems_for(init, base.links.last.arguments, location) : []
316
+ init ? arity_problems_for(init, arguments, location) : []
310
317
  else
311
- arity_problems_for(pin, base.links.last.arguments, location)
318
+ arity_problems_for(pin, arguments, location)
312
319
  end
313
320
  unless ap.empty?
314
321
  result.concat ap
@@ -321,24 +328,26 @@ module Solargraph
321
328
  all_errors = []
322
329
  pin.signatures.sort { |sig| sig.parameters.length }.each do |sig|
323
330
  errors = []
324
- # @todo these should be able to be probed
325
- # @param par [Parameter]
326
- # @param idx [Integer]
327
331
  sig.parameters.each_with_index do |par, idx|
328
- argchain = base.links.last.arguments[idx]
332
+ # @todo add logic mapping up restarg parameters with
333
+ # arguments (including restarg arguments). Use tuples
334
+ # when possible, and when not, ensure provably
335
+ # incorrect situations are detected.
336
+ break if par.decl == :restarg # bail out pending better arg processing
337
+ argchain = arguments[idx]
329
338
  if argchain.nil?
330
339
  if par.decl == :arg
331
- last = base.links.last.arguments.last
332
- if last && last.node.type == :splat
333
- argchain = last
340
+ final_arg = arguments.last
341
+ if final_arg && final_arg.node.type == :splat
342
+ argchain = final_arg
334
343
  next # don't try to apply the type of the splat - unlikely to be specific enough
335
344
  else
336
345
  errors.push Problem.new(location, "Not enough arguments to #{pin.path}")
337
346
  next
338
347
  end
339
348
  else
340
- last = base.links.last.arguments.last
341
- argchain = last if last && [:kwsplat, :hash].include?(last.node.type)
349
+ final_arg = arguments.last
350
+ argchain = final_arg if final_arg && [:kwsplat, :hash].include?(final_arg.node.type)
342
351
  end
343
352
  end
344
353
  if argchain
@@ -346,9 +355,26 @@ module Solargraph
346
355
  errors.concat kwarg_problems_for sig, argchain, api_map, block_pin, locals, location, pin, params, idx
347
356
  next
348
357
  else
349
- last = base.links.last.arguments.last
350
- if last && last.node.type == :splat
351
- next # don't try to apply the type of the splat - unlikely to be specific enough
358
+ if argchain.node.type == :splat && argchain == arguments.last
359
+ final_arg = argchain
360
+ end
361
+ if (final_arg && final_arg.node.type == :splat)
362
+ # The final argument given has been seen and was a
363
+ # splat, which doesn't give us useful types or
364
+ # arities against positional parameters, so let's
365
+ # continue on in case there are any required
366
+ # kwargs we should warn about
367
+ next
368
+ end
369
+
370
+ if argchain.node.type == :splat && par != sig.parameters.last
371
+ # we have been given a splat and there are more
372
+ # arguments to come.
373
+
374
+ # @todo Improve this so that we can skip past the
375
+ # rest of the positional parameters here but still
376
+ # process the kwargs
377
+ break
352
378
  end
353
379
  ptype = params.key?(par.name) ? params[par.name][:qualified] : ComplexType::UNDEFINED
354
380
  ptype = ptype.self_to(par.context.namespace)
@@ -461,7 +487,7 @@ module Solargraph
461
487
  def first_param_hash(pins)
462
488
  pins.each do |pin|
463
489
  # @todo this assignment from parametric use of Hash should not lose its generic
464
- # @type [Hash{String => Hash{Symbol => BasicObject}]
490
+ # @type [Hash{String => Hash{Symbol => BasicObject}}]
465
491
  result = param_hash(pin)
466
492
  return result unless result.empty?
467
493
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solargraph
4
- VERSION = '0.53.3'
4
+ VERSION = '0.54.0'
5
5
  end
@@ -14,7 +14,8 @@ module Solargraph
14
14
  # @return [String]
15
15
  attr_reader :directory
16
16
 
17
- # @return [Hash{String => BasicObject}]
17
+ # @todo To make this strongly typed we'll need a record syntax
18
+ # @return [Hash{String => undefined}]
18
19
  attr_reader :raw_data
19
20
 
20
21
  # @param directory [String]
@@ -128,6 +128,11 @@ module Solargraph
128
128
  end
129
129
  end
130
130
 
131
+ # @return [String, nil]
132
+ def rbs_collection_path
133
+ @gem_rbs_collection ||= read_rbs_collection_path
134
+ end
135
+
131
136
  # Synchronize the workspace from the provided updater.
132
137
  #
133
138
  # @param updater [Source::Updater]
@@ -222,5 +227,13 @@ module Solargraph
222
227
  end
223
228
  end
224
229
  end
230
+
231
+ # @return [String, nil]
232
+ def read_rbs_collection_path
233
+ yaml_file = File.join(directory, 'rbs_collection.yaml')
234
+ return unless File.file?(yaml_file)
235
+
236
+ YAML.load_file(yaml_file)&.fetch('path')
237
+ end
225
238
  end
226
239
  end
@@ -19,17 +19,20 @@ module Solargraph
19
19
  gates: [code_object.namespace.to_s]
20
20
  )
21
21
  location = object_location(code_object, spec)
22
+ name ||= code_object.name.to_s
23
+ return_type = ComplexType::SELF if name == 'new'
22
24
  comments = code_object.docstring ? code_object.docstring.all.to_s : ''
23
25
  pin = Pin::Method.new(
24
26
  location: location,
25
27
  closure: closure,
26
- name: name || code_object.name.to_s,
28
+ name: name,
27
29
  comments: comments,
28
30
  scope: scope || code_object.scope,
29
31
  visibility: visibility || code_object.visibility,
30
32
  # @todo Might need to convert overloads to signatures
31
33
  parameters: [],
32
- explicit: code_object.is_explicit?
34
+ explicit: code_object.is_explicit?,
35
+ return_type: return_type
33
36
  )
34
37
  pin.parameters.concat get_parameters(code_object, location, comments, pin)
35
38
  pin
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solargraph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.53.3
4
+ version: 0.54.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-03-29 00:00:00.000000000 Z
11
+ date: 2025-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backport
@@ -428,7 +428,6 @@ files:
428
428
  - lib/solargraph/language_server/completion_item_kinds.rb
429
429
  - lib/solargraph/language_server/error_codes.rb
430
430
  - lib/solargraph/language_server/host.rb
431
- - lib/solargraph/language_server/host/cataloger.rb
432
431
  - lib/solargraph/language_server/host/diagnoser.rb
433
432
  - lib/solargraph/language_server/host/dispatch.rb
434
433
  - lib/solargraph/language_server/host/message_worker.rb
@@ -479,6 +478,7 @@ files:
479
478
  - lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb
480
479
  - lib/solargraph/language_server/message/workspace/workspace_symbol.rb
481
480
  - lib/solargraph/language_server/message_types.rb
481
+ - lib/solargraph/language_server/progress.rb
482
482
  - lib/solargraph/language_server/request.rb
483
483
  - lib/solargraph/language_server/symbol_kinds.rb
484
484
  - lib/solargraph/language_server/transport.rb
@@ -511,6 +511,7 @@ files:
511
511
  - lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb
512
512
  - lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb
513
513
  - lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb
514
+ - lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb
514
515
  - lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb
515
516
  - lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb
516
517
  - lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module LanguageServer
5
- class Host
6
- # An asynchronous library cataloging handler.
7
- #
8
- class Cataloger
9
- # @param host [Host]
10
- def initialize host
11
- @host = host
12
- @stopped = true
13
- end
14
-
15
- # Stop the catalog thread.
16
- #
17
- # @return [void]
18
- def stop
19
- @stopped = true
20
- end
21
-
22
- # True if the cataloger is stopped.
23
- #
24
- # @return [Boolean]
25
- def stopped?
26
- @stopped
27
- end
28
-
29
- # Start the catalog thread.
30
- #
31
- # @return [void]
32
- def start
33
- return unless stopped?
34
- @stopped = false
35
- Thread.new do
36
- until stopped?
37
- tick
38
- sleep 0.1
39
- end
40
- end
41
- end
42
-
43
- # Perform cataloging.
44
- #
45
- # @return [void]
46
- def tick
47
- host.catalog
48
- end
49
-
50
- private
51
-
52
- # @return [Host]
53
- attr_reader :host
54
- end
55
- end
56
- end
57
- end