solargraph 0.58.3 → 0.59.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 (229) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +12 -5
  4. data/.github/workflows/plugins.yml +54 -34
  5. data/.github/workflows/rspec.yml +15 -28
  6. data/.github/workflows/typecheck.yml +6 -3
  7. data/.rubocop.yml +38 -6
  8. data/.rubocop_todo.yml +53 -966
  9. data/CHANGELOG.md +24 -0
  10. data/Gemfile +3 -1
  11. data/README.md +3 -3
  12. data/Rakefile +26 -23
  13. data/bin/solargraph +2 -1
  14. data/lib/solargraph/api_map/cache.rb +3 -3
  15. data/lib/solargraph/api_map/constants.rb +12 -3
  16. data/lib/solargraph/api_map/index.rb +29 -18
  17. data/lib/solargraph/api_map/source_to_yard.rb +22 -9
  18. data/lib/solargraph/api_map/store.rb +40 -30
  19. data/lib/solargraph/api_map.rb +160 -78
  20. data/lib/solargraph/bench.rb +2 -3
  21. data/lib/solargraph/complex_type/conformance.rb +176 -0
  22. data/lib/solargraph/complex_type/type_methods.rb +31 -18
  23. data/lib/solargraph/complex_type/unique_type.rb +221 -63
  24. data/lib/solargraph/complex_type.rb +173 -59
  25. data/lib/solargraph/convention/active_support_concern.rb +111 -111
  26. data/lib/solargraph/convention/base.rb +50 -50
  27. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -1
  28. data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
  29. data/lib/solargraph/convention/data_definition.rb +5 -2
  30. data/lib/solargraph/convention/gemfile.rb +1 -1
  31. data/lib/solargraph/convention/gemspec.rb +1 -1
  32. data/lib/solargraph/convention/rakefile.rb +1 -1
  33. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
  34. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
  35. data/lib/solargraph/convention/struct_definition.rb +8 -4
  36. data/lib/solargraph/convention.rb +2 -2
  37. data/lib/solargraph/converters/dd.rb +2 -0
  38. data/lib/solargraph/converters/dl.rb +2 -0
  39. data/lib/solargraph/converters/dt.rb +2 -0
  40. data/lib/solargraph/converters/misc.rb +2 -0
  41. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  42. data/lib/solargraph/diagnostics/rubocop.rb +11 -10
  43. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  44. data/lib/solargraph/diagnostics/type_check.rb +11 -10
  45. data/lib/solargraph/diagnostics/update_errors.rb +4 -8
  46. data/lib/solargraph/diagnostics.rb +55 -55
  47. data/lib/solargraph/doc_map.rb +38 -39
  48. data/lib/solargraph/environ.rb +52 -52
  49. data/lib/solargraph/equality.rb +4 -4
  50. data/lib/solargraph/gem_pins.rb +4 -15
  51. data/lib/solargraph/language_server/error_codes.rb +10 -10
  52. data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
  53. data/lib/solargraph/language_server/host/dispatch.rb +3 -3
  54. data/lib/solargraph/language_server/host/message_worker.rb +4 -3
  55. data/lib/solargraph/language_server/host/sources.rb +2 -1
  56. data/lib/solargraph/language_server/host.rb +35 -28
  57. data/lib/solargraph/language_server/message/base.rb +1 -1
  58. data/lib/solargraph/language_server/message/client/register_capability.rb +1 -3
  59. data/lib/solargraph/language_server/message/completion_item/resolve.rb +6 -8
  60. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
  61. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  62. data/lib/solargraph/language_server/message/extended/document_gems.rb +7 -7
  63. data/lib/solargraph/language_server/message/extended/download_core.rb +2 -1
  64. data/lib/solargraph/language_server/message/extended/environment.rb +25 -25
  65. data/lib/solargraph/language_server/message/extended/search.rb +1 -1
  66. data/lib/solargraph/language_server/message/initialize.rb +20 -14
  67. data/lib/solargraph/language_server/message/initialized.rb +28 -28
  68. data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
  69. data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
  70. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +17 -10
  71. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
  72. data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
  73. data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
  74. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +13 -6
  75. data/lib/solargraph/language_server/message/text_document/references.rb +17 -10
  76. data/lib/solargraph/language_server/message/text_document/rename.rb +20 -13
  77. data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
  78. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
  79. data/lib/solargraph/language_server/message/text_document.rb +28 -28
  80. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +34 -28
  81. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +38 -30
  82. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +23 -17
  83. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
  84. data/lib/solargraph/language_server/message.rb +1 -1
  85. data/lib/solargraph/language_server/progress.rb +143 -143
  86. data/lib/solargraph/language_server/request.rb +4 -2
  87. data/lib/solargraph/language_server/transport/adapter.rb +68 -68
  88. data/lib/solargraph/language_server/transport/data_reader.rb +11 -13
  89. data/lib/solargraph/language_server/uri_helpers.rb +2 -2
  90. data/lib/solargraph/language_server.rb +20 -20
  91. data/lib/solargraph/library.rb +57 -38
  92. data/lib/solargraph/location.rb +17 -14
  93. data/lib/solargraph/logging.rb +22 -4
  94. data/lib/solargraph/page.rb +1 -1
  95. data/lib/solargraph/parser/comment_ripper.rb +19 -4
  96. data/lib/solargraph/parser/flow_sensitive_typing.rb +324 -108
  97. data/lib/solargraph/parser/node_processor/base.rb +34 -4
  98. data/lib/solargraph/parser/node_processor.rb +8 -7
  99. data/lib/solargraph/parser/parser_gem/class_methods.rb +30 -14
  100. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -1
  101. data/lib/solargraph/parser/parser_gem/node_chainer.rb +51 -25
  102. data/lib/solargraph/parser/parser_gem/node_methods.rb +181 -73
  103. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +24 -24
  104. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  105. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
  106. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  107. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -12
  108. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +36 -36
  109. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +24 -24
  110. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
  111. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +9 -8
  112. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +24 -24
  113. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  114. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
  115. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  116. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  117. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +40 -40
  118. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
  119. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  120. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  121. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  122. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
  123. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
  124. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +20 -20
  125. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +1 -1
  126. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  127. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
  128. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  129. data/lib/solargraph/parser/parser_gem.rb +2 -0
  130. data/lib/solargraph/parser/region.rb +9 -3
  131. data/lib/solargraph/parser/snippet.rb +3 -1
  132. data/lib/solargraph/parser.rb +2 -0
  133. data/lib/solargraph/pin/base.rb +126 -82
  134. data/lib/solargraph/pin/base_variable.rb +273 -24
  135. data/lib/solargraph/pin/block.rb +29 -6
  136. data/lib/solargraph/pin/breakable.rb +7 -1
  137. data/lib/solargraph/pin/callable.rb +65 -21
  138. data/lib/solargraph/pin/closure.rb +7 -10
  139. data/lib/solargraph/pin/common.rb +24 -6
  140. data/lib/solargraph/pin/compound_statement.rb +55 -0
  141. data/lib/solargraph/pin/constant.rb +3 -5
  142. data/lib/solargraph/pin/conversions.rb +10 -4
  143. data/lib/solargraph/pin/delegated_method.rb +19 -8
  144. data/lib/solargraph/pin/documenting.rb +4 -2
  145. data/lib/solargraph/pin/instance_variable.rb +5 -1
  146. data/lib/solargraph/pin/keyword.rb +0 -4
  147. data/lib/solargraph/pin/local_variable.rb +15 -59
  148. data/lib/solargraph/pin/method.rb +158 -104
  149. data/lib/solargraph/pin/method_alias.rb +8 -0
  150. data/lib/solargraph/pin/namespace.rb +19 -12
  151. data/lib/solargraph/pin/parameter.rb +102 -36
  152. data/lib/solargraph/pin/proxy_type.rb +4 -1
  153. data/lib/solargraph/pin/reference/override.rb +1 -1
  154. data/lib/solargraph/pin/reference/require.rb +14 -14
  155. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  156. data/lib/solargraph/pin/reference/type_alias.rb +16 -0
  157. data/lib/solargraph/pin/reference.rb +20 -0
  158. data/lib/solargraph/pin/search.rb +8 -7
  159. data/lib/solargraph/pin/signature.rb +15 -12
  160. data/lib/solargraph/pin/singleton.rb +11 -11
  161. data/lib/solargraph/pin/symbol.rb +2 -1
  162. data/lib/solargraph/pin/until.rb +2 -4
  163. data/lib/solargraph/pin/while.rb +2 -4
  164. data/lib/solargraph/pin.rb +2 -0
  165. data/lib/solargraph/pin_cache.rb +22 -19
  166. data/lib/solargraph/position.rb +17 -10
  167. data/lib/solargraph/range.rb +16 -15
  168. data/lib/solargraph/rbs_map/conversions.rb +367 -231
  169. data/lib/solargraph/rbs_map/core_fills.rb +18 -11
  170. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  171. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
  172. data/lib/solargraph/rbs_map.rb +76 -32
  173. data/lib/solargraph/server_methods.rb +1 -1
  174. data/lib/solargraph/shell.rb +258 -66
  175. data/lib/solargraph/source/chain/array.rb +3 -12
  176. data/lib/solargraph/source/chain/block_symbol.rb +13 -13
  177. data/lib/solargraph/source/chain/block_variable.rb +13 -13
  178. data/lib/solargraph/source/chain/call.rb +96 -56
  179. data/lib/solargraph/source/chain/class_variable.rb +1 -1
  180. data/lib/solargraph/source/chain/constant.rb +5 -1
  181. data/lib/solargraph/source/chain/global_variable.rb +1 -1
  182. data/lib/solargraph/source/chain/hash.rb +8 -5
  183. data/lib/solargraph/source/chain/head.rb +19 -19
  184. data/lib/solargraph/source/chain/if.rb +12 -10
  185. data/lib/solargraph/source/chain/instance_variable.rb +24 -1
  186. data/lib/solargraph/source/chain/link.rb +12 -22
  187. data/lib/solargraph/source/chain/literal.rb +22 -15
  188. data/lib/solargraph/source/chain/or.rb +10 -4
  189. data/lib/solargraph/source/chain/q_call.rb +2 -0
  190. data/lib/solargraph/source/chain/variable.rb +3 -1
  191. data/lib/solargraph/source/chain/z_super.rb +1 -3
  192. data/lib/solargraph/source/chain.rb +51 -38
  193. data/lib/solargraph/source/change.rb +12 -5
  194. data/lib/solargraph/source/cursor.rb +33 -18
  195. data/lib/solargraph/source/encoding_fixes.rb +6 -7
  196. data/lib/solargraph/source/source_chainer.rb +56 -32
  197. data/lib/solargraph/source/updater.rb +5 -1
  198. data/lib/solargraph/source.rb +59 -35
  199. data/lib/solargraph/source_map/clip.rb +54 -30
  200. data/lib/solargraph/source_map/data.rb +4 -1
  201. data/lib/solargraph/source_map/mapper.rb +69 -42
  202. data/lib/solargraph/source_map.rb +21 -9
  203. data/lib/solargraph/type_checker/problem.rb +3 -1
  204. data/lib/solargraph/type_checker/rules.rb +81 -8
  205. data/lib/solargraph/type_checker.rb +196 -122
  206. data/lib/solargraph/version.rb +1 -1
  207. data/lib/solargraph/workspace/config.rb +14 -11
  208. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  209. data/lib/solargraph/workspace/require_paths.rb +1 -0
  210. data/lib/solargraph/workspace.rb +50 -28
  211. data/lib/solargraph/yard_map/cache.rb +25 -25
  212. data/lib/solargraph/yard_map/helpers.rb +8 -3
  213. data/lib/solargraph/yard_map/mapper/to_constant.rb +28 -28
  214. data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
  215. data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
  216. data/lib/solargraph/yard_map/mapper.rb +13 -8
  217. data/lib/solargraph/yard_map.rb +17 -18
  218. data/lib/solargraph/yard_tags.rb +2 -2
  219. data/lib/solargraph/yardoc.rb +7 -4
  220. data/lib/solargraph.rb +33 -10
  221. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  222. data/rbs/shims/ast/0/node.rbs +1 -1
  223. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  224. data/solargraph.gemspec +37 -35
  225. metadata +41 -42
  226. data/lib/solargraph/type_checker/checks.rb +0 -124
  227. data/lib/solargraph/type_checker/param_def.rb +0 -37
  228. data/lib/solargraph/yard_map/to_method.rb +0 -89
  229. data/rbs/fills/tuple/tuple.rbs +0 -149
@@ -24,12 +24,26 @@ module Solargraph
24
24
  attr_reader :missing_docs
25
25
 
26
26
  # @param pins [Array<Solargraph::Pin::Base>]
27
- def initialize pins: []
27
+ # @param loose_unions [Boolean] if true, a potential type can be
28
+ # inferred if ANY of the UniqueTypes in the base chain's
29
+ # ComplexType match it. If false, every single UniqueTypes in
30
+ # the base must be ALL able to independently provide this
31
+ # type. The former is useful during completion, but the
32
+ # latter is best for typechecking at higher levels.
33
+ #
34
+ def initialize pins: [], loose_unions: true
28
35
  @source_map_hash = {}
29
36
  @cache = Cache.new
37
+ @loose_unions = loose_unions
30
38
  index pins
31
39
  end
32
40
 
41
+ # @param out [StringIO, IO, nil] output stream for logging
42
+ # @return [void]
43
+ def self.reset_core out: nil
44
+ @@core_map = RbsMap::CoreMap.new
45
+ end
46
+
33
47
  #
34
48
  # This is a mutable object, which is cached in the Chain class -
35
49
  # if you add any fields which change the results of calls (not
@@ -37,21 +51,24 @@ module Solargraph
37
51
  #
38
52
 
39
53
  # @param other [Object]
40
- def eql?(other)
54
+ def eql? other
41
55
  self.class == other.class &&
42
- # @sg-ignore Flow sensitive typing needs to handle self.class == other.class
56
+ # @sg-ignore flow sensitive typing needs to handle self.class == other.class
43
57
  equality_fields == other.equality_fields
44
58
  end
45
59
 
46
60
  # @param other [Object]
47
- def ==(other)
48
- self.eql?(other)
61
+ def == other
62
+ eql?(other)
49
63
  end
50
64
 
65
+ # @return [Integer]
51
66
  def hash
52
67
  equality_fields.hash
53
68
  end
54
69
 
70
+ attr_reader :loose_unions
71
+
55
72
  def to_s
56
73
  self.class.to_s
57
74
  end
@@ -98,11 +115,12 @@ module Solargraph
98
115
  end
99
116
  unresolved_requires = (bench.external_requires + conventions_environ.requires + bench.workspace.config.required).to_a.compact.uniq
100
117
  recreate_docmap = @unresolved_requires != unresolved_requires ||
101
- @doc_map&.uncached_yard_gemspecs&.any? ||
102
- @doc_map&.uncached_rbs_collection_gemspecs&.any? ||
103
- @doc_map&.rbs_collection_path != bench.workspace.rbs_collection_path
118
+ # @sg-ignore Unresolved call to rbs_collection_path on Solargraph::Workspace, nil
119
+ workspace.rbs_collection_path != bench.workspace.rbs_collection_path ||
120
+ @doc_map.uncached_gemspecs.any?
121
+
104
122
  if recreate_docmap
105
- @doc_map = DocMap.new(unresolved_requires, [], bench.workspace) # @todo Implement gem preferences
123
+ @doc_map = DocMap.new(unresolved_requires, bench.workspace, out: nil) # @todo Implement gem preferences
106
124
  @unresolved_requires = @doc_map.unresolved_requires
107
125
  end
108
126
  @cache.clear if store.update(@@core_map.pins, @doc_map.pins, conventions_environ.pins, iced_pins, live_pins)
@@ -110,21 +128,14 @@ module Solargraph
110
128
  self
111
129
  end
112
130
 
113
- # @todo need to model type def statement in chains as a symbol so
114
- # that this overload of 'protected' will typecheck @sg-ignore
115
- # @sg-ignore
116
- protected def equality_fields
117
- [self.class, @source_map_hash, conventions_environ, @doc_map, @unresolved_requires]
118
- end
119
-
120
131
  # @return [DocMap]
121
132
  def doc_map
122
- @doc_map ||= DocMap.new([], [])
133
+ @doc_map ||= DocMap.new([], Workspace.new('.'))
123
134
  end
124
135
 
125
136
  # @return [::Array<Gem::Specification>]
126
137
  def uncached_gemspecs
127
- @doc_map&.uncached_gemspecs || []
138
+ doc_map.uncached_gemspecs || []
128
139
  end
129
140
 
130
141
  # @return [::Array<Gem::Specification>]
@@ -142,9 +153,10 @@ module Solargraph
142
153
  @@core_map.pins
143
154
  end
144
155
 
145
- # @param name [String]
156
+ # @param name [String, nil]
146
157
  # @return [YARD::Tags::MacroDirective, nil]
147
158
  def named_macro name
159
+ # @sg-ignore Need to add nil check here
148
160
  store.named_macros[name]
149
161
  end
150
162
 
@@ -180,10 +192,11 @@ module Solargraph
180
192
  # Create an ApiMap with a workspace in the specified directory.
181
193
  #
182
194
  # @param directory [String]
195
+ # @param loose_unions [Boolean] See #initialize
183
196
  #
184
197
  # @return [ApiMap]
185
- def self.load directory
186
- api_map = new
198
+ def self.load directory, loose_unions: true
199
+ api_map = new(loose_unions: loose_unions)
187
200
  workspace = Solargraph::Workspace.new(directory)
188
201
  # api_map.catalog Bench.new(workspace: workspace)
189
202
  library = Library.new(workspace)
@@ -192,18 +205,19 @@ module Solargraph
192
205
  api_map
193
206
  end
194
207
 
195
- # @param out [IO, nil]
208
+ # @param out [StringIO, IO, nil]
209
+ # @param rebuild [Boolean] whether to rebuild the pins even if they are cached
196
210
  # @return [void]
197
- def cache_all!(out)
198
- @doc_map.cache_all!(out)
211
+ def cache_all_for_doc_map! out: $stderr, rebuild: false
212
+ doc_map.cache_all!(out, rebuild: rebuild)
199
213
  end
200
214
 
201
215
  # @param gemspec [Gem::Specification]
202
216
  # @param rebuild [Boolean]
203
- # @param out [IO, nil]
217
+ # @param out [StringIO, IO, nil]
204
218
  # @return [void]
205
- def cache_gem(gemspec, rebuild: false, out: nil)
206
- @doc_map.cache(gemspec, rebuild: rebuild, out: out)
219
+ def cache_gem gemspec, rebuild: false, out: nil
220
+ doc_map.cache(gemspec, rebuild: rebuild, out: out)
207
221
  end
208
222
 
209
223
  class << self
@@ -215,18 +229,19 @@ module Solargraph
215
229
  #
216
230
  #
217
231
  # @param directory [String]
218
- # @param out [IO] The output stream for messages
232
+ # @param out [IO, StringIO, nil] The output stream for messages
233
+ # @param loose_unions [Boolean] See #initialize
219
234
  #
220
235
  # @return [ApiMap]
221
- def self.load_with_cache directory, out
222
- api_map = load(directory)
236
+ def self.load_with_cache directory, out = $stderr, loose_unions: true
237
+ api_map = load(directory, loose_unions: loose_unions)
223
238
  if api_map.uncached_gemspecs.empty?
224
239
  logger.info { "All gems cached for #{directory}" }
225
240
  return api_map
226
241
  end
227
242
 
228
- api_map.cache_all!(out)
229
- load(directory)
243
+ api_map.cache_all_for_doc_map!(out: out)
244
+ load(directory, loose_unions: loose_unions)
230
245
  end
231
246
 
232
247
  # @return [Array<Solargraph::Pin::Base>]
@@ -241,6 +256,12 @@ module Solargraph
241
256
  store.pins_by_class(Pin::Keyword)
242
257
  end
243
258
 
259
+ # @param name [String]
260
+ # @return [ComplexType, nil]
261
+ def unalias name
262
+ store.unalias(name)
263
+ end
264
+
244
265
  # True if the namespace exists.
245
266
  #
246
267
  # @param name [String] The namespace to match
@@ -306,19 +327,19 @@ module Solargraph
306
327
  #
307
328
  # @param pin [Pin::Reference]
308
329
  # @return [String, nil]
309
- def dereference(pin)
330
+ def dereference pin
310
331
  store.constants.dereference(pin)
311
332
  end
312
333
 
313
334
  # @param fqns [String]
314
335
  # @return [Array<Pin::Reference::Extend>]
315
- def get_extends(fqns)
336
+ def get_extends fqns
316
337
  store.get_extends(fqns)
317
338
  end
318
339
 
319
340
  # @param fqns [String]
320
341
  # @return [Array<Pin::Reference::Include>]
321
- def get_includes(fqns)
342
+ def get_includes fqns
322
343
  store.get_includes(fqns)
323
344
  end
324
345
 
@@ -328,29 +349,50 @@ module Solargraph
328
349
  # @param namespace [String] A fully qualified namespace
329
350
  # @param scope [Symbol] :instance or :class
330
351
  # @return [Array<Solargraph::Pin::InstanceVariable>]
331
- def get_instance_variable_pins(namespace, scope = :instance)
352
+ def get_instance_variable_pins namespace, scope = :instance
332
353
  result = []
333
- used = [namespace]
354
+ [namespace]
334
355
  result.concat store.get_instance_variables(namespace, scope)
335
356
  sc_fqns = namespace
336
357
  while (sc = store.get_superclass(sc_fqns))
358
+ # @sg-ignore flow sensitive typing needs to handle "if foo = bar"
337
359
  sc_fqns = store.constants.dereference(sc)
338
360
  result.concat store.get_instance_variables(sc_fqns, scope)
339
361
  end
340
362
  result
341
363
  end
342
364
 
343
- # @sg-ignore Missing @return tag for Solargraph::ApiMap#visible_pins
344
- # @see Solargraph::Parser::FlowSensitiveTyping#visible_pins
345
- def visible_pins(*args, **kwargs, &blk)
346
- Solargraph::Parser::FlowSensitiveTyping.visible_pins(*args, **kwargs, &blk)
365
+ # Find a variable pin by name and where it is used.
366
+ #
367
+ # Resolves our most specific view of this variable's type by
368
+ # preferring pins created by flow-sensitive typing when we have
369
+ # them based on the Closure and Location.
370
+ #
371
+ # @param candidates [Array<Pin::BaseVariable>]
372
+ # @param name [String]
373
+ # @param closure [Pin::Closure]
374
+ # @param location [Location]
375
+ #
376
+ # @return [Pin::BaseVariable, nil]
377
+ def var_at_location candidates, name, closure, location
378
+ # @todo Location can be nil if clips have trouble finding node recipients
379
+ return unless location
380
+
381
+ with_correct_name = candidates.select { |pin| pin.name == name }
382
+ vars_at_location = with_correct_name.reject do |pin|
383
+ # visible_at? excludes the starting position, but we want to
384
+ # include it for this purpose
385
+ !pin.visible_at?(closure, location) && !pin.starts_at?(location)
386
+ end
387
+
388
+ vars_at_location.inject(&:combine_with)
347
389
  end
348
390
 
349
391
  # Get an array of class variable pins for a namespace.
350
392
  #
351
393
  # @param namespace [String] A fully qualified namespace
352
394
  # @return [Enumerable<Solargraph::Pin::ClassVariable>]
353
- def get_class_variable_pins(namespace)
395
+ def get_class_variable_pins namespace
354
396
  prefer_non_nil_variables(store.get_class_variables(namespace))
355
397
  end
356
398
 
@@ -377,11 +419,6 @@ module Solargraph
377
419
  # @param deep [Boolean] True to include superclasses, mixins, etc.
378
420
  # @return [Array<Solargraph::Pin::Method>]
379
421
  def get_methods rooted_tag, scope: :instance, visibility: [:public], deep: true
380
- if rooted_tag.start_with? 'Array('
381
- # Array() are really tuples - use our fill, as the RBS repo
382
- # does not give us definitions for it
383
- rooted_tag = "Solargraph::Fills::Tuple(#{rooted_tag[6..-2]})"
384
- end
385
422
  rooted_type = ComplexType.try_parse(rooted_tag)
386
423
  fqns = rooted_type.namespace
387
424
  namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
@@ -417,7 +454,7 @@ module Solargraph
417
454
  comments: init_pin.comments,
418
455
  closure: init_pin.closure,
419
456
  source: init_pin.source,
420
- type_location: init_pin.type_location,
457
+ type_location: init_pin.type_location
421
458
  )
422
459
  new_pin.parameters = init_pin.parameters.map do |init_param|
423
460
  param = init_param.clone
@@ -476,7 +513,7 @@ module Solargraph
476
513
  result = Set.new
477
514
  complex_type.each do |type|
478
515
  if type.duck_type?
479
- result.add Pin::DuckMethod.new(name: type.to_s[1..-1], source: :api_map)
516
+ result.add Pin::DuckMethod.new(name: type.to_s[1..], source: :api_map)
480
517
  result.merge get_methods('Object')
481
518
  else
482
519
  unless type.nil? || type.name == 'void'
@@ -507,12 +544,14 @@ module Solargraph
507
544
  # @param preserve_generics [Boolean] True to preserve any
508
545
  # unresolved generic parameters, false to erase them
509
546
  # @return [Array<Solargraph::Pin::Method>]
510
- def get_method_stack rooted_tag, name, scope: :instance, visibility: [:private, :protected, :public], preserve_generics: false
547
+ def get_method_stack rooted_tag, name, scope: :instance, visibility: %i[private protected public],
548
+ preserve_generics: false
511
549
  rooted_type = ComplexType.parse(rooted_tag)
512
550
  fqns = rooted_type.namespace
513
551
  namespace_pin = store.get_path_pins(fqns).first
514
552
  methods = if namespace_pin.is_a?(Pin::Constant)
515
- type = namespace_pin.infer(self)
553
+ type = namespace_pin.typify(self)
554
+ type = namespace_pin.probe(self) unless type.defined?
516
555
  if type.defined?
517
556
  namespace_pin = store.get_path_pins(type.namespace).first
518
557
  get_methods(type.namespace, scope: scope, visibility: visibility).select { |p| p.name == name }
@@ -630,18 +669,22 @@ module Solargraph
630
669
  # @param sup [String] The superclass
631
670
  # @param sub [String] The subclass
632
671
  # @return [Boolean]
633
- def super_and_sub?(sup, sub)
672
+ def super_and_sub? sup, sub
634
673
  sup = ComplexType.try_parse(sup)
635
674
  sub = ComplexType.try_parse(sub)
636
675
  # @todo If two literals are different values of the same type, it would
637
676
  # make more sense for super_and_sub? to return true, but there are a
638
677
  # few callers that currently expect this to be false.
678
+ # @sg-ignore flow-sensitive typing should be able to handle redefinition
639
679
  return false if sup.literal? && sub.literal? && sup.to_s != sub.to_s
680
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
640
681
  sup = sup.simplify_literals.to_s
682
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
641
683
  sub = sub.simplify_literals.to_s
642
684
  return true if sup == sub
643
685
  sc_fqns = sub
644
686
  while (sc = store.get_superclass(sc_fqns))
687
+ # @sg-ignore flow sensitive typing needs to handle "if foo = bar"
645
688
  sc_new = store.constants.dereference(sc)
646
689
  # Cyclical inheritance is invalid
647
690
  return false if sc_new == sc_fqns
@@ -658,22 +701,30 @@ module Solargraph
658
701
  # @param module_ns [String] The module namespace (no type parameters)
659
702
  #
660
703
  # @return [Boolean]
661
- def type_include?(host_ns, module_ns)
704
+ def type_include? host_ns, module_ns
662
705
  store.get_includes(host_ns).map { |inc_tag| inc_tag.type.name }.include?(module_ns)
663
706
  end
664
707
 
665
708
  # @param pins [Enumerable<Pin::Base>]
666
709
  # @param visibility [Enumerable<Symbol>]
667
710
  # @return [Array<Pin::Base>]
668
- def resolve_method_aliases pins, visibility = [:public, :private, :protected]
711
+ def resolve_method_aliases pins, visibility = %i[public private protected]
669
712
  with_resolved_aliases = pins.map do |pin|
670
713
  next pin unless pin.is_a?(Pin::MethodAlias)
671
714
  resolved = resolve_method_alias(pin)
715
+ # @sg-ignore Need to add nil check here
672
716
  next nil if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
673
717
  resolved
674
718
  end.compact
675
- logger.debug { "ApiMap#resolve_method_aliases(pins=#{pins.map(&:name)}, visibility=#{visibility}) => #{with_resolved_aliases.map(&:name)}" }
676
- GemPins.combine_method_pins_by_path(with_resolved_aliases)
719
+ logger.debug do
720
+ "ApiMap#resolve_method_aliases(pins=#{pins.map(&:name)}, visibility=#{visibility}) => #{with_resolved_aliases.map(&:name)}"
721
+ end
722
+ with_resolved_aliases
723
+ end
724
+
725
+ # @return [Workspace, nil]
726
+ def workspace
727
+ doc_map.workspace
677
728
  end
678
729
 
679
730
  # @param fq_reference_tag [String] A fully qualified whose method should be pulled in
@@ -687,7 +738,7 @@ module Solargraph
687
738
  # @param skip [Set<String>]
688
739
  # @param no_core [Boolean] Skip core classes if true
689
740
  # @return [Array<Pin::Base>]
690
- def inner_get_methods_from_reference(fq_reference_tag, namespace_pin, type, scope, visibility, deep, skip, no_core)
741
+ def inner_get_methods_from_reference fq_reference_tag, namespace_pin, type, scope, visibility, deep, skip, no_core
691
742
  logger.debug { "ApiMap#add_methods_from_reference(type=#{type}) starting" }
692
743
 
693
744
  # Ensure the types returned by the methods in the referenced
@@ -743,7 +794,7 @@ module Solargraph
743
794
  def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false
744
795
  rooted_type = ComplexType.parse(rooted_tag).force_rooted
745
796
  fqns = rooted_type.namespace
746
- fqns_generic_params = rooted_type.all_params
797
+ rooted_type.all_params
747
798
  namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
748
799
  return [] if no_core && fqns =~ /^(Object|BasicObject|Class|Module)$/
749
800
  reqstr = "#{fqns}|#{scope}|#{visibility.sort}|#{deep}"
@@ -754,7 +805,9 @@ module Solargraph
754
805
  # ensure we start out with any immediate methods in this
755
806
  # namespace so we roughly match the same ordering of get_methods
756
807
  # and obey the 'deep' instruction
757
- direct_convention_methods, convention_methods_by_reference = environ.pins.partition { |p| p.namespace == rooted_tag }
808
+ direct_convention_methods, convention_methods_by_reference = environ.pins.partition do |p|
809
+ p.namespace == rooted_tag
810
+ end
758
811
  result.concat direct_convention_methods
759
812
 
760
813
  if deep && scope == :instance
@@ -766,8 +819,10 @@ module Solargraph
766
819
  # Store#get_methods doesn't know about full tags, just
767
820
  # namespaces; resolving the generics in the method pins is this
768
821
  # class' responsibility
769
- methods = store.get_methods(fqns, scope: scope, visibility: visibility).sort{ |a, b| a.name <=> b.name }
770
- logger.info { "ApiMap#inner_get_methods(rooted_tag=#{rooted_tag.inspect}, scope=#{scope.inspect}, visibility=#{visibility.inspect}, deep=#{deep.inspect}, skip=#{skip.inspect}, fqns=#{fqns}) - added from store: #{methods}" }
822
+ methods = store.get_methods(fqns, scope: scope, visibility: visibility).sort { |a, b| a.name <=> b.name }
823
+ logger.info do
824
+ "ApiMap#inner_get_methods(rooted_tag=#{rooted_tag.inspect}, scope=#{scope.inspect}, visibility=#{visibility.inspect}, deep=#{deep.inspect}, skip=#{skip.inspect}, fqns=#{fqns}) - added from store: #{methods}"
825
+ end
771
826
  result.concat methods
772
827
  if deep
773
828
  result.concat convention_methods_by_reference
@@ -775,21 +830,27 @@ module Solargraph
775
830
  if scope == :instance
776
831
  store.get_includes(fqns).reverse.each do |ref|
777
832
  in_tag = dereference(ref)
778
- result.concat inner_get_methods_from_reference(in_tag, namespace_pin, rooted_type, scope, visibility, deep, skip, true)
833
+ # @sg-ignore Need to add nil check here
834
+ result.concat inner_get_methods_from_reference(in_tag, namespace_pin, rooted_type, scope, visibility, deep,
835
+ skip, true)
779
836
  end
780
837
  rooted_sc_tag = qualify_superclass(rooted_tag)
781
838
  unless rooted_sc_tag.nil?
782
- result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope, visibility, true, skip, no_core)
839
+ result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope,
840
+ visibility, true, skip, no_core)
783
841
  end
784
842
  else
785
- logger.info { "ApiMap#inner_get_methods(#{fqns}, #{scope}, #{visibility}, #{deep}, #{skip}) - looking for get_extends() from #{fqns}" }
843
+ logger.info do
844
+ "ApiMap#inner_get_methods(#{fqns}, #{scope}, #{visibility}, #{deep}, #{skip}) - looking for get_extends() from #{fqns}"
845
+ end
786
846
  store.get_extends(fqns).reverse.each do |em|
787
847
  fqem = dereference(em)
788
848
  result.concat inner_get_methods(fqem, :instance, visibility, deep, skip, true) unless fqem.nil?
789
849
  end
790
850
  rooted_sc_tag = qualify_superclass(rooted_tag)
791
851
  unless rooted_sc_tag.nil?
792
- result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope, visibility, true, skip, true)
852
+ result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope,
853
+ visibility, true, skip, true)
793
854
  end
794
855
  unless no_core || fqns.empty?
795
856
  type = get_namespace_type(fqns)
@@ -817,7 +878,7 @@ module Solargraph
817
878
  def get_namespace_type fqns
818
879
  return nil if fqns.nil?
819
880
  # @type [Pin::Namespace, nil]
820
- pin = store.get_path_pins(fqns).select{|p| p.is_a?(Pin::Namespace)}.first
881
+ pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
821
882
  return nil if pin.nil?
822
883
  pin.type
823
884
  end
@@ -841,18 +902,21 @@ module Solargraph
841
902
 
842
903
  include Logging
843
904
 
844
- private
845
-
846
905
  # @param alias_pin [Pin::MethodAlias]
847
906
  # @return [Pin::Method, nil]
848
- def resolve_method_alias(alias_pin)
907
+ def resolve_method_alias alias_pin
849
908
  ancestors = store.get_ancestors(alias_pin.full_context.reduce_class_type.tag)
909
+ # @type [Pin::Method, nil]
850
910
  original = nil
851
911
 
852
912
  # Search each ancestor for the original method
853
913
  ancestors.each do |ancestor_fqns|
854
914
  next if ancestor_fqns.nil?
855
- ancestor_method_path = "#{ancestor_fqns}#{alias_pin.scope == :instance ? '#' : '.'}#{alias_pin.original}"
915
+ ancestor_method_path = if alias_pin.original == 'new' && alias_pin.scope == :class
916
+ "#{ancestor_fqns}#initialize"
917
+ else
918
+ "#{ancestor_fqns}#{alias_pin.scope == :instance ? '#' : '.'}#{alias_pin.original}"
919
+ end
856
920
 
857
921
  # Search for the original method in the ancestor
858
922
  original = store.get_path_pins(ancestor_method_path).find do |candidate_pin|
@@ -864,21 +928,29 @@ module Solargraph
864
928
  break resolved if resolved
865
929
  end
866
930
 
867
- candidate_pin.is_a?(Pin::Method) && candidate_pin.scope == alias_pin.scope
931
+ candidate_pin.is_a?(Pin::Method)
868
932
  end
869
933
 
870
934
  break if original
871
935
  end
936
+ if original.nil?
937
+ # :nocov:
938
+ Solargraph.assert_or_log(:alias_target_missing) do
939
+ "Rejecting alias - target is missing while looking for #{alias_pin.full_context.tag} #{alias_pin.original} in #{alias_pin.scope} scope = #{alias_pin.inspect}"
940
+ end
941
+ return nil
942
+ # :nocov:
943
+ end
872
944
 
873
945
  # @sg-ignore ignore `received nil` for original
874
- create_resolved_alias_pin(alias_pin, original) if original
946
+ create_resolved_alias_pin(alias_pin, original)
875
947
  end
876
948
 
877
949
  # Fast path for creating resolved alias pins without individual method stack lookups
878
950
  # @param alias_pin [Pin::MethodAlias] The alias pin to resolve
879
951
  # @param original [Pin::Method] The original method pin that was already found
880
952
  # @return [Pin::Method] The resolved method pin
881
- def create_resolved_alias_pin(alias_pin, original)
953
+ def create_resolved_alias_pin alias_pin, original
882
954
  # Build the resolved method pin directly (same logic as resolve_method_alias but without lookup)
883
955
  args = {
884
956
  location: alias_pin.location,
@@ -894,7 +966,7 @@ module Solargraph
894
966
  return_type: original.return_type,
895
967
  source: :resolve_method_alias
896
968
  }
897
- resolved_pin = Pin::Method.new **args
969
+ resolved_pin = Pin::Method.new(**args)
898
970
 
899
971
  # Clone signatures and parameters
900
972
  resolved_pin.signatures.each do |sig|
@@ -916,7 +988,7 @@ module Solargraph
916
988
  # @param rooted_type [ComplexType]
917
989
  # @param pins [Enumerable<Pin::Base>]
918
990
  # @return [Array<Pin::Base>]
919
- def erase_generics(namespace_pin, rooted_type, pins)
991
+ def erase_generics namespace_pin, rooted_type, pins
920
992
  return pins unless should_erase_generics_when_done?(namespace_pin, rooted_type)
921
993
 
922
994
  logger.debug("Erasing generics on namespace_pin=#{namespace_pin} / rooted_type=#{rooted_type}")
@@ -927,19 +999,29 @@ module Solargraph
927
999
 
928
1000
  # @param namespace_pin [Pin::Namespace]
929
1001
  # @param rooted_type [ComplexType]
930
- def should_erase_generics_when_done?(namespace_pin, rooted_type)
1002
+ def should_erase_generics_when_done? namespace_pin, rooted_type
931
1003
  has_generics?(namespace_pin) && !can_resolve_generics?(namespace_pin, rooted_type)
932
1004
  end
933
1005
 
934
1006
  # @param namespace_pin [Pin::Namespace, Pin::Constant]
935
- def has_generics?(namespace_pin)
1007
+ def has_generics? namespace_pin
936
1008
  namespace_pin.is_a?(Pin::Namespace) && !namespace_pin.generics.empty?
937
1009
  end
938
1010
 
939
1011
  # @param namespace_pin [Pin::Namespace]
940
1012
  # @param rooted_type [ComplexType]
941
- def can_resolve_generics?(namespace_pin, rooted_type)
1013
+ def can_resolve_generics? namespace_pin, rooted_type
942
1014
  has_generics?(namespace_pin) && !rooted_type.all_params.empty?
943
1015
  end
1016
+
1017
+ protected
1018
+
1019
+ # @todo need to model type def statement in chains as a symbol so
1020
+ # that this overload of 'protected' will typecheck @sg-ignore
1021
+ # @sg-ignore
1022
+ def equality_fields
1023
+ [self.class, @source_map_hash, conventions_environ, @doc_map, @unresolved_requires, @missing_docs,
1024
+ @loose_unions]
1025
+ end
944
1026
  end
945
1027
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
-
4
3
  module Solargraph
5
4
  # A container of source maps and workspace data to be cataloged in an ApiMap.
6
5
  #
@@ -30,11 +29,11 @@ module Solargraph
30
29
  .to_set
31
30
  end
32
31
 
32
+ # @sg-ignore flow sensitive typing needs better handling of ||= on lvars
33
33
  # @return [Hash{String => SourceMap}]
34
34
  def source_map_hash
35
35
  # @todo Work around #to_h bug in current Ruby head (3.5) with #map#to_h
36
- @source_map_hash ||= source_maps.map { |s| [s.filename, s] }
37
- .to_h
36
+ @source_map_hash ||= source_maps.to_h { |s| [s.filename, s] }
38
37
  end
39
38
 
40
39
  # @return [Set<SourceMap>]