solargraph 0.54.0 → 0.58.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 (200) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +127 -0
  3. data/.github/workflows/plugins.yml +184 -6
  4. data/.github/workflows/rspec.yml +55 -5
  5. data/.github/workflows/typecheck.yml +8 -3
  6. data/.gitignore +7 -0
  7. data/.overcommit.yml +72 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +66 -0
  10. data/.rubocop_todo.yml +1279 -0
  11. data/.yardopts +1 -0
  12. data/CHANGELOG.md +171 -0
  13. data/README.md +20 -6
  14. data/Rakefile +125 -13
  15. data/bin/solargraph +8 -5
  16. data/lib/solargraph/api_map/cache.rb +13 -3
  17. data/lib/solargraph/api_map/constants.rb +279 -0
  18. data/lib/solargraph/api_map/index.rb +193 -0
  19. data/lib/solargraph/api_map/source_to_yard.rb +13 -4
  20. data/lib/solargraph/api_map/store.rb +207 -132
  21. data/lib/solargraph/api_map.rb +394 -261
  22. data/lib/solargraph/bench.rb +18 -1
  23. data/lib/solargraph/complex_type/type_methods.rb +29 -12
  24. data/lib/solargraph/complex_type/unique_type.rb +205 -26
  25. data/lib/solargraph/complex_type.rb +126 -26
  26. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  27. data/lib/solargraph/convention/base.rb +20 -3
  28. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  29. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  30. data/lib/solargraph/convention/data_definition.rb +105 -0
  31. data/lib/solargraph/convention/gemspec.rb +3 -2
  32. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
  33. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
  34. data/lib/solargraph/convention/struct_definition.rb +164 -0
  35. data/lib/solargraph/convention.rb +36 -4
  36. data/lib/solargraph/diagnostics/rubocop.rb +6 -1
  37. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  38. data/lib/solargraph/doc_map.rb +316 -64
  39. data/lib/solargraph/environ.rb +9 -2
  40. data/lib/solargraph/equality.rb +34 -0
  41. data/lib/solargraph/gem_pins.rb +64 -38
  42. data/lib/solargraph/language_server/host/dispatch.rb +2 -0
  43. data/lib/solargraph/language_server/host/message_worker.rb +54 -5
  44. data/lib/solargraph/language_server/host.rb +36 -18
  45. data/lib/solargraph/language_server/message/base.rb +20 -12
  46. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
  47. data/lib/solargraph/language_server/message/extended/document.rb +5 -2
  48. data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
  49. data/lib/solargraph/language_server/message/initialize.rb +3 -1
  50. data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
  51. data/lib/solargraph/language_server/message/text_document/definition.rb +5 -3
  52. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
  53. data/lib/solargraph/language_server/message/text_document/formatting.rb +23 -2
  54. data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
  55. data/lib/solargraph/language_server/message/text_document/type_definition.rb +4 -3
  56. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  57. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
  58. data/lib/solargraph/language_server/progress.rb +27 -2
  59. data/lib/solargraph/language_server/request.rb +4 -1
  60. data/lib/solargraph/library.rb +83 -73
  61. data/lib/solargraph/location.rb +45 -1
  62. data/lib/solargraph/logging.rb +12 -2
  63. data/lib/solargraph/page.rb +3 -0
  64. data/lib/solargraph/parser/comment_ripper.rb +20 -7
  65. data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
  66. data/lib/solargraph/parser/node_processor/base.rb +10 -5
  67. data/lib/solargraph/parser/node_processor.rb +26 -8
  68. data/lib/solargraph/parser/parser_gem/class_methods.rb +10 -18
  69. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  70. data/lib/solargraph/parser/parser_gem/node_chainer.rb +13 -11
  71. data/lib/solargraph/parser/parser_gem/node_methods.rb +10 -19
  72. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
  73. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -0
  74. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +26 -20
  75. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +7 -4
  76. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
  77. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
  78. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
  79. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
  80. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
  81. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
  82. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
  83. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -1
  84. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +14 -2
  85. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
  86. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -0
  87. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
  88. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +3 -1
  89. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +16 -6
  90. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +64 -32
  91. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
  92. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
  93. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
  94. data/lib/solargraph/parser/parser_gem/node_processors.rb +14 -0
  95. data/lib/solargraph/parser/region.rb +4 -1
  96. data/lib/solargraph/parser/snippet.rb +2 -0
  97. data/lib/solargraph/parser.rb +3 -5
  98. data/lib/solargraph/pin/base.rb +417 -42
  99. data/lib/solargraph/pin/base_variable.rb +21 -12
  100. data/lib/solargraph/pin/block.rb +9 -26
  101. data/lib/solargraph/pin/breakable.rb +9 -0
  102. data/lib/solargraph/pin/callable.rb +231 -0
  103. data/lib/solargraph/pin/closure.rb +30 -10
  104. data/lib/solargraph/pin/common.rb +12 -7
  105. data/lib/solargraph/pin/constant.rb +2 -0
  106. data/lib/solargraph/pin/conversions.rb +3 -2
  107. data/lib/solargraph/pin/delegated_method.rb +20 -1
  108. data/lib/solargraph/pin/documenting.rb +16 -0
  109. data/lib/solargraph/pin/instance_variable.rb +2 -2
  110. data/lib/solargraph/pin/keyword.rb +7 -2
  111. data/lib/solargraph/pin/local_variable.rb +15 -7
  112. data/lib/solargraph/pin/method.rb +241 -70
  113. data/lib/solargraph/pin/method_alias.rb +3 -0
  114. data/lib/solargraph/pin/namespace.rb +21 -13
  115. data/lib/solargraph/pin/parameter.rb +94 -32
  116. data/lib/solargraph/pin/proxy_type.rb +17 -7
  117. data/lib/solargraph/pin/reference/override.rb +24 -6
  118. data/lib/solargraph/pin/reference/require.rb +2 -2
  119. data/lib/solargraph/pin/reference/superclass.rb +5 -0
  120. data/lib/solargraph/pin/reference.rb +17 -0
  121. data/lib/solargraph/pin/search.rb +6 -1
  122. data/lib/solargraph/pin/signature.rb +39 -121
  123. data/lib/solargraph/pin/singleton.rb +1 -1
  124. data/lib/solargraph/pin/symbol.rb +8 -2
  125. data/lib/solargraph/pin/until.rb +18 -0
  126. data/lib/solargraph/pin/while.rb +18 -0
  127. data/lib/solargraph/pin.rb +8 -2
  128. data/lib/solargraph/pin_cache.rb +245 -0
  129. data/lib/solargraph/position.rb +19 -0
  130. data/lib/solargraph/range.rb +23 -4
  131. data/lib/solargraph/rbs_map/conversions.rb +315 -99
  132. data/lib/solargraph/rbs_map/core_fills.rb +50 -16
  133. data/lib/solargraph/rbs_map/core_map.rb +41 -11
  134. data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
  135. data/lib/solargraph/rbs_map.rb +87 -16
  136. data/lib/solargraph/shell.rb +117 -17
  137. data/lib/solargraph/source/chain/array.rb +13 -8
  138. data/lib/solargraph/source/chain/block_symbol.rb +1 -1
  139. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  140. data/lib/solargraph/source/chain/call.rb +135 -66
  141. data/lib/solargraph/source/chain/constant.rb +3 -66
  142. data/lib/solargraph/source/chain/hash.rb +9 -3
  143. data/lib/solargraph/source/chain/head.rb +1 -1
  144. data/lib/solargraph/source/chain/if.rb +7 -2
  145. data/lib/solargraph/source/chain/link.rb +38 -6
  146. data/lib/solargraph/source/chain/literal.rb +27 -2
  147. data/lib/solargraph/source/chain/or.rb +2 -2
  148. data/lib/solargraph/source/chain/z_super.rb +1 -1
  149. data/lib/solargraph/source/chain.rb +140 -63
  150. data/lib/solargraph/source/change.rb +2 -2
  151. data/lib/solargraph/source/cursor.rb +4 -4
  152. data/lib/solargraph/source/source_chainer.rb +3 -3
  153. data/lib/solargraph/source.rb +110 -89
  154. data/lib/solargraph/source_map/clip.rb +22 -28
  155. data/lib/solargraph/source_map/data.rb +34 -0
  156. data/lib/solargraph/source_map/mapper.rb +11 -7
  157. data/lib/solargraph/source_map.rb +50 -43
  158. data/lib/solargraph/type_checker/checks.rb +4 -0
  159. data/lib/solargraph/type_checker/param_def.rb +2 -0
  160. data/lib/solargraph/type_checker/rules.rb +35 -8
  161. data/lib/solargraph/type_checker.rb +331 -189
  162. data/lib/solargraph/version.rb +1 -1
  163. data/lib/solargraph/views/_method.erb +10 -10
  164. data/lib/solargraph/views/_namespace.erb +3 -3
  165. data/lib/solargraph/views/document.erb +10 -10
  166. data/lib/solargraph/views/environment.erb +3 -5
  167. data/lib/solargraph/workspace/config.rb +25 -5
  168. data/lib/solargraph/workspace/require_paths.rb +97 -0
  169. data/lib/solargraph/workspace.rb +53 -72
  170. data/lib/solargraph/yard_map/helpers.rb +29 -1
  171. data/lib/solargraph/yard_map/mapper/to_constant.rb +8 -5
  172. data/lib/solargraph/yard_map/mapper/to_method.rb +55 -19
  173. data/lib/solargraph/yard_map/mapper/to_namespace.rb +11 -7
  174. data/lib/solargraph/yard_map/mapper.rb +5 -3
  175. data/lib/solargraph/yard_map/to_method.rb +6 -3
  176. data/lib/solargraph/yardoc.rb +45 -10
  177. data/lib/solargraph.rb +35 -1
  178. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  179. data/rbs/fills/open3/0/open3.rbs +172 -0
  180. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  181. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  182. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  183. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  184. data/rbs/fills/tuple/tuple.rbs +149 -0
  185. data/rbs_collection.yaml +19 -0
  186. data/sig/shims/ast/0/node.rbs +5 -0
  187. data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
  188. data/sig/shims/ast/2.4/ast.rbs +73 -0
  189. data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  190. data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
  191. data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
  192. data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  193. data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  194. data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
  195. data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
  196. data/solargraph.gemspec +32 -10
  197. metadata +237 -37
  198. data/lib/.rubocop.yml +0 -22
  199. data/lib/solargraph/cache.rb +0 -77
  200. data/lib/solargraph/parser/node_methods.rb +0 -83
@@ -8,13 +8,17 @@ 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
14
15
 
15
- # @return [Solargraph::Location]
16
+ # @return [Solargraph::Location, nil]
16
17
  attr_reader :location
17
18
 
19
+ # @return [Solargraph::Location, nil]
20
+ attr_reader :type_location
21
+
18
22
  # @return [String]
19
23
  attr_reader :name
20
24
 
@@ -24,15 +28,346 @@ module Solargraph
24
28
  # @return [::Symbol]
25
29
  attr_accessor :source
26
30
 
31
+ # @type [::Numeric, nil] A priority for determining if pins should be combined or not
32
+ # A nil priority is considered the be the lowest. All code, yard & rbs pins have nil priority
33
+ # Between 2 pins, the one with the higher priority gets chosen. If the priorities are equal, they are combined.
34
+ attr_reader :combine_priority
35
+
36
+ def presence_certain?
37
+ true
38
+ end
39
+
27
40
  # @param location [Solargraph::Location, nil]
41
+ # @param type_location [Solargraph::Location, nil]
28
42
  # @param closure [Solargraph::Pin::Closure, nil]
29
43
  # @param name [String]
30
44
  # @param comments [String]
31
- def initialize location: nil, closure: nil, name: '', comments: ''
45
+ # @param source [Symbol, nil]
46
+ # @param docstring [YARD::Docstring, nil]
47
+ # @param directives [::Array<YARD::Tags::Directive>, nil]
48
+ # @param combine_priority [::Numeric, nil] See attr_reader for combine_priority
49
+ def initialize location: nil, type_location: nil, closure: nil, source: nil, name: '', comments: '', docstring: nil, directives: nil, combine_priority: nil
32
50
  @location = location
51
+ @type_location = type_location
33
52
  @closure = closure
34
53
  @name = name
35
54
  @comments = comments
55
+ @source = source
56
+ @identity = nil
57
+ @docstring = docstring
58
+ @directives = directives
59
+ @combine_priority = combine_priority
60
+
61
+ assert_source_provided
62
+ assert_location_provided
63
+ end
64
+
65
+ # @return [void]
66
+ def assert_location_provided
67
+ return unless best_location.nil? && %i[yardoc source rbs].include?(source)
68
+
69
+ Solargraph.assert_or_log(:best_location, "Neither location nor type_location provided - #{path} #{source} #{self.class}")
70
+ end
71
+
72
+ # @return [Pin::Closure, nil]
73
+ def closure
74
+ Solargraph.assert_or_log(:closure, "Closure not set on #{self.class} #{name.inspect} from #{source.inspect}") unless @closure
75
+ # @type [Pin::Closure, nil]
76
+ @closure
77
+ end
78
+
79
+ # @param other [self]
80
+ # @param attrs [Hash{::Symbol => Object}]
81
+ #
82
+ # @return [self]
83
+ def combine_with(other, attrs={})
84
+ raise "tried to combine #{other.class} with #{self.class}" unless other.class == self.class
85
+ priority_choice = choose_priority(other)
86
+ return priority_choice unless priority_choice.nil?
87
+
88
+ type_location = choose(other, :type_location)
89
+ location = choose(other, :location)
90
+ combined_name = combine_name(other)
91
+ new_attrs = {
92
+ location: location,
93
+ type_location: type_location,
94
+ name: combined_name,
95
+ closure: choose_pin_attr_with_same_name(other, :closure),
96
+ comments: choose_longer(other, :comments),
97
+ source: :combined,
98
+ docstring: choose(other, :docstring),
99
+ directives: combine_directives(other),
100
+ combine_priority: combine_priority
101
+ }.merge(attrs)
102
+ assert_same_macros(other)
103
+ logger.debug { "Base#combine_with(path=#{path}) - other.comments=#{other.comments.inspect}, self.comments = #{self.comments}" }
104
+ out = self.class.new(**new_attrs)
105
+ out.reset_generated!
106
+ out
107
+ end
108
+
109
+ # @param other [self]
110
+ # @return [self, nil] Returns either the pin chosen based on priority or nil
111
+ # A nil return means that the combination process must proceed
112
+ def choose_priority(other)
113
+ if combine_priority.nil? && !other.combine_priority.nil?
114
+ return other
115
+ elsif other.combine_priority.nil? && !combine_priority.nil?
116
+ return self
117
+ elsif !combine_priority.nil? && !other.combine_priority.nil?
118
+ if combine_priority > other.combine_priority
119
+ return self
120
+ elsif combine_priority < other.combine_priority
121
+ return other
122
+ end
123
+ end
124
+
125
+ nil
126
+ end
127
+
128
+ # @param other [self]
129
+ # @param attr [::Symbol]
130
+ # @sg-ignore
131
+ # @return [undefined]
132
+ def choose_longer(other, attr)
133
+ # @type [undefined]
134
+ val1 = send(attr)
135
+ # @type [undefined]
136
+ val2 = other.send(attr)
137
+ return val1 if val1 == val2
138
+ return val2 if val1.nil?
139
+ val1.length > val2.length ? val1 : val2
140
+ end
141
+
142
+ # @param other [self]
143
+ # @return [::Array<YARD::Tags::Directive>, nil]
144
+ def combine_directives(other)
145
+ return self.directives if other.directives.empty?
146
+ return other.directives if directives.empty?
147
+ [directives + other.directives].uniq
148
+ end
149
+
150
+ # @param other [self]
151
+ # @return [String]
152
+ def combine_name(other)
153
+ if needs_consistent_name? || other.needs_consistent_name?
154
+ assert_same(other, :name)
155
+ else
156
+ choose(other, :name)
157
+ end
158
+ end
159
+
160
+ # @return [void]
161
+ def reset_generated!
162
+ # @return_type doesn't go here as subclasses tend to assign it
163
+ # themselves in constructors, and they will deal with setting
164
+ # it in any methods that call this
165
+ #
166
+ # @docstring also doesn't go here, as there is code which
167
+ # directly manipulates docstring without editing comments
168
+ # (e.g., Api::Map::Store#index processes overrides that way
169
+ #
170
+ # Same with @directives, @macros, @maybe_directives, which
171
+ # regenerate docstring
172
+ @deprecated = nil
173
+ reset_conversions
174
+ end
175
+
176
+ def needs_consistent_name?
177
+ true
178
+ end
179
+
180
+ # @sg-ignore def should infer as symbol - "Not enough arguments to Module#protected"
181
+ protected def equality_fields
182
+ [name, location, type_location, closure, source]
183
+ end
184
+
185
+ # @param other [self]
186
+ # @return [ComplexType]
187
+ def combine_return_type(other)
188
+ if return_type.undefined?
189
+ other.return_type
190
+ elsif other.return_type.undefined?
191
+ return_type
192
+ elsif dodgy_return_type_source? && !other.dodgy_return_type_source?
193
+ other.return_type
194
+ elsif other.dodgy_return_type_source? && !dodgy_return_type_source?
195
+ return_type
196
+ else
197
+ all_items = return_type.items + other.return_type.items
198
+ if all_items.any? { |item| item.selfy? } && all_items.any? { |item| item.rooted_tag == context.reduce_class_type.rooted_tag }
199
+ # assume this was a declaration that should have said 'self'
200
+ all_items.delete_if { |item| item.rooted_tag == context.reduce_class_type.rooted_tag }
201
+ end
202
+ ComplexType.new(all_items)
203
+ end
204
+ end
205
+
206
+ def dodgy_return_type_source?
207
+ # uses a lot of 'Object' instead of 'self'
208
+ location&.filename&.include?('core_ext/object/')
209
+ end
210
+
211
+ # when choices are arbitrary, make sure the choice is consistent
212
+ #
213
+ # @param other [Pin::Base]
214
+ # @param attr [::Symbol]
215
+ #
216
+ # @return [Object, nil]
217
+ def choose(other, attr)
218
+ results = [self, other].map(&attr).compact
219
+ # true and false are different classes and can't be sorted
220
+ return true if results.any? { |r| r == true || r == false }
221
+ results.min
222
+ rescue
223
+ 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}")
224
+ raise
225
+ end
226
+
227
+ # @param other [self]
228
+ # @param attr [::Symbol]
229
+ # @sg-ignore
230
+ # @return [undefined]
231
+ def choose_node(other, attr)
232
+ if other.object_id < attr.object_id
233
+ other.send(attr)
234
+ else
235
+ send(attr)
236
+ end
237
+ end
238
+
239
+ # @param other [self]
240
+ # @param attr [::Symbol]
241
+ # @sg-ignore
242
+ # @return [undefined]
243
+ def prefer_rbs_location(other, attr)
244
+ if rbs_location? && !other.rbs_location?
245
+ self.send(attr)
246
+ elsif !rbs_location? && other.rbs_location?
247
+ other.send(attr)
248
+ else
249
+ choose(other, attr)
250
+ end
251
+ end
252
+
253
+ def rbs_location?
254
+ type_location&.rbs?
255
+ end
256
+
257
+ # @param other [self]
258
+ # @return [void]
259
+ def assert_same_macros(other)
260
+ return unless self.source == :yardoc && other.source == :yardoc
261
+ assert_same_count(other, :macros)
262
+ # @param [YARD::Tags::MacroDirective]
263
+ assert_same_array_content(other, :macros) { |macro| macro.tag.name }
264
+ end
265
+
266
+ # @param other [self]
267
+ # @param attr [::Symbol]
268
+ # @return [void]
269
+ # @todo strong typechecking should complain when there are no block-related tags
270
+ def assert_same_array_content(other, attr, &block)
271
+ arr1 = send(attr)
272
+ raise "Expected #{attr} on #{self} to be an Enumerable, got #{arr1.class}" unless arr1.is_a?(::Enumerable)
273
+ # @type arr1 [::Enumerable]
274
+ arr2 = other.send(attr)
275
+ raise "Expected #{attr} on #{other} to be an Enumerable, got #{arr2.class}" unless arr2.is_a?(::Enumerable)
276
+ # @type arr2 [::Enumerable]
277
+
278
+ # @type [undefined]
279
+ values1 = arr1.map(&block)
280
+ # @type [undefined]
281
+ values2 = arr2.map(&block)
282
+ # @sg-ignore
283
+ return arr1 if values1 == values2
284
+ Solargraph.assert_or_log("combine_with_#{attr}".to_sym,
285
+ "Inconsistent #{attr.inspect} values between \nself =#{inspect} and \nother=#{other.inspect}:\n\n self values = #{values1}\nother values =#{attr} = #{values2}")
286
+ arr1
287
+ end
288
+
289
+ # @param other [self]
290
+ # @param attr [::Symbol]
291
+ #
292
+ # @return [::Enumerable]
293
+ def assert_same_count(other, attr)
294
+ # @type [::Enumerable]
295
+ arr1 = self.send(attr)
296
+ raise "Expected #{attr} on #{self} to be an Enumerable, got #{arr1.class}" unless arr1.is_a?(::Enumerable)
297
+ # @type [::Enumerable]
298
+ arr2 = other.send(attr)
299
+ raise "Expected #{attr} on #{other} to be an Enumerable, got #{arr2.class}" unless arr2.is_a?(::Enumerable)
300
+ return arr1 if arr1.count == arr2.count
301
+ Solargraph.assert_or_log("combine_with_#{attr}".to_sym,
302
+ "Inconsistent #{attr.inspect} count value between \nself =#{inspect} and \nother=#{other.inspect}:\n\n self.#{attr} = #{arr1.inspect}\nother.#{attr} = #{arr2.inspect}")
303
+ arr1
304
+ end
305
+
306
+ # @param other [self]
307
+ # @param attr [::Symbol]
308
+ #
309
+ # @sg-ignore
310
+ # @return [undefined]
311
+ def assert_same(other, attr)
312
+ return false if other.nil?
313
+ val1 = send(attr)
314
+ val2 = other.send(attr)
315
+ return val1 if val1 == val2
316
+ Solargraph.assert_or_log("combine_with_#{attr}".to_sym,
317
+ "Inconsistent #{attr.inspect} values between \nself =#{inspect} and \nother=#{other.inspect}:\n\n self.#{attr} = #{val1.inspect}\nother.#{attr} = #{val2.inspect}")
318
+ val1
319
+ end
320
+
321
+ # @param other [self]
322
+ # @param attr [::Symbol]
323
+ # @sg-ignore
324
+ # @return [undefined]
325
+ def choose_pin_attr_with_same_name(other, attr)
326
+ # @type [Pin::Base, nil]
327
+ val1 = send(attr)
328
+ # @type [Pin::Base, nil]
329
+ val2 = other.send(attr)
330
+ raise "Expected pin for #{attr} on\n#{self.inspect},\ngot #{val1.inspect}" unless val1.nil? || val1.is_a?(Pin::Base)
331
+ raise "Expected pin for #{attr} on\n#{other.inspect},\ngot #{val2.inspect}" unless val2.nil? || val2.is_a?(Pin::Base)
332
+ if val1&.name != val2&.name
333
+ Solargraph.assert_or_log("combine_with_#{attr}_name".to_sym,
334
+ "Inconsistent #{attr.inspect} name values between \nself =#{inspect} and \nother=#{other.inspect}:\n\n self.#{attr} = #{val1.inspect}\nother.#{attr} = #{val2.inspect}")
335
+ end
336
+ choose_pin_attr(other, attr)
337
+ end
338
+
339
+ # @param other [self]
340
+ # @param attr [::Symbol]
341
+ #
342
+ # @sg-ignore Missing @return tag for Solargraph::Pin::Base#choose_pin_attr
343
+ # @return [undefined]
344
+ def choose_pin_attr(other, attr)
345
+ # @type [Pin::Base, nil]
346
+ val1 = send(attr)
347
+ # @type [Pin::Base, nil]
348
+ val2 = other.send(attr)
349
+ if val1.class != val2.class
350
+ # :nocov:
351
+ Solargraph.assert_or_log("combine_with_#{attr}_class".to_sym,
352
+ "Inconsistent #{attr.inspect} class values between \nself =#{inspect} and \nother=#{other.inspect}:\n\n self.#{attr} = #{val1.inspect}\nother.#{attr} = #{val2.inspect}")
353
+ return val1
354
+ # :nocov:
355
+ end
356
+ # arbitrary way of choosing a pin
357
+ [val1, val2].compact.max_by do |closure|
358
+ [
359
+ # maximize number of gates, as types in other combined pins may
360
+ # depend on those gates
361
+ closure.gates.length,
362
+ # use basename so that results don't vary system to system
363
+ File.basename(closure.best_location.to_s)
364
+ ]
365
+ end
366
+ end
367
+
368
+ # @return [void]
369
+ def assert_source_provided
370
+ Solargraph.assert_or_log(:source, "source not provided - #{@path} #{@source} #{self.class}") if source.nil?
36
371
  end
37
372
 
38
373
  # @return [String]
@@ -66,11 +401,14 @@ module Solargraph
66
401
  # @param context_type [ComplexType] The receiver type
67
402
  # @return [self]
68
403
  def resolve_generics definitions, context_type
69
- transformed = transform_types { |t| t.resolve_generics(definitions, context_type) if t }
70
- transformed.erase_generics(definitions.generics)
404
+ transform_types { |t| t.resolve_generics(definitions, context_type) if t }
405
+ end
406
+
407
+ def all_rooted?
408
+ !return_type || return_type.all_rooted?
71
409
  end
72
410
 
73
- # @param generics_to_erase [Enumerable<String>]
411
+ # @param generics_to_erase [::Array<String>]
74
412
  # @return [self]
75
413
  def erase_generics(generics_to_erase)
76
414
  return self if generics_to_erase.empty?
@@ -94,7 +432,7 @@ module Solargraph
94
432
  end
95
433
 
96
434
  def to_s
97
- to_rbs
435
+ desc
98
436
  end
99
437
 
100
438
  # @return [Boolean]
@@ -102,12 +440,9 @@ module Solargraph
102
440
  false
103
441
  end
104
442
 
105
- # Pin equality is determined using the #nearly? method and also
106
- # requiring both pins to have the same location.
107
- #
108
- def == other
109
- return false unless nearly? other
110
- comments == other.comments and location == other.location
443
+ # @return [Location, nil]
444
+ def best_location
445
+ location || type_location
111
446
  end
112
447
 
113
448
  # True if the specified pin is a near match to this one. A near match
@@ -126,6 +461,16 @@ module Solargraph
126
461
  )
127
462
  end
128
463
 
464
+ # Pin equality is determined using the #nearly? method and also
465
+ # requiring both pins to have the same location.
466
+ #
467
+ # @param other [Object]
468
+ def == other
469
+ return false unless nearly? other
470
+ # @sg-ignore Should add more explicit type check on other
471
+ comments == other.comments && location == other.location
472
+ end
473
+
129
474
  # The pin's return type.
130
475
  #
131
476
  # @return [ComplexType]
@@ -135,13 +480,13 @@ module Solargraph
135
480
 
136
481
  # @return [YARD::Docstring]
137
482
  def docstring
138
- parse_comments unless defined?(@docstring)
483
+ parse_comments unless @docstring
139
484
  @docstring ||= Solargraph::Source.parse_docstring('').to_docstring
140
485
  end
141
486
 
142
487
  # @return [::Array<YARD::Tags::Directive>]
143
488
  def directives
144
- parse_comments unless defined?(@directives)
489
+ parse_comments unless @directives
145
490
  @directives
146
491
  end
147
492
 
@@ -159,7 +504,7 @@ module Solargraph
159
504
  #
160
505
  # @return [Boolean]
161
506
  def maybe_directives?
162
- return !@directives.empty? if defined?(@directives)
507
+ return !@directives.empty? if defined?(@directives) && @directives
163
508
  @maybe_directives ||= comments.include?('@!')
164
509
  end
165
510
 
@@ -177,7 +522,7 @@ module Solargraph
177
522
  # @param api_map [ApiMap]
178
523
  # @return [ComplexType]
179
524
  def typify api_map
180
- return_type.qualify(api_map, namespace)
525
+ return_type.qualify(api_map, *(closure&.gates || ['']))
181
526
  end
182
527
 
183
528
  # Infer the pin's return type via static code analysis.
@@ -198,26 +543,6 @@ module Solargraph
198
543
  probe api_map
199
544
  end
200
545
 
201
- # Try to merge data from another pin. Merges are only possible if the
202
- # pins are near matches (see the #nearly? method). The changes should
203
- # not have any side effects on the API surface.
204
- #
205
- # @param pin [Pin::Base] The pin to merge into this one
206
- # @return [Boolean] True if the pins were merged
207
- def try_merge! pin
208
- return false unless nearly?(pin)
209
- @location = pin.location
210
- @closure = pin.closure
211
- return true if comments == pin.comments
212
- @comments = pin.comments
213
- @docstring = pin.docstring
214
- @return_type = pin.return_type
215
- @documentation = nil
216
- @deprecated = nil
217
- reset_conversions
218
- true
219
- end
220
-
221
546
  def proxied?
222
547
  @proxied ||= false
223
548
  end
@@ -252,9 +577,22 @@ module Solargraph
252
577
  result
253
578
  end
254
579
 
580
+ # @deprecated
255
581
  # @return [String]
256
582
  def identity
257
- @identity ||= "#{closure.path}|#{name}"
583
+ @identity ||= "#{closure&.path}|#{name}|#{location}"
584
+ end
585
+
586
+ # The namespaces available for resolving the current namespace. Each gate
587
+ # should be a fully qualified namespace or the root namespace (i.e., an
588
+ # empty string.)
589
+ #
590
+ # Example: Given the name 'Bar' and the gates ['Foo', ''],
591
+ # the fully qualified namespace should be 'Foo::Bar' or 'Bar'.
592
+ #
593
+ # @return [Array<String>]
594
+ def gates
595
+ @gates ||= closure&.gates || ['']
258
596
  end
259
597
 
260
598
  # @return [String, nil]
@@ -263,20 +601,53 @@ module Solargraph
263
601
  end
264
602
 
265
603
  # @return [String, nil]
266
- def desc
604
+ def type_desc
605
+ rbs = to_rbs
606
+ # RBS doesn't have a way to represent a Class<x> type
607
+ rbs = return_type.rooted_tags if return_type.name == 'Class'
267
608
  if path
268
- if to_rbs
269
- path + ' ' + to_rbs
609
+ if rbs
610
+ path + ' ' + rbs
270
611
  else
271
612
  path
272
613
  end
273
614
  else
274
- to_rbs
615
+ rbs
275
616
  end
276
617
  end
277
618
 
619
+ # @return [String]
620
+ def inner_desc
621
+ closure_info = closure&.desc
622
+ binder_info = binder&.desc
623
+ "name=#{name.inspect} return_type=#{type_desc}, context=#{context.rooted_tags}, closure=#{closure_info}, binder=#{binder_info}"
624
+ end
625
+
626
+ # @return [String]
627
+ def desc
628
+ "[#{inner_desc}]"
629
+ end
630
+
631
+ # @return [String]
278
632
  def inspect
279
- "#<#{self.class} `#{self.desc}` at #{self.location.inspect}>"
633
+ "#<#{self.class} `#{self.inner_desc}`#{all_location_text} via #{source.inspect}>"
634
+ end
635
+
636
+ # @return [String]
637
+ def all_location_text
638
+ if location.nil? && type_location.nil?
639
+ ''
640
+ elsif !location.nil? && type_location.nil?
641
+ " at #{location.inspect})"
642
+ elsif !type_location.nil? && location.nil?
643
+ " at #{type_location.inspect})"
644
+ else
645
+ " at (#{location.inspect} and #{type_location.inspect})"
646
+ end
647
+ end
648
+
649
+ # @return [void]
650
+ def reset_generated!
280
651
  end
281
652
 
282
653
  protected
@@ -290,6 +661,10 @@ module Solargraph
290
661
  # @return [ComplexType]
291
662
  attr_writer :return_type
292
663
 
664
+ attr_writer :docstring
665
+
666
+ attr_writer :directives
667
+
293
668
  private
294
669
 
295
670
  # @return [void]
@@ -3,20 +3,32 @@
3
3
  module Solargraph
4
4
  module Pin
5
5
  class BaseVariable < Base
6
- include Solargraph::Parser::NodeMethods
7
6
  # include Solargraph::Source::NodeMethods
7
+ include Solargraph::Parser::NodeMethods
8
8
 
9
9
  # @return [Parser::AST::Node, nil]
10
10
  attr_reader :assignment
11
11
 
12
12
  attr_accessor :mass_assignment
13
13
 
14
+ # @param return_type [ComplexType, nil]
15
+ # @param mass_assignment [::Array(Parser::AST::Node, Integer), nil]
14
16
  # @param assignment [Parser::AST::Node, nil]
15
- def initialize assignment: nil, **splat
17
+ def initialize assignment: nil, return_type: nil, mass_assignment: nil, **splat
16
18
  super(**splat)
17
19
  @assignment = assignment
18
20
  # @type [nil, ::Array(Parser::AST::Node, Integer)]
19
21
  @mass_assignment = nil
22
+ @return_type = return_type
23
+ end
24
+
25
+ def combine_with(other, attrs={})
26
+ new_attrs = attrs.merge({
27
+ assignment: assert_same(other, :assignment),
28
+ mass_assignment: assert_same(other, :mass_assignment),
29
+ return_type: combine_return_type(other),
30
+ })
31
+ super(other, new_attrs)
20
32
  end
21
33
 
22
34
  def completion_item_kind
@@ -33,6 +45,8 @@ module Solargraph
33
45
  end
34
46
 
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
 
@@ -57,7 +71,7 @@ module Solargraph
57
71
  # Use the return node for inference. The clip might infer from the
58
72
  # first node in a method call instead of the entire call.
59
73
  chain = Parser.chain(node, nil, nil)
60
- result = chain.infer(api_map, closure, clip.locals).self_to(closure.context.tag)
74
+ result = chain.infer(api_map, closure, clip.locals).self_to_type(closure.context)
61
75
  types.push result unless result.undefined?
62
76
  end
63
77
  end
@@ -88,20 +102,15 @@ 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
108
+ # @sg-ignore Should add type check on other
93
109
  assignment == other.assignment
94
110
  end
95
111
 
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}"
112
+ def type_desc
113
+ "#{super} = #{assignment&.type.inspect}"
105
114
  end
106
115
 
107
116
  private