solargraph 0.53.4 → 0.54.1

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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -0
  3. data/lib/solargraph/api_map/cache.rb +2 -12
  4. data/lib/solargraph/api_map/store.rb +14 -5
  5. data/lib/solargraph/api_map.rb +67 -24
  6. data/lib/solargraph/complex_type/type_methods.rb +70 -39
  7. data/lib/solargraph/complex_type/unique_type.rb +187 -73
  8. data/lib/solargraph/complex_type.rb +105 -40
  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/message_worker.rb +29 -3
  13. data/lib/solargraph/language_server/host/sources.rb +1 -61
  14. data/lib/solargraph/language_server/host.rb +21 -68
  15. data/lib/solargraph/language_server/message/base.rb +1 -1
  16. data/lib/solargraph/language_server/message/initialize.rb +14 -0
  17. data/lib/solargraph/language_server/message/text_document/definition.rb +3 -3
  18. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
  19. data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -0
  20. data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
  21. data/lib/solargraph/language_server/message/text_document/type_definition.rb +3 -3
  22. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
  23. data/lib/solargraph/language_server/progress.rb +135 -0
  24. data/lib/solargraph/language_server.rb +1 -0
  25. data/lib/solargraph/library.rb +144 -113
  26. data/lib/solargraph/location.rb +14 -1
  27. data/lib/solargraph/parser/node_processor/base.rb +3 -2
  28. data/lib/solargraph/parser/node_processor.rb +1 -0
  29. data/lib/solargraph/parser/parser_gem/class_methods.rb +3 -7
  30. data/lib/solargraph/parser/parser_gem/node_chainer.rb +13 -7
  31. data/lib/solargraph/parser/parser_gem/node_methods.rb +1 -5
  32. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +23 -19
  33. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -2
  34. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +53 -0
  35. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +6 -4
  36. data/lib/solargraph/parser/parser_gem/node_processors.rb +2 -0
  37. data/lib/solargraph/parser.rb +2 -5
  38. data/lib/solargraph/pin/base.rb +15 -1
  39. data/lib/solargraph/pin/base_variable.rb +35 -6
  40. data/lib/solargraph/pin/block.rb +48 -11
  41. data/lib/solargraph/pin/callable.rb +147 -0
  42. data/lib/solargraph/pin/closure.rb +8 -3
  43. data/lib/solargraph/pin/common.rb +2 -6
  44. data/lib/solargraph/pin/conversions.rb +3 -2
  45. data/lib/solargraph/pin/delegated_method.rb +5 -1
  46. data/lib/solargraph/pin/documenting.rb +2 -0
  47. data/lib/solargraph/pin/instance_variable.rb +2 -2
  48. data/lib/solargraph/pin/method.rb +54 -32
  49. data/lib/solargraph/pin/namespace.rb +4 -4
  50. data/lib/solargraph/pin/parameter.rb +14 -39
  51. data/lib/solargraph/pin/proxy_type.rb +1 -1
  52. data/lib/solargraph/pin/signature.rb +3 -129
  53. data/lib/solargraph/pin.rb +4 -1
  54. data/lib/solargraph/range.rb +2 -4
  55. data/lib/solargraph/rbs_map/conversions.rb +79 -42
  56. data/lib/solargraph/rbs_map/core_fills.rb +6 -6
  57. data/lib/solargraph/rbs_map.rb +11 -3
  58. data/lib/solargraph/shell.rb +35 -15
  59. data/lib/solargraph/source/chain/array.rb +6 -5
  60. data/lib/solargraph/source/chain/block_symbol.rb +1 -1
  61. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  62. data/lib/solargraph/source/chain/call.rb +78 -50
  63. data/lib/solargraph/source/chain/link.rb +9 -0
  64. data/lib/solargraph/source/chain/or.rb +1 -1
  65. data/lib/solargraph/source/chain.rb +60 -16
  66. data/lib/solargraph/source/cursor.rb +13 -2
  67. data/lib/solargraph/source/updater.rb +1 -0
  68. data/lib/solargraph/source.rb +102 -129
  69. data/lib/solargraph/source_map/clip.rb +4 -4
  70. data/lib/solargraph/source_map/data.rb +30 -0
  71. data/lib/solargraph/source_map/mapper.rb +3 -2
  72. data/lib/solargraph/source_map.rb +37 -15
  73. data/lib/solargraph/type_checker/rules.rb +6 -1
  74. data/lib/solargraph/type_checker.rb +50 -25
  75. data/lib/solargraph/version.rb +1 -1
  76. data/lib/solargraph/views/environment.erb +3 -5
  77. data/lib/solargraph/workspace/config.rb +2 -1
  78. data/lib/solargraph/workspace.rb +13 -0
  79. metadata +6 -3
  80. data/lib/solargraph/language_server/host/cataloger.rb +0 -57
@@ -82,7 +82,7 @@ module Solargraph
82
82
  def convert_self_type_to_pins decl, closure
83
83
  include_pin = Solargraph::Pin::Reference::Include.new(
84
84
  name: decl.name.relative!.to_s,
85
- location: rbs_location_to_location(decl.location),
85
+ type_location: location_decl_to_pin_location(decl.location),
86
86
  closure: closure
87
87
  )
88
88
  pins.push include_pin
@@ -144,6 +144,7 @@ module Solargraph
144
144
  name: decl.name.relative!.to_s,
145
145
  closure: Solargraph::Pin::ROOT_PIN,
146
146
  comments: decl.comment&.string,
147
+ type_location: location_decl_to_pin_location(decl.location),
147
148
  # @todo some type parameters in core/stdlib have default
148
149
  # values; Solargraph doesn't support that yet as so these
149
150
  # get treated as undefined if not specified
@@ -152,6 +153,7 @@ module Solargraph
152
153
  pins.push class_pin
153
154
  if decl.super_class
154
155
  pins.push Solargraph::Pin::Reference::Superclass.new(
156
+ type_location: location_decl_to_pin_location(decl.super_class.location),
155
157
  closure: class_pin,
156
158
  name: decl.super_class.name.relative!.to_s
157
159
  )
@@ -166,6 +168,7 @@ module Solargraph
166
168
  def interface_decl_to_pin decl, closure
167
169
  class_pin = Solargraph::Pin::Namespace.new(
168
170
  type: :module,
171
+ type_location: location_decl_to_pin_location(decl.location),
169
172
  name: decl.name.relative!.to_s,
170
173
  closure: Solargraph::Pin::ROOT_PIN,
171
174
  comments: decl.comment&.string,
@@ -185,6 +188,7 @@ module Solargraph
185
188
  module_pin = Solargraph::Pin::Namespace.new(
186
189
  type: :module,
187
190
  name: decl.name.relative!.to_s,
191
+ type_location: location_decl_to_pin_location(decl.location),
188
192
  closure: Solargraph::Pin::ROOT_PIN,
189
193
  comments: decl.comment&.string,
190
194
  generics: decl.type_params.map(&:name).map(&:to_s),
@@ -199,10 +203,11 @@ module Solargraph
199
203
  # @param name [String]
200
204
  # @param tag [String]
201
205
  # @param comments [String]
206
+ # @param decl [RBS::AST::Declarations::ClassAlias, RBS::AST::Declarations::Constant, RBS::AST::Declarations::ModuleAlias]
202
207
  # @param base [String, nil] Optional conversion of tag to base<tag>
203
208
  #
204
209
  # @return [Solargraph::Pin::Constant]
205
- def create_constant(name, tag, comments, base = nil)
210
+ def create_constant(name, tag, comments, decl, base = nil)
206
211
  parts = name.split('::')
207
212
  if parts.length > 1
208
213
  name = parts.last
@@ -214,10 +219,12 @@ module Solargraph
214
219
  constant_pin = Solargraph::Pin::Constant.new(
215
220
  name: name,
216
221
  closure: closure,
222
+ type_location: location_decl_to_pin_location(decl.location),
217
223
  comments: comments
218
224
  )
219
225
  tag = "#{base}<#{tag}>" if base
220
- constant_pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', tag))
226
+ rooted_tag = ComplexType.parse(tag).force_rooted.rooted_tags
227
+ constant_pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', rooted_tag))
221
228
  constant_pin
222
229
  end
223
230
 
@@ -228,7 +235,7 @@ module Solargraph
228
235
  new_name = decl.new_name.relative!.to_s
229
236
  old_name = decl.old_name.relative!.to_s
230
237
 
231
- pins.push create_constant(new_name, old_name, decl.comment&.string, 'Class')
238
+ pins.push create_constant(new_name, old_name, decl.comment&.string, decl, 'Class')
232
239
  end
233
240
 
234
241
  # @param decl [RBS::AST::Declarations::ModuleAlias]
@@ -238,14 +245,14 @@ module Solargraph
238
245
  new_name = decl.new_name.relative!.to_s
239
246
  old_name = decl.old_name.relative!.to_s
240
247
 
241
- pins.push create_constant(new_name, old_name, decl.comment&.string, 'Module')
248
+ pins.push create_constant(new_name, old_name, decl.comment&.string, decl, 'Module')
242
249
  end
243
250
 
244
251
  # @param decl [RBS::AST::Declarations::Constant]
245
252
  # @return [void]
246
253
  def constant_decl_to_pin decl
247
254
  tag = other_type_to_tag(decl.type)
248
- pins.push create_constant(decl.name.relative!.to_s, tag, decl.comment&.string)
255
+ pins.push create_constant(decl.name.relative!.to_s, tag, decl.comment&.string, decl)
249
256
  end
250
257
 
251
258
  # @param decl [RBS::AST::Declarations::Global]
@@ -253,13 +260,13 @@ module Solargraph
253
260
  def global_decl_to_pin decl
254
261
  closure = Solargraph::Pin::ROOT_PIN
255
262
  name = decl.name.to_s
256
- tag = other_type_to_tag(decl.type)
257
263
  pin = Solargraph::Pin::GlobalVariable.new(
258
264
  name: name,
259
265
  closure: closure,
260
266
  comments: decl.comment&.string,
261
267
  )
262
- pin.docstring.add_tag(YARD::Tags::Tag.new(:type, '', tag))
268
+ rooted_tag = ComplexType.parse(other_type_to_tag(decl.type)).force_rooted.rooted_tags
269
+ pin.docstring.add_tag(YARD::Tags::Tag.new(:type, '', rooted_tag))
263
270
  pins.push pin
264
271
  end
265
272
 
@@ -276,6 +283,7 @@ module Solargraph
276
283
  pin = Solargraph::Pin::Method.new(
277
284
  name: decl.name.to_s,
278
285
  closure: closure,
286
+ type_location: location_decl_to_pin_location(decl.location),
279
287
  comments: decl.comment&.string,
280
288
  scope: :instance,
281
289
  signatures: [],
@@ -295,6 +303,7 @@ module Solargraph
295
303
  name: decl.name.to_s,
296
304
  closure: closure,
297
305
  comments: decl.comment&.string,
306
+ type_location: location_decl_to_pin_location(decl.location),
298
307
  scope: :class,
299
308
  signatures: [],
300
309
  generics: generics
@@ -310,42 +319,42 @@ module Solargraph
310
319
  def method_def_to_sigs decl, pin
311
320
  decl.overloads.map do |overload|
312
321
  generics = overload.method_type.type_params.map(&:to_s)
313
- parameters, return_type = parts_of_function(overload.method_type, pin)
322
+ signature_parameters, signature_return_type = parts_of_function(overload.method_type, pin)
314
323
  block = if overload.method_type.block
315
- Pin::Signature.new(generics, *parts_of_function(overload.method_type.block, pin))
316
- end
317
- return_type = ComplexType.try_parse(method_type_to_tag(overload.method_type))
318
- Pin::Signature.new(generics, parameters, return_type, block)
324
+ block_parameters, block_return_type = parts_of_function(overload.method_type.block, pin)
325
+ Pin::Signature.new(generics: generics, parameters: block_parameters, return_type: block_return_type)
326
+ end
327
+ Pin::Signature.new(generics: generics, parameters: signature_parameters, return_type: signature_return_type, block: block)
319
328
  end
320
329
  end
321
330
 
322
331
  # @param location [RBS::Location, nil]
323
332
  # @return [Solargraph::Location, nil]
324
- def rbs_location_to_location(location)
333
+ def location_decl_to_pin_location(location)
325
334
  return nil if location&.name.nil?
326
335
 
327
336
  start_pos = Position.new(location.start_line - 1, location.start_column)
328
337
  end_pos = Position.new(location.end_line - 1, location.end_column)
329
338
  range = Range.new(start_pos, end_pos)
330
- Location.new(location.name, range)
339
+ Location.new(location.name.to_s, range)
331
340
  end
332
341
 
333
342
  # @param type [RBS::MethodType,RBS::Types::Block]
334
343
  # @param pin [Pin::Method]
335
- # @return [Array<Array<Pin::Parameter>, ComplexType>]
344
+ # @return [Array(Array<Pin::Parameter>, ComplexType)]
336
345
  def parts_of_function type, pin
337
- return [[Solargraph::Pin::Parameter.new(decl: :restarg, name: 'arg', closure: pin)], ComplexType.try_parse(method_type_to_tag(type))] if defined?(RBS::Types::UntypedFunction) && type.type.is_a?(RBS::Types::UntypedFunction)
346
+ return [[Solargraph::Pin::Parameter.new(decl: :restarg, name: 'arg', closure: pin)], ComplexType.try_parse(method_type_to_tag(type)).force_rooted] if defined?(RBS::Types::UntypedFunction) && type.type.is_a?(RBS::Types::UntypedFunction)
338
347
 
339
348
  parameters = []
340
349
  arg_num = -1
341
350
  type.type.required_positionals.each do |param|
342
351
  name = param.name ? param.name.to_s : "arg#{arg_num += 1}"
343
- parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin, return_type: ComplexType.try_parse(other_type_to_tag(param.type)))
352
+ parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin, return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted)
344
353
  end
345
354
  type.type.optional_positionals.each do |param|
346
355
  name = param.name ? param.name.to_s : "arg#{arg_num += 1}"
347
356
  parameters.push Solargraph::Pin::Parameter.new(decl: :optarg, name: name, closure: pin,
348
- return_type: ComplexType.try_parse(other_type_to_tag(param.type)))
357
+ return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted)
349
358
  end
350
359
  if type.type.rest_positionals
351
360
  name = type.type.rest_positionals.name ? type.type.rest_positionals.name.to_s : "arg#{arg_num += 1}"
@@ -358,18 +367,20 @@ module Solargraph
358
367
  type.type.required_keywords.each do |orig, param|
359
368
  name = orig ? orig.to_s : "arg#{arg_num += 1}"
360
369
  parameters.push Solargraph::Pin::Parameter.new(decl: :kwarg, name: name, closure: pin,
361
- return_type: ComplexType.try_parse(other_type_to_tag(param.type)))
370
+ return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted)
362
371
  end
363
372
  type.type.optional_keywords.each do |orig, param|
364
373
  name = orig ? orig.to_s : "arg#{arg_num += 1}"
365
374
  parameters.push Solargraph::Pin::Parameter.new(decl: :kwoptarg, name: name, closure: pin,
366
- return_type: ComplexType.try_parse(other_type_to_tag(param.type)))
375
+ return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted)
367
376
  end
368
377
  if type.type.rest_keywords
369
378
  name = type.type.rest_keywords.name ? type.type.rest_keywords.name.to_s : "arg#{arg_num += 1}"
370
379
  parameters.push Solargraph::Pin::Parameter.new(decl: :kwrestarg, name: type.type.rest_keywords.name.to_s, closure: pin)
371
380
  end
372
- return_type = ComplexType.try_parse(method_type_to_tag(type))
381
+
382
+ rooted_tag = method_type_to_tag(type)
383
+ return_type = ComplexType.try_parse(rooted_tag).force_rooted
373
384
  [parameters, return_type]
374
385
  end
375
386
 
@@ -379,12 +390,14 @@ module Solargraph
379
390
  def attr_reader_to_pin(decl, closure)
380
391
  pin = Solargraph::Pin::Method.new(
381
392
  name: decl.name.to_s,
393
+ type_location: location_decl_to_pin_location(decl.location),
382
394
  closure: closure,
383
395
  comments: decl.comment&.string,
384
396
  scope: :instance,
385
397
  attribute: true
386
398
  )
387
- pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', other_type_to_tag(decl.type)))
399
+ rooted_tag = ComplexType.parse(other_type_to_tag(decl.type)).force_rooted.rooted_tags
400
+ pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', rooted_tag))
388
401
  pins.push pin
389
402
  end
390
403
 
@@ -394,12 +407,14 @@ module Solargraph
394
407
  def attr_writer_to_pin(decl, closure)
395
408
  pin = Solargraph::Pin::Method.new(
396
409
  name: "#{decl.name.to_s}=",
410
+ type_location: location_decl_to_pin_location(decl.location),
397
411
  closure: closure,
398
412
  comments: decl.comment&.string,
399
413
  scope: :instance,
400
414
  attribute: true
401
415
  )
402
- pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', other_type_to_tag(decl.type)))
416
+ rooted_tag = ComplexType.parse(other_type_to_tag(decl.type)).force_rooted.rooted_tags
417
+ pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', rooted_tag))
403
418
  pins.push pin
404
419
  end
405
420
 
@@ -418,9 +433,11 @@ module Solargraph
418
433
  pin = Solargraph::Pin::InstanceVariable.new(
419
434
  name: decl.name.to_s,
420
435
  closure: closure,
436
+ type_location: location_decl_to_pin_location(decl.location),
421
437
  comments: decl.comment&.string
422
438
  )
423
- pin.docstring.add_tag(YARD::Tags::Tag.new(:type, '', other_type_to_tag(decl.type)))
439
+ rooted_tag = ComplexType.parse(other_type_to_tag(decl.type)).force_rooted.rooted_tags
440
+ pin.docstring.add_tag(YARD::Tags::Tag.new(:type, '', rooted_tag))
424
441
  pins.push pin
425
442
  end
426
443
 
@@ -434,7 +451,8 @@ module Solargraph
434
451
  closure: closure,
435
452
  comments: decl.comment&.string
436
453
  )
437
- pin.docstring.add_tag(YARD::Tags::Tag.new(:type, '', other_type_to_tag(decl.type)))
454
+ rooted_tag = ComplexType.parse(other_type_to_tag(decl.type)).force_rooted.rooted_tags
455
+ pin.docstring.add_tag(YARD::Tags::Tag.new(:type, '', rooted_tag))
438
456
  pins.push pin
439
457
  end
440
458
 
@@ -448,7 +466,8 @@ module Solargraph
448
466
  closure: closure,
449
467
  comments: decl.comment&.string
450
468
  )
451
- pin.docstring.add_tag(YARD::Tags::Tag.new(:type, '', other_type_to_tag(decl.type)))
469
+ rooted_tag = ComplexType.parse(other_type_to_tag(decl.type)).force_rooted.rooted_tags
470
+ pin.docstring.add_tag(YARD::Tags::Tag.new(:type, '', rooted_tag))
452
471
  pins.push pin
453
472
  end
454
473
 
@@ -456,10 +475,11 @@ module Solargraph
456
475
  # @param closure [Pin::Namespace]
457
476
  # @return [void]
458
477
  def include_to_pin decl, closure
459
- type = generic_type(decl.name, decl.args)
478
+ type = build_type(decl.name, decl.args)
460
479
  generic_values = type.all_params.map(&:to_s)
461
480
  pins.push Solargraph::Pin::Reference::Include.new(
462
481
  name: decl.name.relative!.to_s,
482
+ type_location: location_decl_to_pin_location(decl.location),
463
483
  generic_values: generic_values,
464
484
  closure: closure
465
485
  )
@@ -471,6 +491,7 @@ module Solargraph
471
491
  def prepend_to_pin decl, closure
472
492
  pins.push Solargraph::Pin::Reference::Prepend.new(
473
493
  name: decl.name.relative!.to_s,
494
+ type_location: location_decl_to_pin_location(decl.location),
474
495
  closure: closure
475
496
  )
476
497
  end
@@ -481,6 +502,7 @@ module Solargraph
481
502
  def extend_to_pin decl, closure
482
503
  pins.push Solargraph::Pin::Reference::Extend.new(
483
504
  name: decl.name.relative!.to_s,
505
+ type_location: location_decl_to_pin_location(decl.location),
484
506
  closure: closure
485
507
  )
486
508
  end
@@ -491,6 +513,7 @@ module Solargraph
491
513
  def alias_to_pin decl, closure
492
514
  pins.push Solargraph::Pin::MethodAlias.new(
493
515
  name: decl.new_name.to_s,
516
+ type_location: location_decl_to_pin_location(decl.location),
494
517
  original: decl.old_name.to_s,
495
518
  closure: closure
496
519
  )
@@ -516,20 +539,24 @@ module Solargraph
516
539
 
517
540
  # @param type_name [RBS::TypeName]
518
541
  # @param type_args [Enumerable<RBS::Types::Bases::Base>]
519
- # @return [ComplexType]
520
- def generic_type(type_name, type_args)
542
+ # @return [ComplexType::UniqueType]
543
+ def build_type(type_name, type_args = [])
521
544
  base = RBS_TO_YARD_TYPE[type_name.relative!.to_s] || type_name.relative!.to_s
522
- params = type_args.map { |a| other_type_to_tag(a) }.reject { |t| t == 'undefined' }
523
- params_str = params.empty? ? '' : "<#{params.join(', ')}>"
524
- type_string = "#{base}#{params_str}"
525
- ComplexType.parse(type_string)
545
+ params = type_args.map { |a| other_type_to_tag(a) }.reject { |t| t == 'undefined' }.map do |t|
546
+ ComplexType.try_parse(t).force_rooted
547
+ end
548
+ if base == 'Hash' && params.length == 2
549
+ ComplexType::UniqueType.new(base, [params.first], [params.last], rooted: true, parameters_type: :hash)
550
+ else
551
+ ComplexType::UniqueType.new(base, [], params, rooted: true, parameters_type: :list)
552
+ end
526
553
  end
527
554
 
528
555
  # @param type_name [RBS::TypeName]
529
556
  # @param type_args [Enumerable<RBS::Types::Bases::Base>]
530
557
  # @return [String]
531
- def generic_type_tag(type_name, type_args)
532
- generic_type(type_name, type_args).tag
558
+ def type_tag(type_name, type_args = [])
559
+ build_type(type_name, type_args).tags
533
560
  end
534
561
 
535
562
  # @param type [RBS::Types::Bases::Base]
@@ -545,7 +572,7 @@ module Solargraph
545
572
  elsif type.is_a?(RBS::Types::Tuple)
546
573
  "Array(#{type.types.map { |t| other_type_to_tag(t) }.join(', ')})"
547
574
  elsif type.is_a?(RBS::Types::Literal)
548
- "#{type.literal}"
575
+ type.literal.to_s
549
576
  elsif type.is_a?(RBS::Types::Union)
550
577
  type.types.map { |t| other_type_to_tag(t) }.join(', ')
551
578
  elsif type.is_a?(RBS::Types::Record)
@@ -560,7 +587,7 @@ module Solargraph
560
587
  elsif type.is_a?(RBS::Types::Variable)
561
588
  "#{Solargraph::ComplexType::GENERIC_TAG_NAME}<#{type.name}>"
562
589
  elsif type.is_a?(RBS::Types::ClassInstance) #&& !type.args.empty?
563
- generic_type_tag(type.name, type.args)
590
+ type_tag(type.name, type.args)
564
591
  elsif type.is_a?(RBS::Types::Bases::Instance)
565
592
  'self'
566
593
  elsif type.is_a?(RBS::Types::Bases::Top)
@@ -577,8 +604,18 @@ module Solargraph
577
604
  type.types.map { |member| other_type_to_tag(member) }.join(', ')
578
605
  elsif type.is_a?(RBS::Types::Proc)
579
606
  'Proc'
580
- elsif type.respond_to?(:name) && type.name.respond_to?(:relative!)
581
- RBS_TO_YARD_TYPE[type.name.relative!.to_s] || type.name.relative!.to_s
607
+ elsif type.is_a?(RBS::Types::Alias)
608
+ # type-level alias use - e.g., 'bool' in "type bool = true | false"
609
+ # @todo ensure these get resolved after processing all aliases
610
+ # @todo handle recursive aliases
611
+ type_tag(type.name, type.args)
612
+ elsif type.is_a?(RBS::Types::Interface)
613
+ # represents a mix-in module which can be considered a
614
+ # subtype of a consumer of it
615
+ type_tag(type.name, type.args)
616
+ elsif type.is_a?(RBS::Types::ClassSingleton)
617
+ # e.g., singleton(String)
618
+ type_tag(type.name)
582
619
  else
583
620
  Solargraph.logger.warn "Unrecognized RBS type: #{type.class} at #{type.location}"
584
621
  'undefined'
@@ -586,14 +623,14 @@ module Solargraph
586
623
  end
587
624
 
588
625
  # @param decl [RBS::AST::Declarations::Class, RBS::AST::Declarations::Module]
589
- # @param closure [Pin::Namespace]
626
+ # @param namespace [Pin::Namespace]
590
627
  # @return [void]
591
628
  def add_mixins decl, namespace
592
629
  decl.each_mixin do |mixin|
593
630
  klass = mixin.is_a?(RBS::AST::Members::Include) ? Pin::Reference::Include : Pin::Reference::Extend
594
631
  pins.push klass.new(
595
632
  name: mixin.name.relative!.to_s,
596
- location: rbs_location_to_location(mixin.location),
633
+ location: location_decl_to_pin_location(mixin.location),
597
634
  closure: namespace
598
635
  )
599
636
  end
@@ -19,17 +19,17 @@ module Solargraph
19
19
  Solargraph::Pin::Method.new(name: 'tap', scope: :instance,
20
20
  closure: Solargraph::Pin::Namespace.new(name: 'Object')),
21
21
  Solargraph::Pin::Method.new(name: 'class', scope: :instance,
22
- closure: Solargraph::Pin::Namespace.new(name: 'Object'), comments: '@return [Class<self>]')
22
+ closure: Solargraph::Pin::Namespace.new(name: 'Object'), comments: '@return [::Class<self>]')
23
23
  ]
24
24
 
25
25
  OVERRIDES = [
26
26
  Override.from_comment('BasicObject#instance_eval', '@yieldreceiver [self]'),
27
27
  Override.from_comment('BasicObject#instance_exec', '@yieldreceiver [self]'),
28
- Override.from_comment('Module#define_method', '@yieldreceiver [Object<self>]'),
29
- Override.from_comment('Module#class_eval', '@yieldreceiver [Class<self>]'),
30
- Override.from_comment('Module#class_exec', '@yieldreceiver [Class<self>]'),
31
- Override.from_comment('Module#module_eval', '@yieldreceiver [Module<self>]'),
32
- Override.from_comment('Module#module_exec', '@yieldreceiver [Module<self>]'),
28
+ Override.from_comment('Module#define_method', '@yieldreceiver [::Object<self>]'),
29
+ Override.from_comment('Module#class_eval', '@yieldreceiver [::Class<self>]'),
30
+ Override.from_comment('Module#class_exec', '@yieldreceiver [::Class<self>]'),
31
+ Override.from_comment('Module#module_eval', '@yieldreceiver [::Module<self>]'),
32
+ Override.from_comment('Module#module_exec', '@yieldreceiver [::Module<self>]'),
33
33
  # RBS does not define Class with a generic, so all calls to
34
34
  # generic() return an 'untyped'. We can do better:
35
35
  Override.method_return('Class#allocate', 'self')
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'pathname'
3
4
  require 'rbs'
4
5
 
5
6
  module Solargraph
@@ -17,10 +18,13 @@ module Solargraph
17
18
  attr_reader :library
18
19
 
19
20
  # @param library [String]
20
- def initialize library, version = nil
21
+ # @param version [String, nil]
22
+ # @param directories [Array<Pathname, String>]
23
+ def initialize library, version = nil, directories: []
21
24
  @library = library
22
25
  @version = version
23
26
  @collection = nil
27
+ @directories = directories
24
28
  loader = RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
25
29
  add_library loader, library, version
26
30
  return unless resolved?
@@ -47,7 +51,11 @@ module Solargraph
47
51
  end
48
52
 
49
53
  def repository
50
- @repository ||= RBS::Repository.new(no_stdlib: false)
54
+ @repository ||= RBS::Repository.new(no_stdlib: false).tap do |repo|
55
+ # @todo Temporarily ignoring external directories due to issues with
56
+ # incomplete/broken gem_rbs_collection installations
57
+ # @directories.each { |dir| repo.add(Pathname.new(dir)) }
58
+ end
51
59
  end
52
60
 
53
61
  # @param library [String]
@@ -71,7 +79,7 @@ module Solargraph
71
79
  Solargraph.logger.info "#{short_name} successfully loaded library #{library}"
72
80
  true
73
81
  else
74
- Solargraph.logger.debug "#{short_name} failed to load library #{library}"
82
+ Solargraph.logger.info "#{short_name} failed to load library #{library}"
75
83
  false
76
84
  end
77
85
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'benchmark'
3
4
  require 'thor'
4
5
  require 'yard'
5
6
 
@@ -88,7 +89,7 @@ module Solargraph
88
89
  )
89
90
  # @return [void]
90
91
  def clear
91
- puts "Deleting the cached documentation"
92
+ puts "Deleting all cached documentation (gems, core and stdlib)"
92
93
  Solargraph::Cache.clear
93
94
  end
94
95
  map 'clear-cache' => :clear
@@ -104,11 +105,26 @@ module Solargraph
104
105
  Cache.save('gems', "#{spec.name}-#{spec.version}.ser", pins)
105
106
  end
106
107
 
107
- desc 'uncache GEM [...GEM]', "Delete cached gem documentation"
108
+ desc 'uncache GEM [...GEM]', "Delete specific cached gem documentation"
109
+ long_desc %(
110
+ Specify one or more gem names to clear. 'core' or 'stdlib' may
111
+ also be specified to clear cached system documentation.
112
+ Documentation will be regenerated as needed.
113
+ )
108
114
  # @return [void]
109
115
  def uncache *gems
110
116
  raise ArgumentError, 'No gems specified.' if gems.empty?
111
117
  gems.each do |gem|
118
+ if gem == 'core'
119
+ Cache.uncache("core.ser")
120
+ next
121
+ end
122
+
123
+ if gem == 'stdlib'
124
+ Cache.uncache("stdlib")
125
+ next
126
+ end
127
+
112
128
  spec = Gem::Specification.find_by_name(gem)
113
129
  Cache.uncache('gems', "#{spec.name}-#{spec.version}.ser")
114
130
  Cache.uncache('gems', "#{spec.name}-#{spec.version}.yardoc")
@@ -149,23 +165,28 @@ module Solargraph
149
165
  # @return [void]
150
166
  def typecheck *files
151
167
  directory = File.realpath(options[:directory])
152
- api_map = Solargraph::ApiMap.load_with_cache(directory)
168
+ api_map = Solargraph::ApiMap.load_with_cache(directory, $stdout)
169
+ probcount = 0
153
170
  if files.empty?
154
171
  files = api_map.source_maps.map(&:filename)
155
172
  else
156
173
  files.map! { |file| File.realpath(file) }
157
174
  end
158
- probcount = 0
159
175
  filecount = 0
160
- files.each do |file|
161
- checker = TypeChecker.new(file, api_map: api_map, level: options[:level].to_sym)
162
- problems = checker.problems
163
- next if problems.empty?
164
- problems.sort! { |a, b| a.location.range.start.line <=> b.location.range.start.line }
165
- puts problems.map { |prob| "#{prob.location.filename}:#{prob.location.range.start.line + 1} - #{prob.message}" }.join("\n")
166
- filecount += 1
167
- probcount += problems.length
168
- end
176
+
177
+ time = Benchmark.measure {
178
+ files.each do |file|
179
+ checker = TypeChecker.new(file, api_map: api_map, level: options[:level].to_sym)
180
+ problems = checker.problems
181
+ next if problems.empty?
182
+ problems.sort! { |a, b| a.location.range.start.line <=> b.location.range.start.line }
183
+ puts problems.map { |prob| "#{prob.location.filename}:#{prob.location.range.start.line + 1} - #{prob.message}" }.join("\n")
184
+ filecount += 1
185
+ probcount += problems.length
186
+ end
187
+ # "
188
+ }
189
+ puts "Typecheck finished in #{time.real} seconds."
169
190
  puts "#{probcount} problem#{probcount != 1 ? 's' : ''} found#{files.length != 1 ? " in #{filecount} of #{files.length} files" : ''}."
170
191
  # "
171
192
  exit 1 if probcount > 0
@@ -182,11 +203,10 @@ module Solargraph
182
203
  option :verbose, type: :boolean, aliases: :v, desc: 'Verbose output', default: false
183
204
  # @return [void]
184
205
  def scan
185
- require 'benchmark'
186
206
  directory = File.realpath(options[:directory])
187
207
  api_map = nil
188
208
  time = Benchmark.measure {
189
- api_map = Solargraph::ApiMap.load_with_cache(directory)
209
+ api_map = Solargraph::ApiMap.load_with_cache(directory, $stdout)
190
210
  api_map.pins.each do |pin|
191
211
  begin
192
212
  puts pin_description(pin) if options[:verbose]
@@ -17,14 +17,15 @@ module Solargraph
17
17
  # @param locals [Enumerable<Pin::LocalVariable>]
18
18
  def resolve api_map, name_pin, locals
19
19
  child_types = @children.map do |child|
20
- child.infer(api_map, name_pin, locals).tag
20
+ child.infer(api_map, name_pin, locals)
21
21
  end
22
- type = if child_types.uniq.length == 1 && child_types.first != 'undefined'
23
- "::Array<#{child_types.first}>"
22
+
23
+ type = if child_types.uniq.length == 1 && child_types.first.defined?
24
+ ComplexType::UniqueType.new('Array', [], child_types.uniq, rooted: true, parameters_type: :list)
24
25
  else
25
- '::Array'
26
+ ComplexType::UniqueType.new('Array', rooted: true)
26
27
  end
27
- [Pin::ProxyType.anonymous(ComplexType.try_parse(type))]
28
+ [Pin::ProxyType.anonymous(type)]
28
29
  end
29
30
  end
30
31
  end
@@ -5,7 +5,7 @@ module Solargraph
5
5
  class Chain
6
6
  class BlockSymbol < Link
7
7
  def resolve api_map, name_pin, locals
8
- [Pin::ProxyType.anonymous(ComplexType.try_parse('Proc'))]
8
+ [Pin::ProxyType.anonymous(ComplexType.try_parse('::Proc'))]
9
9
  end
10
10
  end
11
11
  end
@@ -5,7 +5,7 @@ module Solargraph
5
5
  class Chain
6
6
  class BlockVariable < Link
7
7
  def resolve api_map, name_pin, locals
8
- [Pin::ProxyType.anonymous(ComplexType.try_parse('Proc'))]
8
+ [Pin::ProxyType.anonymous(ComplexType.try_parse('::Proc'))]
9
9
  end
10
10
  end
11
11
  end