solargraph 0.55.1 → 0.56.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 (102) 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 +26 -0
  6. data/README.md +13 -3
  7. data/lib/solargraph/api_map/index.rb +23 -15
  8. data/lib/solargraph/api_map/store.rb +8 -4
  9. data/lib/solargraph/api_map.rb +151 -58
  10. data/lib/solargraph/complex_type/type_methods.rb +6 -1
  11. data/lib/solargraph/complex_type/unique_type.rb +10 -2
  12. data/lib/solargraph/convention/base.rb +3 -3
  13. data/lib/solargraph/convention.rb +3 -3
  14. data/lib/solargraph/doc_map.rb +255 -69
  15. data/lib/solargraph/gem_pins.rb +53 -37
  16. data/lib/solargraph/language_server/host.rb +11 -2
  17. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
  18. data/lib/solargraph/language_server/message/extended/document.rb +5 -2
  19. data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
  20. data/lib/solargraph/library.rb +6 -3
  21. data/lib/solargraph/location.rb +13 -0
  22. data/lib/solargraph/logging.rb +1 -0
  23. data/lib/solargraph/parser/comment_ripper.rb +1 -0
  24. data/lib/solargraph/parser/flow_sensitive_typing.rb +5 -4
  25. data/lib/solargraph/parser/node_processor.rb +3 -1
  26. data/lib/solargraph/parser/parser_gem/class_methods.rb +5 -8
  27. data/lib/solargraph/parser/parser_gem/node_methods.rb +1 -1
  28. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
  29. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +4 -2
  30. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +4 -2
  31. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +4 -3
  32. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
  33. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
  34. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
  35. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
  36. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
  37. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -1
  38. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +6 -4
  39. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  40. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -3
  41. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +28 -16
  42. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +2 -1
  43. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +1 -0
  44. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +1 -0
  45. data/lib/solargraph/parser/region.rb +1 -1
  46. data/lib/solargraph/pin/base.rb +295 -28
  47. data/lib/solargraph/pin/base_variable.rb +9 -8
  48. data/lib/solargraph/pin/callable.rb +74 -3
  49. data/lib/solargraph/pin/closure.rb +18 -1
  50. data/lib/solargraph/pin/common.rb +5 -0
  51. data/lib/solargraph/pin/delegated_method.rb +2 -0
  52. data/lib/solargraph/pin/documenting.rb +16 -0
  53. data/lib/solargraph/pin/keyword.rb +7 -2
  54. data/lib/solargraph/pin/local_variable.rb +8 -5
  55. data/lib/solargraph/pin/method.rb +147 -25
  56. data/lib/solargraph/pin/namespace.rb +7 -2
  57. data/lib/solargraph/pin/parameter.rb +47 -6
  58. data/lib/solargraph/pin/proxy_type.rb +3 -3
  59. data/lib/solargraph/pin/reference/override.rb +10 -6
  60. data/lib/solargraph/pin/reference/require.rb +2 -2
  61. data/lib/solargraph/pin/signature.rb +42 -0
  62. data/lib/solargraph/pin/singleton.rb +1 -1
  63. data/lib/solargraph/pin/symbol.rb +3 -2
  64. data/lib/solargraph/pin.rb +1 -1
  65. data/lib/solargraph/pin_cache.rb +185 -0
  66. data/lib/solargraph/position.rb +9 -0
  67. data/lib/solargraph/range.rb +9 -0
  68. data/lib/solargraph/rbs_map/conversions.rb +183 -56
  69. data/lib/solargraph/rbs_map/core_fills.rb +24 -15
  70. data/lib/solargraph/rbs_map/core_map.rb +34 -11
  71. data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
  72. data/lib/solargraph/rbs_map.rb +74 -17
  73. data/lib/solargraph/shell.rb +17 -18
  74. data/lib/solargraph/source/chain/array.rb +7 -4
  75. data/lib/solargraph/source/chain/block_symbol.rb +1 -1
  76. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  77. data/lib/solargraph/source/chain/call.rb +8 -7
  78. data/lib/solargraph/source/chain/hash.rb +1 -1
  79. data/lib/solargraph/source/chain/head.rb +1 -1
  80. data/lib/solargraph/source/chain/if.rb +1 -1
  81. data/lib/solargraph/source/chain/literal.rb +2 -2
  82. data/lib/solargraph/source/chain/or.rb +1 -1
  83. data/lib/solargraph/source/chain.rb +2 -2
  84. data/lib/solargraph/source_map/mapper.rb +9 -5
  85. data/lib/solargraph/source_map.rb +0 -17
  86. data/lib/solargraph/version.rb +1 -1
  87. data/lib/solargraph/views/_method.erb +10 -10
  88. data/lib/solargraph/views/_namespace.erb +3 -3
  89. data/lib/solargraph/views/document.erb +10 -10
  90. data/lib/solargraph/workspace.rb +15 -5
  91. data/lib/solargraph/yard_map/mapper/to_constant.rb +4 -2
  92. data/lib/solargraph/yard_map/mapper/to_method.rb +14 -1
  93. data/lib/solargraph/yard_map/mapper/to_namespace.rb +4 -2
  94. data/lib/solargraph/yard_map/mapper.rb +4 -3
  95. data/lib/solargraph/yard_map/to_method.rb +4 -2
  96. data/lib/solargraph/yardoc.rb +6 -9
  97. data/lib/solargraph.rb +19 -1
  98. data/rbs/fills/tuple.rbs +150 -0
  99. data/rbs_collection.yaml +19 -0
  100. data/solargraph.gemspec +1 -0
  101. metadata +20 -7
  102. data/lib/solargraph/cache.rb +0 -77
@@ -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,16 @@ 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, closure: self)
124
203
  end
125
- Signature.new(generics: generics, parameters: parameters, return_type: return_type, block: block)
204
+ signature = Signature.new(generics: generics, parameters: parameters, return_type: return_type, block: block, closure: self, source: source)
205
+ block.closure = signature if block
206
+ signature
126
207
  end
127
208
 
128
209
  # @return [::Array<Signature>]
@@ -137,6 +218,14 @@ module Solargraph
137
218
  end
138
219
  end
139
220
 
221
+ # @param return_type [ComplexType]
222
+ # @return [self]
223
+ def proxy_with_signatures return_type
224
+ out = proxy return_type
225
+ out.signatures = out.signatures.map { |sig| sig.proxy return_type }
226
+ out
227
+ end
228
+
140
229
  # @return [String, nil]
141
230
  def detail
142
231
  # This property is not cached in an instance variable because it can
@@ -163,7 +252,7 @@ module Solargraph
163
252
  end
164
253
  end
165
254
 
166
- def desc
255
+ def inner_desc
167
256
  # ensure the signatures line up when logged
168
257
  if signatures.length > 1
169
258
  path + " \n#{to_rbs}\n"
@@ -188,12 +277,26 @@ module Solargraph
188
277
  @path ||= "#{namespace}#{(scope == :instance ? '#' : '.')}#{name}"
189
278
  end
190
279
 
280
+ # @return [String]
281
+ def method_name
282
+ name
283
+ end
284
+
191
285
  def typify api_map
286
+ logger.debug { "Method#typify(self=#{self}, binder=#{binder}, closure=#{closure}, context=#{context.rooted_tags}, return_type=#{return_type.rooted_tags}) - starting" }
192
287
  decl = super
193
- return decl unless decl.undefined?
288
+ unless decl.undefined?
289
+ logger.debug { "Method#typify(self=#{self}, binder=#{binder}, closure=#{closure}, context=#{context}) => #{decl.rooted_tags.inspect} - decl found" }
290
+ return decl
291
+ end
194
292
  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
293
+ logger.debug { "Method#typify(self=#{self}) - type=#{type&.rooted_tags.inspect}" }
294
+ unless type.nil?
295
+ qualified = type.qualify(api_map, namespace)
296
+ logger.debug { "Method#typify(self=#{self}) => #{qualified.rooted_tags.inspect}" }
297
+ return qualified
298
+ end
299
+ super
197
300
  end
198
301
 
199
302
  # @sg-ignore
@@ -280,14 +383,6 @@ module Solargraph
280
383
  attribute? ? infer_from_iv(api_map) : infer_from_return_nodes(api_map)
281
384
  end
282
385
 
283
- # @param pin [Pin::Method]
284
- def try_merge! pin
285
- return false unless super
286
- @node = pin.node
287
- @resolved_ref_tag = false
288
- true
289
- end
290
-
291
386
  # @return [::Array<Pin::Method>]
292
387
  def overloads
293
388
  # Ignore overload tags with nil parameters. If it's not an array, the
@@ -304,10 +399,13 @@ module Solargraph
304
399
  name: name,
305
400
  decl: decl,
306
401
  presence: location ? location.range : nil,
307
- return_type: param_type_from_name(tag, src.first)
402
+ return_type: param_type_from_name(tag, src.first),
403
+ source: :overloads
308
404
  )
309
405
  end,
310
- return_type: ComplexType.try_parse(*tag.docstring.tags(:return).flat_map(&:types))
406
+ closure: self,
407
+ return_type: ComplexType.try_parse(*tag.docstring.tags(:return).flat_map(&:types)),
408
+ source: :overloads,
311
409
  )
312
410
  end
313
411
  @overloads
@@ -340,16 +438,35 @@ module Solargraph
340
438
  self
341
439
  end
342
440
 
441
+ # @param api_map [ApiMap]
442
+ # @return [Array<Pin::Method>]
443
+ def rest_of_stack api_map
444
+ api_map.get_method_stack(method_namespace, method_name, scope: scope).reject { |pin| pin.path == path }
445
+ end
446
+
343
447
  protected
344
448
 
345
449
  attr_writer :block
346
450
 
347
- attr_writer :signatures
348
-
349
451
  attr_writer :signature_help
350
452
 
351
453
  attr_writer :documentation
352
454
 
455
+ def dodgy_visibility_source?
456
+ # as of 2025-03-12, the RBS generator used for
457
+ # e.g. activesupport did not understand 'private' markings
458
+ # inside 'class << self' blocks, but YARD did OK at it
459
+ source == :rbs && scope == :class && type_location&.filename&.include?('generated') && return_type.undefined? ||
460
+ # YARD's RBS generator seems to miss a lot of should-be protected instance methods
461
+ source == :rbs && scope == :instance && namespace.start_with?('YARD::') ||
462
+ # private on attr_readers seems to be broken in Prism's auto-generator script
463
+ source == :rbs && scope == :instance && namespace.start_with?('Prism::') ||
464
+ # The RBS for the RBS gem itself seems to use private as a
465
+ # 'is this a public API' concept, more aggressively than the
466
+ # actual code. Let's respect that and ignore the actual .rb file.
467
+ source == :yardoc && scope == :instance && namespace.start_with?('RBS::')
468
+ end
469
+
353
470
  private
354
471
 
355
472
  # @param name [String]
@@ -410,10 +527,15 @@ module Solargraph
410
527
  resolve_reference match[1], api_map
411
528
  end
412
529
 
530
+ # @return [String]
531
+ def method_namespace
532
+ namespace
533
+ end
534
+
413
535
  # @param api_map [ApiMap]
414
536
  # @return [ComplexType, nil]
415
537
  def typify_from_super api_map
416
- stack = api_map.get_method_stack(namespace, name, scope: scope).reject { |pin| pin.path == path }
538
+ stack = rest_of_stack api_map
417
539
  return nil if stack.empty?
418
540
  stack.each do |pin|
419
541
  return pin.return_type unless pin.return_type.undefined?
@@ -523,7 +645,7 @@ module Solargraph
523
645
 
524
646
  protected
525
647
 
526
- attr_writer :signatures
648
+ attr_writer :return_type
527
649
  end
528
650
  end
529
651
  end
@@ -11,6 +11,11 @@ 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>]
@@ -37,7 +42,7 @@ module Solargraph
37
42
  closure.full_context.namespace + '::'
38
43
  end
39
44
  closure_name += parts.join('::')
40
- @closure = Pin::Namespace.new(name: closure_name, gates: [parts.join('::')])
45
+ @closure = Pin::Namespace.new(name: closure_name, gates: [parts.join('::')], source: :namespace)
41
46
  @context = nil
42
47
  end
43
48
  @name = name
@@ -47,7 +52,7 @@ module Solargraph
47
52
  "#{@type.to_s} #{return_type.all_params.first.to_rbs}#{rbs_generics}".strip
48
53
  end
49
54
 
50
- def desc
55
+ def inner_desc
51
56
  if name.nil? || name.empty?
52
57
  '(top-level)'
53
58
  else
@@ -9,6 +9,10 @@ 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
18
  def initialize decl: :arg, asgn_code: nil, **splat
@@ -17,6 +21,23 @@ module Solargraph
17
21
  @decl = decl
18
22
  end
19
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)
39
+ end
40
+
20
41
  def keyword?
21
42
  [:kwarg, :kwoptarg].include?(decl)
22
43
  end
@@ -25,6 +46,32 @@ module Solargraph
25
46
  decl == :kwrestarg || (assignment && [:HASH, :hash].include?(assignment.type))
26
47
  end
27
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
+
28
75
  def arg?
29
76
  decl == :arg
30
77
  end
@@ -128,12 +175,6 @@ module Solargraph
128
175
  tag.text
129
176
  end
130
177
 
131
- # @param pin [Pin::Parameter]
132
- def try_merge! pin
133
- return false unless super && closure == pin.closure
134
- true
135
- end
136
-
137
178
  private
138
179
 
139
180
  # @return [YARD::Tags::Tag, nil]
@@ -18,16 +18,16 @@ module Solargraph
18
18
  # @param closure [Pin::Namespace, nil] Used as the closure for this pin
19
19
  # @param binder [ComplexType, ComplexType::UniqueType, nil]
20
20
  # @return [ProxyType]
21
- def self.anonymous context, closure: nil, binder: nil
21
+ def self.anonymous context, closure: nil, binder: nil, **kwargs
22
22
  unless closure
23
23
  parts = context.namespace.split('::')
24
24
  namespace = parts[0..-2].join('::').to_s
25
- closure = Solargraph::Pin::Namespace.new(name: namespace)
25
+ closure = Solargraph::Pin::Namespace.new(name: namespace, source: :proxy_type)
26
26
  end
27
27
  # name = parts.last.to_s
28
28
  # ProxyType.new(nil, namespace, name, return_type)
29
29
  ProxyType.new(
30
- closure: closure, return_type: context, binder: binder || context
30
+ closure: closure, return_type: context, binder: binder || context, **kwargs
31
31
  )
32
32
  end
33
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
@@ -4,9 +4,9 @@ module Solargraph
4
4
  module Pin
5
5
  class Reference
6
6
  class Require < Reference
7
- def initialize location, name
7
+ def initialize location, name, **splat
8
8
  # super(location, '', name)
9
- super(location: location, name: name)
9
+ super(location: location, name: name, closure: Pin::ROOT_PIN, **splat)
10
10
  end
11
11
  end
12
12
  end
@@ -1,6 +1,10 @@
1
1
  module Solargraph
2
2
  module Pin
3
3
  class Signature < Callable
4
+ # allow signature to be created before method pin, then set this
5
+ # to the method pin
6
+ attr_writer :closure
7
+
4
8
  def initialize **splat
5
9
  super(**splat)
6
10
  end
@@ -12,6 +16,44 @@ module Solargraph
12
16
  def identity
13
17
  @identity ||= "signature#{object_id}"
14
18
  end
19
+
20
+ attr_writer :closure
21
+
22
+ def dodgy_return_type_source?
23
+ super || closure&.dodgy_return_type_source?
24
+ end
25
+
26
+ def type_location
27
+ super || closure&.type_location
28
+ end
29
+
30
+ def location
31
+ super || closure&.location
32
+ end
33
+
34
+ def typify api_map
35
+ if return_type.defined?
36
+ qualified = return_type.qualify(api_map, closure.namespace)
37
+ logger.debug { "Signature#typify(self=#{self}) => #{qualified.rooted_tags.inspect}" }
38
+ return qualified
39
+ end
40
+ return ComplexType::UNDEFINED if closure.nil?
41
+ return ComplexType::UNDEFINED unless closure.is_a?(Pin::Method)
42
+ method_stack = closure.rest_of_stack api_map
43
+ logger.debug { "Signature#typify(self=#{self}) - method_stack: #{method_stack}" }
44
+ method_stack.each do |pin|
45
+ sig = pin.signatures.find { |s| s.arity == self.arity }
46
+ next unless sig
47
+ unless sig.return_type.undefined?
48
+ qualified = sig.return_type.qualify(api_map, closure.namespace)
49
+ logger.debug { "Signature#typify(self=#{self}) => #{qualified.rooted_tags.inspect}" }
50
+ return qualified
51
+ end
52
+ end
53
+ out = super
54
+ logger.debug { "Signature#typify(self=#{self}) => #{out}" }
55
+ out
56
+ end
15
57
  end
16
58
  end
17
59
  end
@@ -3,7 +3,7 @@
3
3
  module Solargraph
4
4
  module Pin
5
5
  class Singleton < Closure
6
- def initialize name: '', location: nil, closure: nil
6
+ def initialize name: '', location: nil, closure: nil, **splat
7
7
  super
8
8
  end
9
9
  end
@@ -5,8 +5,9 @@ module Solargraph
5
5
  class Symbol < Base
6
6
  # @param location [Solargraph::Location]
7
7
  # @param name [String]
8
- def initialize location, name
9
- super(location: location, name: name)
8
+ def initialize(location, name, **kwargs)
9
+ # @sg-ignore "Unrecognized keyword argument kwargs to Solargraph::Pin::Base#initialize"
10
+ super(location: location, name: name, **kwargs)
10
11
  # @name = name
11
12
  # @location = location
12
13
  end
@@ -39,6 +39,6 @@ module Solargraph
39
39
  autoload :While, 'solargraph/pin/while'
40
40
  autoload :Callable, 'solargraph/pin/callable'
41
41
 
42
- ROOT_PIN = Pin::Namespace.new(type: :class, name: '', closure: nil)
42
+ ROOT_PIN = Pin::Namespace.new(type: :class, name: '', closure: nil, source: :pin_rb)
43
43
  end
44
44
  end