solargraph 0.58.3 → 0.59.0.dev.1

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 (201) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +4 -5
  4. data/.github/workflows/plugins.yml +41 -38
  5. data/.github/workflows/rspec.yml +45 -13
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.gitignore +0 -1
  8. data/.rubocop_todo.yml +27 -49
  9. data/CHANGELOG.md +1 -10
  10. data/README.md +3 -3
  11. data/Rakefile +1 -0
  12. data/lib/solargraph/api_map/cache.rb +3 -3
  13. data/lib/solargraph/api_map/constants.rb +13 -3
  14. data/lib/solargraph/api_map/index.rb +22 -11
  15. data/lib/solargraph/api_map/source_to_yard.rb +13 -1
  16. data/lib/solargraph/api_map/store.rb +11 -8
  17. data/lib/solargraph/api_map.rb +105 -50
  18. data/lib/solargraph/bench.rb +45 -45
  19. data/lib/solargraph/complex_type/conformance.rb +176 -0
  20. data/lib/solargraph/complex_type/type_methods.rb +16 -2
  21. data/lib/solargraph/complex_type/unique_type.rb +170 -20
  22. data/lib/solargraph/complex_type.rb +119 -14
  23. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
  24. data/lib/solargraph/convention/data_definition/data_definition_node.rb +3 -1
  25. data/lib/solargraph/convention/data_definition.rb +4 -1
  26. data/lib/solargraph/convention/gemfile.rb +15 -15
  27. data/lib/solargraph/convention/gemspec.rb +23 -23
  28. data/lib/solargraph/convention/rakefile.rb +17 -17
  29. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
  30. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +1 -0
  31. data/lib/solargraph/convention/struct_definition.rb +5 -1
  32. data/lib/solargraph/convention.rb +78 -78
  33. data/lib/solargraph/converters/dd.rb +17 -17
  34. data/lib/solargraph/converters/dl.rb +15 -15
  35. data/lib/solargraph/converters/dt.rb +15 -15
  36. data/lib/solargraph/converters/misc.rb +1 -1
  37. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  38. data/lib/solargraph/diagnostics/rubocop.rb +1 -0
  39. data/lib/solargraph/diagnostics/rubocop_helpers.rb +2 -0
  40. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  41. data/lib/solargraph/diagnostics/update_errors.rb +41 -41
  42. data/lib/solargraph/doc_map.rb +134 -373
  43. data/lib/solargraph/equality.rb +1 -1
  44. data/lib/solargraph/gem_pins.rb +14 -15
  45. data/lib/solargraph/language_server/error_codes.rb +20 -20
  46. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  47. data/lib/solargraph/language_server/host/dispatch.rb +1 -0
  48. data/lib/solargraph/language_server/host/message_worker.rb +2 -1
  49. data/lib/solargraph/language_server/host/sources.rb +1 -0
  50. data/lib/solargraph/language_server/host.rb +6 -1
  51. data/lib/solargraph/language_server/message/base.rb +97 -97
  52. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -15
  53. data/lib/solargraph/language_server/message/completion_item/resolve.rb +60 -60
  54. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -7
  55. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  56. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  57. data/lib/solargraph/language_server/message/extended/download_core.rb +19 -19
  58. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  59. data/lib/solargraph/language_server/message/initialize.rb +191 -191
  60. data/lib/solargraph/language_server/message/text_document/completion.rb +2 -0
  61. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  62. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +16 -16
  63. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +2 -0
  64. data/lib/solargraph/language_server/message/text_document/formatting.rb +2 -0
  65. data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
  66. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -11
  67. data/lib/solargraph/language_server/message/text_document/references.rb +16 -16
  68. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -19
  69. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -0
  70. data/lib/solargraph/language_server/message/text_document/type_definition.rb +2 -0
  71. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +35 -35
  72. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +40 -40
  73. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +26 -26
  74. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -0
  75. data/lib/solargraph/language_server/message.rb +94 -94
  76. data/lib/solargraph/language_server/request.rb +27 -27
  77. data/lib/solargraph/language_server/transport/data_reader.rb +74 -74
  78. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  79. data/lib/solargraph/library.rb +59 -13
  80. data/lib/solargraph/location.rb +9 -4
  81. data/lib/solargraph/logging.rb +21 -1
  82. data/lib/solargraph/page.rb +92 -92
  83. data/lib/solargraph/parser/comment_ripper.rb +7 -0
  84. data/lib/solargraph/parser/flow_sensitive_typing.rb +330 -102
  85. data/lib/solargraph/parser/node_processor/base.rb +32 -2
  86. data/lib/solargraph/parser/node_processor.rb +7 -6
  87. data/lib/solargraph/parser/parser_gem/class_methods.rb +28 -10
  88. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
  89. data/lib/solargraph/parser/parser_gem/node_chainer.rb +31 -6
  90. data/lib/solargraph/parser/parser_gem/node_methods.rb +27 -7
  91. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  92. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +2 -0
  93. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  94. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -11
  95. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +7 -0
  96. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +37 -37
  97. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  98. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +3 -2
  99. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  100. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  101. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +2 -2
  102. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  103. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  104. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  105. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +1 -0
  106. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +12 -7
  107. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
  108. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  109. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +5 -1
  110. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  111. data/lib/solargraph/parser/parser_gem.rb +12 -12
  112. data/lib/solargraph/parser/region.rb +9 -3
  113. data/lib/solargraph/parser/snippet.rb +1 -1
  114. data/lib/solargraph/parser.rb +23 -23
  115. data/lib/solargraph/pin/base.rb +53 -21
  116. data/lib/solargraph/pin/base_variable.rb +312 -20
  117. data/lib/solargraph/pin/block.rb +26 -4
  118. data/lib/solargraph/pin/breakable.rb +5 -1
  119. data/lib/solargraph/pin/callable.rb +50 -3
  120. data/lib/solargraph/pin/closure.rb +2 -6
  121. data/lib/solargraph/pin/common.rb +20 -5
  122. data/lib/solargraph/pin/compound_statement.rb +55 -0
  123. data/lib/solargraph/pin/constant.rb +45 -45
  124. data/lib/solargraph/pin/conversions.rb +2 -1
  125. data/lib/solargraph/pin/delegated_method.rb +15 -4
  126. data/lib/solargraph/pin/documenting.rb +1 -0
  127. data/lib/solargraph/pin/instance_variable.rb +5 -1
  128. data/lib/solargraph/pin/keyword.rb +0 -4
  129. data/lib/solargraph/pin/local_variable.rb +13 -57
  130. data/lib/solargraph/pin/method.rb +90 -42
  131. data/lib/solargraph/pin/method_alias.rb +8 -0
  132. data/lib/solargraph/pin/namespace.rb +7 -1
  133. data/lib/solargraph/pin/parameter.rb +76 -13
  134. data/lib/solargraph/pin/proxy_type.rb +2 -1
  135. data/lib/solargraph/pin/reference/override.rb +1 -1
  136. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  137. data/lib/solargraph/pin/reference.rb +2 -0
  138. data/lib/solargraph/pin/search.rb +1 -0
  139. data/lib/solargraph/pin/signature.rb +8 -0
  140. data/lib/solargraph/pin/symbol.rb +1 -1
  141. data/lib/solargraph/pin/until.rb +1 -1
  142. data/lib/solargraph/pin/while.rb +1 -1
  143. data/lib/solargraph/pin.rb +2 -0
  144. data/lib/solargraph/pin_cache.rb +477 -57
  145. data/lib/solargraph/position.rb +12 -26
  146. data/lib/solargraph/range.rb +6 -6
  147. data/lib/solargraph/rbs_map/conversions.rb +33 -10
  148. data/lib/solargraph/rbs_map/core_fills.rb +84 -84
  149. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  150. data/lib/solargraph/rbs_map/stdlib_map.rb +34 -5
  151. data/lib/solargraph/rbs_map.rb +74 -20
  152. data/lib/solargraph/server_methods.rb +16 -16
  153. data/lib/solargraph/shell.rb +73 -39
  154. data/lib/solargraph/source/chain/array.rb +37 -37
  155. data/lib/solargraph/source/chain/call.rb +52 -17
  156. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  157. data/lib/solargraph/source/chain/constant.rb +2 -0
  158. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  159. data/lib/solargraph/source/chain/hash.rb +1 -0
  160. data/lib/solargraph/source/chain/if.rb +1 -0
  161. data/lib/solargraph/source/chain/instance_variable.rb +22 -1
  162. data/lib/solargraph/source/chain/link.rb +109 -109
  163. data/lib/solargraph/source/chain/literal.rb +5 -0
  164. data/lib/solargraph/source/chain/or.rb +9 -1
  165. data/lib/solargraph/source/chain/q_call.rb +11 -11
  166. data/lib/solargraph/source/chain/variable.rb +13 -13
  167. data/lib/solargraph/source/chain/z_super.rb +30 -30
  168. data/lib/solargraph/source/chain.rb +25 -22
  169. data/lib/solargraph/source/change.rb +9 -2
  170. data/lib/solargraph/source/cursor.rb +7 -1
  171. data/lib/solargraph/source/source_chainer.rb +13 -3
  172. data/lib/solargraph/source/updater.rb +4 -0
  173. data/lib/solargraph/source.rb +33 -7
  174. data/lib/solargraph/source_map/clip.rb +13 -2
  175. data/lib/solargraph/source_map/data.rb +4 -1
  176. data/lib/solargraph/source_map/mapper.rb +24 -1
  177. data/lib/solargraph/source_map.rb +14 -6
  178. data/lib/solargraph/type_checker/problem.rb +3 -1
  179. data/lib/solargraph/type_checker/rules.rb +75 -2
  180. data/lib/solargraph/type_checker.rb +111 -30
  181. data/lib/solargraph/version.rb +1 -1
  182. data/lib/solargraph/workspace/config.rb +3 -1
  183. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  184. data/lib/solargraph/workspace/require_paths.rb +1 -0
  185. data/lib/solargraph/workspace.rb +158 -16
  186. data/lib/solargraph/yard_map/helpers.rb +2 -1
  187. data/lib/solargraph/yard_map/mapper/to_method.rb +5 -1
  188. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  189. data/lib/solargraph/yard_map/mapper.rb +5 -0
  190. data/lib/solargraph/yard_tags.rb +20 -20
  191. data/lib/solargraph/yardoc.rb +33 -23
  192. data/lib/solargraph.rb +24 -3
  193. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  194. data/rbs/fills/tuple/tuple.rbs +28 -0
  195. data/rbs/shims/ast/0/node.rbs +1 -1
  196. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  197. data/solargraph.gemspec +2 -1
  198. metadata +12 -7
  199. data/lib/solargraph/type_checker/checks.rb +0 -124
  200. data/lib/solargraph/type_checker/param_def.rb +0 -37
  201. data/lib/solargraph/yard_map/to_method.rb +0 -89
@@ -1,16 +1,16 @@
1
- # frozen_string_literal: true
2
-
3
- require 'socket'
4
-
5
- module Solargraph
6
- module ServerMethods
7
- # @return [Integer]
8
- def available_port
9
- socket = Socket.new(:INET, :STREAM, 0)
10
- socket.bind(Addrinfo.tcp("127.0.0.1", 0))
11
- port = socket.local_address.ip_port
12
- socket.close
13
- port
14
- end
15
- end
16
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'socket'
4
+
5
+ module Solargraph
6
+ module ServerMethods
7
+ # @return [Integer]
8
+ def available_port
9
+ socket = Socket.new(:INET, :STREAM, 0)
10
+ socket.bind(Addrinfo.tcp("127.0.0.1", 0))
11
+ port = socket.local_address.ip_port
12
+ socket.close
13
+ port
14
+ end
15
+ end
16
+ end
@@ -3,6 +3,7 @@
3
3
  require 'benchmark'
4
4
  require 'thor'
5
5
  require 'yard'
6
+ require 'yaml'
6
7
 
7
8
  module Solargraph
8
9
  class Shell < Thor
@@ -104,20 +105,8 @@ module Solargraph
104
105
  # @param gem [String]
105
106
  # @param version [String, nil]
106
107
  def cache gem, version = nil
107
- gemspec = Gem::Specification.find_by_name(gem, version)
108
-
109
- if options[:rebuild] || !PinCache.has_yard?(gemspec)
110
- pins = GemPins.build_yard_pins(['yard-activesupport-concern'], gemspec)
111
- PinCache.serialize_yard_gem(gemspec, pins)
112
- end
113
-
114
- workspace = Solargraph::Workspace.new(Dir.pwd)
115
- rbs_map = RbsMap.from_gemspec(gemspec, workspace.rbs_collection_path, workspace.rbs_collection_config_path)
116
- if options[:rebuild] || !PinCache.has_rbs_collection?(gemspec, rbs_map.cache_key)
117
- # cache pins even if result is zero, so we don't retry building pins
118
- pins = rbs_map.pins || []
119
- PinCache.serialize_rbs_collection_gem(gemspec, rbs_map.cache_key, pins)
120
- end
108
+ gems(gem + (version ? "=#{version}" : ''))
109
+ # '
121
110
  end
122
111
 
123
112
  desc 'uncache GEM [...GEM]', "Delete specific cached gem documentation"
@@ -130,39 +119,83 @@ module Solargraph
130
119
  # @return [void]
131
120
  def uncache *gems
132
121
  raise ArgumentError, 'No gems specified.' if gems.empty?
122
+ workspace = Solargraph::Workspace.new(Dir.pwd)
123
+
133
124
  gems.each do |gem|
134
125
  if gem == 'core'
135
- PinCache.uncache_core
126
+ PinCache.uncache_core(out: $stdout)
136
127
  next
137
128
  end
138
129
 
139
130
  if gem == 'stdlib'
140
- PinCache.uncache_stdlib
131
+ PinCache.uncache_stdlib(out: $stdout)
141
132
  next
142
133
  end
143
134
 
144
- spec = Gem::Specification.find_by_name(gem)
145
- PinCache.uncache_gem(spec, out: $stdout)
135
+ spec = workspace.find_gem(gem)
136
+ raise Thor::InvocationError, "Gem '#{gem}' not found" if spec.nil?
137
+
138
+ # @sg-ignore flow sensitive typing needs to handle 'raise if'
139
+ workspace.uncache_gem(spec, out: $stdout)
146
140
  end
147
141
  end
148
142
 
149
- desc 'gems [GEM[=VERSION]]', 'Cache documentation for installed gems'
143
+ desc 'gems [GEM[=VERSION]...] [STDLIB...] [core]', 'Cache documentation for
144
+ installed libraries'
145
+ long_desc %( This command will cache the
146
+ generated type documentation for the specified libraries. While
147
+ Solargraph will generate this on the fly when needed, it takes
148
+ time. This command will generate it in advance, which can be
149
+ useful for CI scenarios.
150
+
151
+ With no arguments, it will cache all libraries in the current
152
+ workspace. If a gem or standard library name is specified, it
153
+ will cache that library's type documentation.
154
+
155
+ An equals sign after a gem will allow a specific gem version
156
+ to be cached.
157
+
158
+ The 'core' argument can be used to cache the type
159
+ documentation for the core Ruby libraries.
160
+
161
+ If the library is already cached, it will be rebuilt if the
162
+ --rebuild option is set.
163
+
164
+ Cached documentation is stored in #{PinCache.base_dir}, which
165
+ can be stored between CI runs.
166
+ )
150
167
  option :rebuild, type: :boolean, desc: 'Rebuild existing documentation', default: false
151
168
  # @param names [Array<String>]
152
169
  # @return [void]
153
170
  def gems *names
154
- api_map = ApiMap.load('.')
171
+ # print time with ms
172
+ workspace = Solargraph::Workspace.new('.')
173
+
155
174
  if names.empty?
156
- Gem::Specification.to_a.each { |spec| do_cache spec, api_map }
157
- STDERR.puts "Documentation cached for all #{Gem::Specification.count} gems."
175
+ workspace.cache_all_for_workspace!($stdout, rebuild: options[:rebuild])
158
176
  else
177
+ $stderr.puts("Caching these gems: #{names}")
159
178
  names.each do |name|
160
- spec = Gem::Specification.find_by_name(*name.split('='))
161
- do_cache spec, api_map
179
+ if name == 'core'
180
+ PinCache.cache_core(out: $stdout) if !PinCache.core? || options[:rebuild]
181
+ next
182
+ end
183
+
184
+ gemspec = workspace.find_gem(*name.split('='))
185
+ if gemspec.nil?
186
+ warn "Gem '#{name}' not found"
187
+ else
188
+ workspace.cache_gem(gemspec, rebuild: options[:rebuild], out: $stdout)
189
+ end
162
190
  rescue Gem::MissingSpecError
163
191
  warn "Gem '#{name}' not found"
192
+ rescue Gem::Requirement::BadRequirementError => e
193
+ warn "Gem '#{name}' failed while loading"
194
+ warn e.message
195
+ # @sg-ignore Need to add nil check here
196
+ warn e.backtrace.join("\n")
164
197
  end
165
- STDERR.puts "Documentation cached for #{names.count} gems."
198
+ $stderr.puts "Documentation cached for #{names.count} gems."
166
199
  end
167
200
  end
168
201
 
@@ -187,7 +220,10 @@ module Solargraph
187
220
  workspace = Solargraph::Workspace.new(directory)
188
221
  level = options[:level].to_sym
189
222
  rules = workspace.rules(level)
190
- api_map = Solargraph::ApiMap.load_with_cache(directory, $stdout)
223
+ api_map =
224
+ Solargraph::ApiMap.load_with_cache(directory, $stdout,
225
+ loose_unions:
226
+ !rules.require_all_unique_types_support_call?)
191
227
  probcount = 0
192
228
  if files.empty?
193
229
  files = api_map.source_maps.map(&:filename)
@@ -195,10 +231,9 @@ module Solargraph
195
231
  files.map! { |file| File.realpath(file) }
196
232
  end
197
233
  filecount = 0
198
-
199
234
  time = Benchmark.measure {
200
235
  files.each do |file|
201
- checker = TypeChecker.new(file, api_map: api_map, level: options[:level].to_sym, workspace: workspace)
236
+ checker = TypeChecker.new(file, api_map: api_map, rules: rules, level: options[:level].to_sym, workspace: workspace)
202
237
  problems = checker.problems
203
238
  next if problems.empty?
204
239
  problems.sort! { |a, b| a.location.range.start.line <=> b.location.range.start.line }
@@ -206,7 +241,6 @@ module Solargraph
206
241
  filecount += 1
207
242
  probcount += problems.length
208
243
  end
209
- # "
210
244
  }
211
245
  puts "Typecheck finished in #{time.real} seconds."
212
246
  puts "#{probcount} problem#{probcount != 1 ? 's' : ''} found#{files.length != 1 ? " in #{filecount} of #{files.length} files" : ''}."
@@ -230,19 +264,25 @@ module Solargraph
230
264
  api_map = nil
231
265
  time = Benchmark.measure {
232
266
  api_map = Solargraph::ApiMap.load_with_cache(directory, $stdout)
267
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
233
268
  api_map.pins.each do |pin|
234
269
  begin
235
270
  puts pin_description(pin) if options[:verbose]
236
271
  pin.typify api_map
237
272
  pin.probe api_map
238
273
  rescue StandardError => e
274
+ # @todo to add nil check here
275
+ # @todo should warn on nil dereference below
239
276
  STDERR.puts "Error testing #{pin_description(pin)} #{pin.location ? "at #{pin.location.filename}:#{pin.location.range.start.line + 1}" : ''}"
240
277
  STDERR.puts "[#{e.class}]: #{e.message}"
278
+ # @todo Need to add nil check here
279
+ # @todo flow sensitive typing should be able to handle redefinition
241
280
  STDERR.puts e.backtrace.join("\n")
242
281
  exit 1
243
282
  end
244
283
  end
245
284
  }
285
+ # @sg-ignore Need to add nil check here
246
286
  puts "Scanned #{directory} (#{api_map.pins.length} pins) in #{time.real} seconds."
247
287
  end
248
288
 
@@ -290,6 +330,7 @@ module Solargraph
290
330
  exit 1
291
331
  when Pin::Namespace
292
332
  if options[:references]
333
+ # @sg-ignore Need to add nil check here
293
334
  superclass_tag = api_map.qualify_superclass(pin.return_type.tag)
294
335
  superclass_pin = api_map.get_path_pins(superclass_tag).first if superclass_tag
295
336
  references[:superclass] = superclass_pin if superclass_pin
@@ -320,6 +361,7 @@ module Solargraph
320
361
  def pin_description pin
321
362
  desc = if pin.path.nil? || pin.path.empty?
322
363
  if pin.closure
364
+ # @sg-ignore Need to add nil check here
323
365
  "#{pin.closure.path} | #{pin.name}"
324
366
  else
325
367
  "#{pin.context.namespace} | #{pin.name}"
@@ -327,20 +369,12 @@ module Solargraph
327
369
  else
328
370
  pin.path
329
371
  end
372
+ # @sg-ignore Need to add nil check here
330
373
  desc += " (#{pin.location.filename} #{pin.location.range.start.line})" if pin.location
331
374
  desc
332
375
  end
333
376
 
334
- # @param gemspec [Gem::Specification]
335
- # @param api_map [ApiMap]
336
- # @return [void]
337
- def do_cache gemspec, api_map
338
- # @todo if the rebuild: option is passed as a positional arg,
339
- # typecheck doesn't complain on the below line
340
- api_map.cache_gem(gemspec, rebuild: options.rebuild, out: $stdout)
341
- end
342
-
343
- # @param type [ComplexType]
377
+ # @param type [ComplexType, ComplexType::UniqueType]
344
378
  # @return [void]
345
379
  def print_type(type)
346
380
  if options[:rbs]
@@ -1,37 +1,37 @@
1
- module Solargraph
2
- class Source
3
- class Chain
4
- class Array < Literal
5
- # @param children [::Array<Chain>]
6
- # @param node [Parser::AST::Node]
7
- def initialize children, node
8
- super('::Array', node)
9
- @children = children
10
- end
11
-
12
- def word
13
- @word ||= "<#{@type}>"
14
- end
15
-
16
- # @param api_map [ApiMap]
17
- # @param name_pin [Pin::Base]
18
- # @param locals [::Array<Pin::Parameter, Pin::LocalVariable>]
19
- def resolve api_map, name_pin, locals
20
- child_types = @children.map do |child|
21
- child.infer(api_map, name_pin, locals).simplify_literals
22
- end
23
- type = if child_types.length == 0 || child_types.any?(&:undefined?)
24
- ComplexType::UniqueType.new('Array', rooted: true)
25
- elsif child_types.uniq.length == 1 && child_types.first.defined?
26
- ComplexType::UniqueType.new('Array', [], child_types.uniq, rooted: true, parameters_type: :list)
27
- elsif child_types.length == 0
28
- ComplexType::UniqueType.new('Array', rooted: true, parameters_type: :list)
29
- else
30
- ComplexType::UniqueType.new('Array', [], child_types, rooted: true, parameters_type: :fixed)
31
- end
32
- [Pin::ProxyType.anonymous(type, source: :chain)]
33
- end
34
- end
35
- end
36
- end
37
- end
1
+ module Solargraph
2
+ class Source
3
+ class Chain
4
+ class Array < Literal
5
+ # @param children [::Array<Chain>]
6
+ # @param node [Parser::AST::Node]
7
+ def initialize children, node
8
+ super('::Array', node)
9
+ @children = children
10
+ end
11
+
12
+ def word
13
+ @word ||= "<#{@type}>"
14
+ end
15
+
16
+ # @param api_map [ApiMap]
17
+ # @param name_pin [Pin::Base]
18
+ # @param locals [::Array<Pin::Parameter, Pin::LocalVariable>]
19
+ def resolve api_map, name_pin, locals
20
+ child_types = @children.map do |child|
21
+ child.infer(api_map, name_pin, locals).simplify_literals
22
+ end
23
+ type = if child_types.length == 0 || child_types.any?(&:undefined?)
24
+ ComplexType::UniqueType.new('Array', rooted: true)
25
+ elsif child_types.uniq.length == 1 && child_types.first.defined?
26
+ ComplexType::UniqueType.new('Array', [], child_types.uniq, rooted: true, parameters_type: :list)
27
+ elsif child_types.length == 0
28
+ ComplexType::UniqueType.new('Array', rooted: true, parameters_type: :list)
29
+ else
30
+ ComplexType::UniqueType.new('Array', [], child_types, rooted: true, parameters_type: :fixed)
31
+ end
32
+ [Pin::ProxyType.anonymous(type, source: :chain)]
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -37,6 +37,7 @@ module Solargraph
37
37
 
38
38
  # @sg-ignore Fix "Not enough arguments to Module#protected"
39
39
  protected def equality_fields
40
+ # @sg-ignore literal arrays in this module turn into ::Solargraph::Source::Chain::Array
40
41
  super + [arguments, block]
41
42
  end
42
43
 
@@ -50,24 +51,35 @@ module Solargraph
50
51
  def resolve api_map, name_pin, locals
51
52
  return super_pins(api_map, name_pin) if word == 'super'
52
53
  return yield_pins(api_map, name_pin) if word == 'yield'
53
- found = if head?
54
- api_map.visible_pins(locals, word, name_pin, location)
55
- else
56
- []
57
- end
58
- return inferred_pins(found, api_map, name_pin, locals) unless found.empty?
59
- pins = name_pin.binder.each_unique_type.flat_map do |context|
54
+ found = api_map.var_at_location(locals, word, name_pin, location) if head?
55
+
56
+ return inferred_pins([found], api_map, name_pin, locals) unless found.nil?
57
+ binder = name_pin.binder
58
+ # this is a q_call - i.e., foo&.bar - assume result of call
59
+ # will be nil or result as if binder were not nil -
60
+ # chain.rb#maybe_nil will add the nil type later, we just
61
+ # need to worry about the not-nil case
62
+
63
+ # @sg-ignore Need to handle duck-typed method calls on union types
64
+ binder = binder.without_nil if nullable?
65
+ # @sg-ignore Need to handle duck-typed method calls on union types
66
+ pin_groups = binder.each_unique_type.map do |context|
60
67
  ns_tag = context.namespace == '' ? '' : context.namespace_type.tag
61
68
  stack = api_map.get_method_stack(ns_tag, word, scope: context.scope)
62
69
  [stack.first].compact
63
70
  end
71
+ # @sg-ignore literal arrays in this module turn into ::Solargraph::Source::Chain::Array
72
+ if !api_map.loose_unions && pin_groups.any? { |pins| pins.empty? }
73
+ pin_groups = []
74
+ end
75
+ pins = pin_groups.flatten.uniq(&:path)
64
76
  return [] if pins.empty?
65
77
  inferred_pins(pins, api_map, name_pin, locals)
66
78
  end
67
79
 
68
80
  private
69
81
 
70
- # @param pins [::Enumerable<Pin::Method>]
82
+ # @param pins [::Enumerable<Pin::Base>]
71
83
  # @param api_map [ApiMap]
72
84
  # @param name_pin [Pin::Base]
73
85
  # @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
@@ -84,9 +96,13 @@ module Solargraph
84
96
  # reject it regardless
85
97
 
86
98
  with_block, without_block = overloads.partition(&:block?)
99
+ # @sg-ignore flow sensitive typing should handle is_a? and next
100
+ # @type Array<Pin::Signature>
87
101
  sorted_overloads = with_block + without_block
88
102
  # @type [Pin::Signature, nil]
89
103
  new_signature_pin = nil
104
+ # @sg-ignore flow sensitive typing should handle is_a? and next
105
+ # @param ol [Pin::Signature]
90
106
  sorted_overloads.each do |ol|
91
107
  next unless ol.arity_matches?(arguments, with_block?)
92
108
  match = true
@@ -99,6 +115,7 @@ module Solargraph
99
115
  break
100
116
  end
101
117
  arg_name_pin = Pin::ProxyType.anonymous(name_pin.context,
118
+ closure: name_pin.closure,
102
119
  gates: name_pin.gates,
103
120
  source: :chain)
104
121
  atype = atypes[idx] ||= arg.infer(api_map, arg_name_pin, locals)
@@ -110,6 +127,7 @@ module Solargraph
110
127
  if match
111
128
  if ol.block && with_block?
112
129
  block_atypes = ol.block.parameters.map(&:return_type)
130
+ # @todo Need to add nil check here
113
131
  if block.links.map(&:class) == [BlockSymbol]
114
132
  # like the bar in foo(&:bar)
115
133
  blocktype = block_symbol_call_type(api_map, name_pin.context, block_atypes, locals)
@@ -140,6 +158,7 @@ module Solargraph
140
158
  #
141
159
  # qualify(), however, happens in the namespace where
142
160
  # the docs were written - from the method pin.
161
+ # @todo Need to add nil check here
143
162
  type = with_params(new_return_type.self_to_type(self_type), self_type).qualify(api_map, *p.gates) if new_return_type.defined?
144
163
  type ||= ComplexType::UNDEFINED
145
164
  end
@@ -149,9 +168,11 @@ module Solargraph
149
168
  next p.proxy(type) if type.defined?
150
169
  if !p.macros.empty?
151
170
  result = process_macro(p, api_map, name_pin.context, locals)
171
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
152
172
  next result unless result.return_type.undefined?
153
173
  elsif !p.directives.empty?
154
174
  result = process_directive(p, api_map, name_pin.context, locals)
175
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
155
176
  next result unless result.return_type.undefined?
156
177
  end
157
178
  p
@@ -162,8 +183,11 @@ module Solargraph
162
183
  reduced_context = name_pin.binder.reduce_class_type
163
184
  pin.proxy(reduced_context)
164
185
  else
186
+ # @sg-ignore Need to add nil check here
165
187
  next pin if pin.return_type.undefined?
188
+ # @sg-ignore Need to add nil check here
166
189
  selfy = pin.return_type.self_to_type(name_pin.binder)
190
+ # @sg-ignore Need to add nil check here
167
191
  selfy == pin.return_type ? pin : pin.proxy(selfy)
168
192
  end
169
193
  end
@@ -171,7 +195,7 @@ module Solargraph
171
195
 
172
196
  # @param pin [Pin::Base]
173
197
  # @param api_map [ApiMap]
174
- # @param context [ComplexType]
198
+ # @param context [ComplexType, ComplexType::UniqueType]
175
199
  # @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
176
200
  # @return [Pin::Base]
177
201
  def process_macro pin, api_map, context, locals
@@ -190,7 +214,7 @@ module Solargraph
190
214
 
191
215
  # @param pin [Pin::Method]
192
216
  # @param api_map [ApiMap]
193
- # @param context [ComplexType]
217
+ # @param context [ComplexType, ComplexType::UniqueType]
194
218
  # @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
195
219
  # @return [Pin::ProxyType]
196
220
  def process_directive pin, api_map, context, locals
@@ -206,21 +230,24 @@ module Solargraph
206
230
  # @param pin [Pin::Base]
207
231
  # @param macro [YARD::Tags::MacroDirective]
208
232
  # @param api_map [ApiMap]
209
- # @param context [ComplexType]
233
+ # @param context [ComplexType, ComplexType::UniqueType]
210
234
  # @param locals [::Array<Pin::LocalVariable, Pin::Parameter>]
211
235
  # @return [Pin::ProxyType]
212
236
  def inner_process_macro pin, macro, api_map, context, locals
213
237
  vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals), source: :chain) }
214
238
  txt = macro.tag.text.clone
239
+ # @sg-ignore Need to add nil check here
215
240
  if txt.empty? && macro.tag.name
216
241
  named = api_map.named_macro(macro.tag.name)
217
242
  txt = named.tag.text.clone if named
218
243
  end
219
244
  i = 1
220
245
  vals.each do |v|
246
+ # @sg-ignore Need to add nil check here
221
247
  txt.gsub!(/\$#{i}/, v.context.namespace)
222
248
  i += 1
223
249
  end
250
+ # @sg-ignore Need to add nil check here
224
251
  docstring = Solargraph::Source.parse_docstring(txt).to_docstring
225
252
  tag = docstring.tag(:return)
226
253
  unless tag.nil? || tag.types.nil?
@@ -246,6 +273,7 @@ module Solargraph
246
273
  def find_method_pin(name_pin)
247
274
  method_pin = name_pin
248
275
  until method_pin.is_a?(Pin::Method)
276
+ # @sg-ignore Need to support this in flow sensitive typing
249
277
  method_pin = method_pin.closure
250
278
  return if method_pin.nil?
251
279
  end
@@ -271,13 +299,14 @@ module Solargraph
271
299
 
272
300
  # @param signature_pin [Pin::Signature]
273
301
  method_pin.signatures.map(&:block).compact.map do |signature_pin|
302
+ # @sg-ignore Need to add nil check here
274
303
  return_type = signature_pin.return_type.qualify(api_map, *name_pin.gates)
275
304
  signature_pin.proxy(return_type)
276
305
  end
277
306
  end
278
307
 
279
308
  # @param type [ComplexType]
280
- # @param context [ComplexType]
309
+ # @param context [ComplexType, ComplexType::UniqueType]
281
310
  # @return [ComplexType]
282
311
  def with_params type, context
283
312
  return type unless type.to_s.include?('$')
@@ -291,13 +320,14 @@ module Solargraph
291
320
  end
292
321
 
293
322
  # @param api_map [ApiMap]
294
- # @param context [ComplexType]
323
+ # @param context [ComplexType, ComplexType::UniqueType]
295
324
  # @param block_parameter_types [::Array<ComplexType>]
296
325
  # @param locals [::Array<Pin::LocalVariable>]
297
326
  # @return [ComplexType, nil]
298
327
  def block_symbol_call_type(api_map, context, block_parameter_types, locals)
299
328
  # Ruby's shorthand for sending the passed in method name
300
329
  # to the first yield parameter with no arguments
330
+ # @sg-ignore Need to add nil check here
301
331
  block_symbol_name = block.links.first.word
302
332
  block_symbol_call_path = "#{block_parameter_types.first}##{block_symbol_name}"
303
333
  callee = api_map.get_path_pins(block_symbol_call_path).first
@@ -305,6 +335,7 @@ module Solargraph
305
335
  # @todo: Figure out why we get unresolved generics at
306
336
  # this point and need to assume method return types
307
337
  # based on the generic type
338
+ # @sg-ignore Need to add nil check here
308
339
  return_type ||= api_map.get_path_pins("#{context.subtypes.first}##{block.links.first.word}").first&.return_type
309
340
  return_type || ComplexType::UNDEFINED
310
341
  end
@@ -312,9 +343,11 @@ module Solargraph
312
343
  # @param api_map [ApiMap]
313
344
  # @return [Pin::Block, nil]
314
345
  def find_block_pin(api_map)
346
+ # @sg-ignore Need to add nil check here
315
347
  node_location = Solargraph::Location.from_node(block.node)
316
- return if node_location.nil?
348
+ return if node_location.nil?
317
349
  block_pins = api_map.get_block_pins
350
+ # @sg-ignore Need to add nil check here
318
351
  block_pins.find { |pin| pin.location.contain?(node_location) }
319
352
  end
320
353
 
@@ -326,10 +359,12 @@ module Solargraph
326
359
  def block_call_type(api_map, name_pin, locals)
327
360
  return nil unless with_block?
328
361
 
329
- block_context_pin = name_pin
330
362
  block_pin = find_block_pin(api_map)
331
- block_context_pin = block_pin.closure if block_pin
332
- block.infer(api_map, block_context_pin, locals)
363
+ # We use the block pin as the closure, as the parameters
364
+ # here will only be defined inside the block itself and we
365
+ # need to be able to see them
366
+ # @sg-ignore Need to add nil check here
367
+ block.infer(api_map, block_pin, locals)
333
368
  end
334
369
  end
335
370
  end
@@ -1,13 +1,13 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- class Source
5
- class Chain
6
- class ClassVariable < Link
7
- def resolve api_map, name_pin, locals
8
- api_map.get_class_variable_pins(name_pin.context.namespace).select{|p| p.name == word}
9
- end
10
- end
11
- end
12
- end
13
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class Source
5
+ class Chain
6
+ class ClassVariable < Link
7
+ def resolve api_map, name_pin, locals
8
+ api_map.get_class_variable_pins(name_pin.context.namespace).select{|p| p.name == word}
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -17,7 +17,9 @@ module Solargraph
17
17
  base = word
18
18
  gates = name_pin.gates
19
19
  end
20
+ # @sg-ignore Need to add nil check here
20
21
  fqns = api_map.resolve(base, gates)
22
+ # @sg-ignore Need to add nil check here
21
23
  api_map.get_path_pins(fqns)
22
24
  end
23
25
  end
@@ -1,13 +1,13 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- class Source
5
- class Chain
6
- class GlobalVariable < Link
7
- def resolve api_map, name_pin, locals
8
- api_map.get_global_variable_pins.select{|p| p.name == word}
9
- end
10
- end
11
- end
12
- end
13
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class Source
5
+ class Chain
6
+ class GlobalVariable < Link
7
+ def resolve api_map, name_pin, locals
8
+ api_map.get_global_variable_pins.select{|p| p.name == word}
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -14,6 +14,7 @@ module Solargraph
14
14
 
15
15
  # @sg-ignore Fix "Not enough arguments to Module#protected"
16
16
  protected def equality_fields
17
+ # @sg-ignore literal arrays in this module turn into ::Solargraph::Source::Chain::Array
17
18
  super + [@splatted]
18
19
  end
19
20
 
@@ -15,6 +15,7 @@ module Solargraph
15
15
 
16
16
  # @sg-ignore Fix "Not enough arguments to Module#protected"
17
17
  protected def equality_fields
18
+ # @sg-ignore literal arrays in this module turn into ::Solargraph::Source::Chain::Array
18
19
  super + [@links]
19
20
  end
20
21
 
@@ -4,9 +4,30 @@ module Solargraph
4
4
  class Source
5
5
  class Chain
6
6
  class InstanceVariable < Link
7
+ # @param word [String]
8
+ # @param node [Parser::AST::Node, nil] The node representing the variable
9
+ # @param location [Location, nil] The location of the variable reference in the source
10
+ def initialize word, node, location
11
+ super(word)
12
+ @node = node
13
+ @location = location
14
+ end
15
+
16
+ # @sg-ignore Declared return type
17
+ # ::Array<::Solargraph::Pin::Base> does not match inferred
18
+ # type ::Array<::Solargraph::Pin::BaseVariable, ::NilClass>
19
+ # for Solargraph::Source::Chain::InstanceVariable#resolve
7
20
  def resolve api_map, name_pin, locals
8
- api_map.get_instance_variable_pins(name_pin.binder.namespace, name_pin.binder.scope).select{|p| p.name == word}
21
+ ivars = api_map.get_instance_variable_pins(name_pin.context.namespace, name_pin.context.scope).select{|p| p.name == word}
22
+ out = api_map.var_at_location(ivars, word, name_pin, location)
23
+ [out].compact
9
24
  end
25
+
26
+ private
27
+
28
+ # @todo: Missed nil violation
29
+ # @return [Location]
30
+ attr_reader :location
10
31
  end
11
32
  end
12
33
  end