solargraph 0.54.4 → 0.56.2

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 (135) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/plugins.yml +2 -0
  3. data/.github/workflows/typecheck.yml +3 -1
  4. data/.gitignore +2 -0
  5. data/CHANGELOG.md +62 -0
  6. data/README.md +13 -3
  7. data/lib/solargraph/api_map/index.rb +24 -16
  8. data/lib/solargraph/api_map/store.rb +48 -23
  9. data/lib/solargraph/api_map.rb +175 -77
  10. data/lib/solargraph/bench.rb +17 -1
  11. data/lib/solargraph/complex_type/type_methods.rb +6 -1
  12. data/lib/solargraph/complex_type/unique_type.rb +98 -9
  13. data/lib/solargraph/complex_type.rb +35 -6
  14. data/lib/solargraph/convention/base.rb +3 -3
  15. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +60 -0
  16. data/lib/solargraph/convention/data_definition/data_definition_node.rb +89 -0
  17. data/lib/solargraph/convention/data_definition.rb +104 -0
  18. data/lib/solargraph/convention/gemspec.rb +2 -1
  19. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +60 -0
  20. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +100 -0
  21. data/lib/solargraph/convention/struct_definition.rb +141 -0
  22. data/lib/solargraph/convention.rb +5 -3
  23. data/lib/solargraph/doc_map.rb +277 -57
  24. data/lib/solargraph/gem_pins.rb +53 -37
  25. data/lib/solargraph/language_server/host/message_worker.rb +10 -7
  26. data/lib/solargraph/language_server/host.rb +12 -2
  27. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
  28. data/lib/solargraph/language_server/message/extended/document.rb +5 -2
  29. data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
  30. data/lib/solargraph/library.rb +45 -17
  31. data/lib/solargraph/location.rb +21 -0
  32. data/lib/solargraph/logging.rb +1 -0
  33. data/lib/solargraph/parser/comment_ripper.rb +12 -6
  34. data/lib/solargraph/parser/flow_sensitive_typing.rb +227 -0
  35. data/lib/solargraph/parser/node_methods.rb +14 -0
  36. data/lib/solargraph/parser/node_processor/base.rb +9 -4
  37. data/lib/solargraph/parser/node_processor.rb +21 -8
  38. data/lib/solargraph/parser/parser_gem/class_methods.rb +16 -14
  39. data/lib/solargraph/parser/parser_gem/node_chainer.rb +10 -10
  40. data/lib/solargraph/parser/parser_gem/node_methods.rb +4 -2
  41. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
  42. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +21 -0
  43. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +4 -2
  44. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +4 -2
  45. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
  46. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
  47. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
  48. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
  49. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
  50. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +21 -0
  51. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
  52. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -1
  53. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +4 -1
  54. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
  55. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +42 -0
  56. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
  57. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +3 -1
  58. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -3
  59. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +28 -16
  60. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
  61. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
  62. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
  63. data/lib/solargraph/parser/parser_gem/node_processors.rb +14 -0
  64. data/lib/solargraph/parser/region.rb +1 -1
  65. data/lib/solargraph/parser.rb +1 -0
  66. data/lib/solargraph/pin/base.rb +316 -28
  67. data/lib/solargraph/pin/base_variable.rb +16 -9
  68. data/lib/solargraph/pin/block.rb +2 -0
  69. data/lib/solargraph/pin/breakable.rb +9 -0
  70. data/lib/solargraph/pin/callable.rb +74 -3
  71. data/lib/solargraph/pin/closure.rb +18 -1
  72. data/lib/solargraph/pin/common.rb +5 -0
  73. data/lib/solargraph/pin/delegated_method.rb +20 -1
  74. data/lib/solargraph/pin/documenting.rb +16 -0
  75. data/lib/solargraph/pin/keyword.rb +7 -2
  76. data/lib/solargraph/pin/local_variable.rb +15 -6
  77. data/lib/solargraph/pin/method.rb +169 -43
  78. data/lib/solargraph/pin/namespace.rb +17 -9
  79. data/lib/solargraph/pin/parameter.rb +60 -11
  80. data/lib/solargraph/pin/proxy_type.rb +12 -6
  81. data/lib/solargraph/pin/reference/override.rb +10 -6
  82. data/lib/solargraph/pin/reference/require.rb +2 -2
  83. data/lib/solargraph/pin/signature.rb +42 -0
  84. data/lib/solargraph/pin/singleton.rb +1 -1
  85. data/lib/solargraph/pin/symbol.rb +3 -2
  86. data/lib/solargraph/pin/until.rb +18 -0
  87. data/lib/solargraph/pin/while.rb +18 -0
  88. data/lib/solargraph/pin.rb +4 -1
  89. data/lib/solargraph/pin_cache.rb +185 -0
  90. data/lib/solargraph/position.rb +9 -0
  91. data/lib/solargraph/range.rb +9 -0
  92. data/lib/solargraph/rbs_map/conversions.rb +221 -67
  93. data/lib/solargraph/rbs_map/core_fills.rb +32 -16
  94. data/lib/solargraph/rbs_map/core_map.rb +34 -11
  95. data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
  96. data/lib/solargraph/rbs_map.rb +74 -17
  97. data/lib/solargraph/shell.rb +17 -18
  98. data/lib/solargraph/source/chain/array.rb +11 -7
  99. data/lib/solargraph/source/chain/block_symbol.rb +1 -1
  100. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  101. data/lib/solargraph/source/chain/call.rb +53 -23
  102. data/lib/solargraph/source/chain/constant.rb +1 -1
  103. data/lib/solargraph/source/chain/hash.rb +4 -3
  104. data/lib/solargraph/source/chain/head.rb +1 -1
  105. data/lib/solargraph/source/chain/if.rb +1 -1
  106. data/lib/solargraph/source/chain/link.rb +2 -0
  107. data/lib/solargraph/source/chain/literal.rb +22 -2
  108. data/lib/solargraph/source/chain/or.rb +1 -1
  109. data/lib/solargraph/source/chain/z_super.rb +1 -1
  110. data/lib/solargraph/source/chain.rb +78 -48
  111. data/lib/solargraph/source/source_chainer.rb +2 -2
  112. data/lib/solargraph/source_map/clip.rb +3 -1
  113. data/lib/solargraph/source_map/mapper.rb +9 -5
  114. data/lib/solargraph/source_map.rb +0 -17
  115. data/lib/solargraph/type_checker/checks.rb +4 -0
  116. data/lib/solargraph/type_checker.rb +35 -8
  117. data/lib/solargraph/version.rb +1 -1
  118. data/lib/solargraph/views/_method.erb +10 -10
  119. data/lib/solargraph/views/_namespace.erb +3 -3
  120. data/lib/solargraph/views/document.erb +10 -10
  121. data/lib/solargraph/workspace/config.rb +1 -1
  122. data/lib/solargraph/workspace.rb +23 -5
  123. data/lib/solargraph/yard_map/helpers.rb +29 -1
  124. data/lib/solargraph/yard_map/mapper/to_constant.rb +7 -5
  125. data/lib/solargraph/yard_map/mapper/to_method.rb +53 -18
  126. data/lib/solargraph/yard_map/mapper/to_namespace.rb +9 -7
  127. data/lib/solargraph/yard_map/mapper.rb +4 -3
  128. data/lib/solargraph/yard_map/to_method.rb +4 -2
  129. data/lib/solargraph/yardoc.rb +7 -8
  130. data/lib/solargraph.rb +32 -1
  131. data/rbs/fills/tuple.rbs +150 -0
  132. data/rbs_collection.yaml +19 -0
  133. data/solargraph.gemspec +2 -1
  134. metadata +37 -9
  135. data/lib/solargraph/cache.rb +0 -77
@@ -9,6 +9,22 @@ require 'solargraph/converters/dt'
9
9
  require 'solargraph/converters/dd'
10
10
  require 'solargraph/converters/misc'
11
11
 
12
+ # @todo upstream this definition
13
+
14
+ # @!parse
15
+ # module ::Kramdown
16
+ # class Document
17
+ # # @return [String]
18
+ # def to_html; end
19
+ # end
20
+ # end
21
+ # module ReverseMarkdown
22
+ # # @param input [String]
23
+ # # @param options [Hash]
24
+ # # @return [String]
25
+ # def self.convert(input, options = {}); end
26
+ # end
27
+
12
28
  module Solargraph
13
29
  module Pin
14
30
  # A module to add the Pin::Base#documentation method.
@@ -3,8 +3,13 @@
3
3
  module Solargraph
4
4
  module Pin
5
5
  class Keyword < Base
6
- def initialize name
7
- super(name: name)
6
+ def initialize(name, **kwargs)
7
+ # @sg-ignore "Unrecognized keyword argument kwargs to Solargraph::Pin::Base#initialize"
8
+ super(name: name, **kwargs)
9
+ end
10
+
11
+ def closure
12
+ @closure ||= Pin::ROOT_PIN
8
13
  end
9
14
 
10
15
  def name
@@ -6,20 +6,29 @@ module Solargraph
6
6
  # @return [Range]
7
7
  attr_reader :presence
8
8
 
9
+ def presence_certain?
10
+ @presence_certain
11
+ end
12
+
9
13
  # @param assignment [AST::Node, nil]
10
14
  # @param presence [Range, nil]
15
+ # @param presence_certain [Boolean]
11
16
  # @param splat [Hash]
12
- def initialize assignment: nil, presence: nil, **splat
17
+ def initialize assignment: nil, presence: nil, presence_certain: false, **splat
13
18
  super(**splat)
14
19
  @assignment = assignment
15
20
  @presence = presence
21
+ @presence_certain = presence_certain
16
22
  end
17
23
 
18
- # @param pin [self]
19
- def try_merge! pin
20
- return false unless super
21
- @presence = pin.presence
22
- true
24
+ def combine_with(other, attrs={})
25
+ new_attrs = {
26
+ assignment: assert_same(other, :assignment),
27
+ presence_certain: assert_same(other, :presence_certain?),
28
+ }.merge(attrs)
29
+ new_attrs[:presence] = assert_same(other, :presence) unless attrs.key?(:presence)
30
+
31
+ super(other, new_attrs)
23
32
  end
24
33
 
25
34
  # @param other_closure [Pin::Closure]
@@ -10,6 +10,8 @@ module Solargraph
10
10
  # @return [::Symbol] :public, :private, or :protected
11
11
  attr_reader :visibility
12
12
 
13
+ attr_writer :signatures
14
+
13
15
  # @return [Parser::AST::Node]
14
16
  attr_reader :node
15
17
 
@@ -31,6 +33,70 @@ module Solargraph
31
33
  @anon_splat = anon_splat
32
34
  end
33
35
 
36
+ # @return [Array<Pin::Signature>]
37
+ def combine_all_signature_pins(*signature_pins)
38
+ by_arity = {}
39
+ signature_pins.each do |signature_pin|
40
+ by_arity[signature_pin.arity] ||= []
41
+ by_arity[signature_pin.arity] << signature_pin
42
+ end
43
+ by_arity.transform_values! do |same_arity_pins|
44
+ same_arity_pins.reduce(nil) do |memo, signature|
45
+ next signature if memo.nil?
46
+ memo.combine_with(signature)
47
+ end
48
+ end
49
+ by_arity.values.flatten
50
+ end
51
+
52
+ # @param other [Pin::Method]
53
+ # @return [Symbol]
54
+ def combine_visibility(other)
55
+ if dodgy_visibility_source? && !other.dodgy_visibility_source?
56
+ other.visibility
57
+ elsif other.dodgy_visibility_source? && !dodgy_visibility_source?
58
+ visibility
59
+ else
60
+ assert_same(other, :visibility)
61
+ end
62
+ end
63
+
64
+ # @param other [Pin::Method]
65
+ # @return [Array<Pin::Signature>]
66
+ def combine_signatures(other)
67
+ all_undefined = signatures.all? { |sig| sig.return_type.undefined? }
68
+ other_all_undefined = other.signatures.all? { |sig| sig.return_type.undefined? }
69
+ if all_undefined && !other_all_undefined
70
+ other.signatures
71
+ elsif other_all_undefined && !all_undefined
72
+ signatures
73
+ else
74
+ combine_all_signature_pins(*signatures, *other.signatures)
75
+ end
76
+ end
77
+
78
+ def combine_with(other, attrs = {})
79
+ sigs = combine_signatures(other)
80
+ parameters = if sigs.length > 0
81
+ [].freeze
82
+ else
83
+ choose(other, :parameters).clone.freeze
84
+ end
85
+ new_attrs = {
86
+ visibility: combine_visibility(other),
87
+ explicit: explicit? || other.explicit?,
88
+ block: combine_blocks(other),
89
+ node: choose_node(other, :node),
90
+ attribute: prefer_rbs_location(other, :attribute?),
91
+ parameters: parameters,
92
+ signatures: sigs,
93
+ anon_splat: assert_same(other, :anon_splat?),
94
+ return_type: nil # pulled from signatures on first call
95
+ }.merge(attrs)
96
+ super(other, new_attrs)
97
+ end
98
+
99
+ # @param other [Pin::Method]
34
100
  def == other
35
101
  super && other.node == node
36
102
  end
@@ -42,11 +108,24 @@ module Solargraph
42
108
  sig.transform_types(&transform)
43
109
  end
44
110
  m.block = block&.transform_types(&transform)
45
- m.signature_help = nil
46
- m.documentation = nil
111
+ m.reset_generated!
47
112
  m
48
113
  end
49
114
 
115
+ # @return [void]
116
+ def reset_generated!
117
+ super
118
+ unless signatures.empty?
119
+ return_type = nil
120
+ @block = :undefined
121
+ parameters = []
122
+ end
123
+ block&.reset_generated!
124
+ @signatures&.each(&:reset_generated!)
125
+ signature_help = nil
126
+ documentation = nil
127
+ end
128
+
50
129
  def all_rooted?
51
130
  super && parameters.all?(&:all_rooted?) && (!block || block&.all_rooted?) && signatures.all?(&:all_rooted?)
52
131
  end
@@ -55,8 +134,7 @@ module Solargraph
55
134
  # @return [Pin::Method]
56
135
  def with_single_signature(signature)
57
136
  m = proxy signature.return_type
58
- m.signature_help = nil
59
- m.documentation = nil
137
+ m.reset_generated!
60
138
  # @todo populating the single parameters/return_type/block
61
139
  # arguments here seems to be needed for some specs to pass,
62
140
  # even though we have a signature with the same information.
@@ -116,13 +194,18 @@ module Solargraph
116
194
  name: name,
117
195
  decl: decl,
118
196
  presence: location ? location.range : nil,
119
- return_type: ComplexType.try_parse(*p.types)
197
+ return_type: ComplexType.try_parse(*p.types),
198
+ source: source
120
199
  )
121
200
  end
122
201
  yield_return_type = ComplexType.try_parse(*yieldreturn_tags.flat_map(&:types))
123
- block = Signature.new(generics: generics, parameters: yield_parameters, return_type: yield_return_type)
202
+ block = Signature.new(generics: generics, parameters: yield_parameters, return_type: yield_return_type, source: source,
203
+ closure: self, location: location, type_location: type_location)
124
204
  end
125
- Signature.new(generics: generics, parameters: parameters, return_type: return_type, block: block)
205
+ signature = Signature.new(generics: generics, parameters: parameters, return_type: return_type, block: block, closure: self, source: source,
206
+ location: location, type_location: type_location)
207
+ block.closure = signature if block
208
+ signature
126
209
  end
127
210
 
128
211
  # @return [::Array<Signature>]
@@ -137,6 +220,14 @@ module Solargraph
137
220
  end
138
221
  end
139
222
 
223
+ # @param return_type [ComplexType]
224
+ # @return [self]
225
+ def proxy_with_signatures return_type
226
+ out = proxy return_type
227
+ out.signatures = out.signatures.map { |sig| sig.proxy return_type }
228
+ out
229
+ end
230
+
140
231
  # @return [String, nil]
141
232
  def detail
142
233
  # This property is not cached in an instance variable because it can
@@ -163,12 +254,12 @@ module Solargraph
163
254
  end
164
255
  end
165
256
 
166
- def desc
257
+ def inner_desc
167
258
  # ensure the signatures line up when logged
168
259
  if signatures.length > 1
169
- "\n#{to_rbs}\n"
260
+ path + " \n#{to_rbs}\n"
170
261
  else
171
- to_rbs
262
+ super
172
263
  end
173
264
  end
174
265
 
@@ -188,21 +279,36 @@ module Solargraph
188
279
  @path ||= "#{namespace}#{(scope == :instance ? '#' : '.')}#{name}"
189
280
  end
190
281
 
282
+ # @return [String]
283
+ def method_name
284
+ name
285
+ end
286
+
191
287
  def typify api_map
288
+ logger.debug { "Method#typify(self=#{self}, binder=#{binder}, closure=#{closure}, context=#{context.rooted_tags}, return_type=#{return_type.rooted_tags}) - starting" }
192
289
  decl = super
193
- return decl unless decl.undefined?
290
+ unless decl.undefined?
291
+ logger.debug { "Method#typify(self=#{self}, binder=#{binder}, closure=#{closure}, context=#{context}) => #{decl.rooted_tags.inspect} - decl found" }
292
+ return decl
293
+ end
194
294
  type = see_reference(api_map) || typify_from_super(api_map)
195
- return type.qualify(api_map, namespace) unless type.nil?
196
- name.end_with?('?') ? ComplexType::BOOLEAN : ComplexType::UNDEFINED
295
+ logger.debug { "Method#typify(self=#{self}) - type=#{type&.rooted_tags.inspect}" }
296
+ unless type.nil?
297
+ qualified = type.qualify(api_map, namespace)
298
+ logger.debug { "Method#typify(self=#{self}) => #{qualified.rooted_tags.inspect}" }
299
+ return qualified
300
+ end
301
+ super
197
302
  end
198
303
 
304
+ # @sg-ignore
199
305
  def documentation
200
306
  if @documentation.nil?
201
- @documentation ||= super || ''
307
+ method_docs ||= super || ''
202
308
  param_tags = docstring.tags(:param)
203
309
  unless param_tags.nil? or param_tags.empty?
204
- @documentation += "\n\n" unless @documentation.empty?
205
- @documentation += "Params:\n"
310
+ method_docs += "\n\n" unless method_docs.empty?
311
+ method_docs += "Params:\n"
206
312
  lines = []
207
313
  param_tags.each do |p|
208
314
  l = "* #{p.name}"
@@ -210,12 +316,12 @@ module Solargraph
210
316
  l += " #{p.text}"
211
317
  lines.push l
212
318
  end
213
- @documentation += lines.join("\n")
319
+ method_docs += lines.join("\n")
214
320
  end
215
321
  yieldparam_tags = docstring.tags(:yieldparam)
216
322
  unless yieldparam_tags.nil? or yieldparam_tags.empty?
217
- @documentation += "\n\n" unless @documentation.empty?
218
- @documentation += "Block Params:\n"
323
+ method_docs += "\n\n" unless method_docs.empty?
324
+ method_docs += "Block Params:\n"
219
325
  lines = []
220
326
  yieldparam_tags.each do |p|
221
327
  l = "* #{p.name}"
@@ -223,12 +329,12 @@ module Solargraph
223
329
  l += " #{p.text}"
224
330
  lines.push l
225
331
  end
226
- @documentation += lines.join("\n")
332
+ method_docs += lines.join("\n")
227
333
  end
228
334
  yieldreturn_tags = docstring.tags(:yieldreturn)
229
335
  unless yieldreturn_tags.empty?
230
- @documentation += "\n\n" unless @documentation.empty?
231
- @documentation += "Block Returns:\n"
336
+ method_docs += "\n\n" unless method_docs.empty?
337
+ method_docs += "Block Returns:\n"
232
338
  lines = []
233
339
  yieldreturn_tags.each do |r|
234
340
  l = "*"
@@ -236,12 +342,12 @@ module Solargraph
236
342
  l += " #{r.text}"
237
343
  lines.push l
238
344
  end
239
- @documentation += lines.join("\n")
345
+ method_docs += lines.join("\n")
240
346
  end
241
347
  return_tags = docstring.tags(:return)
242
348
  unless return_tags.empty?
243
- @documentation += "\n\n" unless @documentation.empty?
244
- @documentation += "Returns:\n"
349
+ method_docs += "\n\n" unless method_docs.empty?
350
+ method_docs += "Returns:\n"
245
351
  lines = []
246
352
  return_tags.each do |r|
247
353
  l = "*"
@@ -249,10 +355,11 @@ module Solargraph
249
355
  l += " #{r.text}"
250
356
  lines.push l
251
357
  end
252
- @documentation += lines.join("\n")
358
+ method_docs += lines.join("\n")
253
359
  end
254
- @documentation += "\n\n" unless @documentation.empty?
255
- @documentation += "Visibility: #{visibility}"
360
+ method_docs += "\n\n" unless method_docs.empty?
361
+ method_docs += "Visibility: #{visibility}"
362
+ @documentation = method_docs
256
363
  concat_example_tags
257
364
  end
258
365
  @documentation.to_s
@@ -278,14 +385,6 @@ module Solargraph
278
385
  attribute? ? infer_from_iv(api_map) : infer_from_return_nodes(api_map)
279
386
  end
280
387
 
281
- # @param pin [Pin::Method]
282
- def try_merge! pin
283
- return false unless super
284
- @node = pin.node
285
- @resolved_ref_tag = false
286
- true
287
- end
288
-
289
388
  # @return [::Array<Pin::Method>]
290
389
  def overloads
291
390
  # Ignore overload tags with nil parameters. If it's not an array, the
@@ -302,10 +401,13 @@ module Solargraph
302
401
  name: name,
303
402
  decl: decl,
304
403
  presence: location ? location.range : nil,
305
- return_type: param_type_from_name(tag, src.first)
404
+ return_type: param_type_from_name(tag, src.first),
405
+ source: :overloads
306
406
  )
307
407
  end,
308
- return_type: ComplexType.try_parse(*tag.docstring.tags(:return).flat_map(&:types))
408
+ closure: self,
409
+ return_type: ComplexType.try_parse(*tag.docstring.tags(:return).flat_map(&:types)),
410
+ source: :overloads,
309
411
  )
310
412
  end
311
413
  @overloads
@@ -315,7 +417,7 @@ module Solargraph
315
417
  @anon_splat
316
418
  end
317
419
 
318
- # @param [ApiMap]
420
+ # @param api_map [ApiMap]
319
421
  # @return [self]
320
422
  def resolve_ref_tag api_map
321
423
  return self if @resolved_ref_tag
@@ -338,16 +440,35 @@ module Solargraph
338
440
  self
339
441
  end
340
442
 
443
+ # @param api_map [ApiMap]
444
+ # @return [Array<Pin::Method>]
445
+ def rest_of_stack api_map
446
+ api_map.get_method_stack(method_namespace, method_name, scope: scope).reject { |pin| pin.path == path }
447
+ end
448
+
341
449
  protected
342
450
 
343
451
  attr_writer :block
344
452
 
345
- attr_writer :signatures
346
-
347
453
  attr_writer :signature_help
348
454
 
349
455
  attr_writer :documentation
350
456
 
457
+ def dodgy_visibility_source?
458
+ # as of 2025-03-12, the RBS generator used for
459
+ # e.g. activesupport did not understand 'private' markings
460
+ # inside 'class << self' blocks, but YARD did OK at it
461
+ source == :rbs && scope == :class && type_location&.filename&.include?('generated') && return_type.undefined? ||
462
+ # YARD's RBS generator seems to miss a lot of should-be protected instance methods
463
+ source == :rbs && scope == :instance && namespace.start_with?('YARD::') ||
464
+ # private on attr_readers seems to be broken in Prism's auto-generator script
465
+ source == :rbs && scope == :instance && namespace.start_with?('Prism::') ||
466
+ # The RBS for the RBS gem itself seems to use private as a
467
+ # 'is this a public API' concept, more aggressively than the
468
+ # actual code. Let's respect that and ignore the actual .rb file.
469
+ source == :yardoc && scope == :instance && namespace.start_with?('RBS::')
470
+ end
471
+
351
472
  private
352
473
 
353
474
  # @param name [String]
@@ -408,10 +529,15 @@ module Solargraph
408
529
  resolve_reference match[1], api_map
409
530
  end
410
531
 
532
+ # @return [String]
533
+ def method_namespace
534
+ namespace
535
+ end
536
+
411
537
  # @param api_map [ApiMap]
412
538
  # @return [ComplexType, nil]
413
539
  def typify_from_super api_map
414
- stack = api_map.get_method_stack(namespace, name, scope: scope).reject { |pin| pin.path == path }
540
+ stack = rest_of_stack api_map
415
541
  return nil if stack.empty?
416
542
  stack.each do |pin|
417
543
  return pin.return_type unless pin.return_type.undefined?
@@ -521,7 +647,7 @@ module Solargraph
521
647
 
522
648
  protected
523
649
 
524
- attr_writer :signatures
650
+ attr_writer :return_type
525
651
  end
526
652
  end
527
653
  end
@@ -11,44 +11,52 @@ module Solargraph
11
11
  # @return [::Symbol] :class or :module
12
12
  attr_reader :type
13
13
 
14
+ # does not assert like super, as a namespace without a closure
15
+ # may be the root level namespace, or it may not yet be
16
+ # qualified
17
+ attr_reader :closure
18
+
14
19
  # @param type [::Symbol] :class or :module
15
20
  # @param visibility [::Symbol] :public or :private
16
21
  # @param gates [::Array<String>]
17
- def initialize type: :class, visibility: :public, gates: [''], **splat
22
+ # @param name [String]
23
+ def initialize type: :class, visibility: :public, gates: [''], name: '', **splat
18
24
  # super(location, namespace, name, comments)
19
- super(**splat)
25
+ super(**splat, name: name)
20
26
  @type = type
21
27
  @visibility = visibility
22
28
  if name.start_with?('::')
23
- @name = name[2..-1]
29
+ # @type [String]
30
+ name = name[2..-1] || ''
24
31
  @closure = Solargraph::Pin::ROOT_PIN
25
32
  end
26
33
  @open_gates = gates
27
- if @name.include?('::')
34
+ if name.include?('::')
28
35
  # In this case, a chained namespace was opened (e.g., Foo::Bar)
29
36
  # but Foo does not exist.
30
- parts = @name.split('::')
31
- @name = parts.pop
37
+ parts = name.split('::')
38
+ name = parts.pop
32
39
  closure_name = if [Solargraph::Pin::ROOT_PIN, nil].include?(closure)
33
40
  ''
34
41
  else
35
42
  closure.full_context.namespace + '::'
36
43
  end
37
44
  closure_name += parts.join('::')
38
- @closure = Pin::Namespace.new(name: closure_name, gates: [parts.join('::')])
45
+ @closure = Pin::Namespace.new(name: closure_name, gates: [parts.join('::')], source: :namespace)
39
46
  @context = nil
40
47
  end
48
+ @name = name
41
49
  end
42
50
 
43
51
  def to_rbs
44
52
  "#{@type.to_s} #{return_type.all_params.first.to_rbs}#{rbs_generics}".strip
45
53
  end
46
54
 
47
- def desc
55
+ def inner_desc
48
56
  if name.nil? || name.empty?
49
57
  '(top-level)'
50
58
  else
51
- return_type.rooted_tags
59
+ super
52
60
  end
53
61
  end
54
62
 
@@ -9,14 +9,33 @@ module Solargraph
9
9
  # @return [String]
10
10
  attr_reader :asgn_code
11
11
 
12
+ # allow this to be set to the method after the method itself has
13
+ # been created
14
+ attr_writer :closure
15
+
12
16
  # @param decl [::Symbol] :arg, :optarg, :kwarg, :kwoptarg, :restarg, :kwrestarg, :block, :blockarg
13
17
  # @param asgn_code [String, nil]
14
- # @param return_type [ComplexType, nil]
15
- def initialize decl: :arg, asgn_code: nil, return_type: nil, **splat
18
+ def initialize decl: :arg, asgn_code: nil, **splat
16
19
  super(**splat)
17
20
  @asgn_code = asgn_code
18
21
  @decl = decl
19
- @return_type = return_type
22
+ end
23
+
24
+ def type_location
25
+ super || closure&.type_location
26
+ end
27
+
28
+ def location
29
+ super || closure&.type_location
30
+ end
31
+
32
+ def combine_with(other, attrs={})
33
+ new_attrs = {
34
+ decl: assert_same(other, :decl),
35
+ presence: choose(other, :presence),
36
+ asgn_code: choose(other, :asgn_code),
37
+ }.merge(attrs)
38
+ super(other, new_attrs)
20
39
  end
21
40
 
22
41
  def keyword?
@@ -27,6 +46,32 @@ module Solargraph
27
46
  decl == :kwrestarg || (assignment && [:HASH, :hash].include?(assignment.type))
28
47
  end
29
48
 
49
+ def needs_consistent_name?
50
+ keyword?
51
+ end
52
+
53
+ # @return [String]
54
+ def arity_decl
55
+ name = (self.name || '(anon)')
56
+ type = (return_type&.to_rbs || 'untyped')
57
+ case decl
58
+ when :arg
59
+ ""
60
+ when :optarg
61
+ "?"
62
+ when :kwarg
63
+ "#{name}:"
64
+ when :kwoptarg
65
+ "?#{name}:"
66
+ when :restarg
67
+ "*"
68
+ when :kwrestarg
69
+ "**"
70
+ else
71
+ "(unknown decl: #{decl})"
72
+ end
73
+ end
74
+
30
75
  def arg?
31
76
  decl == :arg
32
77
  end
@@ -115,18 +160,21 @@ module Solargraph
115
160
  closure.is_a?(Pin::Block) ? typify_block_param(api_map) : typify_method_param(api_map)
116
161
  end
117
162
 
163
+ # @param atype [ComplexType]
164
+ # @param api_map [ApiMap]
165
+ def compatible_arg?(atype, api_map)
166
+ # make sure we get types from up the method
167
+ # inheritance chain if we don't have them on this pin
168
+ ptype = typify api_map
169
+ ptype.undefined? || ptype.can_assign?(api_map, atype) || ptype.generic?
170
+ end
171
+
118
172
  def documentation
119
173
  tag = param_tag
120
174
  return '' if tag.nil? || tag.text.nil?
121
175
  tag.text
122
176
  end
123
177
 
124
- # @param pin [Pin::Parameter]
125
- def try_merge! pin
126
- return false unless super && closure == pin.closure
127
- true
128
- end
129
-
130
178
  private
131
179
 
132
180
  # @return [YARD::Tags::Tag, nil]
@@ -141,8 +189,9 @@ module Solargraph
141
189
  # @param api_map [ApiMap]
142
190
  # @return [ComplexType]
143
191
  def typify_block_param api_map
144
- if closure.is_a?(Pin::Block) && closure.receiver
145
- return closure.typify_parameters(api_map)[index]
192
+ block_pin = closure
193
+ if block_pin.is_a?(Pin::Block) && block_pin.receiver
194
+ return block_pin.typify_parameters(api_map)[index]
146
195
  end
147
196
  ComplexType::UNDEFINED
148
197
  end
@@ -4,24 +4,30 @@ module Solargraph
4
4
  module Pin
5
5
  class ProxyType < Base
6
6
  # @param return_type [ComplexType]
7
- def initialize return_type: ComplexType::UNDEFINED, **splat
7
+ def initialize return_type: ComplexType::UNDEFINED, binder: nil, **splat
8
8
  super(**splat)
9
9
  @return_type = return_type
10
+ @binder = binder if binder
10
11
  end
11
12
 
12
13
  def context
13
14
  @return_type
14
15
  end
15
16
 
16
- # @param return_type [ComplexType]
17
+ # @param context [ComplexType, ComplexType::UniqueType] Used as context for this pin
18
+ # @param closure [Pin::Namespace, nil] Used as the closure for this pin
19
+ # @param binder [ComplexType, ComplexType::UniqueType, nil]
17
20
  # @return [ProxyType]
18
- def self.anonymous return_type
19
- parts = return_type.namespace.split('::')
20
- namespace = parts[0..-2].join('::').to_s
21
+ def self.anonymous context, closure: nil, binder: nil, **kwargs
22
+ unless closure
23
+ parts = context.namespace.split('::')
24
+ namespace = parts[0..-2].join('::').to_s
25
+ closure = Solargraph::Pin::Namespace.new(name: namespace, source: :proxy_type)
26
+ end
21
27
  # name = parts.last.to_s
22
28
  # ProxyType.new(nil, namespace, name, return_type)
23
29
  ProxyType.new(
24
- closure: Solargraph::Pin::Namespace.new(name: namespace), return_type: return_type
30
+ closure: closure, return_type: context, binder: binder || context, **kwargs
25
31
  )
26
32
  end
27
33
  end
@@ -10,18 +10,22 @@ module Solargraph
10
10
  # @return [::Array<Symbol>]
11
11
  attr_reader :delete
12
12
 
13
- def initialize location, name, tags, delete = []
14
- super(location: location, name: name)
13
+ def closure
14
+ nil
15
+ end
16
+
17
+ def initialize location, name, tags, delete = [], **splat
18
+ super(location: location, name: name, **splat)
15
19
  @tags = tags
16
20
  @delete = delete
17
21
  end
18
22
 
19
- def self.method_return name, *tags, delete: []
20
- new(nil, name, [YARD::Tags::Tag.new('return', nil, tags)], delete)
23
+ def self.method_return name, *tags, delete: [], **splat
24
+ new(nil, name, [YARD::Tags::Tag.new('return', nil, tags)], delete, **splat)
21
25
  end
22
26
 
23
- def self.from_comment name, comment
24
- new(nil, name, Solargraph::Source.parse_docstring(comment).to_docstring.tags)
27
+ def self.from_comment name, comment, **splat
28
+ new(nil, name, Solargraph::Source.parse_docstring(comment).to_docstring.tags, **splat)
25
29
  end
26
30
  end
27
31
  end