solargraph 0.50.0 → 0.58.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 (264) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.github/workflows/linting.yml +127 -0
  4. data/.github/workflows/plugins.yml +218 -0
  5. data/.github/workflows/rspec.yml +58 -12
  6. data/.github/workflows/typecheck.yml +39 -0
  7. data/.gitignore +8 -0
  8. data/.overcommit.yml +72 -0
  9. data/.rspec +1 -0
  10. data/.rubocop.yml +66 -0
  11. data/.rubocop_todo.yml +1279 -0
  12. data/.yardopts +3 -2
  13. data/CHANGELOG.md +306 -3
  14. data/README.md +29 -18
  15. data/Rakefile +125 -13
  16. data/SPONSORS.md +2 -9
  17. data/bin/solargraph +3 -0
  18. data/lib/solargraph/api_map/cache.rb +110 -70
  19. data/lib/solargraph/api_map/constants.rb +279 -0
  20. data/lib/solargraph/api_map/index.rb +193 -0
  21. data/lib/solargraph/api_map/source_to_yard.rb +97 -81
  22. data/lib/solargraph/api_map/store.rb +384 -268
  23. data/lib/solargraph/api_map.rb +945 -704
  24. data/lib/solargraph/bench.rb +21 -3
  25. data/lib/solargraph/complex_type/type_methods.rb +228 -134
  26. data/lib/solargraph/complex_type/unique_type.rb +482 -132
  27. data/lib/solargraph/complex_type.rb +444 -254
  28. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  29. data/lib/solargraph/convention/base.rb +20 -3
  30. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  31. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  32. data/lib/solargraph/convention/data_definition.rb +105 -0
  33. data/lib/solargraph/convention/gemspec.rb +3 -2
  34. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
  35. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
  36. data/lib/solargraph/convention/struct_definition.rb +164 -0
  37. data/lib/solargraph/convention.rb +36 -7
  38. data/lib/solargraph/converters/dd.rb +5 -0
  39. data/lib/solargraph/converters/dl.rb +3 -0
  40. data/lib/solargraph/converters/dt.rb +3 -0
  41. data/lib/solargraph/diagnostics/require_not_found.rb +53 -53
  42. data/lib/solargraph/diagnostics/rubocop.rb +118 -112
  43. data/lib/solargraph/diagnostics/rubocop_helpers.rb +68 -65
  44. data/lib/solargraph/diagnostics/type_check.rb +55 -54
  45. data/lib/solargraph/diagnostics.rb +2 -2
  46. data/lib/solargraph/doc_map.rb +439 -0
  47. data/lib/solargraph/environ.rb +9 -2
  48. data/lib/solargraph/equality.rb +34 -0
  49. data/lib/solargraph/gem_pins.rb +98 -0
  50. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  51. data/lib/solargraph/language_server/host/dispatch.rb +130 -111
  52. data/lib/solargraph/language_server/host/message_worker.rb +112 -59
  53. data/lib/solargraph/language_server/host/sources.rb +99 -156
  54. data/lib/solargraph/language_server/host.rb +878 -869
  55. data/lib/solargraph/language_server/message/base.rb +20 -12
  56. data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
  57. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +114 -100
  58. data/lib/solargraph/language_server/message/extended/document.rb +23 -20
  59. data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
  60. data/lib/solargraph/language_server/message/initialize.rb +28 -1
  61. data/lib/solargraph/language_server/message/initialized.rb +1 -0
  62. data/lib/solargraph/language_server/message/text_document/completion.rb +56 -59
  63. data/lib/solargraph/language_server/message/text_document/definition.rb +40 -38
  64. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +26 -23
  65. data/lib/solargraph/language_server/message/text_document/formatting.rb +148 -126
  66. data/lib/solargraph/language_server/message/text_document/hover.rb +58 -56
  67. data/lib/solargraph/language_server/message/text_document/signature_help.rb +24 -24
  68. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -0
  69. data/lib/solargraph/language_server/message/text_document.rb +1 -1
  70. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
  71. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  72. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -23
  73. data/lib/solargraph/language_server/message.rb +1 -0
  74. data/lib/solargraph/language_server/progress.rb +143 -0
  75. data/lib/solargraph/language_server/request.rb +4 -1
  76. data/lib/solargraph/language_server/transport/adapter.rb +16 -1
  77. data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
  78. data/lib/solargraph/language_server.rb +1 -0
  79. data/lib/solargraph/library.rb +683 -551
  80. data/lib/solargraph/location.rb +82 -37
  81. data/lib/solargraph/logging.rb +37 -27
  82. data/lib/solargraph/page.rb +9 -0
  83. data/lib/solargraph/parser/comment_ripper.rb +69 -52
  84. data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
  85. data/lib/solargraph/parser/node_processor/base.rb +92 -77
  86. data/lib/solargraph/parser/node_processor.rb +62 -43
  87. data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +149 -135
  88. data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +4 -1
  89. data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +166 -148
  90. data/lib/solargraph/parser/{legacy → parser_gem}/node_methods.rb +486 -325
  91. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +3 -2
  92. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -0
  93. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +59 -0
  94. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +15 -15
  95. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +46 -42
  96. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +4 -3
  97. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +3 -2
  98. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/def_node.rb +53 -63
  99. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +4 -3
  100. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +3 -2
  101. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
  102. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +40 -38
  103. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +29 -28
  104. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +59 -0
  105. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +10 -9
  106. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -0
  107. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +17 -16
  108. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +38 -36
  109. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sclass_node.rb +52 -42
  110. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +291 -257
  111. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/sym_node.rb +4 -2
  112. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
  113. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
  114. data/lib/solargraph/parser/parser_gem/node_processors.rb +70 -0
  115. data/lib/solargraph/parser/parser_gem.rb +12 -0
  116. data/lib/solargraph/parser/region.rb +69 -66
  117. data/lib/solargraph/parser/snippet.rb +17 -13
  118. data/lib/solargraph/parser.rb +9 -12
  119. data/lib/solargraph/pin/base.rb +729 -299
  120. data/lib/solargraph/pin/base_variable.rb +126 -84
  121. data/lib/solargraph/pin/block.rb +104 -73
  122. data/lib/solargraph/pin/breakable.rb +9 -0
  123. data/lib/solargraph/pin/callable.rb +231 -0
  124. data/lib/solargraph/pin/closure.rb +72 -37
  125. data/lib/solargraph/pin/common.rb +79 -70
  126. data/lib/solargraph/pin/constant.rb +2 -0
  127. data/lib/solargraph/pin/conversions.rb +123 -92
  128. data/lib/solargraph/pin/delegated_method.rb +120 -0
  129. data/lib/solargraph/pin/documenting.rb +114 -105
  130. data/lib/solargraph/pin/instance_variable.rb +34 -30
  131. data/lib/solargraph/pin/keyword.rb +20 -15
  132. data/lib/solargraph/pin/local_variable.rb +75 -55
  133. data/lib/solargraph/pin/method.rb +672 -335
  134. data/lib/solargraph/pin/method_alias.rb +34 -31
  135. data/lib/solargraph/pin/namespace.rb +115 -94
  136. data/lib/solargraph/pin/parameter.rb +275 -206
  137. data/lib/solargraph/pin/proxy_type.rb +39 -29
  138. data/lib/solargraph/pin/reference/override.rb +47 -29
  139. data/lib/solargraph/pin/reference/require.rb +2 -2
  140. data/lib/solargraph/pin/reference/superclass.rb +15 -10
  141. data/lib/solargraph/pin/reference.rb +39 -14
  142. data/lib/solargraph/pin/search.rb +61 -56
  143. data/lib/solargraph/pin/signature.rb +61 -23
  144. data/lib/solargraph/pin/singleton.rb +1 -1
  145. data/lib/solargraph/pin/symbol.rb +53 -47
  146. data/lib/solargraph/pin/until.rb +18 -0
  147. data/lib/solargraph/pin/while.rb +18 -0
  148. data/lib/solargraph/pin.rb +44 -38
  149. data/lib/solargraph/pin_cache.rb +245 -0
  150. data/lib/solargraph/position.rb +132 -100
  151. data/lib/solargraph/range.rb +112 -95
  152. data/lib/solargraph/rbs_map/conversions.rb +823 -394
  153. data/lib/solargraph/rbs_map/core_fills.rb +53 -30
  154. data/lib/solargraph/rbs_map/core_map.rb +58 -38
  155. data/lib/solargraph/rbs_map/stdlib_map.rb +43 -36
  156. data/lib/solargraph/rbs_map.rb +163 -73
  157. data/lib/solargraph/shell.rb +352 -244
  158. data/lib/solargraph/source/chain/array.rb +37 -0
  159. data/lib/solargraph/source/chain/block_symbol.rb +13 -0
  160. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  161. data/lib/solargraph/source/chain/call.rb +337 -215
  162. data/lib/solargraph/source/chain/constant.rb +26 -75
  163. data/lib/solargraph/source/chain/hash.rb +34 -28
  164. data/lib/solargraph/source/chain/head.rb +1 -1
  165. data/lib/solargraph/source/chain/if.rb +28 -0
  166. data/lib/solargraph/source/chain/instance_variable.rb +13 -13
  167. data/lib/solargraph/source/chain/link.rb +44 -6
  168. data/lib/solargraph/source/chain/literal.rb +48 -23
  169. data/lib/solargraph/source/chain/or.rb +23 -23
  170. data/lib/solargraph/source/chain/z_super.rb +4 -4
  171. data/lib/solargraph/source/chain.rb +291 -179
  172. data/lib/solargraph/source/change.rb +82 -79
  173. data/lib/solargraph/source/cursor.rb +166 -164
  174. data/lib/solargraph/source/encoding_fixes.rb +23 -23
  175. data/lib/solargraph/source/source_chainer.rb +194 -191
  176. data/lib/solargraph/source/updater.rb +55 -54
  177. data/lib/solargraph/source.rb +498 -522
  178. data/lib/solargraph/source_map/clip.rb +226 -229
  179. data/lib/solargraph/source_map/data.rb +34 -0
  180. data/lib/solargraph/source_map/mapper.rb +259 -243
  181. data/lib/solargraph/source_map.rb +212 -180
  182. data/lib/solargraph/type_checker/checks.rb +124 -112
  183. data/lib/solargraph/type_checker/param_def.rb +37 -35
  184. data/lib/solargraph/type_checker/problem.rb +32 -32
  185. data/lib/solargraph/type_checker/rules.rb +84 -57
  186. data/lib/solargraph/type_checker.rb +814 -549
  187. data/lib/solargraph/version.rb +5 -5
  188. data/lib/solargraph/views/_method.erb +10 -10
  189. data/lib/solargraph/views/_namespace.erb +3 -3
  190. data/lib/solargraph/views/document.erb +10 -10
  191. data/lib/solargraph/views/environment.erb +3 -5
  192. data/lib/solargraph/workspace/config.rb +255 -231
  193. data/lib/solargraph/workspace/require_paths.rb +97 -0
  194. data/lib/solargraph/workspace.rb +220 -212
  195. data/lib/solargraph/yard_map/cache.rb +6 -0
  196. data/lib/solargraph/yard_map/helpers.rb +44 -16
  197. data/lib/solargraph/yard_map/mapper/to_constant.rb +8 -5
  198. data/lib/solargraph/yard_map/mapper/to_method.rb +130 -81
  199. data/lib/solargraph/yard_map/mapper/to_namespace.rb +31 -27
  200. data/lib/solargraph/yard_map/mapper.rb +79 -77
  201. data/lib/solargraph/yard_map/to_method.rb +89 -79
  202. data/lib/solargraph/yard_map.rb +1 -284
  203. data/lib/solargraph/yard_tags.rb +20 -0
  204. data/lib/solargraph/yardoc.rb +87 -0
  205. data/lib/solargraph.rb +105 -69
  206. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  207. data/rbs/fills/open3/0/open3.rbs +172 -0
  208. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  209. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  210. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  211. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  212. data/rbs/fills/tuple/tuple.rbs +149 -0
  213. data/rbs/shims/ast/0/node.rbs +5 -0
  214. data/rbs/shims/ast/2.4/.rbs_meta.yaml +9 -0
  215. data/rbs/shims/ast/2.4/ast.rbs +73 -0
  216. data/rbs/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  217. data/rbs/shims/parser/3.2.0.1/manifest.yaml +7 -0
  218. data/rbs/shims/parser/3.2.0.1/parser.rbs +201 -0
  219. data/rbs/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  220. data/rbs/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  221. data/rbs/shims/thor/1.2.0.1/manifest.yaml +7 -0
  222. data/rbs/shims/thor/1.2.0.1/thor.rbs +17 -0
  223. data/rbs_collection.yaml +19 -0
  224. data/solargraph.gemspec +39 -11
  225. metadata +354 -97
  226. data/lib/.rubocop.yml +0 -22
  227. data/lib/solargraph/api_map/bundler_methods.rb +0 -22
  228. data/lib/solargraph/cache.rb +0 -53
  229. data/lib/solargraph/convention/rspec.rb +0 -30
  230. data/lib/solargraph/documentor.rb +0 -76
  231. data/lib/solargraph/language_server/host/cataloger.rb +0 -56
  232. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
  233. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -35
  234. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
  235. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
  236. data/lib/solargraph/parser/legacy/node_processors.rb +0 -54
  237. data/lib/solargraph/parser/legacy.rb +0 -12
  238. data/lib/solargraph/parser/node_methods.rb +0 -43
  239. data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -149
  240. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
  241. data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -315
  242. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
  243. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
  244. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -33
  245. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
  246. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
  247. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
  248. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
  249. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
  250. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
  251. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
  252. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
  253. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
  254. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
  255. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
  256. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -45
  257. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -32
  258. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
  259. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
  260. data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -63
  261. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
  262. data/lib/solargraph/parser/rubyvm.rb +0 -40
  263. data/lib/solargraph/rbs_map/core_signs.rb +0 -33
  264. data/lib/yard-solargraph.rb +0 -33
@@ -5,7 +5,7 @@ module Solargraph
5
5
  class Chain
6
6
  class BlockVariable < Link
7
7
  def resolve api_map, name_pin, locals
8
- [Pin::ProxyType.anonymous(ComplexType.try_parse('Proc'))]
8
+ [Pin::ProxyType.anonymous(ComplexType.try_parse('::Proc'), source: :chain)]
9
9
  end
10
10
  end
11
11
  end
@@ -1,215 +1,337 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- class Source
5
- class Chain
6
- class Call < Link
7
- # @return [String]
8
- attr_reader :word
9
-
10
- # @return [Array<Chain>]
11
- attr_reader :arguments
12
-
13
- # @param word [String]
14
- # @param arguments [Array<Chain>]
15
- # @param with_block [Boolean] True if the chain is inside a block
16
- # @param head [Boolean] True if the call is the start of its chain
17
- def initialize word, arguments = [], with_block = false
18
- @word = word
19
- @arguments = arguments
20
- @with_block = with_block
21
- end
22
-
23
- def with_block?
24
- @with_block
25
- end
26
-
27
- # @param api_map [ApiMap]
28
- # @param name_pin [Pin::Base]
29
- # @param locals [Array<Pin::Base>]
30
- def resolve api_map, name_pin, locals
31
- return super_pins(api_map, name_pin) if word == 'super'
32
- found = if head?
33
- locals.select { |p| p.name == word }
34
- else
35
- []
36
- end
37
- return inferred_pins(found, api_map, name_pin.context, locals) unless found.empty?
38
- # @param [ComplexType::UniqueType]
39
- pins = name_pin.binder.each_unique_type.flat_map do |context|
40
- api_map.get_method_stack(context.namespace, word, scope: context.scope)
41
- end
42
- return [] if pins.empty?
43
- inferred_pins(pins, api_map, name_pin.context, locals)
44
- end
45
-
46
- private
47
-
48
- # @param pins [Array<Pin::Base>]
49
- # @param api_map [ApiMap]
50
- # @param context [ComplexType]
51
- # @param locals [Pin::LocalVariable]
52
- # @return [Array<Pin::Base>]
53
- def inferred_pins pins, api_map, context, locals
54
- result = pins.map do |p|
55
- next p unless p.is_a?(Pin::Method)
56
- overloads = p.signatures
57
- # next p if overloads.empty?
58
- type = ComplexType::UNDEFINED
59
- overloads.each do |ol|
60
- next unless arguments_match(arguments, ol)
61
- # next if ol.parameters.last && ol.parameters.last.first.start_with?('&') && ol.parameters.last.last.nil? && !with_block?
62
- match = true
63
- arguments.each_with_index do |arg, idx|
64
- param = ol.parameters[idx]
65
- if param.nil?
66
- match = false unless ol.parameters.any?(&:restarg?)
67
- break
68
- end
69
- atype = arg.infer(api_map, Pin::ProxyType.anonymous(context), locals)
70
- # @todo Weak type comparison
71
- # unless atype.tag == param.return_type.tag || api_map.super_and_sub?(param.return_type.tag, atype.tag)
72
- unless param.return_type.undefined? || atype.name == param.return_type.name || api_map.super_and_sub?(param.return_type.name, atype.name)
73
- match = false
74
- break
75
- end
76
- end
77
- if match
78
- type = extra_return_type(p.docstring, context)
79
- break if type
80
- type = with_params(ol.return_type.self_to(context.to_s), context).qualify(api_map, context.namespace) if ol.return_type.defined?
81
- type ||= ComplexType::UNDEFINED
82
- end
83
- break if type.defined?
84
- end
85
- next p.proxy(type) if type.defined?
86
- type = extra_return_type(p.docstring, context)
87
- if type
88
- next Solargraph::Pin::Method.new(
89
- location: p.location,
90
- closure: p.closure,
91
- name: p.name,
92
- comments: "@return [#{context.subtypes.first.to_s}]",
93
- scope: p.scope,
94
- visibility: p.visibility,
95
- parameters: p.parameters,
96
- node: p.node
97
- )
98
- end
99
- if p.is_a?(Pin::Method) && !p.macros.empty?
100
- result = process_macro(p, api_map, context, locals)
101
- next result unless result.return_type.undefined?
102
- elsif !p.directives.empty?
103
- result = process_directive(p, api_map, context, locals)
104
- next result unless result.return_type.undefined?
105
- end
106
- p
107
- end
108
- result.map do |pin|
109
- if pin.path == 'Class#new' && context.tag != 'Class'
110
- pin.proxy(ComplexType.try_parse(context.namespace))
111
- else
112
- next pin if pin.return_type.undefined?
113
- selfy = pin.return_type.self_to(context.tag)
114
- selfy == pin.return_type ? pin : pin.proxy(selfy)
115
- end
116
- end
117
- end
118
-
119
- # @param pin [Pin::Method]
120
- # @param api_map [ApiMap]
121
- # @param context [ComplexType]
122
- # @param locals [Pin::Base]
123
- # @return [Pin::Base]
124
- def process_macro pin, api_map, context, locals
125
- pin.macros.each do |macro|
126
- result = inner_process_macro(pin, macro, api_map, context, locals)
127
- return result unless result.return_type.undefined?
128
- end
129
- Pin::ProxyType.anonymous(ComplexType::UNDEFINED)
130
- end
131
-
132
- # @param pin [Pin::Method]
133
- # @param api_map [ApiMap]
134
- # @param context [ComplexType]
135
- # @param locals [Pin::Base]
136
- # @return [Pin::ProxyType]
137
- def process_directive pin, api_map, context, locals
138
- pin.directives.each do |dir|
139
- macro = api_map.named_macro(dir.tag.name)
140
- next if macro.nil?
141
- result = inner_process_macro(pin, macro, api_map, context, locals)
142
- return result unless result.return_type.undefined?
143
- end
144
- Pin::ProxyType.anonymous ComplexType::UNDEFINED
145
- end
146
-
147
- # @param pin [Pin]
148
- # @param macro [YARD::Tags::MacroDirective]
149
- # @param api_map [ApiMap]
150
- # @param context [ComplexType]
151
- # @param locals [Array<Pin::Base>]
152
- # @return [Pin::ProxyType]
153
- def inner_process_macro pin, macro, api_map, context, locals
154
- vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
155
- txt = macro.tag.text.clone
156
- if txt.empty? && macro.tag.name
157
- named = api_map.named_macro(macro.tag.name)
158
- txt = named.tag.text.clone if named
159
- end
160
- i = 1
161
- vals.each do |v|
162
- txt.gsub!(/\$#{i}/, v.context.namespace)
163
- i += 1
164
- end
165
- docstring = Solargraph::Source.parse_docstring(txt).to_docstring
166
- tag = docstring.tag(:return)
167
- unless tag.nil? || tag.types.nil?
168
- return Pin::ProxyType.anonymous(ComplexType.try_parse(*tag.types))
169
- end
170
- Pin::ProxyType.anonymous(ComplexType::UNDEFINED)
171
- end
172
-
173
- # @param docstring [YARD::Docstring]
174
- # @param context [ComplexType]
175
- # @return [ComplexType]
176
- def extra_return_type docstring, context
177
- if docstring.has_tag?(:return_single_parameter) #&& context.subtypes.one?
178
- return context.subtypes.first || ComplexType::UNDEFINED
179
- elsif docstring.has_tag?(:return_value_parameter) && context.value_types.one?
180
- return context.value_types.first
181
- end
182
- nil
183
- end
184
-
185
- # @param arguments [Array<Chain>]
186
- # @param signature [Pin::Signature]
187
- # @return [Boolean]
188
- def arguments_match arguments, signature
189
- parameters = signature.parameters
190
- argcount = arguments.length
191
- parcount = parameters.length
192
- parcount -= 1 if !parameters.empty? && parameters.last.block?
193
- return false if signature.block? && !with_block?
194
- return false if argcount < parcount && !(argcount == parcount - 1 && parameters.last.restarg?)
195
- true
196
- end
197
-
198
- # @param api_map [ApiMap]
199
- # @param name_pin [Pin::Base]
200
- # @return [Array<Pin::Base>]
201
- def super_pins api_map, name_pin
202
- pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.context.scope)
203
- pins.reject{|p| p.path == name_pin.path}
204
- end
205
-
206
- # @param type [ComplexType]
207
- # @param context [ComplexType]
208
- def with_params type, context
209
- return type unless type.to_s.include?('$')
210
- ComplexType.try_parse(type.to_s.gsub('$', context.value_types.map(&:tag).join(', ')).gsub('<>', ''))
211
- end
212
- end
213
- end
214
- end
215
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class Source
5
+ class Chain
6
+ #
7
+ # Handles both method calls and local variable references by
8
+ # first looking for a variable with the name 'word', then
9
+ # proceeding to method signature resolution if not found.
10
+ #
11
+ class Call < Chain::Link
12
+ include Solargraph::Parser::NodeMethods
13
+
14
+ # @return [String]
15
+ attr_reader :word
16
+
17
+ # @return [Location]
18
+ attr_reader :location
19
+
20
+ # @return [::Array<Chain>]
21
+ attr_reader :arguments
22
+
23
+ # @return [Chain, nil]
24
+ attr_reader :block
25
+
26
+ # @param word [String]
27
+ # @param location [Location, nil]
28
+ # @param arguments [::Array<Chain>]
29
+ # @param block [Chain, nil]
30
+ def initialize word, location = nil, arguments = [], block = nil
31
+ @word = word
32
+ @location = location
33
+ @arguments = arguments
34
+ @block = block
35
+ fix_block_pass
36
+ end
37
+
38
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
39
+ protected def equality_fields
40
+ super + [arguments, block]
41
+ end
42
+
43
+ def with_block?
44
+ !!@block
45
+ end
46
+
47
+ # @param api_map [ApiMap]
48
+ # @param name_pin [Pin::Closure] name_pin.binder should give us the type of the object on which 'word' will be invoked
49
+ # @param locals [::Array<Pin::LocalVariable>]
50
+ def resolve api_map, name_pin, locals
51
+ return super_pins(api_map, name_pin) if word == 'super'
52
+ 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|
60
+ ns_tag = context.namespace == '' ? '' : context.namespace_type.tag
61
+ stack = api_map.get_method_stack(ns_tag, word, scope: context.scope)
62
+ [stack.first].compact
63
+ end
64
+ return [] if pins.empty?
65
+ inferred_pins(pins, api_map, name_pin, locals)
66
+ end
67
+
68
+ private
69
+
70
+ # @param pins [::Enumerable<Pin::Method>]
71
+ # @param api_map [ApiMap]
72
+ # @param name_pin [Pin::Base]
73
+ # @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
74
+ # @return [::Array<Pin::Base>]
75
+ def inferred_pins pins, api_map, name_pin, locals
76
+ result = pins.map do |p|
77
+ next p unless p.is_a?(Pin::Method)
78
+ overloads = p.signatures
79
+ # next p if overloads.empty?
80
+ type = ComplexType::UNDEFINED
81
+ # start with overloads that require blocks; if we are
82
+ # passing a block, we want to find a signature that will
83
+ # use it. If we didn't pass a block, the logic below will
84
+ # reject it regardless
85
+
86
+ with_block, without_block = overloads.partition(&:block?)
87
+ sorted_overloads = with_block + without_block
88
+ # @type [Pin::Signature, nil]
89
+ new_signature_pin = nil
90
+ sorted_overloads.each do |ol|
91
+ next unless ol.arity_matches?(arguments, with_block?)
92
+ match = true
93
+
94
+ atypes = []
95
+ arguments.each_with_index do |arg, idx|
96
+ param = ol.parameters[idx]
97
+ if param.nil?
98
+ match = ol.parameters.any?(&:restarg?)
99
+ break
100
+ end
101
+ arg_name_pin = Pin::ProxyType.anonymous(name_pin.context,
102
+ gates: name_pin.gates,
103
+ source: :chain)
104
+ atype = atypes[idx] ||= arg.infer(api_map, arg_name_pin, locals)
105
+ unless param.compatible_arg?(atype, api_map) || param.restarg?
106
+ match = false
107
+ break
108
+ end
109
+ end
110
+ if match
111
+ if ol.block && with_block?
112
+ block_atypes = ol.block.parameters.map(&:return_type)
113
+ if block.links.map(&:class) == [BlockSymbol]
114
+ # like the bar in foo(&:bar)
115
+ blocktype = block_symbol_call_type(api_map, name_pin.context, block_atypes, locals)
116
+ else
117
+ blocktype = block_call_type(api_map, name_pin, locals)
118
+ end
119
+ end
120
+ # @type new_signature_pin [Pin::Signature]
121
+ new_signature_pin = ol.resolve_generics_from_context_until_complete(ol.generics, atypes, nil, nil, blocktype)
122
+ new_return_type = new_signature_pin.return_type
123
+ if head?
124
+ # If we're at the head of the chain, we called a
125
+ # method somewhere that marked itself as returning
126
+ # self. Given we didn't invoke this on an object,
127
+ # this must be a method in this same class - so we
128
+ # use our own self type
129
+ self_type = name_pin.context
130
+ else
131
+ # if we're past the head in the chain, whatever the
132
+ # type of the lhs side is what 'self' will be in its
133
+ # declaration - we can't just use the type of the
134
+ # method pin, as this might be a subclass of the
135
+ # place where the method is defined
136
+ self_type = name_pin.binder
137
+ end
138
+ # This same logic applies to the YARD work done by
139
+ # 'with_params()'.
140
+ #
141
+ # qualify(), however, happens in the namespace where
142
+ # the docs were written - from the method pin.
143
+ type = with_params(new_return_type.self_to_type(self_type), self_type).qualify(api_map, *p.gates) if new_return_type.defined?
144
+ type ||= ComplexType::UNDEFINED
145
+ end
146
+ break if type.defined?
147
+ end
148
+ p = p.with_single_signature(new_signature_pin) unless new_signature_pin.nil?
149
+ next p.proxy(type) if type.defined?
150
+ if !p.macros.empty?
151
+ result = process_macro(p, api_map, name_pin.context, locals)
152
+ next result unless result.return_type.undefined?
153
+ elsif !p.directives.empty?
154
+ result = process_directive(p, api_map, name_pin.context, locals)
155
+ next result unless result.return_type.undefined?
156
+ end
157
+ p
158
+ end
159
+ logger.debug { "Call#inferred_pins(name_pin.binder=#{name_pin.binder}, word=#{word}, pins=#{pins.map(&:desc)}, name_pin=#{name_pin}) - result=#{result}" }
160
+ out = result.map do |pin|
161
+ if pin.path == 'Class#new' && name_pin.binder.tag != 'Class'
162
+ reduced_context = name_pin.binder.reduce_class_type
163
+ pin.proxy(reduced_context)
164
+ else
165
+ next pin if pin.return_type.undefined?
166
+ selfy = pin.return_type.self_to_type(name_pin.binder)
167
+ selfy == pin.return_type ? pin : pin.proxy(selfy)
168
+ end
169
+ end
170
+ end
171
+
172
+ # @param pin [Pin::Base]
173
+ # @param api_map [ApiMap]
174
+ # @param context [ComplexType]
175
+ # @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
176
+ # @return [Pin::Base]
177
+ def process_macro pin, api_map, context, locals
178
+ pin.macros.each do |macro|
179
+ # @todo 'Wrong argument type for
180
+ # Solargraph::Source::Chain::Call#inner_process_macro:
181
+ # macro expected YARD::Tags::MacroDirective, received
182
+ # generic<Elem>' is because we lose 'rooted' information
183
+ # in the 'Chain::Array' class internally, leaving
184
+ # ::Array#each shadowed when it shouldn't be.
185
+ result = inner_process_macro(pin, macro, api_map, context, locals)
186
+ return result unless result.return_type.undefined?
187
+ end
188
+ Pin::ProxyType.anonymous(ComplexType::UNDEFINED, source: :chain)
189
+ end
190
+
191
+ # @param pin [Pin::Method]
192
+ # @param api_map [ApiMap]
193
+ # @param context [ComplexType]
194
+ # @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
195
+ # @return [Pin::ProxyType]
196
+ def process_directive pin, api_map, context, locals
197
+ pin.directives.each do |dir|
198
+ macro = api_map.named_macro(dir.tag.name)
199
+ next if macro.nil?
200
+ result = inner_process_macro(pin, macro, api_map, context, locals)
201
+ return result unless result.return_type.undefined?
202
+ end
203
+ Pin::ProxyType.anonymous ComplexType::UNDEFINED, source: :chain
204
+ end
205
+
206
+ # @param pin [Pin::Base]
207
+ # @param macro [YARD::Tags::MacroDirective]
208
+ # @param api_map [ApiMap]
209
+ # @param context [ComplexType]
210
+ # @param locals [::Array<Pin::LocalVariable, Pin::Parameter>]
211
+ # @return [Pin::ProxyType]
212
+ def inner_process_macro pin, macro, api_map, context, locals
213
+ vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals), source: :chain) }
214
+ txt = macro.tag.text.clone
215
+ if txt.empty? && macro.tag.name
216
+ named = api_map.named_macro(macro.tag.name)
217
+ txt = named.tag.text.clone if named
218
+ end
219
+ i = 1
220
+ vals.each do |v|
221
+ txt.gsub!(/\$#{i}/, v.context.namespace)
222
+ i += 1
223
+ end
224
+ docstring = Solargraph::Source.parse_docstring(txt).to_docstring
225
+ tag = docstring.tag(:return)
226
+ unless tag.nil? || tag.types.nil?
227
+ return Pin::ProxyType.anonymous(ComplexType.try_parse(*tag.types), source: :chain)
228
+ end
229
+ Pin::ProxyType.anonymous(ComplexType::UNDEFINED, source: :chain)
230
+ end
231
+
232
+ # @param docstring [YARD::Docstring]
233
+ # @param context [ComplexType]
234
+ # @return [ComplexType, nil]
235
+ def extra_return_type docstring, context
236
+ if docstring.has_tag?('return_single_parameter') #&& context.subtypes.one?
237
+ return context.subtypes.first || ComplexType::UNDEFINED
238
+ elsif docstring.has_tag?('return_value_parameter') && context.value_types.one?
239
+ return context.value_types.first
240
+ end
241
+ nil
242
+ end
243
+
244
+ # @param name_pin [Pin::Base]
245
+ # @return [Pin::Method, nil]
246
+ def find_method_pin(name_pin)
247
+ method_pin = name_pin
248
+ until method_pin.is_a?(Pin::Method)
249
+ method_pin = method_pin.closure
250
+ return if method_pin.nil?
251
+ end
252
+ method_pin
253
+ end
254
+
255
+ # @param api_map [ApiMap]
256
+ # @param name_pin [Pin::Base]
257
+ # @return [::Array<Pin::Base>]
258
+ def super_pins api_map, name_pin
259
+ method_pin = find_method_pin(name_pin)
260
+ return [] if method_pin.nil?
261
+ pins = api_map.get_method_stack(method_pin.namespace, method_pin.name, scope: method_pin.context.scope)
262
+ pins.reject{|p| p.path == name_pin.path}
263
+ end
264
+
265
+ # @param api_map [ApiMap]
266
+ # @param name_pin [Pin::Base]
267
+ # @return [::Array<Pin::Base>]
268
+ def yield_pins api_map, name_pin
269
+ method_pin = find_method_pin(name_pin)
270
+ return [] unless method_pin
271
+
272
+ # @param signature_pin [Pin::Signature]
273
+ method_pin.signatures.map(&:block).compact.map do |signature_pin|
274
+ return_type = signature_pin.return_type.qualify(api_map, *name_pin.gates)
275
+ signature_pin.proxy(return_type)
276
+ end
277
+ end
278
+
279
+ # @param type [ComplexType]
280
+ # @param context [ComplexType]
281
+ # @return [ComplexType]
282
+ def with_params type, context
283
+ return type unless type.to_s.include?('$')
284
+ ComplexType.try_parse(type.to_s.gsub('$', context.value_types.map(&:rooted_tag).join(', ')).gsub('<>', ''))
285
+ end
286
+
287
+ # @return [void]
288
+ def fix_block_pass
289
+ argument = @arguments.last&.links&.first
290
+ @block = @arguments.pop if argument.is_a?(BlockSymbol) || argument.is_a?(BlockVariable)
291
+ end
292
+
293
+ # @param api_map [ApiMap]
294
+ # @param context [ComplexType]
295
+ # @param block_parameter_types [::Array<ComplexType>]
296
+ # @param locals [::Array<Pin::LocalVariable>]
297
+ # @return [ComplexType, nil]
298
+ def block_symbol_call_type(api_map, context, block_parameter_types, locals)
299
+ # Ruby's shorthand for sending the passed in method name
300
+ # to the first yield parameter with no arguments
301
+ block_symbol_name = block.links.first.word
302
+ block_symbol_call_path = "#{block_parameter_types.first}##{block_symbol_name}"
303
+ callee = api_map.get_path_pins(block_symbol_call_path).first
304
+ return_type = callee&.return_type
305
+ # @todo: Figure out why we get unresolved generics at
306
+ # this point and need to assume method return types
307
+ # based on the generic type
308
+ return_type ||= api_map.get_path_pins("#{context.subtypes.first}##{block.links.first.word}").first&.return_type
309
+ return_type || ComplexType::UNDEFINED
310
+ end
311
+
312
+ # @param api_map [ApiMap]
313
+ # @return [Pin::Block, nil]
314
+ def find_block_pin(api_map)
315
+ node_location = Solargraph::Location.from_node(block.node)
316
+ return if node_location.nil?
317
+ block_pins = api_map.get_block_pins
318
+ block_pins.find { |pin| pin.location.contain?(node_location) }
319
+ end
320
+
321
+ # @param api_map [ApiMap]
322
+ # @param name_pin [Pin::Base]
323
+ # @param block_parameter_types [::Array<ComplexType>]
324
+ # @param locals [::Array<Pin::LocalVariable>]
325
+ # @return [ComplexType, nil]
326
+ def block_call_type(api_map, name_pin, locals)
327
+ return nil unless with_block?
328
+
329
+ block_context_pin = name_pin
330
+ 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)
333
+ end
334
+ end
335
+ end
336
+ end
337
+ end