cosmicgraph 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. checksums.yaml +7 -0
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/rspec.yml +41 -0
  4. data/.gitignore +9 -0
  5. data/.rspec +2 -0
  6. data/.yardopts +2 -0
  7. data/CHANGELOG.md +1150 -0
  8. data/Gemfile +7 -0
  9. data/LICENSE +21 -0
  10. data/README.md +136 -0
  11. data/Rakefile +25 -0
  12. data/SPONSORS.md +15 -0
  13. data/bin/solargraph +5 -0
  14. data/cosmicgraph.gemspec +44 -0
  15. data/lib/.rubocop.yml +22 -0
  16. data/lib/solargraph/api_map/bundler_methods.rb +22 -0
  17. data/lib/solargraph/api_map/cache.rb +70 -0
  18. data/lib/solargraph/api_map/source_to_yard.rb +81 -0
  19. data/lib/solargraph/api_map/store.rb +268 -0
  20. data/lib/solargraph/api_map.rb +704 -0
  21. data/lib/solargraph/bench.rb +27 -0
  22. data/lib/solargraph/cache.rb +51 -0
  23. data/lib/solargraph/complex_type/type_methods.rb +134 -0
  24. data/lib/solargraph/complex_type/unique_type.rb +132 -0
  25. data/lib/solargraph/complex_type.rb +254 -0
  26. data/lib/solargraph/convention/base.rb +33 -0
  27. data/lib/solargraph/convention/gemfile.rb +15 -0
  28. data/lib/solargraph/convention/gemspec.rb +22 -0
  29. data/lib/solargraph/convention/rakefile.rb +17 -0
  30. data/lib/solargraph/convention/rspec.rb +30 -0
  31. data/lib/solargraph/convention.rb +49 -0
  32. data/lib/solargraph/converters/dd.rb +12 -0
  33. data/lib/solargraph/converters/dl.rb +12 -0
  34. data/lib/solargraph/converters/dt.rb +12 -0
  35. data/lib/solargraph/converters/misc.rb +1 -0
  36. data/lib/solargraph/diagnostics/base.rb +29 -0
  37. data/lib/solargraph/diagnostics/require_not_found.rb +53 -0
  38. data/lib/solargraph/diagnostics/rubocop.rb +112 -0
  39. data/lib/solargraph/diagnostics/rubocop_helpers.rb +65 -0
  40. data/lib/solargraph/diagnostics/severities.rb +15 -0
  41. data/lib/solargraph/diagnostics/type_check.rb +54 -0
  42. data/lib/solargraph/diagnostics/update_errors.rb +41 -0
  43. data/lib/solargraph/diagnostics.rb +55 -0
  44. data/lib/solargraph/documentor.rb +76 -0
  45. data/lib/solargraph/environ.rb +45 -0
  46. data/lib/solargraph/language_server/completion_item_kinds.rb +35 -0
  47. data/lib/solargraph/language_server/error_codes.rb +20 -0
  48. data/lib/solargraph/language_server/host/cataloger.rb +56 -0
  49. data/lib/solargraph/language_server/host/diagnoser.rb +89 -0
  50. data/lib/solargraph/language_server/host/dispatch.rb +111 -0
  51. data/lib/solargraph/language_server/host/message_worker.rb +59 -0
  52. data/lib/solargraph/language_server/host/sources.rb +156 -0
  53. data/lib/solargraph/language_server/host.rb +869 -0
  54. data/lib/solargraph/language_server/message/base.rb +89 -0
  55. data/lib/solargraph/language_server/message/cancel_request.rb +13 -0
  56. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -0
  57. data/lib/solargraph/language_server/message/client.rb +11 -0
  58. data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -0
  59. data/lib/solargraph/language_server/message/completion_item.rb +11 -0
  60. data/lib/solargraph/language_server/message/exit_notification.rb +13 -0
  61. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +100 -0
  62. data/lib/solargraph/language_server/message/extended/document.rb +20 -0
  63. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -0
  64. data/lib/solargraph/language_server/message/extended/download_core.rb +19 -0
  65. data/lib/solargraph/language_server/message/extended/environment.rb +25 -0
  66. data/lib/solargraph/language_server/message/extended/search.rb +20 -0
  67. data/lib/solargraph/language_server/message/extended.rb +21 -0
  68. data/lib/solargraph/language_server/message/initialize.rb +164 -0
  69. data/lib/solargraph/language_server/message/initialized.rb +27 -0
  70. data/lib/solargraph/language_server/message/method_not_found.rb +16 -0
  71. data/lib/solargraph/language_server/message/method_not_implemented.rb +14 -0
  72. data/lib/solargraph/language_server/message/shutdown.rb +13 -0
  73. data/lib/solargraph/language_server/message/text_document/base.rb +19 -0
  74. data/lib/solargraph/language_server/message/text_document/code_action.rb +17 -0
  75. data/lib/solargraph/language_server/message/text_document/completion.rb +59 -0
  76. data/lib/solargraph/language_server/message/text_document/definition.rb +38 -0
  77. data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -0
  78. data/lib/solargraph/language_server/message/text_document/did_close.rb +15 -0
  79. data/lib/solargraph/language_server/message/text_document/did_open.rb +15 -0
  80. data/lib/solargraph/language_server/message/text_document/did_save.rb +17 -0
  81. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +16 -0
  82. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +23 -0
  83. data/lib/solargraph/language_server/message/text_document/folding_range.rb +26 -0
  84. data/lib/solargraph/language_server/message/text_document/formatting.rb +126 -0
  85. data/lib/solargraph/language_server/message/text_document/hover.rb +56 -0
  86. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +34 -0
  87. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -0
  88. data/lib/solargraph/language_server/message/text_document/references.rb +16 -0
  89. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -0
  90. data/lib/solargraph/language_server/message/text_document/signature_help.rb +24 -0
  91. data/lib/solargraph/language_server/message/text_document.rb +28 -0
  92. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +30 -0
  93. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +40 -0
  94. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -0
  95. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -0
  96. data/lib/solargraph/language_server/message/workspace.rb +14 -0
  97. data/lib/solargraph/language_server/message.rb +93 -0
  98. data/lib/solargraph/language_server/message_types.rb +14 -0
  99. data/lib/solargraph/language_server/request.rb +24 -0
  100. data/lib/solargraph/language_server/symbol_kinds.rb +36 -0
  101. data/lib/solargraph/language_server/transport/adapter.rb +53 -0
  102. data/lib/solargraph/language_server/transport/data_reader.rb +72 -0
  103. data/lib/solargraph/language_server/transport.rb +13 -0
  104. data/lib/solargraph/language_server/uri_helpers.rb +49 -0
  105. data/lib/solargraph/language_server.rb +19 -0
  106. data/lib/solargraph/library.rb +547 -0
  107. data/lib/solargraph/location.rb +37 -0
  108. data/lib/solargraph/logging.rb +27 -0
  109. data/lib/solargraph/page.rb +83 -0
  110. data/lib/solargraph/parser/comment_ripper.rb +52 -0
  111. data/lib/solargraph/parser/legacy/class_methods.rb +135 -0
  112. data/lib/solargraph/parser/legacy/flawed_builder.rb +16 -0
  113. data/lib/solargraph/parser/legacy/node_chainer.rb +148 -0
  114. data/lib/solargraph/parser/legacy/node_methods.rb +325 -0
  115. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +23 -0
  116. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +35 -0
  117. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +15 -0
  118. data/lib/solargraph/parser/legacy/node_processors/block_node.rb +42 -0
  119. data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +35 -0
  120. data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +23 -0
  121. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +63 -0
  122. data/lib/solargraph/parser/legacy/node_processors/defs_node.rb +36 -0
  123. data/lib/solargraph/parser/legacy/node_processors/gvasgn_node.rb +23 -0
  124. data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +38 -0
  125. data/lib/solargraph/parser/legacy/node_processors/lvasgn_node.rb +28 -0
  126. data/lib/solargraph/parser/legacy/node_processors/namespace_node.rb +39 -0
  127. data/lib/solargraph/parser/legacy/node_processors/orasgn_node.rb +16 -0
  128. data/lib/solargraph/parser/legacy/node_processors/resbody_node.rb +36 -0
  129. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +42 -0
  130. data/lib/solargraph/parser/legacy/node_processors/send_node.rb +257 -0
  131. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +18 -0
  132. data/lib/solargraph/parser/legacy/node_processors.rb +54 -0
  133. data/lib/solargraph/parser/legacy.rb +12 -0
  134. data/lib/solargraph/parser/node_methods.rb +43 -0
  135. data/lib/solargraph/parser/node_processor/base.rb +77 -0
  136. data/lib/solargraph/parser/node_processor.rb +43 -0
  137. data/lib/solargraph/parser/region.rb +66 -0
  138. data/lib/solargraph/parser/rubyvm/class_methods.rb +149 -0
  139. data/lib/solargraph/parser/rubyvm/node_chainer.rb +160 -0
  140. data/lib/solargraph/parser/rubyvm/node_methods.rb +315 -0
  141. data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -0
  142. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +85 -0
  143. data/lib/solargraph/parser/rubyvm/node_processors/begin_node.rb +15 -0
  144. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +42 -0
  145. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +33 -0
  146. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +23 -0
  147. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +75 -0
  148. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +68 -0
  149. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +23 -0
  150. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +38 -0
  151. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +39 -0
  152. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +20 -0
  153. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +27 -0
  154. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +39 -0
  155. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +26 -0
  156. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +15 -0
  157. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +45 -0
  158. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +32 -0
  159. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +15 -0
  160. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +279 -0
  161. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +18 -0
  162. data/lib/solargraph/parser/rubyvm/node_processors.rb +63 -0
  163. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +47 -0
  164. data/lib/solargraph/parser/rubyvm.rb +40 -0
  165. data/lib/solargraph/parser/snippet.rb +13 -0
  166. data/lib/solargraph/parser.rb +26 -0
  167. data/lib/solargraph/pin/base.rb +299 -0
  168. data/lib/solargraph/pin/base_variable.rb +84 -0
  169. data/lib/solargraph/pin/block.rb +73 -0
  170. data/lib/solargraph/pin/class_variable.rb +8 -0
  171. data/lib/solargraph/pin/closure.rb +37 -0
  172. data/lib/solargraph/pin/common.rb +70 -0
  173. data/lib/solargraph/pin/constant.rb +43 -0
  174. data/lib/solargraph/pin/conversions.rb +92 -0
  175. data/lib/solargraph/pin/documenting.rb +105 -0
  176. data/lib/solargraph/pin/duck_method.rb +16 -0
  177. data/lib/solargraph/pin/global_variable.rb +8 -0
  178. data/lib/solargraph/pin/instance_variable.rb +30 -0
  179. data/lib/solargraph/pin/keyword.rb +15 -0
  180. data/lib/solargraph/pin/keyword_param.rb +8 -0
  181. data/lib/solargraph/pin/local_variable.rb +55 -0
  182. data/lib/solargraph/pin/method.rb +335 -0
  183. data/lib/solargraph/pin/method_alias.rb +31 -0
  184. data/lib/solargraph/pin/namespace.rb +94 -0
  185. data/lib/solargraph/pin/parameter.rb +206 -0
  186. data/lib/solargraph/pin/proxy_type.rb +29 -0
  187. data/lib/solargraph/pin/reference/extend.rb +10 -0
  188. data/lib/solargraph/pin/reference/include.rb +10 -0
  189. data/lib/solargraph/pin/reference/override.rb +29 -0
  190. data/lib/solargraph/pin/reference/prepend.rb +10 -0
  191. data/lib/solargraph/pin/reference/require.rb +14 -0
  192. data/lib/solargraph/pin/reference/superclass.rb +10 -0
  193. data/lib/solargraph/pin/reference.rb +14 -0
  194. data/lib/solargraph/pin/search.rb +56 -0
  195. data/lib/solargraph/pin/signature.rb +23 -0
  196. data/lib/solargraph/pin/singleton.rb +11 -0
  197. data/lib/solargraph/pin/symbol.rb +47 -0
  198. data/lib/solargraph/pin.rb +38 -0
  199. data/lib/solargraph/position.rb +100 -0
  200. data/lib/solargraph/range.rb +95 -0
  201. data/lib/solargraph/rbs_map/conversions.rb +394 -0
  202. data/lib/solargraph/rbs_map/core_fills.rb +61 -0
  203. data/lib/solargraph/rbs_map/core_map.rb +38 -0
  204. data/lib/solargraph/rbs_map/core_signs.rb +33 -0
  205. data/lib/solargraph/rbs_map/stdlib_map.rb +36 -0
  206. data/lib/solargraph/rbs_map.rb +73 -0
  207. data/lib/solargraph/server_methods.rb +16 -0
  208. data/lib/solargraph/shell.rb +234 -0
  209. data/lib/solargraph/source/chain/block_variable.rb +13 -0
  210. data/lib/solargraph/source/chain/call.rb +215 -0
  211. data/lib/solargraph/source/chain/class_variable.rb +13 -0
  212. data/lib/solargraph/source/chain/constant.rb +75 -0
  213. data/lib/solargraph/source/chain/global_variable.rb +13 -0
  214. data/lib/solargraph/source/chain/hash.rb +28 -0
  215. data/lib/solargraph/source/chain/head.rb +19 -0
  216. data/lib/solargraph/source/chain/instance_variable.rb +13 -0
  217. data/lib/solargraph/source/chain/link.rb +71 -0
  218. data/lib/solargraph/source/chain/literal.rb +23 -0
  219. data/lib/solargraph/source/chain/or.rb +23 -0
  220. data/lib/solargraph/source/chain/q_call.rb +11 -0
  221. data/lib/solargraph/source/chain/variable.rb +13 -0
  222. data/lib/solargraph/source/chain/z_super.rb +30 -0
  223. data/lib/solargraph/source/chain.rb +179 -0
  224. data/lib/solargraph/source/change.rb +79 -0
  225. data/lib/solargraph/source/cursor.rb +164 -0
  226. data/lib/solargraph/source/encoding_fixes.rb +23 -0
  227. data/lib/solargraph/source/source_chainer.rb +191 -0
  228. data/lib/solargraph/source/updater.rb +54 -0
  229. data/lib/solargraph/source.rb +522 -0
  230. data/lib/solargraph/source_map/clip.rb +229 -0
  231. data/lib/solargraph/source_map/completion.rb +23 -0
  232. data/lib/solargraph/source_map/mapper.rb +241 -0
  233. data/lib/solargraph/source_map.rb +180 -0
  234. data/lib/solargraph/type_checker/checks.rb +112 -0
  235. data/lib/solargraph/type_checker/param_def.rb +35 -0
  236. data/lib/solargraph/type_checker/problem.rb +32 -0
  237. data/lib/solargraph/type_checker/rules.rb +57 -0
  238. data/lib/solargraph/type_checker.rb +549 -0
  239. data/lib/solargraph/version.rb +5 -0
  240. data/lib/solargraph/views/_method.erb +62 -0
  241. data/lib/solargraph/views/_name_type_tag.erb +10 -0
  242. data/lib/solargraph/views/_namespace.erb +24 -0
  243. data/lib/solargraph/views/document.erb +23 -0
  244. data/lib/solargraph/views/environment.erb +58 -0
  245. data/lib/solargraph/views/layout.erb +44 -0
  246. data/lib/solargraph/views/search.erb +11 -0
  247. data/lib/solargraph/workspace/config.rb +231 -0
  248. data/lib/solargraph/workspace.rb +212 -0
  249. data/lib/solargraph/yard_map/cache.rb +19 -0
  250. data/lib/solargraph/yard_map/helpers.rb +16 -0
  251. data/lib/solargraph/yard_map/mapper/to_constant.rb +25 -0
  252. data/lib/solargraph/yard_map/mapper/to_method.rb +81 -0
  253. data/lib/solargraph/yard_map/mapper/to_namespace.rb +27 -0
  254. data/lib/solargraph/yard_map/mapper.rb +77 -0
  255. data/lib/solargraph/yard_map/to_method.rb +79 -0
  256. data/lib/solargraph/yard_map.rb +301 -0
  257. data/lib/solargraph.rb +69 -0
  258. data/lib/yard-solargraph.rb +33 -0
  259. metadata +587 -0
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kramdown'
4
+ require 'kramdown-parser-gfm'
5
+ require 'yard'
6
+ require 'reverse_markdown'
7
+ require 'solargraph/converters/dl'
8
+ require 'solargraph/converters/dt'
9
+ require 'solargraph/converters/dd'
10
+ require 'solargraph/converters/misc'
11
+
12
+ module Solargraph
13
+ module Pin
14
+ # A module to add the Pin::Base#documentation method.
15
+ #
16
+ module Documenting
17
+ # A documentation formatter that either performs Markdown conversion for
18
+ # text, or applies backticks for code blocks.
19
+ #
20
+ class DocSection
21
+ # @return [String]
22
+ attr_reader :plaintext
23
+
24
+ # @param code [Boolean] True if this section is a code block
25
+ def initialize code
26
+ @plaintext = String.new('')
27
+ @code = code
28
+ end
29
+
30
+ def code?
31
+ @code
32
+ end
33
+
34
+ # @param text [String]
35
+ # @return [String]
36
+ def concat text
37
+ @plaintext.concat text
38
+ end
39
+
40
+ def to_s
41
+ return "\n```ruby\n#{@plaintext}#{@plaintext.end_with?("\n") ? '' : "\n"}```\n\n" if code?
42
+ ReverseMarkdown.convert unescape_brackets(Kramdown::Document.new(escape_brackets(@plaintext), input: 'GFM').to_html)
43
+ end
44
+
45
+ private
46
+
47
+ # @param text [String]
48
+ # @return [String]
49
+ def escape_brackets text
50
+ # text.gsub(/(\[[^\]]*\])([^\(]|\z)/, '!!!^\1^!!!\2')
51
+ text.gsub('[', '!!!!b').gsub(']', 'e!!!!')
52
+ end
53
+
54
+ # @param text [String]
55
+ # @return [String]
56
+ def unescape_brackets text
57
+ text.gsub('!!!!b', '[').gsub('e!!!!', ']')
58
+ end
59
+ end
60
+
61
+ # @return [String]
62
+ def documentation
63
+ @documentation ||= begin
64
+ # Using DocSections allows for code blocks that start with an empty
65
+ # line and at least two spaces of indentation. This is a common
66
+ # convention in Ruby core documentation, e.g., String#split.
67
+ sections = [DocSection.new(false)]
68
+ normalize_indentation(docstring.to_s).gsub(/\t/, ' ').lines.each do |l|
69
+ if l.strip.empty?
70
+ sections.last.concat l
71
+ else
72
+ if (l =~ /^ [^\s]/ && sections.last.plaintext =~ /(\r?\n[ \t]*?){2,}$/) || (l.start_with?(' ') && sections.last.code?)
73
+ # Code block
74
+ sections.push DocSection.new(true) unless sections.last.code?
75
+ sections.last.concat l[2..-1]
76
+ else
77
+ # Regular documentation
78
+ sections.push DocSection.new(false) if sections.last.code?
79
+ sections.last.concat l
80
+ end
81
+ end
82
+ end
83
+ sections.map(&:to_s).join.strip
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ # @param text [String]
90
+ # @return [String]
91
+ def normalize_indentation text
92
+ text.lines.map { |l| remove_odd_spaces(l) }.join
93
+ end
94
+
95
+ # @param line [String]
96
+ # @return [String]
97
+ def remove_odd_spaces line
98
+ return line unless line.start_with?(' ')
99
+ spaces = line.match(/^ +/)[0].length
100
+ return line unless spaces.odd?
101
+ line[1..-1]
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ # DuckMethod pins are used to add completion items for type tags that
6
+ # use duck typing, e.g., `@param file [#read]`.
7
+ #
8
+ class DuckMethod < Pin::Method
9
+ # @param location [Solargraph::Location]
10
+ # @param name [String]
11
+ # def initialize location, name
12
+ # # super(location, '', name, nil, :instance, :public, [])
13
+ # end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ class GlobalVariable < BaseVariable
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ class InstanceVariable < BaseVariable
6
+ def binder
7
+ closure.binder
8
+ end
9
+
10
+ def scope
11
+ closure.binder.scope
12
+ end
13
+
14
+ def context
15
+ @context ||= begin
16
+ result = super
17
+ if scope == :class
18
+ ComplexType.parse("Class<#{result.namespace}>")
19
+ else
20
+ ComplexType.parse("#{result.namespace}")
21
+ end
22
+ end
23
+ end
24
+
25
+ def nearly? other
26
+ super && binder == other.binder
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ class Keyword < Base
6
+ def initialize name
7
+ super(name: name)
8
+ end
9
+
10
+ def name
11
+ @name
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ class KeywordParam < Symbol
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ class LocalVariable < BaseVariable
6
+ # @return [Range]
7
+ attr_reader :presence
8
+
9
+ def initialize assignment: nil, presence: nil, **splat
10
+ super(**splat)
11
+ @assignment = assignment
12
+ @presence = presence
13
+ end
14
+
15
+ def try_merge! pin
16
+ return false unless super
17
+ @presence = pin.presence
18
+ true
19
+ end
20
+
21
+ # @param other_closure [Pin::Closure]
22
+ # @param other_loc [Location]
23
+ def visible_at?(other_closure, other_loc)
24
+ return true if location.filename == other_loc.filename &&
25
+ presence.include?(other_loc.range.start) &&
26
+ match_named_closure(other_closure, closure)
27
+ end
28
+
29
+ private
30
+
31
+ # @param tag1 [String]
32
+ # @param tag2 [String]
33
+ # @return [Boolean]
34
+ def match_tags tag1, tag2
35
+ # @todo This is an unfortunate hack made necessary by a discrepancy in
36
+ # how tags indicate the root namespace. The long-term solution is to
37
+ # standardize it, whether it's `Class<>`, an empty string, or
38
+ # something else.
39
+ tag1 == tag2 ||
40
+ (['', 'Class<>'].include?(tag1) && ['', 'Class<>'].include?(tag2))
41
+ end
42
+
43
+ def match_named_closure needle, haystack
44
+ return true if needle == haystack || haystack.is_a?(Pin::Block)
45
+ cursor = haystack
46
+ until cursor.nil?
47
+ return true if needle.path == cursor.path
48
+ return false if cursor.path && !cursor.path.empty?
49
+ cursor = cursor.closure
50
+ end
51
+ false
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,335 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ # The base class for method and attribute pins.
6
+ #
7
+ class Method < Closure
8
+ include Solargraph::Parser::NodeMethods
9
+
10
+ # @return [Array<Pin::Parameter>]
11
+ attr_reader :parameters
12
+
13
+ # @return [::Symbol] :public, :private, or :protected
14
+ attr_reader :visibility
15
+
16
+ # @return [Parser::AST::Node]
17
+ attr_reader :node
18
+
19
+ # @param visibility [::Symbol] :public, :protected, or :private
20
+ # @param explicit [Boolean]
21
+ # @param parameters [Array<Pin::Parameter>]
22
+ # @param node [Parser::AST::Node, RubyVM::AbstractSyntaxTree::Node]
23
+ # @param attribute [Boolean]
24
+ def initialize visibility: :public, explicit: true, parameters: [], node: nil, attribute: false, signatures: nil, anon_splat: false, **splat
25
+ super(**splat)
26
+ @visibility = visibility
27
+ @explicit = explicit
28
+ @parameters = parameters
29
+ @node = node
30
+ @attribute = attribute
31
+ @signatures = signatures
32
+ @anon_splat = anon_splat
33
+ end
34
+
35
+ # @return [Array<String>]
36
+ def parameter_names
37
+ @parameter_names ||= parameters.map(&:name)
38
+ end
39
+
40
+ def completion_item_kind
41
+ attribute? ? Solargraph::LanguageServer::CompletionItemKinds::PROPERTY : Solargraph::LanguageServer::CompletionItemKinds::METHOD
42
+ end
43
+
44
+ def symbol_kind
45
+ attribute? ? Solargraph::LanguageServer::SymbolKinds::PROPERTY : LanguageServer::SymbolKinds::METHOD
46
+ end
47
+
48
+ def return_type
49
+ @return_type ||= ComplexType.try_parse(*signatures.map(&:return_type).map(&:to_s))
50
+ end
51
+
52
+ # @return [Array<Signature>]
53
+ def signatures
54
+ @signatures ||= begin
55
+ top_type = generate_complex_type
56
+ result = []
57
+ result.push Signature.new(parameters, top_type) if top_type.defined?
58
+ result.concat(overloads.map { |meth| Signature.new(meth.parameters, meth.return_type) })
59
+ result.push Signature.new(parameters, top_type) if result.empty?
60
+ result
61
+ end
62
+ end
63
+
64
+ # @return [String]
65
+ def detail
66
+ # This property is not cached in an instance variable because it can
67
+ # change when pins get proxied.
68
+ detail = String.new
69
+ detail += if signatures.length > 1
70
+ "(*) "
71
+ else
72
+ "(#{signatures.first.parameters.map(&:full).join(', ')}) " unless signatures.first.parameters.empty?
73
+ end.to_s
74
+ detail += "=#{probed? ? '~' : (proxied? ? '^' : '>')} #{return_type.to_s}" unless return_type.undefined?
75
+ detail.strip!
76
+ return nil if detail.empty?
77
+ detail
78
+ end
79
+
80
+ # @return [Array<Hash>]
81
+ def signature_help
82
+ @signature_help ||= signatures.map do |sig|
83
+ {
84
+ label: name + '(' + sig.parameters.map(&:full).join(', ') + ')',
85
+ documentation: documentation
86
+ }
87
+ end
88
+ end
89
+
90
+ def path
91
+ @path ||= "#{namespace}#{(scope == :instance ? '#' : '.')}#{name}"
92
+ end
93
+
94
+ def typify api_map
95
+ decl = super
96
+ return decl unless decl.undefined?
97
+ type = see_reference(api_map) || typify_from_super(api_map)
98
+ return type.qualify(api_map, namespace) unless type.nil?
99
+ name.end_with?('?') ? ComplexType::BOOLEAN : ComplexType::UNDEFINED
100
+ end
101
+
102
+ def documentation
103
+ if @documentation.nil?
104
+ @documentation ||= super || ''
105
+ param_tags = docstring.tags(:param)
106
+ unless param_tags.nil? or param_tags.empty?
107
+ @documentation += "\n\n" unless @documentation.empty?
108
+ @documentation += "Params:\n"
109
+ lines = []
110
+ param_tags.each do |p|
111
+ l = "* #{p.name}"
112
+ l += " [#{escape_brackets(p.types.join(', '))}]" unless p.types.nil? or p.types.empty?
113
+ l += " #{p.text}"
114
+ lines.push l
115
+ end
116
+ @documentation += lines.join("\n")
117
+ end
118
+ return_tags = docstring.tags(:return)
119
+ unless return_tags.empty?
120
+ @documentation += "\n\n" unless @documentation.empty?
121
+ @documentation += "Returns:\n"
122
+ lines = []
123
+ return_tags.each do |r|
124
+ l = "*"
125
+ l += " [#{escape_brackets(r.types.join(', '))}]" unless r.types.nil? or r.types.empty?
126
+ l += " #{r.text}"
127
+ lines.push l
128
+ end
129
+ @documentation += lines.join("\n")
130
+ end
131
+ @documentation += "\n\n" unless @documentation.empty?
132
+ @documentation += "Visibility: #{visibility}"
133
+ end
134
+ @documentation.to_s
135
+ end
136
+
137
+ def explicit?
138
+ @explicit
139
+ end
140
+
141
+ def attribute?
142
+ @attribute
143
+ end
144
+
145
+ def nearly? other
146
+ return false unless super
147
+ parameters == other.parameters and
148
+ scope == other.scope and
149
+ visibility == other.visibility
150
+ end
151
+
152
+ def probe api_map
153
+ attribute? ? infer_from_iv(api_map) : infer_from_return_nodes(api_map)
154
+ end
155
+
156
+ def try_merge! pin
157
+ return false unless super
158
+ @node = pin.node
159
+ true
160
+ end
161
+
162
+ # @return [Array<Pin::Method>]
163
+ def overloads
164
+ @overloads ||= docstring.tags(:overload).map do |tag|
165
+ Pin::Signature.new(
166
+ tag.parameters.map do |src|
167
+ name, decl = parse_overload_param(src.first)
168
+ Pin::Parameter.new(
169
+ location: location,
170
+ closure: self,
171
+ comments: tag.docstring.all.to_s,
172
+ name: name,
173
+ decl: decl,
174
+ presence: location ? location.range : nil,
175
+ return_type: param_type_from_name(tag, src.first)
176
+ )
177
+ end,
178
+ ComplexType.try_parse(*tag.docstring.tags(:return).flat_map(&:types))
179
+ )
180
+ end
181
+ @overloads
182
+ end
183
+
184
+ def anon_splat?
185
+ @anon_splat
186
+ end
187
+
188
+ private
189
+
190
+ def select_decl name, asgn
191
+ if name.start_with?('**')
192
+ :kwrestarg
193
+ elsif name.start_with?('*')
194
+ :restarg
195
+ elsif name.start_with?('&')
196
+ :blockarg
197
+ elsif name.end_with?(':') && asgn
198
+ :kwoptarg
199
+ elsif name.end_with?(':')
200
+ :kwarg
201
+ elsif asgn
202
+ :optarg
203
+ else
204
+ :arg
205
+ end
206
+ end
207
+
208
+ def clean_param name
209
+ name.gsub(/[*&:]/, '')
210
+ end
211
+
212
+ # @param tag [YARD::Tags::OverloadTag]
213
+ def param_type_from_name(tag, name)
214
+ param = tag.tags(:param).select { |t| t.name == name }.first
215
+ return ComplexType::UNDEFINED unless param
216
+ ComplexType.try_parse(*param.types)
217
+ end
218
+
219
+ # @return [ComplexType]
220
+ def generate_complex_type
221
+ tags = docstring.tags(:return).map(&:types).flatten.reject(&:nil?)
222
+ return ComplexType::UNDEFINED if tags.empty?
223
+ ComplexType.try_parse *tags
224
+ end
225
+
226
+ # @param api_map [ApiMap]
227
+ # @return [ComplexType, nil]
228
+ def see_reference api_map
229
+ docstring.ref_tags.each do |ref|
230
+ next unless ref.tag_name == 'return' && ref.owner
231
+ result = resolve_reference(ref.owner.to_s, api_map)
232
+ return result unless result.nil?
233
+ end
234
+ match = comments.match(/^[ \t]*\(see (.*)\)/m)
235
+ return nil if match.nil?
236
+ resolve_reference match[1], api_map
237
+ end
238
+
239
+ # @param api_map [ApiMap]
240
+ # @return [ComplexType, nil]
241
+ def typify_from_super api_map
242
+ stack = api_map.get_method_stack(namespace, name, scope: scope).reject { |pin| pin.path == path }
243
+ return nil if stack.empty?
244
+ stack.each do |pin|
245
+ return pin.return_type unless pin.return_type.undefined?
246
+ end
247
+ nil
248
+ end
249
+
250
+ # @param ref [String]
251
+ # @param api_map [ApiMap]
252
+ # @return [ComplexType]
253
+ def resolve_reference ref, api_map
254
+ parts = ref.split(/[\.#]/)
255
+ if parts.first.empty? || parts.one?
256
+ path = "#{namespace}#{ref}"
257
+ else
258
+ fqns = api_map.qualify(parts.first, namespace)
259
+ return ComplexType::UNDEFINED if fqns.nil?
260
+ path = fqns + ref[parts.first.length] + parts.last
261
+ end
262
+ pins = api_map.get_path_pins(path)
263
+ pins.each do |pin|
264
+ type = pin.typify(api_map)
265
+ return type unless type.undefined?
266
+ end
267
+ nil
268
+ end
269
+
270
+ # @return [Parser::AST::Node, nil]
271
+ def method_body_node
272
+ return nil if node.nil?
273
+ return node.children[1].children.last if node.type == :DEFN
274
+ return node.children[2].children.last if node.type == :DEFS
275
+ return node.children[2] if node.type == :def || node.type == :DEFS
276
+ return node.children[3] if node.type == :defs
277
+ nil
278
+ end
279
+
280
+ # @param api_map [ApiMap]
281
+ # @return [ComplexType]
282
+ def infer_from_return_nodes api_map
283
+ return ComplexType::UNDEFINED if node.nil?
284
+ result = []
285
+ has_nil = false
286
+ return ComplexType::NIL if method_body_node.nil?
287
+ returns_from(method_body_node).each do |n|
288
+ if n.nil? || [:NIL, :nil].include?(n.type)
289
+ has_nil = true
290
+ next
291
+ end
292
+ rng = Range.from_node(n)
293
+ next unless rng
294
+ clip = api_map.clip_at(
295
+ location.filename,
296
+ rng.ending
297
+ )
298
+ chain = Solargraph::Parser.chain(n, location.filename)
299
+ type = chain.infer(api_map, self, clip.locals)
300
+ result.push type unless type.undefined?
301
+ end
302
+ result.push ComplexType::NIL if has_nil
303
+ return ComplexType::UNDEFINED if result.empty?
304
+ ComplexType.try_parse(*result.map(&:tag).uniq)
305
+ end
306
+
307
+ def infer_from_iv api_map
308
+ types = []
309
+ varname = "@#{name.gsub(/=$/, '')}"
310
+ pins = api_map.get_instance_variable_pins(binder.namespace, binder.scope).select { |iv| iv.name == varname }
311
+ pins.each do |pin|
312
+ type = pin.typify(api_map)
313
+ type = pin.probe(api_map) if type.undefined?
314
+ types.push type if type.defined?
315
+ end
316
+ return ComplexType::UNDEFINED if types.empty?
317
+ ComplexType.try_parse(*types.map(&:tag).uniq)
318
+ end
319
+
320
+ # When YARD parses an overload tag, it includes rest modifiers in the parameters names.
321
+ #
322
+ # @param arg [String]
323
+ # @return [Array(String, Symbol)]
324
+ def parse_overload_param(name)
325
+ if name.start_with?('**')
326
+ [name[2..-1], :kwrestarg]
327
+ elsif name.start_with?('*')
328
+ [name[1..-1], :restarg]
329
+ else
330
+ [name, :arg]
331
+ end
332
+ end
333
+ end
334
+ end
335
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ # Use this class to track method aliases for later remapping. Common
6
+ # examples that defer mapping are aliases for superclass methods or
7
+ # methods from included modules.
8
+ #
9
+ class MethodAlias < Method
10
+ # @return [::Symbol]
11
+ attr_reader :scope
12
+
13
+ # @return [String]
14
+ attr_reader :original
15
+
16
+ def initialize scope: :instance, original: nil, **splat
17
+ super(**splat)
18
+ @scope = scope
19
+ @original = original
20
+ end
21
+
22
+ def visibility
23
+ :public
24
+ end
25
+
26
+ def path
27
+ @path ||= namespace + (scope == :instance ? '#' : '.') + name
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ class Namespace < Closure
6
+ # @return [::Symbol] :public or :private
7
+ attr_reader :visibility
8
+
9
+ # @return [::Symbol] :class or :module
10
+ attr_reader :type
11
+
12
+ attr_reader :parameters
13
+
14
+ # @param type [::Symbol] :class or :module
15
+ # @param visibility [::Symbol] :public or :private
16
+ # @param gates [Array<String>]
17
+ def initialize type: :class, visibility: :public, gates: [''], parameters: [], **splat
18
+ # super(location, namespace, name, comments)
19
+ super(**splat)
20
+ @type = type
21
+ @visibility = visibility
22
+ if name.start_with?('::')
23
+ @name = name[2..-1]
24
+ @closure = Solargraph::Pin::ROOT_PIN
25
+ end
26
+ @open_gates = gates
27
+ if @name.include?('::')
28
+ # In this case, a chained namespace was opened (e.g., Foo::Bar)
29
+ # but Foo does not exist.
30
+ parts = @name.split('::')
31
+ @name = parts.pop
32
+ closure_name = if [Solargraph::Pin::ROOT_PIN, nil].include?(closure)
33
+ ''
34
+ else
35
+ closure.full_context.namespace + '::'
36
+ end
37
+ closure_name += parts.join('::')
38
+ @closure = Pin::Namespace.new(name: closure_name, gates: [parts.join('::')])
39
+ @context = nil
40
+ end
41
+ @parameters = parameters
42
+ end
43
+
44
+ def namespace
45
+ context.namespace
46
+ end
47
+
48
+ def full_context
49
+ @full_context ||= ComplexType.try_parse("#{type.to_s.capitalize}<#{path}>")
50
+ end
51
+
52
+ def binder
53
+ full_context
54
+ end
55
+
56
+ def scope
57
+ context.scope
58
+ end
59
+
60
+ def completion_item_kind
61
+ (type == :class ? LanguageServer::CompletionItemKinds::CLASS : LanguageServer::CompletionItemKinds::MODULE)
62
+ end
63
+
64
+ # @return [Integer]
65
+ def symbol_kind
66
+ (type == :class ? LanguageServer::SymbolKinds::CLASS : LanguageServer::SymbolKinds::MODULE)
67
+ end
68
+
69
+ def path
70
+ @path ||= (namespace.empty? ? '' : "#{namespace}::") + name
71
+ end
72
+
73
+ def return_type
74
+ @return_type ||= ComplexType.try_parse( (type == :class ? 'Class' : 'Module') + "<#{path}>" )
75
+ end
76
+
77
+ def domains
78
+ @domains ||= []
79
+ end
80
+
81
+ def typify api_map
82
+ return_type
83
+ end
84
+
85
+ def gates
86
+ @gates ||= if path.empty?
87
+ @open_gates
88
+ else
89
+ [path] + @open_gates
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end