solargraph 0.59.1 → 0.60.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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +6 -0
  3. data/.github/workflows/plugins.yml +8 -0
  4. data/.github/workflows/rspec.yml +4 -1
  5. data/.github/workflows/typecheck.yml +2 -0
  6. data/.rubocop.yml +1 -0
  7. data/.rubocop_todo.yml +1 -1
  8. data/CHANGELOG.md +18 -0
  9. data/Gemfile +3 -0
  10. data/lib/solargraph/api_map/index.rb +13 -2
  11. data/lib/solargraph/api_map/store.rb +22 -8
  12. data/lib/solargraph/api_map.rb +38 -8
  13. data/lib/solargraph/complex_type/type_methods.rb +1 -0
  14. data/lib/solargraph/complex_type/unique_type.rb +16 -13
  15. data/lib/solargraph/complex_type.rb +5 -0
  16. data/lib/solargraph/convention/active_support_concern.rb +111 -111
  17. data/lib/solargraph/convention/base.rb +50 -50
  18. data/lib/solargraph/diagnostics.rb +55 -55
  19. data/lib/solargraph/doc_map.rb +1 -0
  20. data/lib/solargraph/environ.rb +52 -52
  21. data/lib/solargraph/gem_pins.rb +0 -11
  22. data/lib/solargraph/language_server/message/extended/environment.rb +25 -25
  23. data/lib/solargraph/language_server/message/initialized.rb +28 -28
  24. data/lib/solargraph/language_server/message/text_document.rb +28 -28
  25. data/lib/solargraph/language_server/progress.rb +143 -143
  26. data/lib/solargraph/language_server/transport/adapter.rb +68 -68
  27. data/lib/solargraph/language_server.rb +20 -20
  28. data/lib/solargraph/parser/parser_gem/node_chainer.rb +1 -0
  29. data/lib/solargraph/parser/parser_gem/node_methods.rb +42 -0
  30. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +24 -24
  31. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +36 -36
  32. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +24 -24
  33. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +24 -24
  34. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +29 -5
  35. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +20 -20
  36. data/lib/solargraph/pin/base.rb +31 -3
  37. data/lib/solargraph/pin/callable.rb +2 -2
  38. data/lib/solargraph/pin/common.rb +12 -0
  39. data/lib/solargraph/pin/method.rb +56 -16
  40. data/lib/solargraph/pin/reference/require.rb +14 -14
  41. data/lib/solargraph/pin/singleton.rb +11 -11
  42. data/lib/solargraph/rbs_map/conversions.rb +103 -145
  43. data/lib/solargraph/rbs_translator.rb +206 -0
  44. data/lib/solargraph/shell.rb +131 -64
  45. data/lib/solargraph/source/chain/array.rb +1 -12
  46. data/lib/solargraph/source/chain/block_symbol.rb +13 -13
  47. data/lib/solargraph/source/chain/block_variable.rb +13 -13
  48. data/lib/solargraph/source/chain/call.rb +8 -76
  49. data/lib/solargraph/source/chain/head.rb +19 -19
  50. data/lib/solargraph/source/chain/literal.rb +18 -14
  51. data/lib/solargraph/source/source_chainer.rb +4 -4
  52. data/lib/solargraph/source_map/mapper.rb +5 -135
  53. data/lib/solargraph/source_map.rb +14 -0
  54. data/lib/solargraph/version.rb +19 -1
  55. data/lib/solargraph/yard_map/cache.rb +25 -25
  56. data/lib/solargraph/yard_map/directives/attribute_directive.rb +65 -0
  57. data/lib/solargraph/yard_map/directives/domain_directive.rb +30 -0
  58. data/lib/solargraph/yard_map/directives/method_directive.rb +51 -0
  59. data/lib/solargraph/yard_map/directives/override_directive.rb +30 -0
  60. data/lib/solargraph/yard_map/directives/parse_directive.rb +53 -0
  61. data/lib/solargraph/yard_map/directives/visibility_directive.rb +70 -0
  62. data/lib/solargraph/yard_map/directives.rb +35 -0
  63. data/lib/solargraph/yard_map/macro.rb +113 -0
  64. data/lib/solargraph/yard_map/mapper/to_constant.rb +28 -28
  65. data/lib/solargraph/yard_map/mapper.rb +19 -1
  66. data/lib/solargraph/yard_map.rb +2 -0
  67. data/lib/solargraph.rb +1 -0
  68. data/solargraph.gemspec +1 -0
  69. metadata +24 -2
  70. data/rbs/fills/tuple/tuple.rbs +0 -177
@@ -67,7 +67,6 @@ module Solargraph
67
67
  unless closure.name == '' || decl.name.absolute?
68
68
  Solargraph.assert_or_log(:rbs_closure, "Ignoring closure #{closure.inspect} on interface #{decl.inspect}")
69
69
  end
70
- # STDERR.puts "Skipping interface #{decl.name.relative!}"
71
70
  interface_decl_to_pin decl
72
71
  when RBS::AST::Declarations::TypeAlias
73
72
  # @sg-ignore flow sensitive typing should support case/when
@@ -80,7 +79,7 @@ module Solargraph
80
79
  # @sg-ignore Wrong argument type for Solargraph::Pin::Reference::TypeAlias.new: return_type expected Solargraph::ComplexType, received Solargraph::ComplexType::UniqueType, Solargraph::ComplexType
81
80
  Solargraph::Pin::Reference::TypeAlias.new(
82
81
  # @sg-ignore Unresolved calls to name, type, type_location; return_type type mismatch
83
- name: ComplexType.try_parse(decl.name.to_s).to_s, return_type: other_type_to_type(decl.type).force_rooted, closure: closure, source: :rbs, type_location: location_decl_to_pin_location(decl.location)
82
+ name: ComplexType.try_parse(decl.name.to_s).to_s, return_type: RbsTranslator.to_complex_type(decl.type).force_rooted, closure: closure, source: :rbs, type_location: location_decl_to_pin_location(decl.location)
84
83
  )
85
84
  )
86
85
  when RBS::AST::Declarations::Module
@@ -169,7 +168,8 @@ module Solargraph
169
168
  rbs_name = type_name.relative!.to_s
170
169
  base = RBS_TO_CLASS.fetch(rbs_name, rbs_name)
171
170
 
172
- params = type_args.map { |a| other_type_to_type(a) }
171
+ params = type_args.map { |a| RbsTranslator.to_complex_type(a) }
172
+ # @todo Tuples are in flux
173
173
  # tuples have their own class and are handled in other_type_to_type
174
174
  if base == 'Hash' && params.length == 2
175
175
  ComplexType::UniqueType.new(base, [params.first], [params.last], rooted: type_name.absolute?,
@@ -185,9 +185,9 @@ module Solargraph
185
185
  # @return [void]
186
186
  def convert_self_type_to_pins decl, closure
187
187
  type = build_type(decl.name, decl.args)
188
- generic_values = type.all_params.map(&:rooted_tags)
188
+ generic_values = type.all_params.map(&:to_s)
189
189
  include_pin = Solargraph::Pin::Reference::Include.new(
190
- name: type.name,
190
+ name: decl.name.relative!.to_s,
191
191
  type_location: location_decl_to_pin_location(decl.location),
192
192
  generic_values: generic_values,
193
193
  closure: closure,
@@ -274,7 +274,10 @@ module Solargraph
274
274
  # @type [Hash{String => ComplexType, ComplexType::UniqueType}]
275
275
  generic_defaults = {}
276
276
  decl.type_params.each do |param|
277
- generic_defaults[param.name.to_s] = other_type_to_type param.default_type if param.default_type
277
+ if param.default_type
278
+ complex_type = RbsTranslator.to_complex_type(param.default_type).force_rooted
279
+ generic_defaults[param.name.to_s] = complex_type
280
+ end
278
281
  end
279
282
 
280
283
  class_name = fqns(decl.name)
@@ -297,7 +300,8 @@ module Solargraph
297
300
  pins.push class_pin
298
301
  if decl.super_class
299
302
  type = build_type(decl.super_class.name, decl.super_class.args)
300
- generic_values = type.all_params.map(&:rooted_tags)
303
+ generic_values = type.all_params.map(&:to_s)
304
+ superclass_name = decl.super_class.name.to_s
301
305
  pins.push Solargraph::Pin::Reference::Superclass.new(
302
306
  type_location: location_decl_to_pin_location(decl.super_class.location),
303
307
  closure: class_pin,
@@ -316,7 +320,7 @@ module Solargraph
316
320
  class_pin = Solargraph::Pin::Namespace.new(
317
321
  type: :module,
318
322
  type_location: location_decl_to_pin_location(decl.location),
319
- name: fqns(decl.name),
323
+ name: decl.name.relative!.to_s,
320
324
  closure: Solargraph::Pin::ROOT_PIN,
321
325
  comments: decl.comment&.string,
322
326
  generics: type_parameter_names(decl),
@@ -335,7 +339,7 @@ module Solargraph
335
339
  def module_decl_to_pin decl
336
340
  module_pin = Solargraph::Pin::Namespace.new(
337
341
  type: :module,
338
- name: fqns(decl.name),
342
+ name: decl.name.relative!.to_s,
339
343
  type_location: location_decl_to_pin_location(decl.location),
340
344
  closure: Solargraph::Pin::ROOT_PIN,
341
345
  comments: decl.comment&.string,
@@ -380,6 +384,9 @@ module Solargraph
380
384
  )
381
385
  rooted_tag = type.rooted_tags
382
386
  rooted_tag = "#{base}<#{rooted_tag}>" if base
387
+ # @todo alt version
388
+ # tag = "#{base}<#{tag}>" if base
389
+ # rooted_tag = ComplexType.parse(tag).force_rooted.rooted_tags
383
390
  constant_pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', rooted_tag))
384
391
  constant_pin
385
392
  end
@@ -406,9 +413,8 @@ module Solargraph
406
413
  # @param decl [RBS::AST::Declarations::Constant]
407
414
  # @return [void]
408
415
  def constant_decl_to_pin decl
409
- target_type = other_type_to_type(decl.type)
410
- constant_name = fqns(decl.name)
411
- pins.push create_constant(constant_name, target_type, decl.comment&.string, decl)
416
+ tag = RbsTranslator.to_complex_type(decl.type)
417
+ pins.push create_constant(decl.name.relative!.to_s, tag, decl.comment&.string, decl)
412
418
  end
413
419
 
414
420
  # @param decl [RBS::AST::Declarations::Global]
@@ -423,7 +429,7 @@ module Solargraph
423
429
  type_location: location_decl_to_pin_location(decl.location),
424
430
  source: :rbs
425
431
  )
426
- rooted_tag = other_type_to_type(decl.type).rooted_tags
432
+ rooted_tag = RbsTranslator.to_complex_type(decl.type).force_rooted.rooted_tags
427
433
  pin.docstring.add_tag(YARD::Tags::Tag.new(:type, '', rooted_tag))
428
434
  pins.push pin
429
435
  end
@@ -529,73 +535,69 @@ module Solargraph
529
535
  pin.instance_variable_set(:@return_type, ComplexType::VOID)
530
536
  end
531
537
  end
532
- return unless decl.singleton?
533
- final_scope = :class
534
- name = decl.name.to_s
535
- visibility = calculate_method_visibility(decl, context, closure, final_scope, name)
536
- pin = Solargraph::Pin::Method.new(
537
- name: name,
538
- closure: closure,
539
- comments: decl.comment&.string,
540
- type_location: location_decl_to_pin_location(decl.location),
541
- visibility: visibility,
542
- scope: final_scope,
543
- signatures: [],
544
- generics: generics,
545
- source: :rbs
546
- )
547
- pin.signatures.concat method_def_to_sigs(decl, pin)
548
- pins.push pin
538
+ if decl.singleton?
539
+ final_scope = :class
540
+ name = decl.name.to_s
541
+ visibility = calculate_method_visibility(decl, context, closure, final_scope, name)
542
+ pin = Solargraph::Pin::Method.new(
543
+ name: name,
544
+ closure: closure,
545
+ comments: decl.comment&.string,
546
+ type_location: location_decl_to_pin_location(decl.location),
547
+ visibility: visibility,
548
+ scope: final_scope,
549
+ signatures: [],
550
+ generics: generics,
551
+ source: :rbs
552
+ )
553
+ pin.signatures.concat method_def_to_sigs(decl, pin)
554
+ pins.push pin
555
+ end
549
556
  end
550
557
 
551
558
  # @param decl [RBS::AST::Members::MethodDefinition]
552
559
  # @param pin [Pin::Method]
553
560
  # @return [void]
554
561
  def method_def_to_sigs decl, pin
555
- # @param overload [RBS::AST::Members::MethodDefinition::Overload]
562
+ # rubocop:disable Style/SafeNavigationChainLength
563
+ implicit_nil = decl.overloads.first&.annotations&.map(&:string)&.include?('implicitly-returns-nil') || false
564
+ # rubocop:enable Style/SafeNavigationChainLength # @param overload [RBS::AST::Members::MethodDefinition::Overload]
556
565
  decl.overloads.map do |overload|
557
- # @sg-ignore Wrong argument type for Solargraph::RbsMap::Conversions#location_decl_to_pin_location:
558
- # location expected RBS::Location, nil, received RBS::Location<:type, :type_params>, RBS::AST::Members::Attribute::loc, nil
559
566
  type_location = location_decl_to_pin_location(overload.method_type.location)
560
- generics = type_parameter_names(overload.method_type)
561
- signature_parameters, signature_return_type = parts_of_function(overload.method_type, pin)
562
- rbs_block = overload.method_type.block
563
- block = if rbs_block
564
- block_parameters, block_return_type = parts_of_function(rbs_block, pin)
565
- Pin::Signature.new(generics: generics, parameters: block_parameters,
566
- return_type: block_return_type, source: :rbs,
567
+ generics = overload.method_type.type_params.map(&:name).map(&:to_s)
568
+ signature_parameters, signature_return_type = parts_of_function(overload.method_type, pin, implicit_nil)
569
+ block = if overload.method_type.block
570
+ block_parameters, block_return_type = parts_of_function(overload.method_type.block, pin, implicit_nil)
571
+ Pin::Signature.new(generics: generics, parameters: block_parameters, return_type: block_return_type, source: :rbs,
567
572
  type_location: type_location, closure: pin)
568
573
  end
569
- Pin::Signature.new(generics: generics, parameters: signature_parameters,
570
- return_type: signature_return_type, block: block, source: :rbs,
574
+ Pin::Signature.new(generics: generics, parameters: signature_parameters, return_type: signature_return_type, block: block, source: :rbs,
571
575
  type_location: type_location, closure: pin)
572
576
  end
573
577
  end
574
578
 
575
579
  # @param location [RBS::Location, nil]
576
580
  # @return [Solargraph::Location, nil]
577
- def location_decl_to_pin_location location
581
+ def location_decl_to_pin_location(location)
578
582
  return nil if location&.name.nil?
579
583
 
580
- # @sg-ignore flow sensitive typing should handle return nil if location&.name.nil?
581
584
  start_pos = Position.new(location.start_line - 1, location.start_column)
582
- # @sg-ignore flow sensitive typing should handle return nil if location&.name.nil?
583
585
  end_pos = Position.new(location.end_line - 1, location.end_column)
584
586
  range = Range.new(start_pos, end_pos)
585
- # @sg-ignore flow sensitve typing should handle return nil if location&.name.nil?
586
587
  Location.new(location.name.to_s, range)
587
588
  end
588
589
 
589
590
  # @param type [RBS::MethodType, RBS::Types::Block]
590
591
  # @param pin [Pin::Method]
592
+ # @param implicit_nil [Boolean]
591
593
  # @return [Array(Array<Pin::Parameter>, ComplexType)]
592
- def parts_of_function type, pin
594
+ def parts_of_function type, pin, implicit_nil
593
595
  type_location = pin.type_location
594
596
  if defined?(RBS::Types::UntypedFunction) && type.type.is_a?(RBS::Types::UntypedFunction)
595
597
  return [
596
598
  [Solargraph::Pin::Parameter.new(decl: :restarg, name: 'arg', closure: pin, source: :rbs,
597
599
  type_location: type_location)],
598
- method_type_to_type(type)
600
+ method_type_to_type(type, implicit_nil)
599
601
  ]
600
602
  end
601
603
 
@@ -659,10 +661,21 @@ module Solargraph
659
661
  source: :rbs, type_location: type_location)
660
662
  end
661
663
 
662
- return_type = method_type_to_type(type)
664
+ return_type = method_type_to_type(type, implicit_nil)
663
665
  [parameters, return_type]
664
666
  end
665
667
 
668
+ # @param type [RBS::MethodType,RBS::Types::Block]
669
+ # @param pin [Pin::Method]
670
+ # @param implicit_nil [Boolean]
671
+ # @return [Array(Array<Pin::Parameter>, ComplexType)]
672
+ def parts_of_function type, pin, implicit_nil
673
+ [
674
+ RbsTranslator.to_parameter_pins(type, pin, pin.parameter_names),
675
+ extract_method_type_return_type(type, implicit_nil).force_rooted
676
+ ]
677
+ end
678
+
666
679
  # @param decl [RBS::AST::Members::AttrReader,RBS::AST::Members::AttrAccessor]
667
680
  # @param closure [Pin::Namespace]
668
681
  # @param context [Context]
@@ -681,7 +694,7 @@ module Solargraph
681
694
  visibility: visibility,
682
695
  source: :rbs
683
696
  )
684
- rooted_tag = other_type_to_type(decl.type).rooted_tags
697
+ rooted_tag = RbsTranslator.to_complex_type(decl.type).force_rooted.rooted_tags
685
698
  pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', rooted_tag))
686
699
  logger.debug do
687
700
  "Conversions#attr_reader_to_pin(name=#{name.inspect}, visibility=#{visibility.inspect}) => #{pin.inspect}"
@@ -712,13 +725,13 @@ module Solargraph
712
725
  pin.parameters <<
713
726
  Solargraph::Pin::Parameter.new(
714
727
  name: 'value',
715
- return_type: other_type_to_type(decl.type),
728
+ return_type: RbsTranslator.to_complex_type(decl.type).force_rooted,
716
729
  source: :rbs,
717
730
  closure: pin,
718
731
  type_location: type_location
719
732
  )
720
- rooted_tags = other_type_to_type(decl.type).rooted_tags
721
- pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', rooted_tags))
733
+ rooted_tag = RbsTranslator.to_complex_type(decl.type).force_rooted.rooted_tags
734
+ pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', rooted_tag))
722
735
  pins.push pin
723
736
  end
724
737
 
@@ -742,7 +755,7 @@ module Solargraph
742
755
  comments: decl.comment&.string,
743
756
  source: :rbs
744
757
  )
745
- rooted_tag = other_type_to_type(decl.type).rooted_tags
758
+ rooted_tag = RbsTranslator.to_complex_type(decl.type).force_rooted.rooted_tags
746
759
  pin.docstring.add_tag(YARD::Tags::Tag.new(:type, '', rooted_tag))
747
760
  pins.push pin
748
761
  end
@@ -759,7 +772,7 @@ module Solargraph
759
772
  type_location: location_decl_to_pin_location(decl.location),
760
773
  source: :rbs
761
774
  )
762
- rooted_tag = other_type_to_type(decl.type).rooted_tags
775
+ rooted_tag = RbsTranslator.to_complex_type(decl.type).force_rooted.rooted_tags
763
776
  pin.docstring.add_tag(YARD::Tags::Tag.new(:type, '', rooted_tag))
764
777
  pins.push pin
765
778
  end
@@ -776,7 +789,7 @@ module Solargraph
776
789
  type_location: location_decl_to_pin_location(decl.location),
777
790
  source: :rbs
778
791
  )
779
- rooted_tag = other_type_to_type(decl.type).rooted_tags
792
+ rooted_tag = RbsTranslator.to_complex_type(decl.type).force_rooted.rooted_tags
780
793
  pin.docstring.add_tag(YARD::Tags::Tag.new(:type, '', rooted_tag))
781
794
  pins.push pin
782
795
  end
@@ -786,9 +799,9 @@ module Solargraph
786
799
  # @return [void]
787
800
  def include_to_pin decl, closure
788
801
  type = build_type(decl.name, decl.args)
789
- generic_values = type.all_params.map(&:rooted_tags)
802
+ generic_values = type.all_params.map(&:to_s)
790
803
  pins.push Solargraph::Pin::Reference::Include.new(
791
- name: type.rooted_name, # reference pins use rooted names
804
+ name: decl.name.relative!.to_s,
792
805
  type_location: location_decl_to_pin_location(decl.location),
793
806
  generic_values: generic_values,
794
807
  closure: closure,
@@ -803,9 +816,8 @@ module Solargraph
803
816
  type = build_type(decl.name, decl.args)
804
817
  generic_values = type.all_params.map(&:rooted_tags)
805
818
  pins.push Solargraph::Pin::Reference::Prepend.new(
806
- name: type.rooted_name, # reference pins use rooted names
819
+ name: decl.name.relative!.to_s,
807
820
  type_location: location_decl_to_pin_location(decl.location),
808
- generic_values: generic_values,
809
821
  closure: closure,
810
822
  source: :rbs
811
823
  )
@@ -818,9 +830,8 @@ module Solargraph
818
830
  type = build_type(decl.name, decl.args)
819
831
  generic_values = type.all_params.map(&:rooted_tags)
820
832
  pins.push Solargraph::Pin::Reference::Extend.new(
821
- name: type.rooted_name, # reference pins use rooted names
833
+ name: decl.name.relative!.to_s,
822
834
  type_location: location_decl_to_pin_location(decl.location),
823
- generic_values: generic_values,
824
835
  closure: closure,
825
836
  source: :rbs
826
837
  )
@@ -841,90 +852,37 @@ module Solargraph
841
852
  )
842
853
  end
843
854
 
844
- # @param type [RBS::MethodType, RBS::Types::Block]
845
- # @return [ComplexType, ComplexType::UniqueType]
846
- def method_type_to_type type
847
- other_type_to_type type.type.return_type
848
- end
855
+ RBS_TO_YARD_TYPE = {
856
+ 'bool' => 'Boolean',
857
+ 'string' => 'String',
858
+ 'int' => 'Integer',
859
+ 'untyped' => '',
860
+ 'NilClass' => 'nil'
861
+ }
862
+ private_constant :RBS_TO_YARD_TYPE
849
863
 
850
- # @param type [RBS::Types::Bases::Base,Object] RBS type object.
851
- # Note: Generally these extend from RBS::Types::Bases::Base,
852
- # but not all.
864
+ # Extract a ComplexType from a MethodType's return type.
853
865
  #
854
- # @return [ComplexType, ComplexType::UniqueType]
855
- def other_type_to_type type
856
- case type
857
- when RBS::Types::Optional
858
- # @sg-ignore flow based typing needs to understand case when class pattern
859
- ComplexType.new([other_type_to_type(type.type),
860
- ComplexType::UniqueType::NIL])
861
- when RBS::Types::Bases::Any
862
- ComplexType::UNDEFINED
863
- when RBS::Types::Bases::Bool
864
- ComplexType::BOOLEAN
865
- when RBS::Types::Tuple
866
- # @sg-ignore flow based typing needs to understand case when class pattern
867
- tuple_types = type.types.map { |t| other_type_to_type(t) }
868
- ComplexType::UniqueType.new('Array', [], tuple_types, rooted: true, parameters_type: :fixed)
869
- when RBS::Types::Literal
870
- # @sg-ignore flow based typing needs to understand case when class pattern
871
- ComplexType.try_parse(type.literal.inspect).force_rooted
872
- when RBS::Types::Union
873
- # @sg-ignore flow based typing needs to understand case when class pattern
874
- ComplexType.new(type.types.map { |t| other_type_to_type(t) })
875
- when RBS::Types::Record
876
- # @todo Better record support
877
- ComplexType::UniqueType.new('Hash', rooted: true)
878
- when RBS::Types::Bases::Nil
879
- ComplexType::NIL
880
- when RBS::Types::Bases::Self
881
- ComplexType::SELF
882
- when RBS::Types::Bases::Void
883
- ComplexType::VOID
884
- when RBS::Types::Variable
885
- # @sg-ignore flow based typing needs to understand case when class pattern
886
- ComplexType.parse("generic<#{type.name}>").force_rooted
887
- when RBS::Types::ClassInstance # && !type.args.empty?
888
- # @sg-ignore flow based typing needs to understand case when class pattern
889
- build_type(type.name, type.args)
890
- when RBS::Types::Bases::Instance
891
- ComplexType::SELF
892
- when RBS::Types::Bases::Top
893
- # top is the most super superclass
894
- ComplexType::UniqueType.new('BasicObject', rooted: true)
895
- when RBS::Types::Bases::Bottom
896
- # bottom is used in contexts where nothing will ever return
897
- # - e.g., it could be the return type of 'exit()' or 'raise'
898
- #
899
- # @todo define a specific bottom type and use it to
900
- # determine dead code
901
- ComplexType::UNDEFINED
902
- when RBS::Types::Intersection
903
- # @sg-ignore flow based typing needs to understand case when class pattern
904
- ComplexType.new(type.types.map { |member| other_type_to_type(member) })
905
- when RBS::Types::Proc
906
- ComplexType::UniqueType.new('Proc', rooted: true)
907
- when RBS::Types::Alias
908
- # type-level alias use - e.g., 'bool' in "type bool = true | false"
909
- # @todo ensure these get resolved after processing all aliases
910
- # @todo handle recursive aliases
911
- # @sg-ignore flow based typing needs to understand case when class pattern
912
- build_type(type.name, type.args)
913
- when RBS::Types::Interface
914
- # represents a mix-in module which can be considered a
915
- # subtype of a consumer of it
916
- # @sg-ignore flow based typing needs to understand case when class pattern
917
- build_type(type.name, type.args)
918
- when RBS::Types::ClassSingleton
919
- # e.g., singleton(String)
920
- # @sg-ignore flow based typing needs to understand case when class pattern
921
- build_type(type.name)
866
+ # This method will convert type aliases to concrete types.
867
+ #
868
+ # @param type [RBS::MethodType]
869
+ # @return [ComplexType]
870
+ def extract_method_type_return_type type, implicit_nil
871
+ tag = RbsTranslator.to_complex_type(type.type.return_type)
872
+ return ComplexType.parse("#{tag}, nil") if tag && implicit_nil
873
+ tag
874
+ end
875
+
876
+ # @param type_name [RBS::TypeName]
877
+ # @param type_args [Enumerable<RBS::Types::Bases::Base>]
878
+ # @return [ComplexType::UniqueType]
879
+ def build_type(type_name, type_args = [])
880
+ base = RBS_TO_YARD_TYPE[type_name.relative!.to_s] || type_name.relative!.to_s
881
+ params = type_args.map { |arg| RbsTranslator.to_complex_type(arg).force_rooted }
882
+ if base == 'Hash' && params.length == 2
883
+ ComplexType::UniqueType.new(base, [params.first], [params.last], rooted: true, parameters_type: :hash)
922
884
  else
923
- # RBS doesn't provide a common base class for its type AST nodes
924
- #
925
- # @sg-ignore all types should include location
926
- Solargraph.logger.warn "Unrecognized RBS type: #{type.class} at #{type.location}"
927
- ComplexType::UNDEFINED
885
+ ComplexType::UniqueType.new(base, [], params.reject(&:undefined?), rooted: true, parameters_type: :list)
928
886
  end
929
887
  end
930
888
 
@@ -937,9 +895,9 @@ module Solargraph
937
895
  # @todo are we handling prepend correctly?
938
896
  klass = mixin.is_a?(RBS::AST::Members::Include) ? Pin::Reference::Include : Pin::Reference::Extend
939
897
  type = build_type(mixin.name, mixin.args)
940
- generic_values = type.all_params.map(&:rooted_tags)
898
+ generic_values = type.all_params.map(&:to_s)
941
899
  pins.push klass.new(
942
- name: type.rooted_name, # reference pins use rooted names
900
+ name: mixin.name.relative!.to_s,
943
901
  type_location: location_decl_to_pin_location(mixin.location),
944
902
  generic_values: generic_values,
945
903
  closure: namespace,
@@ -0,0 +1,206 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ # Convert RBS types to complex types and pins.
5
+ #
6
+ module RbsTranslator
7
+ RBS_TO_YARD_TYPE = {
8
+ 'bool' => 'Boolean',
9
+ 'string' => 'String',
10
+ 'int' => 'Integer',
11
+ 'untyped' => '',
12
+ 'NilClass' => 'nil'
13
+ }
14
+
15
+ # @param type [RBS::Types::Bases::Base]
16
+ # @return [ComplexType]
17
+ def self.to_complex_type(type)
18
+ tag = type_to_tag(type)
19
+ ComplexType.try_parse(tag).force_rooted
20
+ end
21
+
22
+ # @param param_type [RBS::Types::Function::Param]
23
+ # @param name [String]
24
+ # @param decl [Symbol]
25
+ # @param closure [Pin::Closure]
26
+ # @return [Pin::Parameter]
27
+ def self.to_parameter_pin(param_type, name, decl, closure)
28
+ return_type = if decl == :restarg
29
+ ComplexType.parse('Array')
30
+ elsif decl == :kwrestarg
31
+ ComplexType.parse('Hash{Symbol => Object}')
32
+ else
33
+ RbsTranslator.to_complex_type(param_type.type)
34
+ end
35
+ Solargraph::Pin::Parameter.new(decl: decl, name: name, closure: closure, return_type: return_type, source: :rbs, type_location: to_sg_location(param_type.location) || closure.type_location)
36
+ end
37
+
38
+ # @param method_type [RBS::MethodType]
39
+ # @param closure [Pin::Closure]
40
+ # @param parameter_names [Array<String>]
41
+ # @return [Array<Pin::Parameter>]
42
+ def self.to_parameter_pins method_type, closure, parameter_names = []
43
+ if defined?(RBS::Types::UntypedFunction) && method_type.type.is_a?(RBS::Types::UntypedFunction)
44
+ return [
45
+ Solargraph::Pin::Parameter.new(decl: :restarg, name: 'arg', closure: closure, source: :rbs)
46
+ ]
47
+ end
48
+
49
+ arg_num = 0
50
+ params = []
51
+ method_type.type.required_positionals.each do |param|
52
+ params.push RbsTranslator.to_parameter_pin(param, param.name&.to_s || parameter_names[arg_num] || "arg_#{arg_num}", :arg, closure)
53
+ arg_num += 1
54
+ end
55
+ method_type.type.optional_positionals.each do |param|
56
+ params.push RbsTranslator.to_parameter_pin(param, param.name&.to_s || parameter_names[arg_num] || "arg_#{arg_num}", :optarg, closure)
57
+ arg_num += 1
58
+ end
59
+ if method_type.type.rest_positionals
60
+ params.push RbsTranslator.to_parameter_pin(method_type.type.rest_positionals, method_type.type.rest_positionals.name&.to_s || parameter_names[arg_num] || "arg_#{arg_num}", :restarg, closure)
61
+ arg_num += 1
62
+ end
63
+ method_type.type.required_keywords.each do |param|
64
+ params.push RbsTranslator.to_parameter_pin(param.last, param.first.to_s, :kwarg, closure)
65
+ arg_num += 1
66
+ end
67
+ method_type.type.optional_keywords.each do |param|
68
+ params.push RbsTranslator.to_parameter_pin(param.last, param.first.to_s, :kwoptarg, closure)
69
+ arg_num += 1
70
+ end
71
+ if method_type.type.rest_keywords
72
+ params.push RbsTranslator.to_parameter_pin(method_type.type.rest_keywords, method_type.type.rest_keywords.name&.to_s || parameter_names[arg_num] || "arg_#{arg_num}", :kwrestarg, closure)
73
+ end
74
+ params
75
+ end
76
+
77
+ # @param method_type [RBS::MethodType]
78
+ # @param closure [Pin::Closure]
79
+ # @param parameter_names [Array<String>]
80
+ # @return [Pin::Signature]
81
+ def self.to_signature method_type, closure, parameter_names = []
82
+ # There may be edge cases here around different signatures
83
+ # having different type params / orders - we may need to match
84
+ # this data model and have generics live in signatures to
85
+ # handle those correctly
86
+ generics = method_type.type_params.map(&:name).map(&:to_s).uniq
87
+ parameters = to_parameter_pins(method_type, closure, parameter_names)
88
+ return_type = to_complex_type(method_type.type.return_type)
89
+ block = if method_type.block
90
+ block_parameters = to_parameter_pins(method_type.block, closure)
91
+ block_return_type = to_complex_type(method_type.block.type.return_type)
92
+ Pin::Signature.new(generics: generics, parameters: block_parameters, return_type: block_return_type, source: :rbs, type_location: closure.location, closure: closure)
93
+ end
94
+ Pin::Signature.new(generics: generics, parameters: parameters, return_type: return_type, block: block, source: :rbs, type_location: closure.location, closure: closure)
95
+ end
96
+
97
+ # @param type_name [RBS::TypeName]
98
+ # @param type_args [Enumerable<RBS::Types::Bases::Base>]
99
+ # @return [ComplexType::UniqueType]
100
+ def self.build_unique_type(type_name, type_args = [])
101
+ base = RBS_TO_YARD_TYPE[type_name.relative!.to_s] || type_name.relative!.to_s
102
+ params = type_args.map do |a|
103
+ RbsTranslator.to_complex_type(a)
104
+ end
105
+ if base == 'Hash' && params.length == 2
106
+ ComplexType::UniqueType.new(base, [params.first], [params.last], rooted: true, parameters_type: :hash)
107
+ else
108
+ ComplexType::UniqueType.new(base, [], params.reject(&:undefined?), rooted: true, parameters_type: :list)
109
+ end
110
+ end
111
+
112
+ # @param location [RBS::Location, nil]
113
+ # @return [Solargraph::Location, nil]
114
+ def self.to_sg_location(location)
115
+ return nil if location&.name.nil?
116
+
117
+ start_pos = Position.new(location.start_line - 1, location.start_column)
118
+ end_pos = Position.new(location.end_line - 1, location.end_column)
119
+ range = Range.new(start_pos, end_pos)
120
+ Location.new(location.name.to_s, range)
121
+ end
122
+
123
+ class << self
124
+ private
125
+
126
+ # @param type [RBS::Types::Bases::Base]
127
+ # @return [String]
128
+ def type_to_tag type
129
+ case type
130
+ when RBS::Types::Optional
131
+ "#{type_to_tag(type.type)}, nil"
132
+ when RBS::Types::Bases::Bool
133
+ 'Boolean'
134
+ when RBS::Types::Tuple
135
+ "Array(#{type.types.map { |t| type_to_tag(t) }.join(', ')})"
136
+ when RBS::Types::Literal
137
+ type.literal.inspect
138
+ when RBS::Types::Union
139
+ type.types.map { |t| type_to_tag(t) }.join(', ')
140
+ when RBS::Types::Record
141
+ # @todo Better record support
142
+ 'Hash'
143
+ when RBS::Types::Bases::Nil
144
+ 'nil'
145
+ when RBS::Types::Bases::Void
146
+ 'void'
147
+ when RBS::Types::Variable
148
+ "#{Solargraph::ComplexType::GENERIC_TAG_NAME}<#{type.name}>"
149
+ when RBS::Types::Bases::Self, RBS::Types::Bases::Instance
150
+ 'self'
151
+ when RBS::Types::Bases::Top
152
+ # `Top` is the most super superclass
153
+ 'BasicObject'
154
+ when RBS::Types::Intersection
155
+ type.types.map { |member| type_to_tag(member) }.join(', ')
156
+ when RBS::Types::Proc
157
+ 'Proc'
158
+ when RBS::Types::ClassInstance, RBS::Types::Alias, RBS::Types::Interface
159
+ # `Alias` is a top-level type alias, e.g., 'bool' in "type bool = true | false"
160
+ # @todo ensure these get resolved after processing all aliases
161
+ # @todo handle recursive aliases
162
+ #
163
+ # `Interface represents a mix-in module which can be considered a
164
+ # subtype of a consumer of it
165
+ #
166
+ type_tag(type.name, type.args)
167
+ when RBS::Types::ClassSingleton
168
+ # e.g., singleton(String)
169
+ type_tag(type.name)
170
+ when RBS::Types::Bases::Any, RBS::Types::Bases::Bottom
171
+ # `Bottom`` is used in contexts where nothing will ever return
172
+ # - e.g., it could be the return type of 'exit()' or 'raise'
173
+ # @todo define a specific bottom type and use it to
174
+ # determine dead code
175
+ #
176
+ 'undefined'
177
+ else
178
+ Solargraph.logger.warn "Unrecognized RBS type: #{type.class} at #{type.location}"
179
+ 'undefined'
180
+ end
181
+ end
182
+
183
+ # @param type_name [RBS::TypeName]
184
+ # @param type_args [Enumerable<RBS::Types::Bases::Base>]
185
+ # @return [String]
186
+ def type_tag(type_name, type_args = [])
187
+ build_type(type_name, type_args).tags
188
+ end
189
+
190
+ # @param type_name [RBS::TypeName]
191
+ # @param type_args [Enumerable<RBS::Types::Bases::Base>]
192
+ # @return [ComplexType::UniqueType]
193
+ def build_type(type_name, type_args = [])
194
+ base = RBS_TO_YARD_TYPE[type_name.relative!.to_s] || type_name.relative!.to_s
195
+ params = type_args.map { |a| type_to_tag(a) }.map do |t|
196
+ ComplexType.try_parse(t)
197
+ end
198
+ if base == 'Hash' && params.length == 2
199
+ ComplexType::UniqueType.new(base, [params.first], [params.last], rooted: true, parameters_type: :hash)
200
+ else
201
+ ComplexType::UniqueType.new(base, [], params.reject(&:undefined?), rooted: true, parameters_type: :list)
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end