solargraph 0.39.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (252) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +28 -0
  5. data/.yardopts +2 -0
  6. data/Gemfile +7 -0
  7. data/LICENSE +21 -0
  8. data/README.md +104 -0
  9. data/Rakefile +14 -0
  10. data/SPONSORS.md +9 -0
  11. data/bin/solargraph +5 -0
  12. data/lib/.rubocop.yml +21 -0
  13. data/lib/solargraph.rb +66 -0
  14. data/lib/solargraph/api_map.rb +745 -0
  15. data/lib/solargraph/api_map/bundler_methods.rb +27 -0
  16. data/lib/solargraph/api_map/cache.rb +66 -0
  17. data/lib/solargraph/api_map/source_to_yard.rb +81 -0
  18. data/lib/solargraph/api_map/store.rb +267 -0
  19. data/lib/solargraph/bundle.rb +26 -0
  20. data/lib/solargraph/complex_type.rb +213 -0
  21. data/lib/solargraph/complex_type/type_methods.rb +127 -0
  22. data/lib/solargraph/complex_type/unique_type.rb +75 -0
  23. data/lib/solargraph/convention.rb +38 -0
  24. data/lib/solargraph/convention/base.rb +25 -0
  25. data/lib/solargraph/convention/gemfile.rb +18 -0
  26. data/lib/solargraph/convention/gemspec.rb +25 -0
  27. data/lib/solargraph/convention/rspec.rb +24 -0
  28. data/lib/solargraph/converters/dd.rb +12 -0
  29. data/lib/solargraph/converters/dl.rb +12 -0
  30. data/lib/solargraph/converters/dt.rb +12 -0
  31. data/lib/solargraph/converters/misc.rb +1 -0
  32. data/lib/solargraph/core_fills.rb +159 -0
  33. data/lib/solargraph/diagnostics.rb +55 -0
  34. data/lib/solargraph/diagnostics/base.rb +29 -0
  35. data/lib/solargraph/diagnostics/require_not_found.rb +37 -0
  36. data/lib/solargraph/diagnostics/rubocop.rb +90 -0
  37. data/lib/solargraph/diagnostics/rubocop_helpers.rb +64 -0
  38. data/lib/solargraph/diagnostics/severities.rb +15 -0
  39. data/lib/solargraph/diagnostics/type_check.rb +54 -0
  40. data/lib/solargraph/diagnostics/update_errors.rb +41 -0
  41. data/lib/solargraph/documentor.rb +76 -0
  42. data/lib/solargraph/environ.rb +40 -0
  43. data/lib/solargraph/language_server.rb +19 -0
  44. data/lib/solargraph/language_server/completion_item_kinds.rb +35 -0
  45. data/lib/solargraph/language_server/error_codes.rb +20 -0
  46. data/lib/solargraph/language_server/host.rb +741 -0
  47. data/lib/solargraph/language_server/host/cataloger.rb +56 -0
  48. data/lib/solargraph/language_server/host/diagnoser.rb +81 -0
  49. data/lib/solargraph/language_server/host/dispatch.rb +112 -0
  50. data/lib/solargraph/language_server/host/sources.rb +156 -0
  51. data/lib/solargraph/language_server/message.rb +92 -0
  52. data/lib/solargraph/language_server/message/base.rb +85 -0
  53. data/lib/solargraph/language_server/message/cancel_request.rb +13 -0
  54. data/lib/solargraph/language_server/message/client.rb +11 -0
  55. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -0
  56. data/lib/solargraph/language_server/message/completion_item.rb +11 -0
  57. data/lib/solargraph/language_server/message/completion_item/resolve.rb +57 -0
  58. data/lib/solargraph/language_server/message/exit_notification.rb +13 -0
  59. data/lib/solargraph/language_server/message/extended.rb +21 -0
  60. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +95 -0
  61. data/lib/solargraph/language_server/message/extended/document.rb +20 -0
  62. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -0
  63. data/lib/solargraph/language_server/message/extended/download_core.rb +23 -0
  64. data/lib/solargraph/language_server/message/extended/environment.rb +25 -0
  65. data/lib/solargraph/language_server/message/extended/search.rb +20 -0
  66. data/lib/solargraph/language_server/message/initialize.rb +153 -0
  67. data/lib/solargraph/language_server/message/initialized.rb +26 -0
  68. data/lib/solargraph/language_server/message/method_not_found.rb +16 -0
  69. data/lib/solargraph/language_server/message/method_not_implemented.rb +14 -0
  70. data/lib/solargraph/language_server/message/shutdown.rb +13 -0
  71. data/lib/solargraph/language_server/message/text_document.rb +28 -0
  72. data/lib/solargraph/language_server/message/text_document/base.rb +19 -0
  73. data/lib/solargraph/language_server/message/text_document/code_action.rb +17 -0
  74. data/lib/solargraph/language_server/message/text_document/completion.rb +57 -0
  75. data/lib/solargraph/language_server/message/text_document/definition.rb +38 -0
  76. data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -0
  77. data/lib/solargraph/language_server/message/text_document/did_close.rb +15 -0
  78. data/lib/solargraph/language_server/message/text_document/did_open.rb +15 -0
  79. data/lib/solargraph/language_server/message/text_document/did_save.rb +17 -0
  80. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +23 -0
  81. data/lib/solargraph/language_server/message/text_document/folding_range.rb +26 -0
  82. data/lib/solargraph/language_server/message/text_document/formatting.rb +78 -0
  83. data/lib/solargraph/language_server/message/text_document/hover.rb +44 -0
  84. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +34 -0
  85. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -0
  86. data/lib/solargraph/language_server/message/text_document/references.rb +16 -0
  87. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -0
  88. data/lib/solargraph/language_server/message/text_document/signature_help.rb +29 -0
  89. data/lib/solargraph/language_server/message/workspace.rb +14 -0
  90. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +29 -0
  91. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +33 -0
  92. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -0
  93. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -0
  94. data/lib/solargraph/language_server/message_types.rb +14 -0
  95. data/lib/solargraph/language_server/request.rb +24 -0
  96. data/lib/solargraph/language_server/symbol_kinds.rb +36 -0
  97. data/lib/solargraph/language_server/transport.rb +13 -0
  98. data/lib/solargraph/language_server/transport/adapter.rb +56 -0
  99. data/lib/solargraph/language_server/transport/data_reader.rb +72 -0
  100. data/lib/solargraph/language_server/uri_helpers.rb +49 -0
  101. data/lib/solargraph/library.rb +414 -0
  102. data/lib/solargraph/location.rb +37 -0
  103. data/lib/solargraph/logging.rb +27 -0
  104. data/lib/solargraph/page.rb +83 -0
  105. data/lib/solargraph/parser.rb +26 -0
  106. data/lib/solargraph/parser/comment_ripper.rb +52 -0
  107. data/lib/solargraph/parser/legacy.rb +12 -0
  108. data/lib/solargraph/parser/legacy/class_methods.rb +109 -0
  109. data/lib/solargraph/parser/legacy/flawed_builder.rb +16 -0
  110. data/lib/solargraph/parser/legacy/node_chainer.rb +118 -0
  111. data/lib/solargraph/parser/legacy/node_methods.rb +300 -0
  112. data/lib/solargraph/parser/legacy/node_processors.rb +54 -0
  113. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +23 -0
  114. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +35 -0
  115. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +15 -0
  116. data/lib/solargraph/parser/legacy/node_processors/block_node.rb +22 -0
  117. data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +25 -0
  118. data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +23 -0
  119. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +63 -0
  120. data/lib/solargraph/parser/legacy/node_processors/defs_node.rb +36 -0
  121. data/lib/solargraph/parser/legacy/node_processors/gvasgn_node.rb +23 -0
  122. data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +38 -0
  123. data/lib/solargraph/parser/legacy/node_processors/lvasgn_node.rb +28 -0
  124. data/lib/solargraph/parser/legacy/node_processors/namespace_node.rb +39 -0
  125. data/lib/solargraph/parser/legacy/node_processors/orasgn_node.rb +16 -0
  126. data/lib/solargraph/parser/legacy/node_processors/resbody_node.rb +36 -0
  127. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +21 -0
  128. data/lib/solargraph/parser/legacy/node_processors/send_node.rb +234 -0
  129. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +18 -0
  130. data/lib/solargraph/parser/node_methods.rb +43 -0
  131. data/lib/solargraph/parser/node_processor.rb +43 -0
  132. data/lib/solargraph/parser/node_processor/base.rb +77 -0
  133. data/lib/solargraph/parser/region.rb +66 -0
  134. data/lib/solargraph/parser/rubyvm.rb +40 -0
  135. data/lib/solargraph/parser/rubyvm/class_methods.rb +150 -0
  136. data/lib/solargraph/parser/rubyvm/node_chainer.rb +135 -0
  137. data/lib/solargraph/parser/rubyvm/node_methods.rb +284 -0
  138. data/lib/solargraph/parser/rubyvm/node_processors.rb +61 -0
  139. data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -0
  140. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +62 -0
  141. data/lib/solargraph/parser/rubyvm/node_processors/begin_node.rb +15 -0
  142. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +22 -0
  143. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +22 -0
  144. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +23 -0
  145. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +64 -0
  146. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +57 -0
  147. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +23 -0
  148. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +38 -0
  149. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +39 -0
  150. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +20 -0
  151. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +27 -0
  152. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +39 -0
  153. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +31 -0
  154. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +15 -0
  155. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +45 -0
  156. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +21 -0
  157. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +15 -0
  158. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +255 -0
  159. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +18 -0
  160. data/lib/solargraph/parser/snippet.rb +13 -0
  161. data/lib/solargraph/pin.rb +39 -0
  162. data/lib/solargraph/pin/attribute.rb +49 -0
  163. data/lib/solargraph/pin/base.rb +296 -0
  164. data/lib/solargraph/pin/base_method.rb +141 -0
  165. data/lib/solargraph/pin/base_variable.rb +84 -0
  166. data/lib/solargraph/pin/block.rb +48 -0
  167. data/lib/solargraph/pin/class_variable.rb +8 -0
  168. data/lib/solargraph/pin/closure.rb +37 -0
  169. data/lib/solargraph/pin/common.rb +70 -0
  170. data/lib/solargraph/pin/constant.rb +43 -0
  171. data/lib/solargraph/pin/conversions.rb +97 -0
  172. data/lib/solargraph/pin/documenting.rb +110 -0
  173. data/lib/solargraph/pin/duck_method.rb +16 -0
  174. data/lib/solargraph/pin/global_variable.rb +8 -0
  175. data/lib/solargraph/pin/instance_variable.rb +30 -0
  176. data/lib/solargraph/pin/keyword.rb +15 -0
  177. data/lib/solargraph/pin/keyword_param.rb +8 -0
  178. data/lib/solargraph/pin/local_variable.rb +21 -0
  179. data/lib/solargraph/pin/localized.rb +43 -0
  180. data/lib/solargraph/pin/method.rb +111 -0
  181. data/lib/solargraph/pin/method_alias.rb +31 -0
  182. data/lib/solargraph/pin/namespace.rb +85 -0
  183. data/lib/solargraph/pin/parameter.rb +206 -0
  184. data/lib/solargraph/pin/proxy_type.rb +29 -0
  185. data/lib/solargraph/pin/reference.rb +14 -0
  186. data/lib/solargraph/pin/reference/extend.rb +10 -0
  187. data/lib/solargraph/pin/reference/include.rb +10 -0
  188. data/lib/solargraph/pin/reference/override.rb +29 -0
  189. data/lib/solargraph/pin/reference/prepend.rb +10 -0
  190. data/lib/solargraph/pin/reference/require.rb +14 -0
  191. data/lib/solargraph/pin/reference/superclass.rb +10 -0
  192. data/lib/solargraph/pin/singleton.rb +11 -0
  193. data/lib/solargraph/pin/symbol.rb +47 -0
  194. data/lib/solargraph/pin/yard_pin.rb +12 -0
  195. data/lib/solargraph/pin/yard_pin/constant.rb +25 -0
  196. data/lib/solargraph/pin/yard_pin/method.rb +65 -0
  197. data/lib/solargraph/pin/yard_pin/namespace.rb +27 -0
  198. data/lib/solargraph/pin/yard_pin/yard_mixin.rb +26 -0
  199. data/lib/solargraph/position.rb +112 -0
  200. data/lib/solargraph/range.rb +95 -0
  201. data/lib/solargraph/server_methods.rb +16 -0
  202. data/lib/solargraph/shell.rb +221 -0
  203. data/lib/solargraph/source.rb +533 -0
  204. data/lib/solargraph/source/chain.rb +172 -0
  205. data/lib/solargraph/source/chain/block_variable.rb +13 -0
  206. data/lib/solargraph/source/chain/call.rb +203 -0
  207. data/lib/solargraph/source/chain/class_variable.rb +13 -0
  208. data/lib/solargraph/source/chain/constant.rb +75 -0
  209. data/lib/solargraph/source/chain/global_variable.rb +13 -0
  210. data/lib/solargraph/source/chain/head.rb +35 -0
  211. data/lib/solargraph/source/chain/instance_variable.rb +13 -0
  212. data/lib/solargraph/source/chain/link.rb +67 -0
  213. data/lib/solargraph/source/chain/literal.rb +23 -0
  214. data/lib/solargraph/source/chain/or.rb +23 -0
  215. data/lib/solargraph/source/chain/variable.rb +13 -0
  216. data/lib/solargraph/source/chain/z_super.rb +184 -0
  217. data/lib/solargraph/source/change.rb +79 -0
  218. data/lib/solargraph/source/cursor.rb +164 -0
  219. data/lib/solargraph/source/encoding_fixes.rb +23 -0
  220. data/lib/solargraph/source/source_chainer.rb +189 -0
  221. data/lib/solargraph/source/updater.rb +54 -0
  222. data/lib/solargraph/source_map.rb +170 -0
  223. data/lib/solargraph/source_map/clip.rb +190 -0
  224. data/lib/solargraph/source_map/completion.rb +23 -0
  225. data/lib/solargraph/source_map/mapper.rb +199 -0
  226. data/lib/solargraph/stdlib_fills.rb +32 -0
  227. data/lib/solargraph/type_checker.rb +498 -0
  228. data/lib/solargraph/type_checker/checks.rb +95 -0
  229. data/lib/solargraph/type_checker/param_def.rb +35 -0
  230. data/lib/solargraph/type_checker/problem.rb +32 -0
  231. data/lib/solargraph/type_checker/rules.rb +53 -0
  232. data/lib/solargraph/version.rb +5 -0
  233. data/lib/solargraph/views/_method.erb +62 -0
  234. data/lib/solargraph/views/_name_type_tag.erb +10 -0
  235. data/lib/solargraph/views/_namespace.erb +24 -0
  236. data/lib/solargraph/views/document.erb +23 -0
  237. data/lib/solargraph/views/environment.erb +58 -0
  238. data/lib/solargraph/views/layout.erb +44 -0
  239. data/lib/solargraph/views/search.erb +11 -0
  240. data/lib/solargraph/workspace.rb +209 -0
  241. data/lib/solargraph/workspace/config.rb +215 -0
  242. data/lib/solargraph/yard_map.rb +420 -0
  243. data/lib/solargraph/yard_map/cache.rb +19 -0
  244. data/lib/solargraph/yard_map/core_docs.rb +170 -0
  245. data/lib/solargraph/yard_map/core_gen.rb +76 -0
  246. data/lib/solargraph/yard_map/mapper.rb +71 -0
  247. data/lib/solargraph/yard_map/rdoc_to_yard.rb +136 -0
  248. data/lib/yard-solargraph.rb +30 -0
  249. data/solargraph.gemspec +41 -0
  250. data/travis-bundler.rb +11 -0
  251. data/yardoc/2.2.2.tar.gz +0 -0
  252. metadata +575 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 86abdabe74326a279a6dc6c3f02ff09dc469e1e92cfd5f89ac3a3363ce47e146
4
+ data.tar.gz: 1772fe6f16f7531758d5c5853201b86c334eec8ef3f049ae764f6aa3d2d4c118
5
+ SHA512:
6
+ metadata.gz: 6256341e8373235c53af95ab62fc61b02c2a3b755391786d6d28ae8b2373a141f8b4b875789760adfbdf333dfd020bff15d791c4d423cd90f5b96b6e8d9e2750
7
+ data.tar.gz: da4580767cecf3c62ad1e949a3ee0a97ac3a07785e52cacc5d53977f6ac6db8db4507c912136455646be196aa915920632e776aec98ddeb1d686868539707290
@@ -0,0 +1,9 @@
1
+ /Gemfile.lock
2
+ .Gemfile
3
+ .idea
4
+ .vscode
5
+ .yardoc
6
+ .solargraph.yml
7
+ doc
8
+ coverage
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,28 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1
4
+ - 2.2
5
+ - 2.3
6
+ - 2.4
7
+ - 2.5
8
+ - 2.6
9
+ - 2.7
10
+ - jruby-head
11
+ matrix:
12
+ include:
13
+ - rvm: 2.4
14
+ os: osx
15
+ - rvm: 2.6
16
+ os: osx
17
+ - rvm: 2.7
18
+ os: osx
19
+ allow_failures:
20
+ - rvm: 2.7
21
+ os: osx
22
+ - rvm: jruby-head
23
+
24
+ before_install:
25
+ - ruby ./travis-bundler.rb
26
+ - bundle install
27
+ before_script: yard gems
28
+ script: rspec
@@ -0,0 +1,2 @@
1
+ lib/**/*.rb
2
+ -e lib/yard-solargraph.rb
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec name: '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.
@@ -0,0 +1,104 @@
1
+ # Solargraph
2
+
3
+ ## A Ruby Language Server
4
+
5
+ Solargraph provides a comprehensive suite of tools for Ruby programming: intellisense, diagnostics, inline documentation, and type checking.
6
+
7
+ ## Online Demo
8
+
9
+ A web-based demonstration of Solargraph's autocomplete is available at https://solargraph.org/demo.
10
+
11
+ ## Installation
12
+
13
+ Install the gem from the command line:
14
+
15
+ gem install solargraph
16
+
17
+ Or add it to your Gemfile:
18
+
19
+ gem 'solargraph', group: :development
20
+
21
+ ## Using Solargraph
22
+
23
+ Plug-ins and extensions are available for the following editors:
24
+
25
+ * **Visual Studio Code**
26
+ * Extension: https://marketplace.visualstudio.com/items?itemName=castwide.solargraph
27
+ * GitHub: https://github.com/castwide/vscode-solargraph
28
+
29
+ * **Atom**
30
+ * Package: https://atom.io/packages/ruby-solargraph
31
+ * GitHub: https://github.com/castwide/atom-solargraph
32
+
33
+ * **Vim**
34
+ * GitHub: https://github.com/autozimu/LanguageClient-neovim
35
+
36
+ * **Emacs**
37
+ * GitHub: https://github.com/guskovd/emacs-solargraph
38
+
39
+ * **Eclipse**
40
+ * Plugin: https://marketplace.eclipse.org/content/ruby-solargraph
41
+ * GitHub: https://github.com/PyvesB/eclipse-solargraph
42
+
43
+ ### Gem Support
44
+
45
+ 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).
46
+
47
+ 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.
48
+
49
+ 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.
50
+
51
+ ### Type Checking
52
+
53
+ 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.
54
+
55
+ ### Updating Core Documentation
56
+
57
+ The Solargraph gem ships with documentation for Ruby 2.2.2. You can download documentation for other Ruby versions from the command line.
58
+
59
+ $ solargraph list-cores # List the installed documentation versions
60
+ $ solargraph available-cores # List the versions available for download
61
+ $ solargraph download-core # Install the best match for your Ruby version
62
+ $ solargraph clear # Reset the documentation cache
63
+
64
+ ### The Documentation Cache
65
+
66
+ 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.
67
+
68
+ 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.
69
+
70
+ ### Solargraph and Bundler
71
+
72
+ 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.
73
+
74
+ In the Gemfile:
75
+
76
+ gem 'solargraph', group: :development
77
+
78
+ 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.
79
+
80
+ 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`.
81
+
82
+ ### Integrating Other Editors
83
+
84
+ 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).
85
+
86
+ ### More Information
87
+
88
+ See [https://solargraph.org/guides](https://solargraph.org/guides) for more tips and tutorials about Solargraph.
89
+
90
+ ## Contributing to Solargraph
91
+
92
+ ### Bug Reports and Feature Requests
93
+
94
+ [GitHub Issues](https://github.com/castwide/solargraph/issues) are the best place to ask questions, report problems, and suggest improvements.
95
+
96
+ ### Development
97
+
98
+ 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.
99
+
100
+ ### Sponsorship and Donation
101
+
102
+ Use Patreon to support ongoing development of Solargraph at [https://www.patreon.com/castwide](https://www.patreon.com/castwide).
103
+
104
+ You can also make one-time donations via PayPal at [https://www.paypal.me/castwide](https://www.paypal.me/castwide).
@@ -0,0 +1,14 @@
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
@@ -0,0 +1,9 @@
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
+ ## Named Sponsors
8
+
9
+ - Emily Strickland
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'solargraph'
4
+
5
+ Solargraph::Shell.start(ARGV)
@@ -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
+
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'solargraph/version'
4
+
5
+ # The top-level namespace for the Solargraph code mapping, documentation,
6
+ # static analysis, and language server libraries.
7
+ #
8
+ module Solargraph
9
+ class InvalidOffsetError < RangeError; end
10
+ class DiagnosticsError < RuntimeError; end
11
+ class FileNotFoundError < RuntimeError; end
12
+ class SourceNotAvailableError < StandardError; end
13
+ class ComplexTypeError < StandardError; end
14
+ class WorkspaceTooLargeError < RuntimeError; end
15
+ class BundleNotFoundError < StandardError; end
16
+
17
+ autoload :Position, 'solargraph/position'
18
+ autoload :Range, 'solargraph/range'
19
+ autoload :Location, 'solargraph/location'
20
+ autoload :Shell, 'solargraph/shell'
21
+ autoload :Source, 'solargraph/source'
22
+ autoload :SourceMap, 'solargraph/source_map'
23
+ autoload :ApiMap, 'solargraph/api_map'
24
+ autoload :YardMap, 'solargraph/yard_map'
25
+ autoload :Pin, 'solargraph/pin'
26
+ autoload :ServerMethods, 'solargraph/server_methods'
27
+ autoload :CoreFills, 'solargraph/core_fills'
28
+ autoload :StdlibFills, 'solargraph/stdlib_fills'
29
+ autoload :LanguageServer, 'solargraph/language_server'
30
+ autoload :Workspace, 'solargraph/workspace'
31
+ autoload :Page, 'solargraph/page'
32
+ autoload :Library, 'solargraph/library'
33
+ autoload :Diagnostics, 'solargraph/diagnostics'
34
+ autoload :ComplexType, 'solargraph/complex_type'
35
+ autoload :Bundle, 'solargraph/bundle'
36
+ autoload :Logging, 'solargraph/logging'
37
+ autoload :TypeChecker, 'solargraph/type_checker'
38
+ autoload :Environ, 'solargraph/environ'
39
+ autoload :Convention, 'solargraph/convention'
40
+ autoload :Documentor, 'solargraph/documentor'
41
+ autoload :Parser, 'solargraph/parser'
42
+
43
+ dir = File.dirname(__FILE__)
44
+ YARDOC_PATH = File.realpath(File.join(dir, '..', 'yardoc'))
45
+ YARD_EXTENSION_FILE = File.join(dir, 'yard-solargraph.rb')
46
+ VIEWS_PATH = File.join(dir, 'solargraph', 'views')
47
+
48
+ # A convenience method for Solargraph::Logging.logger.
49
+ #
50
+ # @return [Logger]
51
+ def self.logger
52
+ Solargraph::Logging.logger
53
+ end
54
+
55
+ # A helper method that runs Bundler.with_unbundled_env or falls back to
56
+ # Bundler.with_clean env for earlier versions of Bundler.
57
+ #
58
+ def self.with_clean_env &block
59
+ meth = if Bundler.respond_to?(:with_unbundled_env)
60
+ :with_unbundled_env
61
+ else
62
+ :with_clean_env
63
+ end
64
+ Bundler.send meth, &block
65
+ end
66
+ end
@@ -0,0 +1,745 @@
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
+ @mutex = Mutex.new
30
+ @method_alias_stack = []
31
+ index pins
32
+ end
33
+
34
+ # @param pins [Array<Pin::Base>]
35
+ # @return [self]
36
+ def index pins
37
+ @mutex.synchronize {
38
+ @source_map_hash.clear
39
+ @cache.clear
40
+ @store = Store.new(pins + YardMap.new.pins)
41
+ @unresolved_requires = []
42
+ workspace_filenames.clear
43
+ }
44
+ self
45
+ end
46
+
47
+ # Map a single source.
48
+ #
49
+ # @param source [Source]
50
+ # @return [self]
51
+ def map source
52
+ catalog Bundle.new(opened: [source])
53
+ self
54
+ end
55
+
56
+ # @param name [String]
57
+ # @return [YARD::Tags::MacroDirective, nil]
58
+ def named_macro name
59
+ store.named_macros[name]
60
+ end
61
+
62
+ # Catalog a bundle.
63
+ #
64
+ # @param bundle [Bundle]
65
+ # @return [self]
66
+ def catalog bundle
67
+ new_map_hash = {}
68
+ # Bundle always needs to be merged if it adds or removes sources
69
+ merged = (bundle.sources.length == source_map_hash.values.length)
70
+ bundle.sources.each do |source|
71
+ if source_map_hash.key?(source.filename)
72
+ if source_map_hash[source.filename].code == source.code && source_map_hash[source.filename].source.synchronized? && source.synchronized?
73
+ new_map_hash[source.filename] = source_map_hash[source.filename]
74
+ elsif !source.synchronized?
75
+ new_map_hash[source.filename] = source_map_hash[source.filename]
76
+ # @todo Smelly instance variable access
77
+ new_map_hash[source.filename].instance_variable_set(:@source, source)
78
+ else
79
+ map = Solargraph::SourceMap.map(source)
80
+ if source_map_hash[source.filename].try_merge!(map)
81
+ new_map_hash[source.filename] = source_map_hash[source.filename]
82
+ else
83
+ new_map_hash[source.filename] = map
84
+ merged = false
85
+ end
86
+ end
87
+ else
88
+ map = Solargraph::SourceMap.map(source)
89
+ new_map_hash[source.filename] = map
90
+ merged = false
91
+ end
92
+ end
93
+ return self if merged
94
+ implicit.clear
95
+ pins = []
96
+ reqs = Set.new
97
+ # @param map [SourceMap]
98
+ new_map_hash.values.each do |map|
99
+ implicit.merge map.environ
100
+ pins.concat map.pins
101
+ reqs.merge map.requires.map(&:name)
102
+ end
103
+ reqs.merge bundle.workspace.config.required
104
+ local_path_hash.clear
105
+ unless bundle.workspace.require_paths.empty?
106
+ file_keys = new_map_hash.keys
107
+ workspace_path = Pathname.new(bundle.workspace.directory)
108
+ reqs.delete_if do |r|
109
+ bundle.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
+ pins.concat implicit.overrides
122
+ br = reqs.include?('bundler/require') ? require_from_bundle(bundle.workspace.directory) : {}
123
+ reqs.merge br.keys
124
+ yard_map.change(reqs.to_a, br, bundle.workspace.gemnames)
125
+ new_store = Store.new(pins + yard_map.pins)
126
+ @mutex.synchronize {
127
+ @cache.clear
128
+ @source_map_hash = new_map_hash
129
+ @store = new_store
130
+ @unresolved_requires = yard_map.unresolved_requires
131
+ workspace_filenames.clear
132
+ workspace_filenames.concat bundle.workspace.filenames
133
+ }
134
+ self
135
+ end
136
+
137
+ # @return [Environ]
138
+ def implicit
139
+ @implicit ||= Environ.new
140
+ end
141
+
142
+ # @return [Hash{String => String}]
143
+ def local_path_hash
144
+ @local_paths ||= {}
145
+ end
146
+
147
+ # @param filename [String]
148
+ # @param position [Position, Array(Integer, Integer)]
149
+ # @return [Source::Cursor]
150
+ def cursor_at filename, position
151
+ position = Position.normalize(position)
152
+ raise FileNotFoundError, "File not found: #{filename}" unless source_map_hash.has_key?(filename)
153
+ source_map_hash[filename].cursor_at(position)
154
+ end
155
+
156
+ # Get a clip by filename and position.
157
+ #
158
+ # @param filename [String]
159
+ # @param position [Position, Array(Integer, Integer)]
160
+ # @return [SourceMap::Clip]
161
+ def clip_at filename, position
162
+ position = Position.normalize(position)
163
+ SourceMap::Clip.new(self, cursor_at(filename, position))
164
+ end
165
+
166
+ # Create an ApiMap with a workspace in the specified directory.
167
+ #
168
+ # @param directory [String]
169
+ # @return [ApiMap]
170
+ def self.load directory
171
+ api_map = self.new
172
+ workspace = Solargraph::Workspace.new(directory)
173
+ api_map.catalog Bundle.new(workspace: workspace)
174
+ api_map
175
+ end
176
+
177
+ # @return [Array<Solargraph::Pin::Base>]
178
+ def pins
179
+ store.pins
180
+ end
181
+
182
+ # An array of pins based on Ruby keywords (`if`, `end`, etc.).
183
+ #
184
+ # @return [Array<Solargraph::Pin::Keyword>]
185
+ def self.keywords
186
+ @keywords ||= CoreFills::KEYWORDS.map{ |s|
187
+ Pin::Keyword.new(s)
188
+ }.freeze
189
+ end
190
+
191
+ # An array of namespace names defined in the ApiMap.
192
+ #
193
+ # @return [Set<String>]
194
+ def namespaces
195
+ store.namespaces
196
+ end
197
+
198
+ # True if the namespace exists.
199
+ #
200
+ # @param name [String] The namespace to match
201
+ # @param context [String] The context to search
202
+ # @return [Boolean]
203
+ def namespace_exists? name, context = ''
204
+ !qualify(name, context).nil?
205
+ end
206
+
207
+ # Get suggestions for constants in the specified namespace. The result
208
+ # may contain both constant and namespace pins.
209
+ #
210
+ # @param namespace [String] The namespace
211
+ # @param contexts [Array<String>] The contexts
212
+ # @return [Array<Solargraph::Pin::Base>]
213
+ def get_constants namespace, *contexts
214
+ namespace ||= ''
215
+ contexts.push '' if contexts.empty?
216
+ cached = cache.get_constants(namespace, contexts)
217
+ return cached.clone unless cached.nil?
218
+ skip = Set.new
219
+ result = []
220
+ contexts.each do |context|
221
+ fqns = qualify(namespace, context)
222
+ visibility = [:public]
223
+ visibility.push :private if fqns == context
224
+ result.concat inner_get_constants(fqns, visibility, skip)
225
+ end
226
+ cache.set_constants(namespace, contexts, result)
227
+ result
228
+ end
229
+
230
+ # Get a fully qualified namespace name. This method will start the search
231
+ # in the specified context until it finds a match for the name.
232
+ #
233
+ # @param namespace [String, nil] The namespace to match
234
+ # @param context [String] The context to search
235
+ # @return [String]
236
+ def qualify namespace, context = ''
237
+ return namespace if ['self', nil].include?(namespace)
238
+ cached = cache.get_qualified_namespace(namespace, context)
239
+ return cached.clone unless cached.nil?
240
+ result = if namespace.start_with?('::')
241
+ inner_qualify(namespace[2..-1], '', Set.new)
242
+ else
243
+ inner_qualify(namespace, context, Set.new)
244
+ end
245
+ cache.set_qualified_namespace(namespace, context, result)
246
+ result
247
+ end
248
+
249
+ # Get an array of instance variable pins defined in specified namespace
250
+ # and scope.
251
+ #
252
+ # @param namespace [String] A fully qualified namespace
253
+ # @param scope [Symbol] :instance or :class
254
+ # @return [Array<Solargraph::Pin::InstanceVariable>]
255
+ def get_instance_variable_pins(namespace, scope = :instance)
256
+ result = []
257
+ used = [namespace]
258
+ result.concat store.get_instance_variables(namespace, scope)
259
+ sc = qualify_lower(store.get_superclass(namespace), namespace)
260
+ until sc.nil? || used.include?(sc)
261
+ used.push sc
262
+ result.concat store.get_instance_variables(sc, scope)
263
+ sc = qualify_lower(store.get_superclass(sc), sc)
264
+ end
265
+ result
266
+ end
267
+
268
+ # Get an array of class variable pins for a namespace.
269
+ #
270
+ # @param namespace [String] A fully qualified namespace
271
+ # @return [Array<Solargraph::Pin::ClassVariable>]
272
+ def get_class_variable_pins(namespace)
273
+ prefer_non_nil_variables(store.get_class_variables(namespace))
274
+ end
275
+
276
+ # @return [Array<Solargraph::Pin::Base>]
277
+ def get_symbols
278
+ store.get_symbols
279
+ end
280
+
281
+ # @return [Array<Solargraph::Pin::GlobalVariable>]
282
+ def get_global_variable_pins
283
+ # @todo Slow version
284
+ pins.select{ |p| p.is_a?(Pin::GlobalVariable) }
285
+ end
286
+
287
+ # Get an array of methods available in a particular context.
288
+ #
289
+ # @param fqns [String] The fully qualified namespace to search for methods
290
+ # @param scope [Symbol] :class or :instance
291
+ # @param visibility [Array<Symbol>] :public, :protected, and/or :private
292
+ # @param deep [Boolean] True to include superclasses, mixins, etc.
293
+ # @return [Array<Solargraph::Pin::BaseMethod>]
294
+ def get_methods fqns, scope: :instance, visibility: [:public], deep: true
295
+ cached = cache.get_methods(fqns, scope, visibility, deep)
296
+ return cached.clone unless cached.nil?
297
+ result = []
298
+ skip = Set.new
299
+ if fqns == ''
300
+ # @todo Implement domains
301
+ implicit.domains.each do |domain|
302
+ type = ComplexType.try_parse(domain)
303
+ next if type.undefined?
304
+ result.concat inner_get_methods(type.name, type.scope, [:public], deep, skip)
305
+ end
306
+ result.concat inner_get_methods(fqns, :class, visibility, deep, skip)
307
+ result.concat inner_get_methods(fqns, :instance, visibility, deep, skip)
308
+ result.concat inner_get_methods('Kernel', :instance, visibility, deep, skip)
309
+ else
310
+ result.concat inner_get_methods(fqns, scope, visibility, deep, skip)
311
+ result.concat inner_get_methods('Kernel', :instance, [:public], deep, skip) if visibility.include?(:private)
312
+ end
313
+ resolved = resolve_method_aliases(result, visibility)
314
+ cache.set_methods(fqns, scope, visibility, deep, resolved)
315
+ resolved
316
+ end
317
+
318
+ # Get an array of method pins for a complex type.
319
+ #
320
+ # The type's namespace and the context should be fully qualified. If the
321
+ # context matches the namespace type or is a subclass of the type,
322
+ # protected methods are included in the results. If protected methods are
323
+ # included and internal is true, private methods are also included.
324
+ #
325
+ # @example
326
+ # api_map = Solargraph::ApiMap.new
327
+ # type = Solargraph::ComplexType.parse('String')
328
+ # api_map.get_complex_type_methods(type)
329
+ #
330
+ # @param type [Solargraph::ComplexType] The complex type of the namespace
331
+ # @param context [String] The context from which the type is referenced
332
+ # @param internal [Boolean] True to include private methods
333
+ # @return [Array<Solargraph::Pin::Base>]
334
+ def get_complex_type_methods type, context = '', internal = false
335
+ # This method does not qualify the complex type's namespace because
336
+ # it can cause conflicts between similar names, e.g., `Foo` vs.
337
+ # `Other::Foo`. It still takes a context argument to determine whether
338
+ # protected and private methods are visible.
339
+ return [] if type.undefined? || type.void?
340
+ result = []
341
+ if type.duck_type?
342
+ type.select(&:duck_type?).each do |t|
343
+ result.push Pin::DuckMethod.new(name: t.tag[1..-1])
344
+ end
345
+ result.concat get_methods('Object')
346
+ else
347
+ unless type.nil? || type.name == 'void'
348
+ visibility = [:public]
349
+ if type.namespace == context || super_and_sub?(type.namespace, context)
350
+ visibility.push :protected
351
+ visibility.push :private if internal
352
+ end
353
+ result.concat get_methods(type.namespace, scope: type.scope, visibility: visibility)
354
+ end
355
+ end
356
+ result
357
+ end
358
+
359
+ # Get a stack of method pins for a method name in a namespace. The order
360
+ # of the pins corresponds to the ancestry chain, with highest precedence
361
+ # first.
362
+ #
363
+ # @example
364
+ # api_map.get_method_stack('Subclass', 'method_name')
365
+ # #=> [ <Subclass#method_name pin>, <Superclass#method_name pin> ]
366
+ #
367
+ # @param fqns [String]
368
+ # @param name [String]
369
+ # @param scope [Symbol] :instance or :class
370
+ # @return [Array<Solargraph::Pin::BaseMethod>]
371
+ def get_method_stack fqns, name, scope: :instance
372
+ get_methods(fqns, scope: scope, visibility: [:private, :protected, :public]).select{|p| p.name == name}
373
+ end
374
+
375
+ # Get an array of all suggestions that match the specified path.
376
+ #
377
+ # @deprecated Use #get_path_pins instead.
378
+ #
379
+ # @param path [String] The path to find
380
+ # @return [Array<Solargraph::Pin::Base>]
381
+ def get_path_suggestions path
382
+ return [] if path.nil?
383
+ result = []
384
+ result.concat store.get_path_pins(path)
385
+ resolve_method_aliases(result)
386
+ end
387
+
388
+ # Get an array of pins that match the specified path.
389
+ #
390
+ # @param path [String]
391
+ # @return [Array<Pin::Base>]
392
+ def get_path_pins path
393
+ get_path_suggestions(path)
394
+ end
395
+
396
+ # Get a list of documented paths that match the query.
397
+ #
398
+ # @example
399
+ # api_map.query('str') # Results will include `String` and `Struct`
400
+ #
401
+ # @param query [String] The text to match
402
+ # @return [Array<String>]
403
+ def search query
404
+ rake_yard(store)
405
+ found = []
406
+ code_object_paths.each do |k|
407
+ if found.empty? || (query.include?('.') || query.include?('#')) || !(k.include?('.') || k.include?('#'))
408
+ found.push k if k.downcase.include?(query.downcase)
409
+ end
410
+ end
411
+ found
412
+ end
413
+
414
+ # Get YARD documentation for the specified path.
415
+ #
416
+ # @example
417
+ # api_map.document('String#split')
418
+ #
419
+ # @param path [String] The path to find
420
+ # @return [Array<YARD::CodeObject::Base>]
421
+ def document path
422
+ rake_yard(store)
423
+ docs = []
424
+ docs.push code_object_at(path) unless code_object_at(path).nil?
425
+ docs
426
+ end
427
+
428
+ # Get an array of all symbols in the workspace that match the query.
429
+ #
430
+ # @param query [String]
431
+ # @return [Array<Pin::Base>]
432
+ def query_symbols query
433
+ result = []
434
+ source_map_hash.values.each do |s|
435
+ result.concat s.query_symbols(query)
436
+ end
437
+ result
438
+ end
439
+
440
+ # @param location [Solargraph::Location]
441
+ # @return [Array<Solargraph::Pin::Base>]
442
+ def locate_pins location
443
+ return [] if location.nil? || !source_map_hash.has_key?(location.filename)
444
+ source_map_hash[location.filename].locate_pins(location)
445
+ end
446
+
447
+ # @raise [FileNotFoundError] if the cursor's file is not in the ApiMap
448
+ # @param cursor [Source::Cursor]
449
+ # @return [SourceMap::Clip]
450
+ def clip cursor
451
+ raise FileNotFoundError, "ApiMap did not catalog #{cursor.filename}" unless source_map_hash.has_key?(cursor.filename)
452
+ SourceMap::Clip.new(self, cursor)
453
+ end
454
+
455
+ # Get an array of document symbols from a file.
456
+ #
457
+ # @param filename [String]
458
+ # @return [Array<Pin::Symbol>]
459
+ def document_symbols filename
460
+ return [] unless source_map_hash.has_key?(filename) # @todo Raise error?
461
+ source_map_hash[filename].document_symbols
462
+ end
463
+
464
+ # @return [Array<SourceMap>]
465
+ def source_maps
466
+ source_map_hash.values
467
+ end
468
+
469
+ # Get a source map by filename.
470
+ #
471
+ # @param filename [String]
472
+ # @return [SourceMap]
473
+ def source_map filename
474
+ raise FileNotFoundError, "Source map for `#{filename}` not found" unless source_map_hash.has_key?(filename)
475
+ source_map_hash[filename]
476
+ end
477
+
478
+ # True if the specified file was included in a bundle, i.e., it's either
479
+ # included in a workspace or open in a library.
480
+ #
481
+ # @param filename [String]
482
+ def bundled? filename
483
+ source_map_hash.keys.include?(filename)
484
+ end
485
+
486
+ # True if the specified file is included in the workspace.
487
+ #
488
+ # @param filename [String]
489
+ def workspaced? filename
490
+ workspace_filenames.include?(filename)
491
+ end
492
+
493
+ # @param location [Location]
494
+ # @return [Location]
495
+ def require_reference_at location
496
+ map = source_map(location.filename)
497
+ pin = map.requires.select { |pin| pin.location.range.contain?(location.range.start) }.first
498
+ return nil if pin.nil?
499
+ if local_path_hash.key?(pin.name)
500
+ return Location.new(local_path_hash[pin.name], Solargraph::Range.from_to(0, 0, 0, 0))
501
+ end
502
+ yard_map.require_reference(pin.name)
503
+ rescue FileNotFoundError
504
+ nil
505
+ end
506
+
507
+ # Check if a class is a superclass of another class.
508
+ #
509
+ # @param sup [String] The superclass
510
+ # @param sub [String] The subclass
511
+ # @return [Boolean]
512
+ def super_and_sub?(sup, sub)
513
+ fqsup = qualify(sup)
514
+ cls = qualify(sub)
515
+ until fqsup.nil? || cls.nil?
516
+ return true if cls == fqsup
517
+ cls = qualify_superclass(cls)
518
+ end
519
+ false
520
+ end
521
+
522
+ private
523
+
524
+ # @return [Array<String>]
525
+ def workspace_filenames
526
+ @workspace_filenames ||= []
527
+ end
528
+
529
+ # @return [YardMap]
530
+ def yard_map
531
+ @yard_map ||= YardMap.new
532
+ end
533
+
534
+ # A hash of source maps with filename keys.
535
+ #
536
+ # @return [Hash{String => SourceMap}]
537
+ def source_map_hash
538
+ @mutex.synchronize { @source_map_hash }
539
+ end
540
+
541
+ # @return [ApiMap::Store]
542
+ def store
543
+ @mutex.synchronize { @store }
544
+ end
545
+
546
+ # @return [Solargraph::ApiMap::Cache]
547
+ def cache
548
+ @mutex.synchronize { @cache }
549
+ end
550
+
551
+ # @param fqns [String] A fully qualified namespace
552
+ # @param scope [Symbol] :class or :instance
553
+ # @param visibility [Array<Symbol>] :public, :protected, and/or :private
554
+ # @param deep [Boolean]
555
+ # @param skip [Set<String>]
556
+ # @param no_core [Boolean] Skip core classes if true
557
+ # @return [Array<Pin::Base>]
558
+ def inner_get_methods fqns, scope, visibility, deep, skip, no_core = false
559
+ return [] if no_core && fqns =~ /^(Object|BasicObject|Class|Module|Kernel)$/
560
+ reqstr = "#{fqns}|#{scope}|#{visibility.sort}|#{deep}"
561
+ return [] if skip.include?(reqstr)
562
+ skip.add reqstr
563
+ result = []
564
+ if deep && scope == :instance
565
+ store.get_prepends(fqns).reverse.each do |im|
566
+ fqim = qualify(im, fqns)
567
+ result.concat inner_get_methods(fqim, scope, visibility, deep, skip, true) unless fqim.nil?
568
+ end
569
+ end
570
+ result.concat store.get_methods(fqns, scope: scope, visibility: visibility).sort{ |a, b| a.name <=> b.name }
571
+ if deep
572
+ if scope == :instance
573
+ store.get_includes(fqns).reverse.each do |im|
574
+ fqim = qualify(im, fqns)
575
+ result.concat inner_get_methods(fqim, scope, visibility, deep, skip, true) unless fqim.nil?
576
+ end
577
+ fqsc = qualify_superclass(fqns)
578
+ unless fqsc.nil?
579
+ result.concat inner_get_methods(fqsc, scope, visibility, true, skip, no_core) unless fqsc.nil?
580
+ end
581
+ else
582
+ store.get_extends(fqns).reverse.each do |em|
583
+ fqem = qualify(em, fqns)
584
+ result.concat inner_get_methods(fqem, :instance, visibility, deep, skip, true) unless fqem.nil?
585
+ end
586
+ fqsc = qualify_superclass(fqns)
587
+ unless fqsc.nil?
588
+ result.concat inner_get_methods(fqsc, scope, visibility, true, skip, true) unless fqsc.nil?
589
+ end
590
+ unless no_core || fqns.empty?
591
+ type = get_namespace_type(fqns)
592
+ result.concat inner_get_methods('Class', :instance, visibility, deep, skip, no_core) if type == :class
593
+ result.concat inner_get_methods('Module', :instance, visibility, deep, skip, no_core)
594
+ end
595
+ end
596
+ store.domains(fqns).each do |d|
597
+ dt = ComplexType.try_parse(d)
598
+ result.concat inner_get_methods(dt.namespace, dt.scope, [:public], deep, skip)
599
+ end
600
+ end
601
+ result
602
+ end
603
+
604
+ # @param fqns [String]
605
+ # @param visibility [Array<Symbol>]
606
+ # @param skip [Set<String>]
607
+ # @return [Array<Pin::Base>]
608
+ def inner_get_constants fqns, visibility, skip
609
+ return [] if fqns.nil? || skip.include?(fqns)
610
+ skip.add fqns
611
+ result = []
612
+ store.get_prepends(fqns).each do |is|
613
+ result.concat inner_get_constants(qualify(is, fqns), [:public], skip)
614
+ end
615
+ result.concat store.get_constants(fqns, visibility)
616
+ .sort { |a, b| a.name <=> b.name }
617
+ store.get_includes(fqns).each do |is|
618
+ result.concat inner_get_constants(qualify(is, fqns), [:public], skip)
619
+ end
620
+ fqsc = qualify_superclass(fqns)
621
+ unless %w[Object BasicObject].include?(fqsc)
622
+ result.concat inner_get_constants(fqsc, [:public], skip)
623
+ end
624
+ result
625
+ end
626
+
627
+ # @return [Hash]
628
+ def path_macros
629
+ @path_macros ||= {}
630
+ end
631
+
632
+ # @param namespace [String]
633
+ # @param context [String]
634
+ # @return [String]
635
+ def qualify_lower namespace, context
636
+ qualify namespace, context.split('::')[0..-2].join('::')
637
+ end
638
+
639
+ def qualify_superclass fqsub
640
+ sup = store.get_superclass(fqsub)
641
+ return nil if sup.nil?
642
+ parts = fqsub.split('::')
643
+ last = parts.pop
644
+ parts.pop if last == sup
645
+ qualify(sup, parts.join('::'))
646
+ end
647
+
648
+ # @param name [String]
649
+ # @param root [String]
650
+ # @param skip [Set<String>]
651
+ # @return [String, nil]
652
+ def inner_qualify name, root, skip
653
+ return nil if name.nil?
654
+ return nil if skip.include?(root)
655
+ skip.add root
656
+ if name == ''
657
+ if root == ''
658
+ return ''
659
+ else
660
+ return inner_qualify(root, '', skip)
661
+ end
662
+ else
663
+ return name if root == '' && store.namespace_exists?(name)
664
+ roots = root.to_s.split('::')
665
+ while roots.length > 0
666
+ fqns = roots.join('::') + '::' + name
667
+ return fqns if store.namespace_exists?(fqns)
668
+ incs = store.get_includes(roots.join('::'))
669
+ incs.each do |inc|
670
+ foundinc = inner_qualify(name, inc, skip)
671
+ return foundinc unless foundinc.nil?
672
+ end
673
+ roots.pop
674
+ end
675
+ incs = store.get_includes('')
676
+ incs.each do |inc|
677
+ foundinc = inner_qualify(name, inc, skip)
678
+ return foundinc unless foundinc.nil?
679
+ end
680
+ return name if store.namespace_exists?(name)
681
+ end
682
+ end
683
+
684
+ # Get the namespace's type (Class or Module).
685
+ #
686
+ # @param fqns [String] A fully qualified namespace
687
+ # @return [Symbol, nil] :class, :module, or nil
688
+ def get_namespace_type fqns
689
+ return nil if fqns.nil?
690
+ # @type [Pin::Namespace, nil]
691
+ pin = store.get_path_pins(fqns).select{|p| p.is_a?(Pin::Namespace)}.first
692
+ return nil if pin.nil?
693
+ pin.type
694
+ end
695
+
696
+ # Sort an array of pins to put nil or undefined variables last.
697
+ #
698
+ # @param pins [Array<Solargraph::Pin::Base>]
699
+ # @return [Array<Solargraph::Pin::Base>]
700
+ def prefer_non_nil_variables pins
701
+ result = []
702
+ nil_pins = []
703
+ pins.each do |pin|
704
+ if pin.variable? && pin.nil_assignment?
705
+ nil_pins.push pin
706
+ else
707
+ result.push pin
708
+ end
709
+ end
710
+ result + nil_pins
711
+ end
712
+
713
+ # @param pins [Array<Pin::Base>]
714
+ # @param visibility [Array<Symbol>]
715
+ # @return [Array<Pin::Base>]
716
+ def resolve_method_aliases pins, visibility = [:public, :private, :protected]
717
+ result = []
718
+ pins.each do |pin|
719
+ resolved = resolve_method_alias(pin)
720
+ next unless visibility.include?(resolved.visibility)
721
+ result.push resolved
722
+ end
723
+ result
724
+ end
725
+
726
+ # @param pin [Pin::MethodAlias, Pin::Base]
727
+ # @return [Pin::BaseMethod]
728
+ def resolve_method_alias pin
729
+ return pin if !pin.is_a?(Pin::MethodAlias) || @method_alias_stack.include?(pin.path)
730
+ @method_alias_stack.push pin.path
731
+ origin = get_method_stack(pin.full_context.namespace, pin.original, scope: pin.scope).first
732
+ @method_alias_stack.pop
733
+ return pin if origin.nil?
734
+ Pin::Method.new(
735
+ location: pin.location,
736
+ closure: pin.closure,
737
+ name: pin.name,
738
+ comments: origin.comments,
739
+ scope: origin.scope,
740
+ visibility: origin.visibility,
741
+ parameters: origin.parameters
742
+ )
743
+ end
744
+ end
745
+ end