jimeh-solargraph 0.40.4.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 (252) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +54 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +24 -0
  6. data/.yardopts +2 -0
  7. data/CHANGELOG.md +1003 -0
  8. data/Gemfile +7 -0
  9. data/LICENSE +21 -0
  10. data/README.md +123 -0
  11. data/Rakefile +25 -0
  12. data/SPONSORS.md +15 -0
  13. data/bin/solargraph +5 -0
  14. data/jimeh-solargraph.gemspec +44 -0
  15. data/lib/.rubocop.yml +21 -0
  16. data/lib/solargraph.rb +67 -0
  17. data/lib/solargraph/api_map.rb +752 -0
  18. data/lib/solargraph/api_map/bundler_methods.rb +27 -0
  19. data/lib/solargraph/api_map/cache.rb +70 -0
  20. data/lib/solargraph/api_map/source_to_yard.rb +81 -0
  21. data/lib/solargraph/api_map/store.rb +256 -0
  22. data/lib/solargraph/bench.rb +30 -0
  23. data/lib/solargraph/compat.rb +23 -0
  24. data/lib/solargraph/complex_type.rb +213 -0
  25. data/lib/solargraph/complex_type/type_methods.rb +127 -0
  26. data/lib/solargraph/complex_type/unique_type.rb +75 -0
  27. data/lib/solargraph/convention.rb +47 -0
  28. data/lib/solargraph/convention/base.rb +33 -0
  29. data/lib/solargraph/convention/gemfile.rb +15 -0
  30. data/lib/solargraph/convention/gemspec.rb +22 -0
  31. data/lib/solargraph/convention/rspec.rb +21 -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.rb +55 -0
  37. data/lib/solargraph/diagnostics/base.rb +29 -0
  38. data/lib/solargraph/diagnostics/require_not_found.rb +37 -0
  39. data/lib/solargraph/diagnostics/rubocop.rb +90 -0
  40. data/lib/solargraph/diagnostics/rubocop_helpers.rb +45 -0
  41. data/lib/solargraph/diagnostics/severities.rb +15 -0
  42. data/lib/solargraph/diagnostics/type_check.rb +54 -0
  43. data/lib/solargraph/diagnostics/update_errors.rb +41 -0
  44. data/lib/solargraph/documentor.rb +78 -0
  45. data/lib/solargraph/environ.rb +45 -0
  46. data/lib/solargraph/language_server.rb +19 -0
  47. data/lib/solargraph/language_server/completion_item_kinds.rb +35 -0
  48. data/lib/solargraph/language_server/error_codes.rb +20 -0
  49. data/lib/solargraph/language_server/host.rb +746 -0
  50. data/lib/solargraph/language_server/host/cataloger.rb +56 -0
  51. data/lib/solargraph/language_server/host/diagnoser.rb +81 -0
  52. data/lib/solargraph/language_server/host/dispatch.rb +112 -0
  53. data/lib/solargraph/language_server/host/sources.rb +156 -0
  54. data/lib/solargraph/language_server/message.rb +92 -0
  55. data/lib/solargraph/language_server/message/base.rb +85 -0
  56. data/lib/solargraph/language_server/message/cancel_request.rb +13 -0
  57. data/lib/solargraph/language_server/message/client.rb +11 -0
  58. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -0
  59. data/lib/solargraph/language_server/message/completion_item.rb +11 -0
  60. data/lib/solargraph/language_server/message/completion_item/resolve.rb +57 -0
  61. data/lib/solargraph/language_server/message/exit_notification.rb +13 -0
  62. data/lib/solargraph/language_server/message/extended.rb +21 -0
  63. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +100 -0
  64. data/lib/solargraph/language_server/message/extended/document.rb +20 -0
  65. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -0
  66. data/lib/solargraph/language_server/message/extended/download_core.rb +23 -0
  67. data/lib/solargraph/language_server/message/extended/environment.rb +25 -0
  68. data/lib/solargraph/language_server/message/extended/search.rb +20 -0
  69. data/lib/solargraph/language_server/message/initialize.rb +153 -0
  70. data/lib/solargraph/language_server/message/initialized.rb +26 -0
  71. data/lib/solargraph/language_server/message/method_not_found.rb +16 -0
  72. data/lib/solargraph/language_server/message/method_not_implemented.rb +14 -0
  73. data/lib/solargraph/language_server/message/shutdown.rb +13 -0
  74. data/lib/solargraph/language_server/message/text_document.rb +28 -0
  75. data/lib/solargraph/language_server/message/text_document/base.rb +19 -0
  76. data/lib/solargraph/language_server/message/text_document/code_action.rb +17 -0
  77. data/lib/solargraph/language_server/message/text_document/completion.rb +57 -0
  78. data/lib/solargraph/language_server/message/text_document/definition.rb +38 -0
  79. data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -0
  80. data/lib/solargraph/language_server/message/text_document/did_close.rb +15 -0
  81. data/lib/solargraph/language_server/message/text_document/did_open.rb +15 -0
  82. data/lib/solargraph/language_server/message/text_document/did_save.rb +17 -0
  83. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +23 -0
  84. data/lib/solargraph/language_server/message/text_document/folding_range.rb +26 -0
  85. data/lib/solargraph/language_server/message/text_document/formatting.rb +105 -0
  86. data/lib/solargraph/language_server/message/text_document/hover.rb +44 -0
  87. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +34 -0
  88. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -0
  89. data/lib/solargraph/language_server/message/text_document/references.rb +16 -0
  90. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -0
  91. data/lib/solargraph/language_server/message/text_document/signature_help.rb +29 -0
  92. data/lib/solargraph/language_server/message/workspace.rb +14 -0
  93. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +29 -0
  94. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +33 -0
  95. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -0
  96. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -0
  97. data/lib/solargraph/language_server/message_types.rb +14 -0
  98. data/lib/solargraph/language_server/request.rb +24 -0
  99. data/lib/solargraph/language_server/symbol_kinds.rb +36 -0
  100. data/lib/solargraph/language_server/transport.rb +13 -0
  101. data/lib/solargraph/language_server/transport/adapter.rb +56 -0
  102. data/lib/solargraph/language_server/transport/data_reader.rb +72 -0
  103. data/lib/solargraph/language_server/uri_helpers.rb +49 -0
  104. data/lib/solargraph/library.rb +426 -0
  105. data/lib/solargraph/location.rb +37 -0
  106. data/lib/solargraph/logging.rb +27 -0
  107. data/lib/solargraph/page.rb +83 -0
  108. data/lib/solargraph/parser.rb +26 -0
  109. data/lib/solargraph/parser/comment_ripper.rb +52 -0
  110. data/lib/solargraph/parser/legacy.rb +12 -0
  111. data/lib/solargraph/parser/legacy/class_methods.rb +109 -0
  112. data/lib/solargraph/parser/legacy/flawed_builder.rb +16 -0
  113. data/lib/solargraph/parser/legacy/node_chainer.rb +118 -0
  114. data/lib/solargraph/parser/legacy/node_methods.rb +311 -0
  115. data/lib/solargraph/parser/legacy/node_processors.rb +54 -0
  116. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +23 -0
  117. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +35 -0
  118. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +15 -0
  119. data/lib/solargraph/parser/legacy/node_processors/block_node.rb +22 -0
  120. data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +25 -0
  121. data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +23 -0
  122. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +63 -0
  123. data/lib/solargraph/parser/legacy/node_processors/defs_node.rb +36 -0
  124. data/lib/solargraph/parser/legacy/node_processors/gvasgn_node.rb +23 -0
  125. data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +38 -0
  126. data/lib/solargraph/parser/legacy/node_processors/lvasgn_node.rb +28 -0
  127. data/lib/solargraph/parser/legacy/node_processors/namespace_node.rb +39 -0
  128. data/lib/solargraph/parser/legacy/node_processors/orasgn_node.rb +16 -0
  129. data/lib/solargraph/parser/legacy/node_processors/resbody_node.rb +36 -0
  130. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +21 -0
  131. data/lib/solargraph/parser/legacy/node_processors/send_node.rb +257 -0
  132. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +18 -0
  133. data/lib/solargraph/parser/node_methods.rb +43 -0
  134. data/lib/solargraph/parser/node_processor.rb +43 -0
  135. data/lib/solargraph/parser/node_processor/base.rb +80 -0
  136. data/lib/solargraph/parser/region.rb +66 -0
  137. data/lib/solargraph/parser/rubyvm.rb +40 -0
  138. data/lib/solargraph/parser/rubyvm/class_methods.rb +150 -0
  139. data/lib/solargraph/parser/rubyvm/node_chainer.rb +135 -0
  140. data/lib/solargraph/parser/rubyvm/node_methods.rb +301 -0
  141. data/lib/solargraph/parser/rubyvm/node_processors.rb +62 -0
  142. data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -0
  143. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +86 -0
  144. data/lib/solargraph/parser/rubyvm/node_processors/begin_node.rb +15 -0
  145. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +22 -0
  146. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +22 -0
  147. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +23 -0
  148. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +64 -0
  149. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +57 -0
  150. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +23 -0
  151. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +38 -0
  152. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +39 -0
  153. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +20 -0
  154. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +27 -0
  155. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +39 -0
  156. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +26 -0
  157. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +15 -0
  158. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +45 -0
  159. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +21 -0
  160. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +15 -0
  161. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +277 -0
  162. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +18 -0
  163. data/lib/solargraph/parser/snippet.rb +13 -0
  164. data/lib/solargraph/pin.rb +36 -0
  165. data/lib/solargraph/pin/base.rb +296 -0
  166. data/lib/solargraph/pin/base_variable.rb +84 -0
  167. data/lib/solargraph/pin/block.rb +62 -0
  168. data/lib/solargraph/pin/class_variable.rb +8 -0
  169. data/lib/solargraph/pin/closure.rb +37 -0
  170. data/lib/solargraph/pin/common.rb +70 -0
  171. data/lib/solargraph/pin/constant.rb +43 -0
  172. data/lib/solargraph/pin/conversions.rb +96 -0
  173. data/lib/solargraph/pin/documenting.rb +105 -0
  174. data/lib/solargraph/pin/duck_method.rb +16 -0
  175. data/lib/solargraph/pin/global_variable.rb +8 -0
  176. data/lib/solargraph/pin/instance_variable.rb +30 -0
  177. data/lib/solargraph/pin/keyword.rb +15 -0
  178. data/lib/solargraph/pin/keyword_param.rb +8 -0
  179. data/lib/solargraph/pin/local_variable.rb +21 -0
  180. data/lib/solargraph/pin/localized.rb +43 -0
  181. data/lib/solargraph/pin/method.rb +245 -0
  182. data/lib/solargraph/pin/method_alias.rb +31 -0
  183. data/lib/solargraph/pin/namespace.rb +85 -0
  184. data/lib/solargraph/pin/parameter.rb +206 -0
  185. data/lib/solargraph/pin/proxy_type.rb +29 -0
  186. data/lib/solargraph/pin/reference.rb +14 -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/singleton.rb +11 -0
  194. data/lib/solargraph/pin/symbol.rb +47 -0
  195. data/lib/solargraph/position.rb +100 -0
  196. data/lib/solargraph/range.rb +95 -0
  197. data/lib/solargraph/server_methods.rb +16 -0
  198. data/lib/solargraph/shell.rb +222 -0
  199. data/lib/solargraph/source.rb +537 -0
  200. data/lib/solargraph/source/chain.rb +154 -0
  201. data/lib/solargraph/source/chain/block_variable.rb +13 -0
  202. data/lib/solargraph/source/chain/call.rb +203 -0
  203. data/lib/solargraph/source/chain/class_variable.rb +13 -0
  204. data/lib/solargraph/source/chain/constant.rb +75 -0
  205. data/lib/solargraph/source/chain/global_variable.rb +13 -0
  206. data/lib/solargraph/source/chain/head.rb +35 -0
  207. data/lib/solargraph/source/chain/instance_variable.rb +13 -0
  208. data/lib/solargraph/source/chain/link.rb +67 -0
  209. data/lib/solargraph/source/chain/literal.rb +23 -0
  210. data/lib/solargraph/source/chain/or.rb +23 -0
  211. data/lib/solargraph/source/chain/variable.rb +13 -0
  212. data/lib/solargraph/source/chain/z_super.rb +30 -0
  213. data/lib/solargraph/source/change.rb +79 -0
  214. data/lib/solargraph/source/cursor.rb +164 -0
  215. data/lib/solargraph/source/encoding_fixes.rb +23 -0
  216. data/lib/solargraph/source/source_chainer.rb +190 -0
  217. data/lib/solargraph/source/updater.rb +54 -0
  218. data/lib/solargraph/source_map.rb +188 -0
  219. data/lib/solargraph/source_map/clip.rb +224 -0
  220. data/lib/solargraph/source_map/completion.rb +23 -0
  221. data/lib/solargraph/source_map/mapper.rb +215 -0
  222. data/lib/solargraph/type_checker.rb +503 -0
  223. data/lib/solargraph/type_checker/checks.rb +99 -0
  224. data/lib/solargraph/type_checker/param_def.rb +35 -0
  225. data/lib/solargraph/type_checker/problem.rb +32 -0
  226. data/lib/solargraph/type_checker/rules.rb +57 -0
  227. data/lib/solargraph/version.rb +5 -0
  228. data/lib/solargraph/views/_method.erb +62 -0
  229. data/lib/solargraph/views/_name_type_tag.erb +10 -0
  230. data/lib/solargraph/views/_namespace.erb +24 -0
  231. data/lib/solargraph/views/document.erb +23 -0
  232. data/lib/solargraph/views/environment.erb +58 -0
  233. data/lib/solargraph/views/layout.erb +44 -0
  234. data/lib/solargraph/views/search.erb +11 -0
  235. data/lib/solargraph/workspace.rb +209 -0
  236. data/lib/solargraph/workspace/config.rb +230 -0
  237. data/lib/solargraph/yard_map.rb +435 -0
  238. data/lib/solargraph/yard_map/cache.rb +19 -0
  239. data/lib/solargraph/yard_map/core_docs.rb +170 -0
  240. data/lib/solargraph/yard_map/core_fills.rb +185 -0
  241. data/lib/solargraph/yard_map/core_gen.rb +76 -0
  242. data/lib/solargraph/yard_map/helpers.rb +16 -0
  243. data/lib/solargraph/yard_map/mapper.rb +77 -0
  244. data/lib/solargraph/yard_map/mapper/to_constant.rb +25 -0
  245. data/lib/solargraph/yard_map/mapper/to_method.rb +78 -0
  246. data/lib/solargraph/yard_map/mapper/to_namespace.rb +27 -0
  247. data/lib/solargraph/yard_map/rdoc_to_yard.rb +140 -0
  248. data/lib/solargraph/yard_map/stdlib_fills.rb +43 -0
  249. data/lib/solargraph/yard_map/to_method.rb +79 -0
  250. data/lib/yard-solargraph.rb +30 -0
  251. data/yardoc/2.2.2.tar.gz +0 -0
  252. metadata +564 -0
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec name: 'jimeh-solargraph'
4
+
5
+ # Local gemfile for development tools, etc.
6
+ local_gemfile = File.expand_path(".Gemfile", __dir__)
7
+ instance_eval File.read local_gemfile if File.exist? local_gemfile
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017-2019 by Fred Snyder for Castwide Technologies
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,123 @@
1
+ # Solargraph
2
+
3
+ **NOTE:** This is a fork of [solargraph][1] which aims to very quickly
4
+ incorporate fixes from outstanding [Pull Requests][2] and release them as a gem
5
+ called `jimeh-solargraph`. You can easily [compare][3] changes which have been
6
+ added to this fork.
7
+
8
+ [1]: https://github.com/castwide/solargraph
9
+ [2]: https://github.com/castwide/solargraph/pulls
10
+ [3]: https://github.com/castwide/solargraph/compare/master...jimeh:master
11
+
12
+ To use this gem, you should first uninstall the `solargraph` gem to avoid
13
+ conflicts, as both gems provide a binary called `solargraph`.
14
+
15
+ The version of `jimeh-solargraph` will follow that of `solargraph`, with an
16
+ additional number added at the end. For example solargraph 0.40.4 will be
17
+ 0.40.4.1 of jimeh-solargraph. The final digit will be incremented
18
+ independently of the previous three digits that make up solargraph's version.
19
+
20
+ ---
21
+
22
+ ## A Ruby Language Server
23
+
24
+ Solargraph provides a comprehensive suite of tools for Ruby programming: intellisense, diagnostics, inline documentation, and type checking.
25
+
26
+ ## Online Demo
27
+
28
+ A web-based demonstration of Solargraph's autocomplete is available at https://solargraph.org/demo.
29
+
30
+ ## Installation
31
+
32
+ Install the gem from the command line:
33
+
34
+ gem install jimeh-solargraph
35
+
36
+ Or add it to your Gemfile:
37
+
38
+ gem 'jimeh-solargraph', group: :development
39
+
40
+ ## Using Solargraph
41
+
42
+ Plug-ins and extensions are available for the following editors:
43
+
44
+ * **Visual Studio Code**
45
+ * Extension: https://marketplace.visualstudio.com/items?itemName=castwide.solargraph
46
+ * GitHub: https://github.com/castwide/vscode-solargraph
47
+
48
+ * **Atom**
49
+ * Package: https://atom.io/packages/ruby-solargraph
50
+ * GitHub: https://github.com/castwide/atom-solargraph
51
+
52
+ * **Vim**
53
+ * GitHub: https://github.com/autozimu/LanguageClient-neovim
54
+
55
+ * **Emacs**
56
+ * GitHub: https://github.com/guskovd/emacs-solargraph
57
+
58
+ * **Eclipse**
59
+ * Plugin: https://marketplace.eclipse.org/content/ruby-solargraph
60
+ * GitHub: https://github.com/PyvesB/eclipse-solargraph
61
+
62
+ ### Gem Support
63
+
64
+ Solargraph is capable of providing code completion and documentation for gems that have YARD documentation. You can make sure your gems are documented by running `yard gems` from the command line. (YARD is included as one of Solargraph's gem dependencies. The first time you run it might take a while if you have a lot of gems installed).
65
+
66
+ When editing code, a `require` call that references a gem will pull the documentation into the code maps and include the gem's API in code completion and intellisense.
67
+
68
+ If your project automatically requires bundled gems (e.g., `require 'bundler/require'`), Solargraph will add all of the Gemfile's default dependecies to the map.
69
+
70
+ ### Type Checking
71
+
72
+ As of version 0.33.0, Solargraph includes a [type checker](https://github.com/castwide/solargraph/issues/192) that uses a combination of YARD tags and code analysis to report missing type definitions. In strict mode, it performs type inference to determine whether the tags match the types it detects from code.
73
+
74
+ ### Updating Core Documentation
75
+
76
+ The Solargraph gem ships with documentation for Ruby 2.2.2. You can download documentation for other Ruby versions from the command line.
77
+
78
+ $ solargraph list-cores # List the installed documentation versions
79
+ $ solargraph available-cores # List the versions available for download
80
+ $ solargraph download-core # Install the best match for your Ruby version
81
+ $ solargraph clear # Reset the documentation cache
82
+
83
+ ### The Documentation Cache
84
+
85
+ Solargraph uses a cache directory to store documentation for the Ruby core and customized documentation for certain gems. The default location is `~/.solargraph/cache`, e.g., `/home/<username>/.solargraph/cache` on Linux or `C:\Users\<username>\.solargraph` on Windows.
86
+
87
+ You can change the location of the cache directory with the `SOLARGRAPH_CACHE` environment variable. This can be useful if you want the cache to comply with the XDG Base Directory Specification.
88
+
89
+ ### Solargraph and Bundler
90
+
91
+ If you're using the language server with a project that uses Bundler, the most comprehensive way to use your bundled gems is to bundle Solargraph.
92
+
93
+ In the Gemfile:
94
+
95
+ gem 'solargraph', group: :development
96
+
97
+ Run `bundle install` and use `bundle exec yard gems` to generate the documentation. This process documents cached or vendored gems, or even gems that are installed from a local path.
98
+
99
+ In order to make sure you're using the correct dependencies, you can start the language server with Bundler. In VS Code, there's a `solargraph.useBundler` option. Other clients will vary, but the command you probably want to run is `bundle exec solargraph socket` or `bundle exec solargraph stdio`.
100
+
101
+ ### Integrating Other Editors
102
+
103
+ The [language server protocol](https://microsoft.github.io/language-server-protocol/specification) is the recommended way for integrating Solargraph into editors and IDEs. Clients can connect using either stdio or TCP. Language client developers should refer to [https://solargraph.org/guides/language-server](https://solargraph.org/guides/language-server).
104
+
105
+ ### More Information
106
+
107
+ See [https://solargraph.org/guides](https://solargraph.org/guides) for more tips and tutorials about Solargraph.
108
+
109
+ ## Contributing to Solargraph
110
+
111
+ ### Bug Reports and Feature Requests
112
+
113
+ [GitHub Issues](https://github.com/castwide/solargraph/issues) are the best place to ask questions, report problems, and suggest improvements.
114
+
115
+ ### Development
116
+
117
+ Code contributions are always appreciated. Feel free to fork the repo and submit pull requests. Check for open issues that could use help. Start new issues to discuss changes that have a major impact on the code or require large time commitments.
118
+
119
+ ### Sponsorship and Donation
120
+
121
+ Use Patreon to support ongoing development of Solargraph at [https://www.patreon.com/castwide](https://www.patreon.com/castwide).
122
+
123
+ You can also make one-time donations via PayPal at [https://www.paypal.me/castwide](https://www.paypal.me/castwide).
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ require 'rake'
2
+ require 'rspec/core/rake_task'
3
+ require 'bundler/gem_tasks'
4
+
5
+ begin
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new(:spec)
8
+ rescue LoadError
9
+ end
10
+
11
+ desc "Open a Pry session preloaded with this library"
12
+ task :console do
13
+ sh "pry -I lib -r solargraph.rb"
14
+ end
15
+
16
+ desc "Run the type checker"
17
+ task :typecheck do
18
+ sh "bundle exec solargraph typecheck --level typed"
19
+ end
20
+
21
+ desc "Run all tests"
22
+ task :test do
23
+ Rake::Task["typecheck"].invoke
24
+ Rake::Task["spec"].invoke
25
+ end
data/SPONSORS.md ADDED
@@ -0,0 +1,15 @@
1
+ # Sponsors
2
+
3
+ Solargraph is developed and maintained by [Castwide Technologies](https://castwide.com).
4
+
5
+ The following people and organizations provide funding or other resources. [Become a sponsor](https://patreon.com/castwide)
6
+
7
+ ## Linked Sponsors
8
+
9
+ - **[Calyptix Security](https://www.calyptix.com/)**
10
+
11
+ ## Named Sponsors
12
+
13
+ - Emily Strickland
14
+ - Tom de Grunt
15
+ - Akira Yamada
data/bin/solargraph ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'solargraph'
4
+
5
+ Solargraph::Shell.start(ARGV)
@@ -0,0 +1,44 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/lib'
2
+ require 'solargraph/version'
3
+ require 'date'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'jimeh-solargraph'
7
+ s.version = Solargraph::VERSION
8
+ s.date = Date.today.strftime("%Y-%m-%d")
9
+ s.summary = "A Ruby language server"
10
+ s.description = "IDE tools for code completion, inline documentation, and static analysis"
11
+ s.authors = ["Fred Snyder"]
12
+ s.email = 'admin@castwide.com'
13
+ s.files = Dir.chdir(File.expand_path('..', __FILE__)) do
14
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
15
+ end
16
+ s.homepage = 'http://solargraph.org'
17
+ s.license = 'MIT'
18
+ s.executables = ['solargraph']
19
+ s.metadata = {
20
+ 'source_code_uri' => 'https://github.com/jimeh/solargraph',
21
+ }
22
+
23
+ s.required_ruby_version = '>= 2.4'
24
+
25
+ s.add_runtime_dependency 'backport', '~> 1.1'
26
+ s.add_runtime_dependency 'benchmark'
27
+ s.add_runtime_dependency 'bundler', '>= 1.17.2'
28
+ s.add_runtime_dependency 'e2mmap'
29
+ s.add_runtime_dependency 'jaro_winkler', '~> 1.5'
30
+ s.add_runtime_dependency 'kramdown', '~> 2.3'
31
+ s.add_runtime_dependency 'kramdown-parser-gfm', '~> 1.1'
32
+ s.add_runtime_dependency 'parser', '~> 3.0'
33
+ s.add_runtime_dependency 'reverse_markdown', '>= 1.0.5', '< 3'
34
+ s.add_runtime_dependency 'rubocop', '>= 0.52'
35
+ s.add_runtime_dependency 'thor', '~> 1.0'
36
+ s.add_runtime_dependency 'tilt', '~> 2.0'
37
+ s.add_runtime_dependency 'yard', '~> 0.9', '>= 0.9.24'
38
+
39
+ s.add_development_dependency 'pry', '~> 0.11.3'
40
+ s.add_development_dependency 'public_suffix', '~> 3.1'
41
+ s.add_development_dependency 'rspec', '~> 3.5', '>= 3.5.0'
42
+ s.add_development_dependency 'simplecov', '~> 0.14'
43
+ s.add_development_dependency 'webmock', '~> 3.6'
44
+ end
data/lib/.rubocop.yml ADDED
@@ -0,0 +1,21 @@
1
+ Layout/EndOfLine:
2
+ EnforcedStyle: lf
3
+ Style/MethodDefParentheses:
4
+ Enabled: false
5
+ Layout/EmptyLineAfterGuardClause:
6
+ Enabled: false
7
+ Layout/SpaceAroundMethodCallOperator:
8
+ Enabled: true
9
+ Lint/RaiseException:
10
+ Enabled: true
11
+ Lint/StructNewOverride:
12
+ Enabled: true
13
+ Style/ExponentialNotation:
14
+ Enabled: true
15
+ Style/HashEachMethods:
16
+ Enabled: true
17
+ Style/HashTransformKeys:
18
+ Enabled: true
19
+ Style/HashTransformValues:
20
+ Enabled: true
21
+
data/lib/solargraph.rb ADDED
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ Encoding.default_external = 'UTF-8'
4
+
5
+ require 'solargraph/compat'
6
+ require 'solargraph/version'
7
+
8
+ # The top-level namespace for the Solargraph code mapping, documentation,
9
+ # static analysis, and language server libraries.
10
+ #
11
+ module Solargraph
12
+ class InvalidOffsetError < RangeError; end
13
+ class DiagnosticsError < RuntimeError; end
14
+ class FileNotFoundError < RuntimeError; end
15
+ class SourceNotAvailableError < StandardError; end
16
+ class ComplexTypeError < StandardError; end
17
+ class WorkspaceTooLargeError < RuntimeError; end
18
+ class BundleNotFoundError < StandardError; end
19
+
20
+ autoload :Position, 'solargraph/position'
21
+ autoload :Range, 'solargraph/range'
22
+ autoload :Location, 'solargraph/location'
23
+ autoload :Shell, 'solargraph/shell'
24
+ autoload :Source, 'solargraph/source'
25
+ autoload :SourceMap, 'solargraph/source_map'
26
+ autoload :ApiMap, 'solargraph/api_map'
27
+ autoload :YardMap, 'solargraph/yard_map'
28
+ autoload :Pin, 'solargraph/pin'
29
+ autoload :ServerMethods, 'solargraph/server_methods'
30
+ autoload :LanguageServer, 'solargraph/language_server'
31
+ autoload :Workspace, 'solargraph/workspace'
32
+ autoload :Page, 'solargraph/page'
33
+ autoload :Library, 'solargraph/library'
34
+ autoload :Diagnostics, 'solargraph/diagnostics'
35
+ autoload :ComplexType, 'solargraph/complex_type'
36
+ autoload :Bench, 'solargraph/bench'
37
+ autoload :Logging, 'solargraph/logging'
38
+ autoload :TypeChecker, 'solargraph/type_checker'
39
+ autoload :Environ, 'solargraph/environ'
40
+ autoload :Convention, 'solargraph/convention'
41
+ autoload :Documentor, 'solargraph/documentor'
42
+ autoload :Parser, 'solargraph/parser'
43
+
44
+ dir = File.dirname(__FILE__)
45
+ YARDOC_PATH = File.realpath(File.join(dir, '..', 'yardoc'))
46
+ YARD_EXTENSION_FILE = File.join(dir, 'yard-solargraph.rb')
47
+ VIEWS_PATH = File.join(dir, 'solargraph', 'views')
48
+
49
+ # A convenience method for Solargraph::Logging.logger.
50
+ #
51
+ # @return [Logger]
52
+ def self.logger
53
+ Solargraph::Logging.logger
54
+ end
55
+
56
+ # A helper method that runs Bundler.with_unbundled_env or falls back to
57
+ # Bundler.with_clean_env for earlier versions of Bundler.
58
+ #
59
+ def self.with_clean_env &block
60
+ meth = if Bundler.respond_to?(:with_unbundled_env)
61
+ :with_unbundled_env
62
+ else
63
+ :with_clean_env
64
+ end
65
+ Bundler.send meth, &block
66
+ end
67
+ end
@@ -0,0 +1,752 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ require 'set'
5
+ require 'pathname'
6
+ require 'yard'
7
+ require 'yard-solargraph'
8
+
9
+ module Solargraph
10
+ # An aggregate provider for information about workspaces, sources, gems, and
11
+ # the Ruby core.
12
+ #
13
+ class ApiMap
14
+ autoload :Cache, 'solargraph/api_map/cache'
15
+ autoload :SourceToYard, 'solargraph/api_map/source_to_yard'
16
+ autoload :Store, 'solargraph/api_map/store'
17
+ autoload :BundlerMethods, 'solargraph/api_map/bundler_methods'
18
+
19
+ include SourceToYard
20
+ include BundlerMethods
21
+
22
+ # @return [Array<String>]
23
+ attr_reader :unresolved_requires
24
+
25
+ # @param pins [Array<Solargraph::Pin::Base>]
26
+ def initialize pins: []
27
+ @source_map_hash = {}
28
+ @cache = Cache.new
29
+ @method_alias_stack = []
30
+ index pins
31
+ end
32
+
33
+ # @param pins [Array<Pin::Base>]
34
+ # @return [self]
35
+ def index pins
36
+ catalog Bench.new(pins: pins)
37
+ self
38
+ end
39
+
40
+ # Map a single source.
41
+ #
42
+ # @param source [Source]
43
+ # @return [self]
44
+ def map source
45
+ catalog Bench.new(opened: [source])
46
+ self
47
+ end
48
+
49
+ # @param name [String]
50
+ # @return [YARD::Tags::MacroDirective, nil]
51
+ def named_macro name
52
+ store.named_macros[name]
53
+ end
54
+
55
+ # Catalog a bench.
56
+ #
57
+ # @param bench [Bench]
58
+ # @return [self]
59
+ def catalog bench
60
+ new_map_hash = {}
61
+ # Bench always needs to be merged if it adds or removes sources
62
+ merged = (bench.sources.length == source_map_hash.values.length)
63
+ bench.sources.each do |source|
64
+ if source_map_hash.key?(source.filename)
65
+ if source_map_hash[source.filename].code == source.code &&
66
+ source_map_hash[source.filename].source.synchronized? &&
67
+ source.synchronized?
68
+ new_map_hash[source.filename] = source_map_hash[source.filename]
69
+ elsif !source.synchronized?
70
+ new_map_hash[source.filename] = source_map_hash[source.filename]
71
+ # @todo Smelly instance variable access
72
+ new_map_hash[source.filename].instance_variable_set(:@source, source)
73
+ else
74
+ map = Solargraph::SourceMap.map(source)
75
+ if source_map_hash[source.filename].try_merge!(map)
76
+ new_map_hash[source.filename] = source_map_hash[source.filename]
77
+ else
78
+ new_map_hash[source.filename] = map
79
+ merged = false
80
+ end
81
+ end
82
+ else
83
+ map = Solargraph::SourceMap.map(source)
84
+ new_map_hash[source.filename] = map
85
+ merged = false
86
+ end
87
+ end
88
+ return self if bench.pins.empty? && @store && merged
89
+ implicit.clear
90
+ pins = []
91
+ reqs = Set.new
92
+ # @param map [SourceMap]
93
+ new_map_hash.each_value do |map|
94
+ pins.concat map.pins
95
+ reqs.merge map.requires.map(&:name)
96
+ end
97
+ pins.concat bench.pins
98
+ reqs.merge bench.workspace.config.required
99
+ @required = reqs
100
+ bench.sources.each do |src|
101
+ implicit.merge new_map_hash[src.filename].environ
102
+ end
103
+ # implicit.merge Convention.for_global(self)
104
+ local_path_hash.clear
105
+ unless bench.workspace.require_paths.empty?
106
+ file_keys = new_map_hash.keys
107
+ workspace_path = Pathname.new(bench.workspace.directory)
108
+ reqs.delete_if do |r|
109
+ bench.workspace.require_paths.any? do |base|
110
+ pn = workspace_path.join(base, "#{r}.rb").to_s
111
+ if file_keys.include? pn
112
+ local_path_hash[r] = pn
113
+ true
114
+ else
115
+ false
116
+ end
117
+ end
118
+ end
119
+ end
120
+ reqs.merge implicit.requires
121
+ br = reqs.include?('bundler/require') ? require_from_bundle(bench.workspace.directory) : {}
122
+ reqs.merge br.keys
123
+ yard_map.change(reqs.to_a, br, bench.workspace.gemnames)
124
+ new_store = Store.new(yard_map.pins + implicit.pins + pins)
125
+ @cache.clear
126
+ @source_map_hash = new_map_hash
127
+ @store = new_store
128
+ @unresolved_requires = yard_map.unresolved_requires
129
+ workspace_filenames.clear
130
+ workspace_filenames.concat bench.workspace.filenames
131
+ @rebindable_method_names = nil
132
+ store.block_pins.each { |blk| blk.rebind(self) }
133
+ self
134
+ end
135
+
136
+ def required
137
+ @required ||= Set.new
138
+ end
139
+
140
+ # @return [Environ]
141
+ def implicit
142
+ @implicit ||= Environ.new
143
+ end
144
+
145
+ # @return [Hash{String => String}]
146
+ def local_path_hash
147
+ @local_paths ||= {}
148
+ end
149
+
150
+ # @param filename [String]
151
+ # @param position [Position, Array(Integer, Integer)]
152
+ # @return [Source::Cursor]
153
+ def cursor_at filename, position
154
+ position = Position.normalize(position)
155
+ raise FileNotFoundError, "File not found: #{filename}" unless source_map_hash.key?(filename)
156
+ source_map_hash[filename].cursor_at(position)
157
+ end
158
+
159
+ # Get a clip by filename and position.
160
+ #
161
+ # @param filename [String]
162
+ # @param position [Position, Array(Integer, Integer)]
163
+ # @return [SourceMap::Clip]
164
+ def clip_at filename, position
165
+ position = Position.normalize(position)
166
+ SourceMap::Clip.new(self, cursor_at(filename, position))
167
+ end
168
+
169
+ # Create an ApiMap with a workspace in the specified directory.
170
+ #
171
+ # @param directory [String]
172
+ # @return [ApiMap]
173
+ def self.load directory
174
+ api_map = new
175
+ workspace = Solargraph::Workspace.new(directory)
176
+ api_map.catalog Bench.new(workspace: workspace)
177
+ api_map
178
+ end
179
+
180
+ # @return [Array<Solargraph::Pin::Base>]
181
+ def pins
182
+ store.pins
183
+ end
184
+
185
+ def rebindable_method_names
186
+ @rebindable_method_names ||= begin
187
+ result = yard_map.rebindable_method_names
188
+ source_maps.each do |map|
189
+ result.merge map.rebindable_method_names
190
+ end
191
+ result
192
+ end
193
+ end
194
+
195
+ # An array of pins based on Ruby keywords (`if`, `end`, etc.).
196
+ #
197
+ # @return [Array<Solargraph::Pin::Keyword>]
198
+ def keyword_pins
199
+ store.pins_by_class(Pin::Keyword)
200
+ end
201
+
202
+ # An array of namespace names defined in the ApiMap.
203
+ #
204
+ # @return [Set<String>]
205
+ def namespaces
206
+ store.namespaces
207
+ end
208
+
209
+ # True if the namespace exists.
210
+ #
211
+ # @param name [String] The namespace to match
212
+ # @param context [String] The context to search
213
+ # @return [Boolean]
214
+ def namespace_exists? name, context = ''
215
+ !qualify(name, context).nil?
216
+ end
217
+
218
+ # Get suggestions for constants in the specified namespace. The result
219
+ # may contain both constant and namespace pins.
220
+ #
221
+ # @param namespace [String] The namespace
222
+ # @param contexts [Array<String>] The contexts
223
+ # @return [Array<Solargraph::Pin::Base>]
224
+ def get_constants namespace, *contexts
225
+ namespace ||= ''
226
+ contexts.push '' if contexts.empty?
227
+ cached = cache.get_constants(namespace, contexts)
228
+ return cached.clone unless cached.nil?
229
+ skip = Set.new
230
+ result = []
231
+ contexts.each do |context|
232
+ fqns = qualify(namespace, context)
233
+ visibility = [:public]
234
+ visibility.push :private if fqns == context
235
+ result.concat inner_get_constants(fqns, visibility, skip)
236
+ end
237
+ cache.set_constants(namespace, contexts, result)
238
+ result
239
+ end
240
+
241
+ # Get a fully qualified namespace name. This method will start the search
242
+ # in the specified context until it finds a match for the name.
243
+ #
244
+ # @param namespace [String, nil] The namespace to match
245
+ # @param context [String] The context to search
246
+ # @return [String]
247
+ def qualify namespace, context = ''
248
+ return namespace if ['self', nil].include?(namespace)
249
+ cached = cache.get_qualified_namespace(namespace, context)
250
+ return cached.clone unless cached.nil?
251
+ result = if namespace.start_with?('::')
252
+ inner_qualify(namespace[2..-1], '', Set.new)
253
+ else
254
+ inner_qualify(namespace, context, Set.new)
255
+ end
256
+ cache.set_qualified_namespace(namespace, context, result)
257
+ result
258
+ end
259
+
260
+ # Get an array of instance variable pins defined in specified namespace
261
+ # and scope.
262
+ #
263
+ # @param namespace [String] A fully qualified namespace
264
+ # @param scope [Symbol] :instance or :class
265
+ # @return [Array<Solargraph::Pin::InstanceVariable>]
266
+ def get_instance_variable_pins(namespace, scope = :instance)
267
+ result = []
268
+ used = [namespace]
269
+ result.concat store.get_instance_variables(namespace, scope)
270
+ sc = qualify_lower(store.get_superclass(namespace), namespace)
271
+ until sc.nil? || used.include?(sc)
272
+ used.push sc
273
+ result.concat store.get_instance_variables(sc, scope)
274
+ sc = qualify_lower(store.get_superclass(sc), sc)
275
+ end
276
+ result
277
+ end
278
+
279
+ # Get an array of class variable pins for a namespace.
280
+ #
281
+ # @param namespace [String] A fully qualified namespace
282
+ # @return [Array<Solargraph::Pin::ClassVariable>]
283
+ def get_class_variable_pins(namespace)
284
+ prefer_non_nil_variables(store.get_class_variables(namespace))
285
+ end
286
+
287
+ # @return [Array<Solargraph::Pin::Base>]
288
+ def get_symbols
289
+ store.get_symbols
290
+ end
291
+
292
+ # @return [Array<Solargraph::Pin::GlobalVariable>]
293
+ def get_global_variable_pins
294
+ store.pins_by_class(Pin::GlobalVariable)
295
+ end
296
+
297
+ # Get an array of methods available in a particular context.
298
+ #
299
+ # @param fqns [String] The fully qualified namespace to search for methods
300
+ # @param scope [Symbol] :class or :instance
301
+ # @param visibility [Array<Symbol>] :public, :protected, and/or :private
302
+ # @param deep [Boolean] True to include superclasses, mixins, etc.
303
+ # @return [Array<Solargraph::Pin::Method>]
304
+ def get_methods fqns, scope: :instance, visibility: [:public], deep: true
305
+ cached = cache.get_methods(fqns, scope, visibility, deep)
306
+ return cached.clone unless cached.nil?
307
+ result = []
308
+ skip = Set.new
309
+ if fqns == ''
310
+ # @todo Implement domains
311
+ implicit.domains.each do |domain|
312
+ type = ComplexType.try_parse(domain)
313
+ next if type.undefined?
314
+ result.concat inner_get_methods(type.name, type.scope, [:public], deep, skip)
315
+ end
316
+ result.concat inner_get_methods(fqns, :class, visibility, deep, skip)
317
+ result.concat inner_get_methods(fqns, :instance, visibility, deep, skip)
318
+ result.concat inner_get_methods('Kernel', :instance, visibility, deep, skip)
319
+ else
320
+ result.concat inner_get_methods(fqns, scope, visibility, deep, skip)
321
+ result.concat inner_get_methods('Kernel', :instance, [:public], deep, skip) if visibility.include?(:private)
322
+ end
323
+ resolved = resolve_method_aliases(result, visibility)
324
+ cache.set_methods(fqns, scope, visibility, deep, resolved)
325
+ resolved
326
+ end
327
+
328
+ # Get an array of method pins for a complex type.
329
+ #
330
+ # The type's namespace and the context should be fully qualified. If the
331
+ # context matches the namespace type or is a subclass of the type,
332
+ # protected methods are included in the results. If protected methods are
333
+ # included and internal is true, private methods are also included.
334
+ #
335
+ # @example
336
+ # api_map = Solargraph::ApiMap.new
337
+ # type = Solargraph::ComplexType.parse('String')
338
+ # api_map.get_complex_type_methods(type)
339
+ #
340
+ # @param type [Solargraph::ComplexType] The complex type of the namespace
341
+ # @param context [String] The context from which the type is referenced
342
+ # @param internal [Boolean] True to include private methods
343
+ # @return [Array<Solargraph::Pin::Base>]
344
+ def get_complex_type_methods type, context = '', internal = false
345
+ # This method does not qualify the complex type's namespace because
346
+ # it can cause conflicts between similar names, e.g., `Foo` vs.
347
+ # `Other::Foo`. It still takes a context argument to determine whether
348
+ # protected and private methods are visible.
349
+ return [] if type.undefined? || type.void?
350
+ result = []
351
+ if type.duck_type?
352
+ type.select(&:duck_type?).each do |t|
353
+ result.push Pin::DuckMethod.new(name: t.tag[1..-1])
354
+ end
355
+ result.concat get_methods('Object')
356
+ else
357
+ unless type.nil? || type.name == 'void'
358
+ visibility = [:public]
359
+ if type.namespace == context || super_and_sub?(type.namespace, context)
360
+ visibility.push :protected
361
+ visibility.push :private if internal
362
+ end
363
+ result.concat get_methods(type.namespace, scope: type.scope, visibility: visibility)
364
+ end
365
+ end
366
+ result
367
+ end
368
+
369
+ # Get a stack of method pins for a method name in a namespace. The order
370
+ # of the pins corresponds to the ancestry chain, with highest precedence
371
+ # first.
372
+ #
373
+ # @example
374
+ # api_map.get_method_stack('Subclass', 'method_name')
375
+ # #=> [ <Subclass#method_name pin>, <Superclass#method_name pin> ]
376
+ #
377
+ # @param fqns [String]
378
+ # @param name [String]
379
+ # @param scope [Symbol] :instance or :class
380
+ # @return [Array<Solargraph::Pin::Method>]
381
+ def get_method_stack fqns, name, scope: :instance
382
+ get_methods(fqns, scope: scope, visibility: [:private, :protected, :public]).select { |p| p.name == name }
383
+ end
384
+
385
+ # Get an array of all suggestions that match the specified path.
386
+ #
387
+ # @deprecated Use #get_path_pins instead.
388
+ #
389
+ # @param path [String] The path to find
390
+ # @return [Array<Solargraph::Pin::Base>]
391
+ def get_path_suggestions path
392
+ return [] if path.nil?
393
+ resolve_method_aliases store.get_path_pins(path)
394
+ end
395
+
396
+ # Get an array of pins that match the specified path.
397
+ #
398
+ # @param path [String]
399
+ # @return [Array<Pin::Base>]
400
+ def get_path_pins path
401
+ get_path_suggestions(path)
402
+ end
403
+
404
+ # Get a list of documented paths that match the query.
405
+ #
406
+ # @example
407
+ # api_map.query('str') # Results will include `String` and `Struct`
408
+ #
409
+ # @param query [String] The text to match
410
+ # @return [Array<String>]
411
+ def search query
412
+ rake_yard(store)
413
+ found = []
414
+ code_object_paths.each do |k|
415
+ if (found.empty? || (query.include?('.') || query.include?('#')) || !(k.include?('.') || k.include?('#'))) &&
416
+ k.downcase.include?(query.downcase)
417
+ found.push k
418
+ end
419
+ end
420
+ found
421
+ end
422
+
423
+ # Get YARD documentation for the specified path.
424
+ #
425
+ # @example
426
+ # api_map.document('String#split')
427
+ #
428
+ # @param path [String] The path to find
429
+ # @return [Array<YARD::CodeObjects::Base>]
430
+ def document path
431
+ rake_yard(store)
432
+ docs = []
433
+ docs.push code_object_at(path) unless code_object_at(path).nil?
434
+ docs
435
+ end
436
+
437
+ # Get an array of all symbols in the workspace that match the query.
438
+ #
439
+ # @param query [String]
440
+ # @return [Array<Pin::Base>]
441
+ def query_symbols query
442
+ result = []
443
+ source_map_hash.each_value { |s| result.concat s.query_symbols(query) }
444
+ result
445
+ end
446
+
447
+ # @param location [Solargraph::Location]
448
+ # @return [Array<Solargraph::Pin::Base>]
449
+ def locate_pins location
450
+ return [] if location.nil? || !source_map_hash.key?(location.filename)
451
+ resolve_method_aliases source_map_hash[location.filename].locate_pins(location)
452
+ end
453
+
454
+ # @raise [FileNotFoundError] if the cursor's file is not in the ApiMap
455
+ # @param cursor [Source::Cursor]
456
+ # @return [SourceMap::Clip]
457
+ def clip cursor
458
+ raise FileNotFoundError, "ApiMap did not catalog #{cursor.filename}" unless source_map_hash.key?(cursor.filename)
459
+ SourceMap::Clip.new(self, cursor)
460
+ end
461
+
462
+ # Get an array of document symbols from a file.
463
+ #
464
+ # @param filename [String]
465
+ # @return [Array<Pin::Symbol>]
466
+ def document_symbols filename
467
+ return [] unless source_map_hash.key?(filename) # @todo Raise error?
468
+ resolve_method_aliases source_map_hash[filename].document_symbols
469
+ end
470
+
471
+ # @return [Array<SourceMap>]
472
+ def source_maps
473
+ source_map_hash.values
474
+ end
475
+
476
+ # Get a source map by filename.
477
+ #
478
+ # @param filename [String]
479
+ # @return [SourceMap]
480
+ def source_map filename
481
+ raise FileNotFoundError, "Source map for `#{filename}` not found" unless source_map_hash.key?(filename)
482
+ source_map_hash[filename]
483
+ end
484
+
485
+ # True if the specified file was included in a bundle, i.e., it's either
486
+ # included in a workspace or open in a library.
487
+ #
488
+ # @param filename [String]
489
+ def bundled? filename
490
+ source_map_hash.keys.include?(filename)
491
+ end
492
+
493
+ # True if the specified file is included in the workspace.
494
+ #
495
+ # @param filename [String]
496
+ def workspaced? filename
497
+ workspace_filenames.include?(filename)
498
+ end
499
+
500
+ # @param location [Location]
501
+ # @return [Location]
502
+ def require_reference_at location
503
+ map = source_map(location.filename)
504
+ pin = map.requires.select { |p| p.location.range.contain?(location.range.start) }.first
505
+ return nil if pin.nil?
506
+ if local_path_hash.key?(pin.name)
507
+ return Location.new(local_path_hash[pin.name], Solargraph::Range.from_to(0, 0, 0, 0))
508
+ end
509
+ yard_map.require_reference(pin.name)
510
+ rescue FileNotFoundError
511
+ nil
512
+ end
513
+
514
+ # Check if a class is a superclass of another class.
515
+ #
516
+ # @param sup [String] The superclass
517
+ # @param sub [String] The subclass
518
+ # @return [Boolean]
519
+ def super_and_sub?(sup, sub)
520
+ fqsup = qualify(sup)
521
+ cls = qualify(sub)
522
+ until fqsup.nil? || cls.nil?
523
+ return true if cls == fqsup
524
+ cls = qualify_superclass(cls)
525
+ end
526
+ false
527
+ end
528
+
529
+ # @return [YardMap]
530
+ def yard_map
531
+ @yard_map ||= YardMap.new
532
+ end
533
+
534
+ private
535
+
536
+ # @return [Array<String>]
537
+ def workspace_filenames
538
+ @workspace_filenames ||= []
539
+ end
540
+
541
+ # A hash of source maps with filename keys.
542
+ #
543
+ # @return [Hash{String => SourceMap}]
544
+ attr_reader :source_map_hash
545
+
546
+ # @return [ApiMap::Store]
547
+ attr_reader :store
548
+
549
+ # @return [Solargraph::ApiMap::Cache]
550
+ attr_reader :cache
551
+
552
+ # @param fqns [String] A fully qualified namespace
553
+ # @param scope [Symbol] :class or :instance
554
+ # @param visibility [Array<Symbol>] :public, :protected, and/or :private
555
+ # @param deep [Boolean]
556
+ # @param skip [Set<String>]
557
+ # @param no_core [Boolean] Skip core classes if true
558
+ # @return [Array<Pin::Base>]
559
+ def inner_get_methods fqns, scope, visibility, deep, skip, no_core = false
560
+ return [] if no_core && fqns =~ /^(Object|BasicObject|Class|Module|Kernel)$/
561
+ reqstr = "#{fqns}|#{scope}|#{visibility.sort}|#{deep}"
562
+ return [] if skip.include?(reqstr)
563
+ skip.add reqstr
564
+ result = []
565
+ if deep && scope == :instance
566
+ store.get_prepends(fqns).reverse.each do |im|
567
+ fqim = qualify(im, fqns)
568
+ result.concat inner_get_methods(fqim, scope, visibility, deep, skip, true) unless fqim.nil?
569
+ end
570
+ end
571
+ result.concat store.get_methods(fqns, scope: scope, visibility: visibility).sort{ |a, b| a.name <=> b.name }
572
+ if deep
573
+ if scope == :instance
574
+ store.get_includes(fqns).reverse.each do |im|
575
+ fqim = qualify(im, fqns)
576
+ result.concat inner_get_methods(fqim, scope, visibility, deep, skip, true) unless fqim.nil?
577
+ end
578
+ fqsc = qualify_superclass(fqns)
579
+ unless fqsc.nil?
580
+ result.concat inner_get_methods(fqsc, scope, visibility, true, skip, no_core) unless fqsc.nil?
581
+ end
582
+ else
583
+ store.get_extends(fqns).reverse.each do |em|
584
+ fqem = qualify(em, fqns)
585
+ result.concat inner_get_methods(fqem, :instance, visibility, deep, skip, true) unless fqem.nil?
586
+ end
587
+ fqsc = qualify_superclass(fqns)
588
+ unless fqsc.nil?
589
+ result.concat inner_get_methods(fqsc, scope, visibility, true, skip, true) unless fqsc.nil?
590
+ end
591
+ unless no_core || fqns.empty?
592
+ type = get_namespace_type(fqns)
593
+ result.concat inner_get_methods('Class', :instance, visibility, deep, skip, no_core) if type == :class
594
+ result.concat inner_get_methods('Module', :instance, visibility, deep, skip, no_core)
595
+ end
596
+ end
597
+ store.domains(fqns).each do |d|
598
+ dt = ComplexType.try_parse(d)
599
+ result.concat inner_get_methods(dt.namespace, dt.scope, [:public], deep, skip)
600
+ end
601
+ end
602
+ result
603
+ end
604
+
605
+ # @param fqns [String]
606
+ # @param visibility [Array<Symbol>]
607
+ # @param skip [Set<String>]
608
+ # @return [Array<Pin::Base>]
609
+ def inner_get_constants fqns, visibility, skip
610
+ return [] if fqns.nil? || skip.include?(fqns)
611
+ skip.add fqns
612
+ result = []
613
+ store.get_prepends(fqns).each do |is|
614
+ result.concat inner_get_constants(qualify(is, fqns), [:public], skip)
615
+ end
616
+ result.concat store.get_constants(fqns, visibility)
617
+ .sort { |a, b| a.name <=> b.name }
618
+ store.get_includes(fqns).each do |is|
619
+ result.concat inner_get_constants(qualify(is, fqns), [:public], skip)
620
+ end
621
+ fqsc = qualify_superclass(fqns)
622
+ unless %w[Object BasicObject].include?(fqsc)
623
+ result.concat inner_get_constants(fqsc, [:public], skip)
624
+ end
625
+ result
626
+ end
627
+
628
+ # @return [Hash]
629
+ def path_macros
630
+ @path_macros ||= {}
631
+ end
632
+
633
+ # @param namespace [String]
634
+ # @param context [String]
635
+ # @return [String]
636
+ def qualify_lower namespace, context
637
+ qualify namespace, context.split('::')[0..-2].join('::')
638
+ end
639
+
640
+ def qualify_superclass fqsub
641
+ sup = store.get_superclass(fqsub)
642
+ return nil if sup.nil?
643
+ parts = fqsub.split('::')
644
+ last = parts.pop
645
+ parts.pop if last == sup
646
+ qualify(sup, parts.join('::'))
647
+ end
648
+
649
+ # @param name [String]
650
+ # @param root [String]
651
+ # @param skip [Set<String>]
652
+ # @return [String, nil]
653
+ def inner_qualify name, root, skip
654
+ return nil if name.nil?
655
+ return nil if skip.include?(root)
656
+ skip.add root
657
+ possibles = []
658
+ if name == ''
659
+ if root == ''
660
+ return ''
661
+ else
662
+ return inner_qualify(root, '', skip)
663
+ end
664
+ else
665
+ return name if root == '' && store.namespace_exists?(name)
666
+ roots = root.to_s.split('::')
667
+ while roots.length > 0
668
+ fqns = roots.join('::') + '::' + name
669
+ return fqns if store.namespace_exists?(fqns)
670
+ incs = store.get_includes(roots.join('::'))
671
+ incs.each do |inc|
672
+ foundinc = inner_qualify(name, inc, skip)
673
+ possibles.push foundinc unless foundinc.nil?
674
+ end
675
+ roots.pop
676
+ end
677
+ if possibles.empty?
678
+ incs = store.get_includes('')
679
+ incs.each do |inc|
680
+ foundinc = inner_qualify(name, inc, skip)
681
+ possibles.push foundinc unless foundinc.nil?
682
+ end
683
+ end
684
+ return name if store.namespace_exists?(name)
685
+ return possibles.last
686
+ end
687
+ end
688
+
689
+ # Get the namespace's type (Class or Module).
690
+ #
691
+ # @param fqns [String] A fully qualified namespace
692
+ # @return [Symbol, nil] :class, :module, or nil
693
+ def get_namespace_type fqns
694
+ return nil if fqns.nil?
695
+ # @type [Pin::Namespace, nil]
696
+ pin = store.get_path_pins(fqns).select{|p| p.is_a?(Pin::Namespace)}.first
697
+ return nil if pin.nil?
698
+ pin.type
699
+ end
700
+
701
+ # Sort an array of pins to put nil or undefined variables last.
702
+ #
703
+ # @param pins [Array<Solargraph::Pin::Base>]
704
+ # @return [Array<Solargraph::Pin::Base>]
705
+ def prefer_non_nil_variables pins
706
+ result = []
707
+ nil_pins = []
708
+ pins.each do |pin|
709
+ if pin.variable? && pin.nil_assignment?
710
+ nil_pins.push pin
711
+ else
712
+ result.push pin
713
+ end
714
+ end
715
+ result + nil_pins
716
+ end
717
+
718
+ # @param pins [Array<Pin::Base>]
719
+ # @param visibility [Array<Symbol>]
720
+ # @return [Array<Pin::Base>]
721
+ def resolve_method_aliases pins, visibility = [:public, :private, :protected]
722
+ result = []
723
+ pins.each do |pin|
724
+ resolved = resolve_method_alias(pin)
725
+ next if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
726
+ result.push resolved
727
+ end
728
+ result
729
+ end
730
+
731
+ # @param pin [Pin::MethodAlias, Pin::Base]
732
+ # @return [Pin::Method]
733
+ def resolve_method_alias pin
734
+ return pin if !pin.is_a?(Pin::MethodAlias) || @method_alias_stack.include?(pin.path)
735
+ @method_alias_stack.push pin.path
736
+ origin = get_method_stack(pin.full_context.namespace, pin.original, scope: pin.scope).first
737
+ @method_alias_stack.pop
738
+ return pin if origin.nil?
739
+ args = {
740
+ location: pin.location,
741
+ closure: pin.closure,
742
+ name: pin.name,
743
+ comments: origin.comments,
744
+ scope: origin.scope,
745
+ visibility: origin.visibility,
746
+ parameters: origin.parameters,
747
+ attribute: origin.attribute?
748
+ }
749
+ Pin::Method.new **args
750
+ end
751
+ end
752
+ end