solargraph 0.39.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +28 -0
- data/.yardopts +2 -0
- data/Gemfile +7 -0
- data/LICENSE +21 -0
- data/README.md +104 -0
- data/Rakefile +14 -0
- data/SPONSORS.md +9 -0
- data/bin/solargraph +5 -0
- data/lib/.rubocop.yml +21 -0
- data/lib/solargraph.rb +66 -0
- data/lib/solargraph/api_map.rb +745 -0
- data/lib/solargraph/api_map/bundler_methods.rb +27 -0
- data/lib/solargraph/api_map/cache.rb +66 -0
- data/lib/solargraph/api_map/source_to_yard.rb +81 -0
- data/lib/solargraph/api_map/store.rb +267 -0
- data/lib/solargraph/bundle.rb +26 -0
- data/lib/solargraph/complex_type.rb +213 -0
- data/lib/solargraph/complex_type/type_methods.rb +127 -0
- data/lib/solargraph/complex_type/unique_type.rb +75 -0
- data/lib/solargraph/convention.rb +38 -0
- data/lib/solargraph/convention/base.rb +25 -0
- data/lib/solargraph/convention/gemfile.rb +18 -0
- data/lib/solargraph/convention/gemspec.rb +25 -0
- data/lib/solargraph/convention/rspec.rb +24 -0
- data/lib/solargraph/converters/dd.rb +12 -0
- data/lib/solargraph/converters/dl.rb +12 -0
- data/lib/solargraph/converters/dt.rb +12 -0
- data/lib/solargraph/converters/misc.rb +1 -0
- data/lib/solargraph/core_fills.rb +159 -0
- data/lib/solargraph/diagnostics.rb +55 -0
- data/lib/solargraph/diagnostics/base.rb +29 -0
- data/lib/solargraph/diagnostics/require_not_found.rb +37 -0
- data/lib/solargraph/diagnostics/rubocop.rb +90 -0
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +64 -0
- data/lib/solargraph/diagnostics/severities.rb +15 -0
- data/lib/solargraph/diagnostics/type_check.rb +54 -0
- data/lib/solargraph/diagnostics/update_errors.rb +41 -0
- data/lib/solargraph/documentor.rb +76 -0
- data/lib/solargraph/environ.rb +40 -0
- data/lib/solargraph/language_server.rb +19 -0
- data/lib/solargraph/language_server/completion_item_kinds.rb +35 -0
- data/lib/solargraph/language_server/error_codes.rb +20 -0
- data/lib/solargraph/language_server/host.rb +741 -0
- data/lib/solargraph/language_server/host/cataloger.rb +56 -0
- data/lib/solargraph/language_server/host/diagnoser.rb +81 -0
- data/lib/solargraph/language_server/host/dispatch.rb +112 -0
- data/lib/solargraph/language_server/host/sources.rb +156 -0
- data/lib/solargraph/language_server/message.rb +92 -0
- data/lib/solargraph/language_server/message/base.rb +85 -0
- data/lib/solargraph/language_server/message/cancel_request.rb +13 -0
- data/lib/solargraph/language_server/message/client.rb +11 -0
- data/lib/solargraph/language_server/message/client/register_capability.rb +15 -0
- data/lib/solargraph/language_server/message/completion_item.rb +11 -0
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +57 -0
- data/lib/solargraph/language_server/message/exit_notification.rb +13 -0
- data/lib/solargraph/language_server/message/extended.rb +21 -0
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +95 -0
- data/lib/solargraph/language_server/message/extended/document.rb +20 -0
- data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -0
- data/lib/solargraph/language_server/message/extended/download_core.rb +23 -0
- data/lib/solargraph/language_server/message/extended/environment.rb +25 -0
- data/lib/solargraph/language_server/message/extended/search.rb +20 -0
- data/lib/solargraph/language_server/message/initialize.rb +153 -0
- data/lib/solargraph/language_server/message/initialized.rb +26 -0
- data/lib/solargraph/language_server/message/method_not_found.rb +16 -0
- data/lib/solargraph/language_server/message/method_not_implemented.rb +14 -0
- data/lib/solargraph/language_server/message/shutdown.rb +13 -0
- data/lib/solargraph/language_server/message/text_document.rb +28 -0
- data/lib/solargraph/language_server/message/text_document/base.rb +19 -0
- data/lib/solargraph/language_server/message/text_document/code_action.rb +17 -0
- data/lib/solargraph/language_server/message/text_document/completion.rb +57 -0
- data/lib/solargraph/language_server/message/text_document/definition.rb +38 -0
- data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -0
- data/lib/solargraph/language_server/message/text_document/did_close.rb +15 -0
- data/lib/solargraph/language_server/message/text_document/did_open.rb +15 -0
- data/lib/solargraph/language_server/message/text_document/did_save.rb +17 -0
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +23 -0
- data/lib/solargraph/language_server/message/text_document/folding_range.rb +26 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +78 -0
- data/lib/solargraph/language_server/message/text_document/hover.rb +44 -0
- data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +34 -0
- data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -0
- data/lib/solargraph/language_server/message/text_document/references.rb +16 -0
- data/lib/solargraph/language_server/message/text_document/rename.rb +19 -0
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +29 -0
- data/lib/solargraph/language_server/message/workspace.rb +14 -0
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +29 -0
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +33 -0
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -0
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -0
- data/lib/solargraph/language_server/message_types.rb +14 -0
- data/lib/solargraph/language_server/request.rb +24 -0
- data/lib/solargraph/language_server/symbol_kinds.rb +36 -0
- data/lib/solargraph/language_server/transport.rb +13 -0
- data/lib/solargraph/language_server/transport/adapter.rb +56 -0
- data/lib/solargraph/language_server/transport/data_reader.rb +72 -0
- data/lib/solargraph/language_server/uri_helpers.rb +49 -0
- data/lib/solargraph/library.rb +414 -0
- data/lib/solargraph/location.rb +37 -0
- data/lib/solargraph/logging.rb +27 -0
- data/lib/solargraph/page.rb +83 -0
- data/lib/solargraph/parser.rb +26 -0
- data/lib/solargraph/parser/comment_ripper.rb +52 -0
- data/lib/solargraph/parser/legacy.rb +12 -0
- data/lib/solargraph/parser/legacy/class_methods.rb +109 -0
- data/lib/solargraph/parser/legacy/flawed_builder.rb +16 -0
- data/lib/solargraph/parser/legacy/node_chainer.rb +118 -0
- data/lib/solargraph/parser/legacy/node_methods.rb +300 -0
- data/lib/solargraph/parser/legacy/node_processors.rb +54 -0
- data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +23 -0
- data/lib/solargraph/parser/legacy/node_processors/args_node.rb +35 -0
- data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +15 -0
- data/lib/solargraph/parser/legacy/node_processors/block_node.rb +22 -0
- data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +25 -0
- data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +23 -0
- data/lib/solargraph/parser/legacy/node_processors/def_node.rb +63 -0
- data/lib/solargraph/parser/legacy/node_processors/defs_node.rb +36 -0
- data/lib/solargraph/parser/legacy/node_processors/gvasgn_node.rb +23 -0
- data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +38 -0
- data/lib/solargraph/parser/legacy/node_processors/lvasgn_node.rb +28 -0
- data/lib/solargraph/parser/legacy/node_processors/namespace_node.rb +39 -0
- data/lib/solargraph/parser/legacy/node_processors/orasgn_node.rb +16 -0
- data/lib/solargraph/parser/legacy/node_processors/resbody_node.rb +36 -0
- data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +21 -0
- data/lib/solargraph/parser/legacy/node_processors/send_node.rb +234 -0
- data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +18 -0
- data/lib/solargraph/parser/node_methods.rb +43 -0
- data/lib/solargraph/parser/node_processor.rb +43 -0
- data/lib/solargraph/parser/node_processor/base.rb +77 -0
- data/lib/solargraph/parser/region.rb +66 -0
- data/lib/solargraph/parser/rubyvm.rb +40 -0
- data/lib/solargraph/parser/rubyvm/class_methods.rb +150 -0
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +135 -0
- data/lib/solargraph/parser/rubyvm/node_methods.rb +284 -0
- data/lib/solargraph/parser/rubyvm/node_processors.rb +61 -0
- data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -0
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +62 -0
- data/lib/solargraph/parser/rubyvm/node_processors/begin_node.rb +15 -0
- data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +22 -0
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +22 -0
- data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +23 -0
- data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +64 -0
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +57 -0
- data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +23 -0
- data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +38 -0
- data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +39 -0
- data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +20 -0
- data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +27 -0
- data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +39 -0
- data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +31 -0
- data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +15 -0
- data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +45 -0
- data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +21 -0
- data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +15 -0
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +255 -0
- data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +18 -0
- data/lib/solargraph/parser/snippet.rb +13 -0
- data/lib/solargraph/pin.rb +39 -0
- data/lib/solargraph/pin/attribute.rb +49 -0
- data/lib/solargraph/pin/base.rb +296 -0
- data/lib/solargraph/pin/base_method.rb +141 -0
- data/lib/solargraph/pin/base_variable.rb +84 -0
- data/lib/solargraph/pin/block.rb +48 -0
- data/lib/solargraph/pin/class_variable.rb +8 -0
- data/lib/solargraph/pin/closure.rb +37 -0
- data/lib/solargraph/pin/common.rb +70 -0
- data/lib/solargraph/pin/constant.rb +43 -0
- data/lib/solargraph/pin/conversions.rb +97 -0
- data/lib/solargraph/pin/documenting.rb +110 -0
- data/lib/solargraph/pin/duck_method.rb +16 -0
- data/lib/solargraph/pin/global_variable.rb +8 -0
- data/lib/solargraph/pin/instance_variable.rb +30 -0
- data/lib/solargraph/pin/keyword.rb +15 -0
- data/lib/solargraph/pin/keyword_param.rb +8 -0
- data/lib/solargraph/pin/local_variable.rb +21 -0
- data/lib/solargraph/pin/localized.rb +43 -0
- data/lib/solargraph/pin/method.rb +111 -0
- data/lib/solargraph/pin/method_alias.rb +31 -0
- data/lib/solargraph/pin/namespace.rb +85 -0
- data/lib/solargraph/pin/parameter.rb +206 -0
- data/lib/solargraph/pin/proxy_type.rb +29 -0
- data/lib/solargraph/pin/reference.rb +14 -0
- data/lib/solargraph/pin/reference/extend.rb +10 -0
- data/lib/solargraph/pin/reference/include.rb +10 -0
- data/lib/solargraph/pin/reference/override.rb +29 -0
- data/lib/solargraph/pin/reference/prepend.rb +10 -0
- data/lib/solargraph/pin/reference/require.rb +14 -0
- data/lib/solargraph/pin/reference/superclass.rb +10 -0
- data/lib/solargraph/pin/singleton.rb +11 -0
- data/lib/solargraph/pin/symbol.rb +47 -0
- data/lib/solargraph/pin/yard_pin.rb +12 -0
- data/lib/solargraph/pin/yard_pin/constant.rb +25 -0
- data/lib/solargraph/pin/yard_pin/method.rb +65 -0
- data/lib/solargraph/pin/yard_pin/namespace.rb +27 -0
- data/lib/solargraph/pin/yard_pin/yard_mixin.rb +26 -0
- data/lib/solargraph/position.rb +112 -0
- data/lib/solargraph/range.rb +95 -0
- data/lib/solargraph/server_methods.rb +16 -0
- data/lib/solargraph/shell.rb +221 -0
- data/lib/solargraph/source.rb +533 -0
- data/lib/solargraph/source/chain.rb +172 -0
- data/lib/solargraph/source/chain/block_variable.rb +13 -0
- data/lib/solargraph/source/chain/call.rb +203 -0
- data/lib/solargraph/source/chain/class_variable.rb +13 -0
- data/lib/solargraph/source/chain/constant.rb +75 -0
- data/lib/solargraph/source/chain/global_variable.rb +13 -0
- data/lib/solargraph/source/chain/head.rb +35 -0
- data/lib/solargraph/source/chain/instance_variable.rb +13 -0
- data/lib/solargraph/source/chain/link.rb +67 -0
- data/lib/solargraph/source/chain/literal.rb +23 -0
- data/lib/solargraph/source/chain/or.rb +23 -0
- data/lib/solargraph/source/chain/variable.rb +13 -0
- data/lib/solargraph/source/chain/z_super.rb +184 -0
- data/lib/solargraph/source/change.rb +79 -0
- data/lib/solargraph/source/cursor.rb +164 -0
- data/lib/solargraph/source/encoding_fixes.rb +23 -0
- data/lib/solargraph/source/source_chainer.rb +189 -0
- data/lib/solargraph/source/updater.rb +54 -0
- data/lib/solargraph/source_map.rb +170 -0
- data/lib/solargraph/source_map/clip.rb +190 -0
- data/lib/solargraph/source_map/completion.rb +23 -0
- data/lib/solargraph/source_map/mapper.rb +199 -0
- data/lib/solargraph/stdlib_fills.rb +32 -0
- data/lib/solargraph/type_checker.rb +498 -0
- data/lib/solargraph/type_checker/checks.rb +95 -0
- data/lib/solargraph/type_checker/param_def.rb +35 -0
- data/lib/solargraph/type_checker/problem.rb +32 -0
- data/lib/solargraph/type_checker/rules.rb +53 -0
- data/lib/solargraph/version.rb +5 -0
- data/lib/solargraph/views/_method.erb +62 -0
- data/lib/solargraph/views/_name_type_tag.erb +10 -0
- data/lib/solargraph/views/_namespace.erb +24 -0
- data/lib/solargraph/views/document.erb +23 -0
- data/lib/solargraph/views/environment.erb +58 -0
- data/lib/solargraph/views/layout.erb +44 -0
- data/lib/solargraph/views/search.erb +11 -0
- data/lib/solargraph/workspace.rb +209 -0
- data/lib/solargraph/workspace/config.rb +215 -0
- data/lib/solargraph/yard_map.rb +420 -0
- data/lib/solargraph/yard_map/cache.rb +19 -0
- data/lib/solargraph/yard_map/core_docs.rb +170 -0
- data/lib/solargraph/yard_map/core_gen.rb +76 -0
- data/lib/solargraph/yard_map/mapper.rb +71 -0
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +136 -0
- data/lib/yard-solargraph.rb +30 -0
- data/solargraph.gemspec +41 -0
- data/travis-bundler.rb +11 -0
- data/yardoc/2.2.2.tar.gz +0 -0
- metadata +575 -0
checksums.yaml
ADDED
@@ -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
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -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
|
data/.yardopts
ADDED
data/Gemfile
ADDED
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,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).
|
data/Rakefile
ADDED
@@ -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
|
data/SPONSORS.md
ADDED
@@ -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
|
data/bin/solargraph
ADDED
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,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
|