solargraph 0.58.2 → 0.59.0.dev.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 (154) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +4 -5
  4. data/.github/workflows/plugins.yml +40 -36
  5. data/.github/workflows/rspec.yml +45 -13
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.gitignore +0 -1
  8. data/.rubocop_todo.yml +27 -49
  9. data/CHANGELOG.md +1 -7
  10. data/README.md +3 -3
  11. data/Rakefile +1 -0
  12. data/lib/solargraph/api_map/cache.rb +3 -3
  13. data/lib/solargraph/api_map/constants.rb +13 -3
  14. data/lib/solargraph/api_map/index.rb +22 -11
  15. data/lib/solargraph/api_map/source_to_yard.rb +13 -1
  16. data/lib/solargraph/api_map/store.rb +11 -8
  17. data/lib/solargraph/api_map.rb +105 -50
  18. data/lib/solargraph/complex_type/conformance.rb +176 -0
  19. data/lib/solargraph/complex_type/type_methods.rb +16 -2
  20. data/lib/solargraph/complex_type/unique_type.rb +170 -20
  21. data/lib/solargraph/complex_type.rb +119 -14
  22. data/lib/solargraph/convention/data_definition/data_definition_node.rb +3 -1
  23. data/lib/solargraph/convention/data_definition.rb +4 -1
  24. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
  25. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +1 -0
  26. data/lib/solargraph/convention/struct_definition.rb +5 -1
  27. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  28. data/lib/solargraph/diagnostics/rubocop.rb +1 -0
  29. data/lib/solargraph/diagnostics/rubocop_helpers.rb +2 -0
  30. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  31. data/lib/solargraph/doc_map.rb +134 -373
  32. data/lib/solargraph/equality.rb +1 -1
  33. data/lib/solargraph/gem_pins.rb +14 -15
  34. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  35. data/lib/solargraph/language_server/host/dispatch.rb +1 -0
  36. data/lib/solargraph/language_server/host/message_worker.rb +2 -1
  37. data/lib/solargraph/language_server/host/sources.rb +1 -0
  38. data/lib/solargraph/language_server/host.rb +6 -1
  39. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -7
  40. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  41. data/lib/solargraph/language_server/message/text_document/completion.rb +2 -0
  42. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  43. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +2 -0
  44. data/lib/solargraph/language_server/message/text_document/formatting.rb +2 -0
  45. data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
  46. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -0
  47. data/lib/solargraph/language_server/message/text_document/type_definition.rb +2 -0
  48. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -0
  49. data/lib/solargraph/library.rb +59 -13
  50. data/lib/solargraph/location.rb +9 -4
  51. data/lib/solargraph/logging.rb +21 -1
  52. data/lib/solargraph/parser/comment_ripper.rb +7 -0
  53. data/lib/solargraph/parser/flow_sensitive_typing.rb +330 -102
  54. data/lib/solargraph/parser/node_processor/base.rb +32 -2
  55. data/lib/solargraph/parser/node_processor.rb +7 -6
  56. data/lib/solargraph/parser/parser_gem/class_methods.rb +28 -10
  57. data/lib/solargraph/parser/parser_gem/node_chainer.rb +31 -6
  58. data/lib/solargraph/parser/parser_gem/node_methods.rb +27 -7
  59. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  60. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +2 -0
  61. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  62. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -11
  63. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +7 -0
  64. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  65. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +3 -2
  66. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  67. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  68. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +2 -2
  69. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  70. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  71. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  72. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +1 -0
  73. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +12 -7
  74. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  75. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +5 -1
  76. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  77. data/lib/solargraph/parser/region.rb +9 -3
  78. data/lib/solargraph/parser/snippet.rb +1 -1
  79. data/lib/solargraph/pin/base.rb +53 -21
  80. data/lib/solargraph/pin/base_variable.rb +312 -20
  81. data/lib/solargraph/pin/block.rb +26 -4
  82. data/lib/solargraph/pin/breakable.rb +5 -1
  83. data/lib/solargraph/pin/callable.rb +50 -3
  84. data/lib/solargraph/pin/closure.rb +2 -6
  85. data/lib/solargraph/pin/common.rb +20 -5
  86. data/lib/solargraph/pin/compound_statement.rb +55 -0
  87. data/lib/solargraph/pin/conversions.rb +2 -1
  88. data/lib/solargraph/pin/delegated_method.rb +15 -4
  89. data/lib/solargraph/pin/documenting.rb +1 -0
  90. data/lib/solargraph/pin/instance_variable.rb +5 -1
  91. data/lib/solargraph/pin/keyword.rb +0 -4
  92. data/lib/solargraph/pin/local_variable.rb +13 -57
  93. data/lib/solargraph/pin/method.rb +90 -42
  94. data/lib/solargraph/pin/method_alias.rb +8 -0
  95. data/lib/solargraph/pin/namespace.rb +7 -1
  96. data/lib/solargraph/pin/parameter.rb +76 -13
  97. data/lib/solargraph/pin/proxy_type.rb +2 -1
  98. data/lib/solargraph/pin/reference/override.rb +1 -1
  99. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  100. data/lib/solargraph/pin/reference.rb +2 -0
  101. data/lib/solargraph/pin/search.rb +1 -0
  102. data/lib/solargraph/pin/signature.rb +8 -0
  103. data/lib/solargraph/pin/symbol.rb +1 -1
  104. data/lib/solargraph/pin/until.rb +1 -1
  105. data/lib/solargraph/pin/while.rb +1 -1
  106. data/lib/solargraph/pin.rb +2 -0
  107. data/lib/solargraph/pin_cache.rb +477 -57
  108. data/lib/solargraph/position.rb +12 -26
  109. data/lib/solargraph/range.rb +6 -6
  110. data/lib/solargraph/rbs_map/conversions.rb +33 -10
  111. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  112. data/lib/solargraph/rbs_map/stdlib_map.rb +34 -5
  113. data/lib/solargraph/rbs_map.rb +74 -20
  114. data/lib/solargraph/shell.rb +73 -28
  115. data/lib/solargraph/source/chain/call.rb +52 -17
  116. data/lib/solargraph/source/chain/constant.rb +2 -0
  117. data/lib/solargraph/source/chain/hash.rb +1 -0
  118. data/lib/solargraph/source/chain/if.rb +1 -0
  119. data/lib/solargraph/source/chain/instance_variable.rb +22 -1
  120. data/lib/solargraph/source/chain/literal.rb +5 -0
  121. data/lib/solargraph/source/chain/or.rb +9 -1
  122. data/lib/solargraph/source/chain.rb +25 -22
  123. data/lib/solargraph/source/change.rb +9 -2
  124. data/lib/solargraph/source/cursor.rb +7 -1
  125. data/lib/solargraph/source/source_chainer.rb +13 -3
  126. data/lib/solargraph/source/updater.rb +4 -0
  127. data/lib/solargraph/source.rb +33 -7
  128. data/lib/solargraph/source_map/clip.rb +13 -2
  129. data/lib/solargraph/source_map/data.rb +4 -1
  130. data/lib/solargraph/source_map/mapper.rb +24 -1
  131. data/lib/solargraph/source_map.rb +14 -6
  132. data/lib/solargraph/type_checker/problem.rb +3 -1
  133. data/lib/solargraph/type_checker/rules.rb +75 -2
  134. data/lib/solargraph/type_checker.rb +111 -30
  135. data/lib/solargraph/version.rb +1 -1
  136. data/lib/solargraph/workspace/config.rb +3 -1
  137. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  138. data/lib/solargraph/workspace/require_paths.rb +1 -0
  139. data/lib/solargraph/workspace.rb +158 -16
  140. data/lib/solargraph/yard_map/helpers.rb +2 -1
  141. data/lib/solargraph/yard_map/mapper/to_method.rb +5 -1
  142. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  143. data/lib/solargraph/yard_map/mapper.rb +5 -0
  144. data/lib/solargraph/yardoc.rb +33 -23
  145. data/lib/solargraph.rb +24 -3
  146. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  147. data/rbs/fills/tuple/tuple.rbs +28 -0
  148. data/rbs/shims/ast/0/node.rbs +1 -1
  149. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  150. data/solargraph.gemspec +2 -1
  151. metadata +12 -7
  152. data/lib/solargraph/type_checker/checks.rb +0 -124
  153. data/lib/solargraph/type_checker/param_def.rb +0 -37
  154. data/lib/solargraph/yard_map/to_method.rb +0 -89
@@ -19,7 +19,6 @@ module Solargraph
19
19
  @ending = ending
20
20
  end
21
21
 
22
- # @sg-ignore Fix "Not enough arguments to Module#protected"
23
22
  protected def equality_fields
24
23
  [start, ending]
25
24
  end
@@ -27,12 +26,9 @@ module Solargraph
27
26
  # @param other [BasicObject]
28
27
  def <=>(other)
29
28
  return nil unless other.is_a?(Range)
30
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
31
29
  if start == other.start
32
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
33
30
  ending <=> other.ending
34
31
  else
35
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
36
32
  start <=> other.start
37
33
  end
38
34
  end
@@ -54,8 +50,11 @@ module Solargraph
54
50
  # @return [Boolean]
55
51
  def contain? position
56
52
  position = Position.normalize(position)
53
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
57
54
  return false if position.line < start.line || position.line > ending.line
55
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
58
56
  return false if position.line == start.line && position.character < start.character
57
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
59
58
  return false if position.line == ending.line && position.character > ending.character
60
59
  true
61
60
  end
@@ -63,9 +62,11 @@ module Solargraph
63
62
  # True if the range contains the specified position and the position does not precede it.
64
63
  #
65
64
  # @param position [Position, Array(Integer, Integer)]
65
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
66
66
  # @return [Boolean]
67
67
  def include? position
68
68
  position = Position.normalize(position)
69
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
69
70
  contain?(position) && !(position.line == start.line && position.character == start.character)
70
71
  end
71
72
 
@@ -82,7 +83,7 @@ module Solargraph
82
83
 
83
84
  # Get a range from a node.
84
85
  #
85
- # @param node [Parser::AST::Node]
86
+ # @param node [::Parser::AST::Node]
86
87
  # @return [Range, nil]
87
88
  def self.from_node node
88
89
  if node&.loc && node.loc.expression
@@ -101,7 +102,6 @@ module Solargraph
101
102
 
102
103
  def == other
103
104
  return false unless other.is_a?(Range)
104
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
105
105
  start == other.start && ending == other.ending
106
106
  end
107
107
 
@@ -65,7 +65,7 @@ module Solargraph
65
65
  # STDERR.puts "Skipping interface #{decl.name.relative!}"
66
66
  interface_decl_to_pin decl, closure
67
67
  when RBS::AST::Declarations::TypeAlias
68
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
68
+ # @sg-ignore flow sensitive typing should support case/when
69
69
  type_aliases[decl.name.to_s] = decl
70
70
  when RBS::AST::Declarations::Module
71
71
  module_decl_to_pin decl
@@ -96,7 +96,7 @@ module Solargraph
96
96
  type = build_type(decl.name, decl.args)
97
97
  generic_values = type.all_params.map(&:to_s)
98
98
  include_pin = Solargraph::Pin::Reference::Include.new(
99
- name: decl.name.relative!.to_s,
99
+ name: type.rooted_name,
100
100
  type_location: location_decl_to_pin_location(decl.location),
101
101
  generic_values: generic_values,
102
102
  closure: closure,
@@ -120,32 +120,44 @@ module Solargraph
120
120
  def convert_member_to_pin member, closure, context
121
121
  case member
122
122
  when RBS::AST::Members::MethodDefinition
123
+ # @sg-ignore flow based typing needs to understand case when class pattern
123
124
  method_def_to_pin(member, closure, context)
124
125
  when RBS::AST::Members::AttrReader
126
+ # @sg-ignore flow based typing needs to understand case when class pattern
125
127
  attr_reader_to_pin(member, closure, context)
126
128
  when RBS::AST::Members::AttrWriter
129
+ # @sg-ignore flow based typing needs to understand case when class pattern
127
130
  attr_writer_to_pin(member, closure, context)
128
131
  when RBS::AST::Members::AttrAccessor
132
+ # @sg-ignore flow based typing needs to understand case when class pattern
129
133
  attr_accessor_to_pin(member, closure, context)
130
134
  when RBS::AST::Members::Include
135
+ # @sg-ignore flow based typing needs to understand case when class pattern
131
136
  include_to_pin(member, closure)
132
137
  when RBS::AST::Members::Prepend
138
+ # @sg-ignore flow based typing needs to understand case when class pattern
133
139
  prepend_to_pin(member, closure)
134
140
  when RBS::AST::Members::Extend
141
+ # @sg-ignore flow based typing needs to understand case when class pattern
135
142
  extend_to_pin(member, closure)
136
143
  when RBS::AST::Members::Alias
144
+ # @sg-ignore flow based typing needs to understand case when class pattern
137
145
  alias_to_pin(member, closure)
138
146
  when RBS::AST::Members::ClassInstanceVariable
147
+ # @sg-ignore flow based typing needs to understand case when class pattern
139
148
  civar_to_pin(member, closure)
140
149
  when RBS::AST::Members::ClassVariable
150
+ # @sg-ignore flow based typing needs to understand case when class pattern
141
151
  cvar_to_pin(member, closure)
142
152
  when RBS::AST::Members::InstanceVariable
153
+ # @sg-ignore flow based typing needs to understand case when class pattern
143
154
  ivar_to_pin(member, closure)
144
155
  when RBS::AST::Members::Public
145
156
  return Context.new(:public)
146
157
  when RBS::AST::Members::Private
147
158
  return Context.new(:private)
148
159
  when RBS::AST::Declarations::Base
160
+ # @sg-ignore flow based typing needs to understand case when class pattern
149
161
  convert_decl_to_pin(member, closure)
150
162
  else
151
163
  Solargraph.logger.warn "Skipping member type #{member.class}"
@@ -232,12 +244,14 @@ module Solargraph
232
244
  convert_self_types_to_pins decl, module_pin
233
245
  convert_members_to_pins decl, module_pin
234
246
 
247
+ raise "Invalid type for module declaration: #{module_pin.class}" unless module_pin.is_a?(Pin::Namespace)
248
+
235
249
  add_mixins decl, module_pin.closure
236
250
  end
237
251
 
238
252
  # @param name [String]
239
253
  # @param tag [String]
240
- # @param comments [String]
254
+ # @param comments [String, nil]
241
255
  # @param decl [RBS::AST::Declarations::ClassAlias, RBS::AST::Declarations::Constant, RBS::AST::Declarations::ModuleAlias]
242
256
  # @param base [String, nil] Optional conversion of tag to base<tag>
243
257
  #
@@ -246,6 +260,7 @@ module Solargraph
246
260
  parts = name.split('::')
247
261
  if parts.length > 1
248
262
  name = parts.last
263
+ # @sg-ignore Need to add nil check here
249
264
  closure = pins.select { |pin| pin && pin.path == parts[0..-2].join('::') }.first
250
265
  else
251
266
  name = parts.first
@@ -347,12 +362,11 @@ module Solargraph
347
362
  ["Rainbow::Presenter", :instance, "wrap_with_sgr"] => :private,
348
363
  }
349
364
 
350
- # @param decl [RBS::AST::Members::MethodDefinition, RBS::AST::Members::AttrReader, RBS::AST::Members::AttrAccessor]
365
+ # @param decl [RBS::AST::Members::MethodDefinition, RBS::AST::Members::AttrReader, RBS::AST::Members::AttrWriter, RBS::AST::Members::AttrAccessor]
351
366
  # @param closure [Pin::Closure]
352
367
  # @param context [Context]
353
368
  # @param scope [Symbol] :instance or :class
354
369
  # @param name [String] The name of the method
355
- # @sg-ignore
356
370
  # @return [Symbol]
357
371
  def calculate_method_visibility(decl, context, closure, scope, name)
358
372
  override_key = [closure.path, scope, name]
@@ -432,8 +446,9 @@ module Solargraph
432
446
  type_location = location_decl_to_pin_location(overload.method_type.location)
433
447
  generics = overload.method_type.type_params.map(&:name).map(&:to_s)
434
448
  signature_parameters, signature_return_type = parts_of_function(overload.method_type, pin)
435
- block = if overload.method_type.block
436
- block_parameters, block_return_type = parts_of_function(overload.method_type.block, pin)
449
+ rbs_block = overload.method_type.block
450
+ block = if rbs_block
451
+ block_parameters, block_return_type = parts_of_function(rbs_block, pin)
437
452
  Pin::Signature.new(generics: generics, parameters: block_parameters, return_type: block_return_type, source: :rbs,
438
453
  type_location: type_location, closure: pin)
439
454
  end
@@ -447,9 +462,12 @@ module Solargraph
447
462
  def location_decl_to_pin_location(location)
448
463
  return nil if location&.name.nil?
449
464
 
465
+ # @sg-ignore flow sensitive typing should handle return nil if location&.name.nil?
450
466
  start_pos = Position.new(location.start_line - 1, location.start_column)
467
+ # @sg-ignore flow sensitive typing should handle return nil if location&.name.nil?
451
468
  end_pos = Position.new(location.end_line - 1, location.end_column)
452
469
  range = Range.new(start_pos, end_pos)
470
+ # @sg-ignore flow sensitve typing should handle return nil if location&.name.nil?
453
471
  Location.new(location.name.to_s, range)
454
472
  end
455
473
 
@@ -705,7 +723,7 @@ module Solargraph
705
723
  'NilClass' => 'nil'
706
724
  }
707
725
 
708
- # @param type [RBS::MethodType]
726
+ # @param type [RBS::MethodType, RBS::Types::Block]
709
727
  # @return [String]
710
728
  def method_type_to_tag type
711
729
  if type_aliases.key?(type.type.return_type.to_s)
@@ -737,7 +755,9 @@ module Solargraph
737
755
  build_type(type_name, type_args).tags
738
756
  end
739
757
 
740
- # @param type [RBS::Types::Bases::Base]
758
+ # @param type [RBS::Types::Bases::Base,Object] RBS type object.
759
+ # Note: Generally these extend from RBS::Types::Bases::Base,
760
+ # but not all.
741
761
  # @return [String]
742
762
  def other_type_to_tag type
743
763
  if type.is_a?(RBS::Types::Optional)
@@ -794,13 +814,16 @@ module Solargraph
794
814
  # e.g., singleton(String)
795
815
  type_tag(type.name)
796
816
  else
817
+ # RBS doesn't provide a common base class for its type AST nodes
818
+ #
819
+ # @sg-ignore all types should include location
797
820
  Solargraph.logger.warn "Unrecognized RBS type: #{type.class} at #{type.location}"
798
821
  'undefined'
799
822
  end
800
823
  end
801
824
 
802
825
  # @param decl [RBS::AST::Declarations::Class, RBS::AST::Declarations::Module]
803
- # @param namespace [Pin::Namespace]
826
+ # @param namespace [Pin::Namespace, nil]
804
827
  # @return [void]
805
828
  def add_mixins decl, namespace
806
829
  # @param mixin [RBS::AST::Members::Include, RBS::AST::Members::Members::Extend, RBS::AST::Members::Members::Prepend]
@@ -15,31 +15,38 @@ module Solargraph
15
15
 
16
16
  def initialize; end
17
17
 
18
+ # @param out [IO, nil] output stream for logging
18
19
  # @return [Enumerable<Pin::Base>]
19
- def pins
20
+ def pins out: $stderr
20
21
  return @pins if @pins
22
+ @pins = cache_core(out: out)
23
+ end
21
24
 
22
- @pins = []
25
+ # @param out [StringIO, IO, nil] output stream for logging
26
+ # @return [Array<Pin::Base>]
27
+ def cache_core out: $stderr
28
+ new_pins = []
23
29
  cache = PinCache.deserialize_core
24
- if cache
25
- @pins.replace cache
26
- else
27
- @pins.concat conversions.pins
30
+ return cache if cache
31
+ new_pins.concat conversions.pins
32
+
33
+ # Avoid RBS::DuplicatedDeclarationError by loading in a different EnvironmentLoader
34
+ fill_loader = RBS::EnvironmentLoader.new(core_root: nil, repository: RBS::Repository.new(no_stdlib: false))
35
+ fill_loader.add(path: Pathname(FILLS_DIRECTORY))
36
+ out&.puts 'Caching RBS pins for Ruby core'
37
+ fill_conversions = Conversions.new(loader: fill_loader)
38
+ new_pins.concat fill_conversions.pins
28
39
 
29
- # Avoid RBS::DuplicatedDeclarationError by loading in a different EnvironmentLoader
30
- fill_loader = RBS::EnvironmentLoader.new(core_root: nil, repository: RBS::Repository.new(no_stdlib: false))
31
- fill_loader.add(path: Pathname(FILLS_DIRECTORY))
32
- fill_conversions = Conversions.new(loader: fill_loader)
33
- @pins.concat fill_conversions.pins
40
+ # add some overrides
41
+ new_pins.concat RbsMap::CoreFills::ALL
34
42
 
35
- @pins.concat RbsMap::CoreFills::ALL
43
+ # process overrides, then remove any which couldn't be resolved
44
+ processed = ApiMap::Store.new(new_pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) }
45
+ new_pins.replace processed
36
46
 
37
- processed = ApiMap::Store.new(pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) }
38
- @pins.replace processed
47
+ PinCache.serialize_core new_pins
39
48
 
40
- PinCache.serialize_core @pins
41
- end
42
- @pins
49
+ new_pins
43
50
  end
44
51
 
45
52
  private
@@ -12,19 +12,23 @@ module Solargraph
12
12
  # @type [Hash{String => RbsMap}]
13
13
  @stdlib_maps_hash = {}
14
14
 
15
+
16
+ # @param rebuild [Boolean] build pins regardless of whether we
17
+ # have cached them already
15
18
  # @param library [String]
16
- def initialize library
19
+ # @param out [StringIO, IO, nil] where to log messages
20
+ def initialize library, rebuild: false, out: $stderr
17
21
  cached_pins = PinCache.deserialize_stdlib_require library
18
- if cached_pins
22
+ if cached_pins && !rebuild
19
23
  @pins = cached_pins
20
24
  @resolved = true
21
25
  @loaded = true
22
26
  logger.debug { "Deserialized #{cached_pins.length} cached pins for stdlib require #{library.inspect}" }
23
- else
24
- super
27
+ elsif self.class.source.has? library, nil
28
+ super(library, out: out)
25
29
  unless resolved?
26
30
  @pins = []
27
- logger.info { "Could not resolve #{library.inspect}" }
31
+ logger.debug { "StdlibMap could not resolve #{library.inspect}" }
28
32
  return
29
33
  end
30
34
  generated_pins = pins
@@ -33,6 +37,31 @@ module Solargraph
33
37
  end
34
38
  end
35
39
 
40
+ # @return [RBS::Collection::Sources::Stdlib]
41
+ def self.source
42
+ @source ||= RBS::Collection::Sources::Stdlib.instance
43
+ end
44
+
45
+ # @param name [String]
46
+ # @param version [String, nil]
47
+ # @return [Array<Hash{String => String}>, nil]
48
+ def self.stdlib_dependencies name, version = nil
49
+ if source.has?(name, version)
50
+ # @sg-ignore we are relying on undocumented behavior where
51
+ # passing version=nil gives the latest version it has
52
+ source.dependencies_of(name, version)
53
+ else
54
+ []
55
+ end
56
+ end
57
+
58
+ def resolve_dependencies?
59
+ # there are 'virtual' dependencies for stdlib gems in RBS that
60
+ # aren't represented in the actual gemspecs that we'd
61
+ # otherwise use
62
+ true
63
+ end
64
+
36
65
  # @param library [String]
37
66
  # @return [StdlibMap]
38
67
  def self.load library
@@ -26,7 +26,8 @@ module Solargraph
26
26
  # @param version [String, nil]
27
27
  # @param rbs_collection_config_path [String, Pathname, nil]
28
28
  # @param rbs_collection_paths [Array<Pathname, String>]
29
- def initialize library, version = nil, rbs_collection_config_path: nil, rbs_collection_paths: []
29
+ # @param out [StringIO, IO, nil] where to log messages
30
+ def initialize library, version = nil, rbs_collection_config_path: nil, rbs_collection_paths: [], out: $stderr
30
31
  if rbs_collection_config_path.nil? && !rbs_collection_paths.empty?
31
32
  raise 'Please provide rbs_collection_config_path if you provide rbs_collection_paths'
32
33
  end
@@ -37,6 +38,28 @@ module Solargraph
37
38
  add_library loader, library, version
38
39
  end
39
40
 
41
+ CACHE_KEY_GEM_EXPORT = 'gem-export'
42
+ CACHE_KEY_UNRESOLVED = 'unresolved'
43
+ CACHE_KEY_STDLIB = 'stdlib'
44
+ CACHE_KEY_LOCAL = 'local'
45
+
46
+ # @param cache_key [String, nil]
47
+ # @return [String, nil] a description of the source of the RBS info
48
+ def self.rbs_source_desc cache_key
49
+ case cache_key
50
+ when CACHE_KEY_GEM_EXPORT
51
+ 'RBS gem export'
52
+ when CACHE_KEY_UNRESOLVED
53
+ nil
54
+ when CACHE_KEY_STDLIB
55
+ 'RBS standard library'
56
+ when CACHE_KEY_LOCAL
57
+ 'local RBS shims'
58
+ else
59
+ 'RBS collection'
60
+ end
61
+ end
62
+
40
63
  # @return [RBS::EnvironmentLoader]
41
64
  def loader
42
65
  @loader ||= RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
@@ -47,10 +70,15 @@ module Solargraph
47
70
  # updated upstream for the same library and version. May change
48
71
  # if the config for where information comes form changes.
49
72
  def cache_key
73
+ return CACHE_KEY_UNRESOLVED unless resolved?
74
+
50
75
  @hextdigest ||= begin
51
76
  # @type [String, nil]
52
77
  data = nil
78
+ # @type gem_config [nil, Hash{String => Hash{String => String}}]
79
+ gem_config = nil
53
80
  if rbs_collection_config_path
81
+ # @sg-ignore flow sensitive typing needs to handle attrs
54
82
  lockfile_path = RBS::Collection::Config.to_lockfile_path(Pathname.new(rbs_collection_config_path))
55
83
  if lockfile_path.exist?
56
84
  collection_config = RBS::Collection::Config.from_path lockfile_path
@@ -58,16 +86,22 @@ module Solargraph
58
86
  data = gem_config&.to_s
59
87
  end
60
88
  end
61
- if data.nil? || data.empty?
62
- if resolved?
63
- # definitely came from the gem itself and not elsewhere -
64
- # only one version per gem
65
- 'gem-export'
89
+ if gem_config.nil?
90
+ CACHE_KEY_STDLIB
91
+ else
92
+ # @type [String]
93
+ source = gem_config.dig('source', 'type')
94
+ case source
95
+ when 'rubygems'
96
+ CACHE_KEY_GEM_EXPORT
97
+ when 'local'
98
+ CACHE_KEY_LOCAL
99
+ when 'stdlib'
100
+ CACHE_KEY_STDLIB
66
101
  else
67
- 'unresolved'
102
+ # @sg-ignore Need to add nil check here
103
+ Digest::SHA1.hexdigest(data)
68
104
  end
69
- else
70
- Digest::SHA1.hexdigest(data)
71
105
  end
72
106
  end
73
107
  end
@@ -77,6 +111,10 @@ module Solargraph
77
111
  # @param rbs_collection_config_path [String, Pathname, nil]
78
112
  # @return [RbsMap]
79
113
  def self.from_gemspec gemspec, rbs_collection_path, rbs_collection_config_path
114
+ # prefers stdlib RBS if available
115
+ rbs_map = RbsMap::StdlibMap.new(gemspec.name)
116
+ return rbs_map if rbs_map.resolved?
117
+
80
118
  rbs_map = RbsMap.new(gemspec.name, gemspec.version,
81
119
  rbs_collection_paths: [rbs_collection_path].compact,
82
120
  rbs_collection_config_path: rbs_collection_config_path)
@@ -88,14 +126,22 @@ module Solargraph
88
126
  rbs_collection_config_path: rbs_collection_config_path)
89
127
  end
90
128
 
129
+ # @param out [IO, nil] where to log messages
91
130
  # @return [Array<Pin::Base>]
92
- def pins
93
- @pins ||= resolved? ? conversions.pins : []
131
+ def pins out: $stderr
132
+ @pins ||= if resolved?
133
+ conversions.pins
134
+ else
135
+ []
136
+ end
94
137
  end
95
138
 
96
139
  # @generic T
97
140
  # @param path [String]
98
141
  # @param klass [Class<generic<T>>]
142
+ #
143
+ # @sg-ignore Need to be able to resolve generics based on a
144
+ # Class<generic<T>> param
99
145
  # @return [generic<T>, nil]
100
146
  def path_pin path, klass = Pin::Base
101
147
  pin = pins.find { |p| p.path == path }
@@ -140,19 +186,27 @@ module Solargraph
140
186
  @conversions ||= Conversions.new(loader: loader)
141
187
  end
142
188
 
189
+ def resolve_dependencies?
190
+ # we need to resolve dependencies via gemfile.lock manually for
191
+ # YARD regardless, so use same mechanism here so we don't
192
+ # duplicate work generating pins from dependencies
193
+ false
194
+ end
195
+
143
196
  # @param loader [RBS::EnvironmentLoader]
144
197
  # @param library [String]
145
- # @param version [String, nil]
198
+ # @param version [String, nil] the version of the library to load, or nil for any
199
+ # @param out [StringIO, IO, nil] where to log messages
146
200
  # @return [Boolean] true if adding the library succeeded
147
- def add_library loader, library, version
201
+ def add_library loader, library, version, out: $stderr
148
202
  @resolved = if loader.has_library?(library: library, version: version)
149
- loader.add library: library, version: version
150
- logger.debug { "#{short_name} successfully loaded library #{library}:#{version}" }
151
- true
152
- else
153
- logger.info { "#{short_name} did not find data for library #{library}:#{version}" }
154
- false
155
- end
203
+ loader.add library: library, version: version, resolve_dependencies: resolve_dependencies?
204
+ logger.debug { "#{short_name} successfully loaded library #{library}:#{version}" }
205
+ true
206
+ else
207
+ logger.info { "#{short_name} did not find data for library #{library}:#{version}" }
208
+ false
209
+ end
156
210
  end
157
211
 
158
212
  # @return [String]