solargraph 0.54.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 (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 +70 -0
  6. data/README.md +13 -3
  7. data/lib/solargraph/api_map/cache.rb +10 -1
  8. data/lib/solargraph/api_map/index.rb +175 -0
  9. data/lib/solargraph/api_map/store.rb +79 -126
  10. data/lib/solargraph/api_map.rb +247 -93
  11. data/lib/solargraph/bench.rb +17 -1
  12. data/lib/solargraph/complex_type/type_methods.rb +13 -1
  13. data/lib/solargraph/complex_type/unique_type.rb +118 -9
  14. data/lib/solargraph/complex_type.rb +48 -18
  15. data/lib/solargraph/convention/base.rb +3 -3
  16. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +60 -0
  17. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +100 -0
  18. data/lib/solargraph/convention/struct_definition.rb +101 -0
  19. data/lib/solargraph/convention.rb +5 -3
  20. data/lib/solargraph/doc_map.rb +274 -56
  21. data/lib/solargraph/equality.rb +33 -0
  22. data/lib/solargraph/gem_pins.rb +53 -37
  23. data/lib/solargraph/language_server/host/message_worker.rb +31 -11
  24. data/lib/solargraph/language_server/host.rb +24 -13
  25. data/lib/solargraph/language_server/message/base.rb +19 -12
  26. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
  27. data/lib/solargraph/language_server/message/extended/document.rb +5 -2
  28. data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
  29. data/lib/solargraph/language_server/message/initialize.rb +3 -1
  30. data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
  31. data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -0
  32. data/lib/solargraph/library.rb +13 -11
  33. data/lib/solargraph/location.rb +28 -0
  34. data/lib/solargraph/logging.rb +1 -0
  35. data/lib/solargraph/parser/comment_ripper.rb +12 -6
  36. data/lib/solargraph/parser/flow_sensitive_typing.rb +227 -0
  37. data/lib/solargraph/parser/node_methods.rb +15 -1
  38. data/lib/solargraph/parser/node_processor.rb +3 -1
  39. data/lib/solargraph/parser/parser_gem/class_methods.rb +16 -14
  40. data/lib/solargraph/parser/parser_gem/node_chainer.rb +17 -23
  41. data/lib/solargraph/parser/parser_gem/node_methods.rb +5 -3
  42. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
  43. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +21 -0
  44. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +4 -2
  45. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +4 -2
  46. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +23 -2
  47. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
  48. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
  49. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
  50. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
  51. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +21 -0
  52. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
  53. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +4 -3
  54. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +29 -6
  55. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +41 -0
  56. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  57. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -3
  58. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +28 -16
  59. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +2 -1
  60. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
  61. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
  62. data/lib/solargraph/parser/parser_gem/node_processors.rb +10 -0
  63. data/lib/solargraph/parser/region.rb +1 -1
  64. data/lib/solargraph/parser.rb +1 -0
  65. data/lib/solargraph/pin/base.rb +326 -43
  66. data/lib/solargraph/pin/base_variable.rb +18 -10
  67. data/lib/solargraph/pin/block.rb +3 -3
  68. data/lib/solargraph/pin/breakable.rb +9 -0
  69. data/lib/solargraph/pin/callable.rb +77 -6
  70. data/lib/solargraph/pin/closure.rb +18 -1
  71. data/lib/solargraph/pin/common.rb +5 -0
  72. data/lib/solargraph/pin/delegated_method.rb +20 -1
  73. data/lib/solargraph/pin/documenting.rb +16 -0
  74. data/lib/solargraph/pin/keyword.rb +7 -2
  75. data/lib/solargraph/pin/local_variable.rb +15 -6
  76. data/lib/solargraph/pin/method.rb +172 -42
  77. data/lib/solargraph/pin/namespace.rb +17 -9
  78. data/lib/solargraph/pin/parameter.rb +61 -11
  79. data/lib/solargraph/pin/proxy_type.rb +12 -6
  80. data/lib/solargraph/pin/reference/override.rb +10 -6
  81. data/lib/solargraph/pin/reference/require.rb +2 -2
  82. data/lib/solargraph/pin/signature.rb +42 -0
  83. data/lib/solargraph/pin/singleton.rb +1 -1
  84. data/lib/solargraph/pin/symbol.rb +3 -2
  85. data/lib/solargraph/pin/until.rb +18 -0
  86. data/lib/solargraph/pin/while.rb +18 -0
  87. data/lib/solargraph/pin.rb +4 -1
  88. data/lib/solargraph/pin_cache.rb +185 -0
  89. data/lib/solargraph/position.rb +16 -0
  90. data/lib/solargraph/range.rb +16 -0
  91. data/lib/solargraph/rbs_map/conversions.rb +199 -66
  92. data/lib/solargraph/rbs_map/core_fills.rb +32 -16
  93. data/lib/solargraph/rbs_map/core_map.rb +34 -11
  94. data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
  95. data/lib/solargraph/rbs_map.rb +74 -16
  96. data/lib/solargraph/shell.rb +19 -18
  97. data/lib/solargraph/source/chain/array.rb +12 -8
  98. data/lib/solargraph/source/chain/block_symbol.rb +1 -1
  99. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  100. data/lib/solargraph/source/chain/call.rb +62 -25
  101. data/lib/solargraph/source/chain/constant.rb +1 -1
  102. data/lib/solargraph/source/chain/hash.rb +9 -3
  103. data/lib/solargraph/source/chain/head.rb +1 -1
  104. data/lib/solargraph/source/chain/if.rb +6 -1
  105. data/lib/solargraph/source/chain/link.rb +19 -5
  106. data/lib/solargraph/source/chain/literal.rb +27 -2
  107. data/lib/solargraph/source/chain/or.rb +1 -1
  108. data/lib/solargraph/source/chain/z_super.rb +1 -1
  109. data/lib/solargraph/source/chain.rb +106 -62
  110. data/lib/solargraph/source/cursor.rb +1 -11
  111. data/lib/solargraph/source/source_chainer.rb +2 -2
  112. data/lib/solargraph/source.rb +2 -1
  113. data/lib/solargraph/source_map/clip.rb +4 -2
  114. data/lib/solargraph/source_map/mapper.rb +9 -5
  115. data/lib/solargraph/source_map.rb +0 -17
  116. data/lib/solargraph/type_checker/checks.rb +4 -0
  117. data/lib/solargraph/type_checker.rb +41 -14
  118. data/lib/solargraph/version.rb +1 -1
  119. data/lib/solargraph/views/_method.erb +10 -10
  120. data/lib/solargraph/views/_namespace.erb +3 -3
  121. data/lib/solargraph/views/document.erb +10 -10
  122. data/lib/solargraph/workspace/config.rb +7 -3
  123. data/lib/solargraph/workspace.rb +16 -6
  124. data/lib/solargraph/yard_map/mapper/to_constant.rb +5 -2
  125. data/lib/solargraph/yard_map/mapper/to_method.rb +55 -15
  126. data/lib/solargraph/yard_map/mapper/to_namespace.rb +5 -2
  127. data/lib/solargraph/yard_map/mapper.rb +5 -3
  128. data/lib/solargraph/yard_map/to_method.rb +4 -2
  129. data/lib/solargraph/yardoc.rb +6 -9
  130. data/lib/solargraph.rb +20 -1
  131. data/rbs/fills/tuple.rbs +150 -0
  132. data/rbs_collection.yaml +19 -0
  133. data/solargraph.gemspec +6 -5
  134. metadata +56 -29
  135. data/lib/solargraph/cache.rb +0 -77
@@ -8,6 +8,7 @@ module Solargraph
8
8
  include Common
9
9
  include Conversions
10
10
  include Documenting
11
+ include Logging
11
12
 
12
13
  # @return [YARD::CodeObjects::Base]
13
14
  attr_reader :code_object
@@ -27,17 +28,284 @@ module Solargraph
27
28
  # @return [::Symbol]
28
29
  attr_accessor :source
29
30
 
31
+ def presence_certain?
32
+ true
33
+ end
34
+
30
35
  # @param location [Solargraph::Location, nil]
31
36
  # @param type_location [Solargraph::Location, nil]
32
37
  # @param closure [Solargraph::Pin::Closure, nil]
33
38
  # @param name [String]
34
39
  # @param comments [String]
35
- def initialize location: nil, type_location: nil, closure: nil, name: '', comments: ''
40
+ # @param source [Symbol, nil]
41
+ # @param docstring [YARD::Docstring, nil]
42
+ # @param directives [::Array<YARD::Tags::Directive>, nil]
43
+ def initialize location: nil, type_location: nil, closure: nil, source: nil, name: '', comments: '', docstring: nil, directives: nil
36
44
  @location = location
37
45
  @type_location = type_location
38
46
  @closure = closure
39
47
  @name = name
40
48
  @comments = comments
49
+ @source = source
50
+ @identity = nil
51
+ @docstring = docstring
52
+ @directives = directives
53
+ assert_source_provided
54
+ end
55
+
56
+ # @param other [self]
57
+ # @param attrs [Hash{Symbol => Object}]
58
+ #
59
+ # @return [self]
60
+ def combine_with(other, attrs={})
61
+ raise "tried to combine #{other.class} with #{self.class}" unless other.class == self.class
62
+ type_location = choose(other, :type_location)
63
+ location = choose(other, :location)
64
+ combined_name = combine_name(other)
65
+ new_attrs = {
66
+ location: location,
67
+ type_location: type_location,
68
+ name: combined_name,
69
+ closure: choose_pin_attr_with_same_name(other, :closure),
70
+ comments: choose_longer(other, :comments),
71
+ source: :combined,
72
+ docstring: choose(other, :docstring),
73
+ directives: combine_directives(other),
74
+ }.merge(attrs)
75
+ assert_same_macros(other)
76
+ logger.debug { "Base#combine_with(path=#{path}) - other.comments=#{other.comments.inspect}, self.comments = #{self.comments}" }
77
+ out = self.class.new(**new_attrs)
78
+ out.reset_generated!
79
+ out
80
+ end
81
+
82
+ # @param other [self]
83
+ # @param attr [::Symbol]
84
+ # @sg-ignore
85
+ # @return [undefined]
86
+ def choose_longer(other, attr)
87
+ # @type [undefined]
88
+ val1 = send(attr)
89
+ # @type [undefined]
90
+ val2 = other.send(attr)
91
+ return val1 if val1 == val2
92
+ return val2 if val1.nil?
93
+ # @sg-ignore
94
+ val1.length > val2.length ? val1 : val2
95
+ end
96
+
97
+ # @param other [self]
98
+ # @return [::Array<YARD::Tags::Directive>, nil]
99
+ def combine_directives(other)
100
+ return self.directives if other.directives.empty?
101
+ return other.directives if directives.empty?
102
+ [directives + other.directives].uniq
103
+ end
104
+
105
+ # @param other [self]
106
+ # @return [String]
107
+ def combine_name(other)
108
+ if needs_consistent_name? || other.needs_consistent_name?
109
+ assert_same(other, :name)
110
+ else
111
+ choose(other, :name)
112
+ end
113
+ end
114
+
115
+ # @return [void]
116
+ def reset_generated!
117
+ # @return_type doesn't go here as subclasses tend to assign it
118
+ # themselves in constructors, and they will deal with setting
119
+ # it in any methods that call this
120
+ #
121
+ # @docstring also doesn't go here, as there is code which
122
+ # directly manipulates docstring without editing comments
123
+ # (e.g., Api::Map::Store#index processes overrides that way
124
+ #
125
+ # Same with @directives, @macros, @maybe_directives, which
126
+ # regenerate docstring
127
+ @deprecated = nil
128
+ reset_conversions
129
+ end
130
+
131
+ def needs_consistent_name?
132
+ true
133
+ end
134
+
135
+ # @sg-ignore def should infer as symbol - "Not enough arguments to Module#protected"
136
+ protected def equality_fields
137
+ [name, location, type_location, closure, source]
138
+ end
139
+
140
+ # @param other [self]
141
+ # @return [ComplexType]
142
+ def combine_return_type(other)
143
+ if return_type.undefined?
144
+ other.return_type
145
+ elsif other.return_type.undefined?
146
+ return_type
147
+ elsif dodgy_return_type_source? && !other.dodgy_return_type_source?
148
+ other.return_type
149
+ elsif other.dodgy_return_type_source? && !dodgy_return_type_source?
150
+ return_type
151
+ else
152
+ all_items = return_type.items + other.return_type.items
153
+ if all_items.any? { |item| item.selfy? } && all_items.any? { |item| item.rooted_tag == context.rooted_tag }
154
+ # assume this was a declaration that should have said 'self'
155
+ all_items.delete_if { |item| item.rooted_tag == context.rooted_tag }
156
+ end
157
+ ComplexType.new(all_items)
158
+ end
159
+ end
160
+
161
+ def dodgy_return_type_source?
162
+ # uses a lot of 'Object' instead of 'self'
163
+ location&.filename&.include?('core_ext/object/')
164
+ end
165
+
166
+ # when choices are arbitrary, make sure the choice is consistent
167
+ #
168
+ # @param other [Pin::Base]
169
+ # @param attr [::Symbol]
170
+ #
171
+ # @return [Object, nil]
172
+ def choose(other, attr)
173
+ results = [self, other].map(&attr).compact
174
+ # true and false are different classes and can't be sorted
175
+ return true if results.any? { |r| r == true || r == false }
176
+ results.min
177
+ rescue
178
+ STDERR.puts("Problem handling #{attr} for \n#{self.inspect}\n and \n#{other.inspect}\n\n#{self.send(attr).inspect} vs #{other.send(attr).inspect}")
179
+ raise
180
+ end
181
+
182
+ # @param other [self]
183
+ # @param attr [Symbol]
184
+ # @sg-ignore
185
+ # @return [undefined]
186
+ def choose_node(other, attr)
187
+ if other.object_id < attr.object_id
188
+ other.send(attr)
189
+ else
190
+ send(attr)
191
+ end
192
+ end
193
+
194
+ # @param other [self]
195
+ # @param attr [::Symbol]
196
+ # @sg-ignore
197
+ # @return [undefined]
198
+ def prefer_rbs_location(other, attr)
199
+ if rbs_location? && !other.rbs_location?
200
+ self.send(attr)
201
+ elsif !rbs_location? && other.rbs_location?
202
+ other.send(attr)
203
+ else
204
+ choose(other, attr)
205
+ end
206
+ end
207
+
208
+ def rbs_location?
209
+ type_location&.rbs?
210
+ end
211
+
212
+ # @param other [self]
213
+ # @return [void]
214
+ def assert_same_macros(other)
215
+ return unless self.source == :yardoc && other.source == :yardoc
216
+ assert_same_count(other, :macros)
217
+ assert_same_array_content(other, :macros) { |macro| macro.tag.name }
218
+ end
219
+
220
+ # @param other [self]
221
+ # @param attr [::Symbol]
222
+ # @return [void]
223
+ # @todo strong typechecking should complain when there are no block-related tags
224
+ def assert_same_array_content(other, attr, &block)
225
+ arr1 = send(attr)
226
+ raise "Expected #{attr} on #{self} to be an Enumerable, got #{arr1.class}" unless arr1.is_a?(::Enumerable)
227
+ # @type arr1 [::Enumerable]
228
+ arr2 = other.send(attr)
229
+ raise "Expected #{attr} on #{other} to be an Enumerable, got #{arr2.class}" unless arr2.is_a?(::Enumerable)
230
+ # @type arr2 [::Enumerable]
231
+
232
+ # @sg-ignore
233
+ # @type [undefined]
234
+ values1 = arr1.map(&block)
235
+ # @type [undefined]
236
+ values2 = arr2.map(&block)
237
+ # @sg-ignore
238
+ return arr1 if values1 == values2
239
+ Solargraph.assert_or_log("combine_with_#{attr}".to_sym,
240
+ "Inconsistent #{attr.inspect} values between \nself =#{inspect} and \nother=#{other.inspect}:\n\n self values = #{values1}\nother values =#{attr} = #{values2}")
241
+ arr1
242
+ end
243
+
244
+ # @param other [self]
245
+ # @param attr [::Symbol]
246
+ #
247
+ # @return [::Enumerable]
248
+ def assert_same_count(other, attr)
249
+ # @type [::Enumerable]
250
+ arr1 = self.send(attr)
251
+ raise "Expected #{attr} on #{self} to be an Enumerable, got #{arr1.class}" unless arr1.is_a?(::Enumerable)
252
+ # @type [::Enumerable]
253
+ arr2 = other.send(attr)
254
+ raise "Expected #{attr} on #{other} to be an Enumerable, got #{arr2.class}" unless arr2.is_a?(::Enumerable)
255
+ return arr1 if arr1.count == arr2.count
256
+ Solargraph.assert_or_log("combine_with_#{attr}".to_sym,
257
+ "Inconsistent #{attr.inspect} count value between \nself =#{inspect} and \nother=#{other.inspect}:\n\n self.#{attr} = #{arr1.inspect}\nother.#{attr} = #{arr2.inspect}")
258
+ arr1
259
+ end
260
+
261
+ # @param other [self]
262
+ # @param attr [::Symbol]
263
+ #
264
+ # @return [Object, nil]
265
+ def assert_same(other, attr)
266
+ return false if other.nil?
267
+ val1 = send(attr)
268
+ val2 = other.send(attr)
269
+ return val1 if val1 == val2
270
+ Solargraph.assert_or_log("combine_with_#{attr}".to_sym,
271
+ "Inconsistent #{attr.inspect} values between \nself =#{inspect} and \nother=#{other.inspect}:\n\n self.#{attr} = #{val1.inspect}\nother.#{attr} = #{val2.inspect}")
272
+ val1
273
+ end
274
+
275
+ # @param other [self]
276
+ # @param attr [::Symbol]
277
+ # @sg-ignore
278
+ # @return [undefined]
279
+ def choose_pin_attr_with_same_name(other, attr)
280
+ # @type [Pin::Base, nil]
281
+ val1 = send(attr)
282
+ # @type [Pin::Base, nil]
283
+ val2 = other.send(attr)
284
+ raise "Expected pin for #{attr} on\n#{self.inspect},\ngot #{val1.inspect}" unless val1.nil? || val1.is_a?(Pin::Base)
285
+ raise "Expected pin for #{attr} on\n#{other.inspect},\ngot #{val2.inspect}" unless val2.nil? || val2.is_a?(Pin::Base)
286
+ if val1&.name != val2&.name
287
+ Solargraph.assert_or_log("combine_with_#{attr}_name".to_sym,
288
+ "Inconsistent #{attr.inspect} name values between \nself =#{inspect} and \nother=#{other.inspect}:\n\n self.#{attr} = #{val1.inspect}\nother.#{attr} = #{val2.inspect}")
289
+ end
290
+ choose_pin_attr(other, attr)
291
+ end
292
+
293
+ def choose_pin_attr(other, attr)
294
+ # @type [Pin::Base, nil]
295
+ val1 = send(attr)
296
+ # @type [Pin::Base, nil]
297
+ val2 = other.send(attr)
298
+ if val1.class != val2.class
299
+ Solargraph.assert_or_log("combine_with_#{attr}_class".to_sym,
300
+ "Inconsistent #{attr.inspect} class values between \nself =#{inspect} and \nother=#{other.inspect}:\n\n self.#{attr} = #{val1.inspect}\nother.#{attr} = #{val2.inspect}")
301
+ return val1
302
+ end
303
+ # arbitrary way of choosing a pin
304
+ [val1, val2].compact.min_by { _1.best_location.to_s }
305
+ end
306
+
307
+ def assert_source_provided
308
+ Solargraph.assert_or_log(:source, "source not provided - #{@path} #{@source} #{self.class}") if source.nil?
41
309
  end
42
310
 
43
311
  # @return [String]
@@ -71,15 +339,14 @@ module Solargraph
71
339
  # @param context_type [ComplexType] The receiver type
72
340
  # @return [self]
73
341
  def resolve_generics definitions, context_type
74
- transformed = transform_types { |t| t.resolve_generics(definitions, context_type) if t }
75
- transformed.erase_generics(definitions.generics)
342
+ transform_types { |t| t.resolve_generics(definitions, context_type) if t }
76
343
  end
77
344
 
78
345
  def all_rooted?
79
346
  !return_type || return_type.all_rooted?
80
347
  end
81
348
 
82
- # @param generics_to_erase [Enumerable<String>]
349
+ # @param generics_to_erase [::Array<String>]
83
350
  # @return [self]
84
351
  def erase_generics(generics_to_erase)
85
352
  return self if generics_to_erase.empty?
@@ -103,7 +370,7 @@ module Solargraph
103
370
  end
104
371
 
105
372
  def to_s
106
- to_rbs
373
+ desc
107
374
  end
108
375
 
109
376
  # @return [Boolean]
@@ -116,14 +383,6 @@ module Solargraph
116
383
  location || type_location
117
384
  end
118
385
 
119
- # Pin equality is determined using the #nearly? method and also
120
- # requiring both pins to have the same location.
121
- #
122
- def == other
123
- return false unless nearly? other
124
- comments == other.comments and location == other.location
125
- end
126
-
127
386
  # True if the specified pin is a near match to this one. A near match
128
387
  # indicates that the pins contain mostly the same data. Any differences
129
388
  # between them should not have an impact on the API surface.
@@ -140,6 +399,15 @@ module Solargraph
140
399
  )
141
400
  end
142
401
 
402
+ # Pin equality is determined using the #nearly? method and also
403
+ # requiring both pins to have the same location.
404
+ #
405
+ # @param other [self]
406
+ def == other
407
+ return false unless nearly? other
408
+ comments == other.comments && location == other.location
409
+ end
410
+
143
411
  # The pin's return type.
144
412
  #
145
413
  # @return [ComplexType]
@@ -149,13 +417,13 @@ module Solargraph
149
417
 
150
418
  # @return [YARD::Docstring]
151
419
  def docstring
152
- parse_comments unless defined?(@docstring)
420
+ parse_comments unless @docstring
153
421
  @docstring ||= Solargraph::Source.parse_docstring('').to_docstring
154
422
  end
155
423
 
156
424
  # @return [::Array<YARD::Tags::Directive>]
157
425
  def directives
158
- parse_comments unless defined?(@directives)
426
+ parse_comments unless @directives
159
427
  @directives
160
428
  end
161
429
 
@@ -173,7 +441,7 @@ module Solargraph
173
441
  #
174
442
  # @return [Boolean]
175
443
  def maybe_directives?
176
- return !@directives.empty? if defined?(@directives)
444
+ return !@directives.empty? if defined?(@directives) && @directives
177
445
  @maybe_directives ||= comments.include?('@!')
178
446
  end
179
447
 
@@ -212,26 +480,6 @@ module Solargraph
212
480
  probe api_map
213
481
  end
214
482
 
215
- # Try to merge data from another pin. Merges are only possible if the
216
- # pins are near matches (see the #nearly? method). The changes should
217
- # not have any side effects on the API surface.
218
- #
219
- # @param pin [Pin::Base] The pin to merge into this one
220
- # @return [Boolean] True if the pins were merged
221
- def try_merge! pin
222
- return false unless nearly?(pin)
223
- @location = pin.location
224
- @closure = pin.closure
225
- return true if comments == pin.comments
226
- @comments = pin.comments
227
- @docstring = pin.docstring
228
- @return_type = pin.return_type
229
- @documentation = nil
230
- @deprecated = nil
231
- reset_conversions
232
- true
233
- end
234
-
235
483
  def proxied?
236
484
  @proxied ||= false
237
485
  end
@@ -266,9 +514,10 @@ module Solargraph
266
514
  result
267
515
  end
268
516
 
517
+ # @deprecated
269
518
  # @return [String]
270
519
  def identity
271
- @identity ||= "#{closure.path}|#{name}"
520
+ @identity ||= "#{closure&.path}|#{name}|#{location}"
272
521
  end
273
522
 
274
523
  # @return [String, nil]
@@ -276,21 +525,51 @@ module Solargraph
276
525
  return_type.to_rbs
277
526
  end
278
527
 
279
- # @return [String, nil]
280
- def desc
528
+ # @return [String]
529
+ def type_desc
530
+ rbs = to_rbs
531
+ # RBS doesn't have a way to represent a Class<x> type
532
+ rbs = return_type.rooted_tags if return_type.name == 'Class'
281
533
  if path
282
- if to_rbs
283
- path + ' ' + to_rbs
534
+ if rbs
535
+ path + ' ' + rbs
284
536
  else
285
537
  path
286
538
  end
287
539
  else
288
- to_rbs
540
+ rbs
289
541
  end
290
542
  end
291
543
 
544
+ # @return [String]
545
+ def inner_desc
546
+ closure_info = closure&.desc
547
+ binder_info = binder&.desc
548
+ "name=#{name.inspect} return_type=#{type_desc}, context=#{context.rooted_tags}, closure=#{closure_info}, binder=#{binder_info}"
549
+ end
550
+
551
+ def desc
552
+ "[#{inner_desc}]"
553
+ end
554
+
555
+ # @return [String]
292
556
  def inspect
293
- "#<#{self.class} `#{self.desc}` at #{self.location.inspect}>"
557
+ "#<#{self.class} `#{self.inner_desc}`#{all_location_text} via #{source.inspect}>"
558
+ end
559
+
560
+ def all_location_text
561
+ if location.nil? && type_location.nil?
562
+ ''
563
+ elsif !location.nil? && type_location.nil?
564
+ " at #{location.inspect})"
565
+ elsif !type_location.nil? && location.nil?
566
+ " at #{type_location.inspect})"
567
+ else
568
+ " at (#{location.inspect} and #{type_location.inspect})"
569
+ end
570
+ end
571
+
572
+ def reset_generated!
294
573
  end
295
574
 
296
575
  protected
@@ -304,6 +583,10 @@ module Solargraph
304
583
  # @return [ComplexType]
305
584
  attr_writer :return_type
306
585
 
586
+ attr_writer :docstring
587
+
588
+ attr_writer :directives
589
+
307
590
  private
308
591
 
309
592
  # @return [void]
@@ -11,12 +11,23 @@ module Solargraph
11
11
 
12
12
  attr_accessor :mass_assignment
13
13
 
14
+ # @param return_type [ComplexType, nil]
14
15
  # @param assignment [Parser::AST::Node, nil]
15
- def initialize assignment: nil, **splat
16
+ def initialize assignment: nil, return_type: nil, **splat
16
17
  super(**splat)
17
18
  @assignment = assignment
18
19
  # @type [nil, ::Array(Parser::AST::Node, Integer)]
19
20
  @mass_assignment = nil
21
+ @return_type = return_type
22
+ end
23
+
24
+ def combine_with(other, attrs={})
25
+ attrs.merge({
26
+ assignment: assert_same(other, :assignment),
27
+ mass_assignment: assert_same(other, :mass_assignment),
28
+ return_type: combine_return_type(other),
29
+ })
30
+ super(other, attrs)
20
31
  end
21
32
 
22
33
  def completion_item_kind
@@ -32,7 +43,10 @@ module Solargraph
32
43
  @return_type ||= generate_complex_type
33
44
  end
34
45
 
46
+ # @sg-ignore
35
47
  def nil_assignment?
48
+ # this will always be false - should it be return_type ==
49
+ # ComplexType::NIL or somesuch?
36
50
  return_type.nil?
37
51
  end
38
52
 
@@ -88,20 +102,14 @@ module Solargraph
88
102
  ComplexType::UNDEFINED
89
103
  end
90
104
 
105
+ # @param other [Object]
91
106
  def == other
92
107
  return false unless super
93
108
  assignment == other.assignment
94
109
  end
95
110
 
96
- def try_merge! pin
97
- return false unless super
98
- @assignment = pin.assignment
99
- @return_type = pin.return_type
100
- true
101
- end
102
-
103
- def desc
104
- "#{to_rbs} = #{assignment&.type.inspect}"
111
+ def type_desc
112
+ "#{super} = #{assignment&.type.inspect}"
105
113
  end
106
114
 
107
115
  private
@@ -3,6 +3,8 @@
3
3
  module Solargraph
4
4
  module Pin
5
5
  class Block < Callable
6
+ include Breakable
7
+
6
8
  # @return [Parser::AST::Node]
7
9
  attr_reader :receiver
8
10
 
@@ -36,14 +38,12 @@ module Solargraph
36
38
  #
37
39
  # @return [::Array<ComplexType>]
38
40
  def destructure_yield_types(yield_types, parameters)
39
- return yield_types if yield_types.length == parameters.length
40
-
41
41
  # yielding a tuple into a block will destructure the tuple
42
42
  if yield_types.length == 1
43
43
  yield_type = yield_types.first
44
44
  return yield_type.all_params if yield_type.tuple? && yield_type.all_params.length == parameters.length
45
45
  end
46
- parameters.map { ComplexType::UNDEFINED }
46
+ parameters.map.with_index { |_, idx| yield_types[idx] || ComplexType::UNDEFINED }
47
47
  end
48
48
 
49
49
  # @param api_map [ApiMap]
@@ -0,0 +1,9 @@
1
+ module Solargraph
2
+ module Pin
3
+ # Mix-in for pins which enclose code which the 'break' statement works with-in - e.g., blocks, when, until, ...
4
+ module Breakable
5
+ # @return [Parser::AST::Node]
6
+ attr_reader :node
7
+ end
8
+ end
9
+ end
@@ -3,10 +3,10 @@
3
3
  module Solargraph
4
4
  module Pin
5
5
  class Callable < Closure
6
- # @return [self]
6
+ # @return [Signature]
7
7
  attr_reader :block
8
8
 
9
- attr_reader :parameters
9
+ attr_accessor :parameters
10
10
 
11
11
  # @return [ComplexType, nil]
12
12
  attr_reader :return_type
@@ -21,11 +21,67 @@ module Solargraph
21
21
  @parameters = parameters
22
22
  end
23
23
 
24
+ def method_namespace
25
+ closure.namespace
26
+ end
27
+
28
+ def combine_blocks(other)
29
+ if block.nil?
30
+ other.block
31
+ elsif other.block.nil?
32
+ block
33
+ else
34
+ choose_pin_attr(other, :block)
35
+ end
36
+ end
37
+
38
+ # @param other [self]
39
+ # @param attrs [Hash{Symbol => Object}]
40
+ #
41
+ # @return [self]
42
+ def combine_with(other, attrs={})
43
+ new_attrs = {
44
+ block: combine_blocks(other),
45
+ return_type: combine_return_type(other),
46
+ }.merge(attrs)
47
+ new_attrs[:parameters] = choose_parameters(other).clone.freeze unless new_attrs.key?(:parameters)
48
+ super(other, new_attrs)
49
+ end
50
+
24
51
  # @return [::Array<String>]
25
52
  def parameter_names
26
53
  @parameter_names ||= parameters.map(&:name)
27
54
  end
28
55
 
56
+ def generics
57
+ []
58
+ end
59
+
60
+ def choose_parameters(other)
61
+ raise "Trying to combine two pins with different arities - \nself =#{inspect}, \nother=#{other.inspect}, \n\n self.arity=#{self.arity}, \nother.arity=#{other.arity}" if other.arity != arity
62
+ parameters.zip(other.parameters).map do |param, other_param|
63
+ if param.nil? && other_param.block?
64
+ other_param
65
+ elsif other_param.nil? && param.block?
66
+ param
67
+ else
68
+ param.combine_with(other_param)
69
+ end
70
+ end
71
+ end
72
+
73
+ def blockless_parameters
74
+ if parameters.last&.block?
75
+ parameters[0..-2]
76
+ else
77
+ parameters
78
+ end
79
+ end
80
+
81
+ def arity
82
+ [generics, blockless_parameters.map(&:arity_decl), block&.arity]
83
+ end
84
+
29
85
  # @param generics_to_resolve [Enumerable<String>]
30
86
  # @param arg_types [Array<ComplexType>, nil]
31
87
  # @param return_type_context [ComplexType, nil]
@@ -57,7 +113,24 @@ module Solargraph
57
113
  callable
58
114
  end
59
115
 
60
- # @param generics_to_resolve [Enumerable<String>]
116
+ def typify api_map
117
+ type = super
118
+ return type if type.defined?
119
+ if method_name.end_with?('?')
120
+ logger.debug { "Callable#typify(self=#{self}) => Boolean (? suffix)" }
121
+ ComplexType::BOOLEAN
122
+ else
123
+ logger.debug { "Callable#typify(self=#{self}) => undefined" }
124
+ ComplexType::UNDEFINED
125
+ end
126
+ end
127
+
128
+ def method_name
129
+ raise "closure was nil in #{self.inspect}" if closure.nil?
130
+ @method_name ||= closure.name
131
+ end
132
+
133
+ # @param generics_to_resolve [::Array<String>]
61
134
  # @param arg_types [Array<ComplexType>, nil]
62
135
  # @param return_type_context [ComplexType, nil]
63
136
  # @param yield_arg_types [Array<ComplexType>, nil]
@@ -113,7 +186,7 @@ module Solargraph
113
186
  end
114
187
 
115
188
  # @param arguments [::Array<Chain>]
116
- # @param signature [Pin::Signature]
189
+ # @param with_block [Boolean]
117
190
  # @return [Boolean]
118
191
  def arity_matches? arguments, with_block
119
192
  argcount = arguments.length
@@ -140,8 +213,6 @@ module Solargraph
140
213
  protected
141
214
 
142
215
  attr_writer :block
143
-
144
- attr_writer :parameters
145
216
  end
146
217
  end
147
218
  end