jimeh-solargraph 0.40.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yml +54 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +24 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +1003 -0
- data/Gemfile +7 -0
- data/LICENSE +21 -0
- data/README.md +123 -0
- data/Rakefile +25 -0
- data/SPONSORS.md +15 -0
- data/bin/solargraph +5 -0
- data/jimeh-solargraph.gemspec +44 -0
- data/lib/.rubocop.yml +21 -0
- data/lib/solargraph.rb +67 -0
- data/lib/solargraph/api_map.rb +752 -0
- data/lib/solargraph/api_map/bundler_methods.rb +27 -0
- data/lib/solargraph/api_map/cache.rb +70 -0
- data/lib/solargraph/api_map/source_to_yard.rb +81 -0
- data/lib/solargraph/api_map/store.rb +256 -0
- data/lib/solargraph/bench.rb +30 -0
- data/lib/solargraph/compat.rb +23 -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 +47 -0
- data/lib/solargraph/convention/base.rb +33 -0
- data/lib/solargraph/convention/gemfile.rb +15 -0
- data/lib/solargraph/convention/gemspec.rb +22 -0
- data/lib/solargraph/convention/rspec.rb +21 -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/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 +45 -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 +78 -0
- data/lib/solargraph/environ.rb +45 -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 +746 -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 +100 -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 +105 -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 +426 -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 +311 -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 +257 -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 +80 -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 +301 -0
- data/lib/solargraph/parser/rubyvm/node_processors.rb +62 -0
- data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -0
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +86 -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 +26 -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 +277 -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 +36 -0
- data/lib/solargraph/pin/base.rb +296 -0
- data/lib/solargraph/pin/base_variable.rb +84 -0
- data/lib/solargraph/pin/block.rb +62 -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 +96 -0
- data/lib/solargraph/pin/documenting.rb +105 -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 +245 -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/position.rb +100 -0
- data/lib/solargraph/range.rb +95 -0
- data/lib/solargraph/server_methods.rb +16 -0
- data/lib/solargraph/shell.rb +222 -0
- data/lib/solargraph/source.rb +537 -0
- data/lib/solargraph/source/chain.rb +154 -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 +30 -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 +190 -0
- data/lib/solargraph/source/updater.rb +54 -0
- data/lib/solargraph/source_map.rb +188 -0
- data/lib/solargraph/source_map/clip.rb +224 -0
- data/lib/solargraph/source_map/completion.rb +23 -0
- data/lib/solargraph/source_map/mapper.rb +215 -0
- data/lib/solargraph/type_checker.rb +503 -0
- data/lib/solargraph/type_checker/checks.rb +99 -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 +57 -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 +230 -0
- data/lib/solargraph/yard_map.rb +435 -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_fills.rb +185 -0
- data/lib/solargraph/yard_map/core_gen.rb +76 -0
- data/lib/solargraph/yard_map/helpers.rb +16 -0
- data/lib/solargraph/yard_map/mapper.rb +77 -0
- data/lib/solargraph/yard_map/mapper/to_constant.rb +25 -0
- data/lib/solargraph/yard_map/mapper/to_method.rb +78 -0
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +27 -0
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +140 -0
- data/lib/solargraph/yard_map/stdlib_fills.rb +43 -0
- data/lib/solargraph/yard_map/to_method.rb +79 -0
- data/lib/yard-solargraph.rb +30 -0
- data/yardoc/2.2.2.tar.gz +0 -0
- metadata +564 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Solargraph::LanguageServer::Message::Workspace::WorkspaceSymbol < Solargraph::LanguageServer::Message::Base
|
4
|
+
include Solargraph::LanguageServer::UriHelpers
|
5
|
+
|
6
|
+
def process
|
7
|
+
pins = host.query_symbols(params['query'])
|
8
|
+
info = pins.map do |pin|
|
9
|
+
uri = file_to_uri(pin.location.filename)
|
10
|
+
{
|
11
|
+
name: pin.name,
|
12
|
+
containerName: pin.namespace,
|
13
|
+
kind: pin.symbol_kind,
|
14
|
+
location: {
|
15
|
+
uri: uri,
|
16
|
+
range: pin.location.range.to_hash
|
17
|
+
},
|
18
|
+
deprecated: pin.deprecated?
|
19
|
+
}
|
20
|
+
end
|
21
|
+
set_result info
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module LanguageServer
|
5
|
+
class Request
|
6
|
+
# @param id [Integer]
|
7
|
+
# @param &block The block that processes the client's response
|
8
|
+
def initialize id, &block
|
9
|
+
@id = id
|
10
|
+
@block = block
|
11
|
+
end
|
12
|
+
|
13
|
+
# @param result [Object]
|
14
|
+
# @return [void]
|
15
|
+
def process result
|
16
|
+
@block.call(result) unless @block.nil?
|
17
|
+
end
|
18
|
+
|
19
|
+
def send_response
|
20
|
+
# noop
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module LanguageServer
|
5
|
+
# The SymbolKind constants for the language server protocol.
|
6
|
+
#
|
7
|
+
module SymbolKinds
|
8
|
+
FILE = 1
|
9
|
+
MODULE = 2
|
10
|
+
NAMESPACE = 3
|
11
|
+
PACKAGE = 4
|
12
|
+
CLASS = 5
|
13
|
+
METHOD = 6
|
14
|
+
PROPERTY = 7
|
15
|
+
FIELD = 8
|
16
|
+
CONSTRUCTOR = 9
|
17
|
+
ENUM = 10
|
18
|
+
INTERFACE = 11
|
19
|
+
FUNCTION = 12
|
20
|
+
VARIABLE = 13
|
21
|
+
CONSTANT = 14
|
22
|
+
STRING = 15
|
23
|
+
NUMBER = 16
|
24
|
+
BOOLEAN = 17
|
25
|
+
ARRAY = 18
|
26
|
+
OBJECT = 19
|
27
|
+
KEY = 20
|
28
|
+
NULL = 21
|
29
|
+
ENUM_MEMBER = 22
|
30
|
+
STRUCT = 23
|
31
|
+
EVENT = 24
|
32
|
+
OPERATOR = 25
|
33
|
+
TYPE_PARAMETER = 26
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module LanguageServer
|
5
|
+
# The Transport namespace contains concrete implementations of
|
6
|
+
# communication protocols for language servers.
|
7
|
+
#
|
8
|
+
module Transport
|
9
|
+
autoload :Adapter, 'solargraph/language_server/transport/adapter'
|
10
|
+
autoload :DataReader, 'solargraph/language_server/transport/data_reader'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'backport'
|
4
|
+
|
5
|
+
module Solargraph
|
6
|
+
module LanguageServer
|
7
|
+
module Transport
|
8
|
+
# A common module for running language servers in Backport.
|
9
|
+
#
|
10
|
+
module Adapter
|
11
|
+
def opening
|
12
|
+
@host = Solargraph::LanguageServer::Host.new
|
13
|
+
@host.add_observer self
|
14
|
+
@host.start
|
15
|
+
@data_reader = Solargraph::LanguageServer::Transport::DataReader.new
|
16
|
+
@data_reader.set_message_handler do |message|
|
17
|
+
process message
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def closing
|
22
|
+
@host.stop
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param data [String]
|
26
|
+
def receiving data
|
27
|
+
@data_reader.receive data
|
28
|
+
end
|
29
|
+
|
30
|
+
def update
|
31
|
+
if @host.stopped?
|
32
|
+
shutdown
|
33
|
+
else
|
34
|
+
tmp = @host.flush
|
35
|
+
write tmp unless tmp.empty?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# @param request [String]
|
42
|
+
# @return [void]
|
43
|
+
def process request
|
44
|
+
message = @host.receive(request)
|
45
|
+
message.send_response
|
46
|
+
# tmp = @host.flush
|
47
|
+
# write tmp unless tmp.empty?
|
48
|
+
end
|
49
|
+
|
50
|
+
def shutdown
|
51
|
+
Backport.stop unless @host.options['transport'] == 'external'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Solargraph
|
6
|
+
module LanguageServer
|
7
|
+
module Transport
|
8
|
+
class DataReader
|
9
|
+
def initialize
|
10
|
+
@in_header = true
|
11
|
+
@content_length = 0
|
12
|
+
@buffer = String.new
|
13
|
+
end
|
14
|
+
|
15
|
+
# Declare a block to be executed for each message received from the
|
16
|
+
# client.
|
17
|
+
#
|
18
|
+
# @yieldparam [Hash] The message received from the client
|
19
|
+
def set_message_handler &block
|
20
|
+
@message_handler = block
|
21
|
+
end
|
22
|
+
|
23
|
+
# Process raw data received from the client. The data will be parsed
|
24
|
+
# into messages based on the JSON-RPC protocol. Each message will be
|
25
|
+
# passed to the block declared via set_message_handler. Incomplete data
|
26
|
+
# will be buffered and subsequent data will be appended to the buffer.
|
27
|
+
#
|
28
|
+
# @param data [String]
|
29
|
+
def receive data
|
30
|
+
data.each_char do |char|
|
31
|
+
@buffer.concat char
|
32
|
+
if @in_header
|
33
|
+
prepare_to_parse_message if @buffer.end_with?("\r\n\r\n")
|
34
|
+
else
|
35
|
+
parse_message_from_buffer if @buffer.bytesize == @content_length
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# @return [void]
|
43
|
+
def prepare_to_parse_message
|
44
|
+
@in_header = false
|
45
|
+
@buffer.each_line do |line|
|
46
|
+
parts = line.split(':').map(&:strip)
|
47
|
+
if parts[0] == 'Content-Length'
|
48
|
+
@content_length = parts[1].to_i
|
49
|
+
break
|
50
|
+
end
|
51
|
+
end
|
52
|
+
@buffer.clear
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [void]
|
56
|
+
def parse_message_from_buffer
|
57
|
+
begin
|
58
|
+
msg = JSON.parse(@buffer)
|
59
|
+
@message_handler.call msg unless @message_handler.nil?
|
60
|
+
rescue JSON::ParserError => e
|
61
|
+
Solargraph::Logging.logger.warn "Failed to parse request: #{e.message}"
|
62
|
+
Solargraph::Logging.logger.debug "Buffer: #{@buffer}"
|
63
|
+
ensure
|
64
|
+
@buffer.clear
|
65
|
+
@in_header = true
|
66
|
+
@content_length = 0
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
module Solargraph
|
6
|
+
module LanguageServer
|
7
|
+
# Methods to handle conversions between file URIs and paths.
|
8
|
+
#
|
9
|
+
module UriHelpers
|
10
|
+
module_function
|
11
|
+
|
12
|
+
# Convert a file URI to a path.
|
13
|
+
#
|
14
|
+
# @param uri [String]
|
15
|
+
# @return [String]
|
16
|
+
def uri_to_file uri
|
17
|
+
decode(uri).sub(/^file\:\/\//, '').sub(/^\/([a-z]\:)/i, '\1')
|
18
|
+
end
|
19
|
+
|
20
|
+
# Convert a file path to a URI.
|
21
|
+
#
|
22
|
+
# @param file [String]
|
23
|
+
# @return [String]
|
24
|
+
def file_to_uri file
|
25
|
+
"file://#{encode(file.gsub(/^([a-z]\:)/i, '/\1'))}"
|
26
|
+
end
|
27
|
+
|
28
|
+
# Encode text to be used as a URI path component in LSP.
|
29
|
+
#
|
30
|
+
# @param text [String]
|
31
|
+
# @return [String]
|
32
|
+
def encode text
|
33
|
+
CGI.escape(text)
|
34
|
+
.gsub('%3A', ':')
|
35
|
+
.gsub('%5C', '\\')
|
36
|
+
.gsub('%2F', '/')
|
37
|
+
.gsub('+', '%20')
|
38
|
+
end
|
39
|
+
|
40
|
+
# Decode text from a URI path component in LSP.
|
41
|
+
#
|
42
|
+
# @param text [String]
|
43
|
+
# @return [String]
|
44
|
+
def decode text
|
45
|
+
CGI.unescape(text)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,426 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
# A Library handles coordination between a Workspace and an ApiMap.
|
5
|
+
#
|
6
|
+
class Library
|
7
|
+
include Logging
|
8
|
+
|
9
|
+
# @return [Solargraph::Workspace]
|
10
|
+
attr_reader :workspace
|
11
|
+
|
12
|
+
# @return [String, nil]
|
13
|
+
attr_reader :name
|
14
|
+
|
15
|
+
# @return [Source, nil]
|
16
|
+
attr_reader :current
|
17
|
+
|
18
|
+
# @param workspace [Solargraph::Workspace]
|
19
|
+
# @param name [String, nil]
|
20
|
+
def initialize workspace = Solargraph::Workspace.new, name = nil
|
21
|
+
@workspace = workspace
|
22
|
+
@name = name
|
23
|
+
api_map.catalog bench
|
24
|
+
@synchronized = true
|
25
|
+
@catalog_mutex = Mutex.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def inspect
|
29
|
+
# Let's not deal with insane data dumps in spec failures
|
30
|
+
to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
# True if the ApiMap is up to date with the library's workspace and open
|
34
|
+
# files.
|
35
|
+
#
|
36
|
+
# @return [Boolean]
|
37
|
+
def synchronized?
|
38
|
+
@synchronized
|
39
|
+
end
|
40
|
+
|
41
|
+
# Attach a source to the library.
|
42
|
+
#
|
43
|
+
# The attached source does not need to be a part of the workspace. The
|
44
|
+
# library will include it in the ApiMap while it's attached. Only one
|
45
|
+
# source can be attached to the library at a time.
|
46
|
+
#
|
47
|
+
# @param source [Source, nil]
|
48
|
+
# @return [void]
|
49
|
+
def attach source
|
50
|
+
mutex.synchronize do
|
51
|
+
@synchronized = (@current == source) if synchronized?
|
52
|
+
@current = source
|
53
|
+
catalog
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# True if the specified file is currently attached.
|
58
|
+
#
|
59
|
+
# @param filename [String]
|
60
|
+
# @return [Boolean]
|
61
|
+
def attached? filename
|
62
|
+
!@current.nil? && @current.filename == filename
|
63
|
+
end
|
64
|
+
alias open? attached?
|
65
|
+
|
66
|
+
# Detach the specified file if it is currently attached to the library.
|
67
|
+
#
|
68
|
+
# @param filename [String]
|
69
|
+
# @return [Boolean] True if the specified file was detached
|
70
|
+
def detach filename
|
71
|
+
return false if @current.nil? || @current.filename != filename
|
72
|
+
attach nil
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
76
|
+
# True if the specified file is included in the workspace (but not
|
77
|
+
# necessarily open).
|
78
|
+
#
|
79
|
+
# @param filename [String]
|
80
|
+
# @return [Boolean]
|
81
|
+
def contain? filename
|
82
|
+
workspace.has_file?(filename)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Create a source to be added to the workspace. The file is ignored if it is
|
86
|
+
# neither open in the library nor included in the workspace.
|
87
|
+
#
|
88
|
+
# @param filename [String]
|
89
|
+
# @param text [String] The contents of the file
|
90
|
+
# @return [Boolean] True if the file was added to the workspace.
|
91
|
+
def create filename, text
|
92
|
+
result = false
|
93
|
+
mutex.synchronize do
|
94
|
+
next unless contain?(filename) || open?(filename) || workspace.would_merge?(filename)
|
95
|
+
@synchronized = false
|
96
|
+
source = Solargraph::Source.load_string(text, filename)
|
97
|
+
workspace.merge(source)
|
98
|
+
result = true
|
99
|
+
end
|
100
|
+
result
|
101
|
+
end
|
102
|
+
|
103
|
+
# Create a file source from a file on disk. The file is ignored if it is
|
104
|
+
# neither open in the library nor included in the workspace.
|
105
|
+
#
|
106
|
+
# @param filename [String]
|
107
|
+
# @return [Boolean] True if the file was added to the workspace.
|
108
|
+
def create_from_disk filename
|
109
|
+
result = false
|
110
|
+
mutex.synchronize do
|
111
|
+
next if File.directory?(filename) || !File.exist?(filename)
|
112
|
+
next unless contain?(filename) || open?(filename) || workspace.would_merge?(filename)
|
113
|
+
@synchronized = false
|
114
|
+
source = Solargraph::Source.load_string(File.read(filename), filename)
|
115
|
+
workspace.merge(source)
|
116
|
+
result = true
|
117
|
+
end
|
118
|
+
result
|
119
|
+
end
|
120
|
+
|
121
|
+
# Delete a file from the library. Deleting a file will make it unavailable
|
122
|
+
# for checkout and optionally remove it from the workspace unless the
|
123
|
+
# workspace configuration determines that it should still exist.
|
124
|
+
#
|
125
|
+
# @param filename [String]
|
126
|
+
# @return [Boolean] True if the file was deleted
|
127
|
+
def delete filename
|
128
|
+
detach filename
|
129
|
+
result = false
|
130
|
+
mutex.synchronize do
|
131
|
+
result = workspace.remove(filename)
|
132
|
+
@synchronized = !result if synchronized?
|
133
|
+
end
|
134
|
+
result
|
135
|
+
end
|
136
|
+
|
137
|
+
# Close a file in the library. Closing a file will make it unavailable for
|
138
|
+
# checkout although it may still exist in the workspace.
|
139
|
+
#
|
140
|
+
# @param filename [String]
|
141
|
+
# @return [void]
|
142
|
+
def close filename
|
143
|
+
mutex.synchronize do
|
144
|
+
@synchronized = false
|
145
|
+
@current = nil if @current && @current.filename == filename
|
146
|
+
catalog
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Get completion suggestions at the specified file and location.
|
151
|
+
#
|
152
|
+
# @param filename [String] The file to analyze
|
153
|
+
# @param line [Integer] The zero-based line number
|
154
|
+
# @param column [Integer] The zero-based column number
|
155
|
+
# @return [SourceMap::Completion]
|
156
|
+
# @todo Take a Location instead of filename/line/column
|
157
|
+
def completions_at filename, line, column
|
158
|
+
position = Position.new(line, column)
|
159
|
+
cursor = Source::Cursor.new(read(filename), position)
|
160
|
+
api_map.clip(cursor).complete
|
161
|
+
end
|
162
|
+
|
163
|
+
# Get definition suggestions for the expression at the specified file and
|
164
|
+
# location.
|
165
|
+
#
|
166
|
+
# @param filename [String] The file to analyze
|
167
|
+
# @param line [Integer] The zero-based line number
|
168
|
+
# @param column [Integer] The zero-based column number
|
169
|
+
# @return [Array<Solargraph::Pin::Base>]
|
170
|
+
# @todo Take filename/position instead of filename/line/column
|
171
|
+
def definitions_at filename, line, column
|
172
|
+
position = Position.new(line, column)
|
173
|
+
cursor = Source::Cursor.new(read(filename), position)
|
174
|
+
if cursor.comment?
|
175
|
+
source = read(filename)
|
176
|
+
offset = Solargraph::Position.to_offset(source.code, Solargraph::Position.new(line, column))
|
177
|
+
lft = source.code[0..offset-1].match(/\[[a-z0-9_:<, ]*?([a-z0-9_:]*)\z/i)
|
178
|
+
rgt = source.code[offset..-1].match(/^([a-z0-9_]*)(:[a-z0-9_:]*)?[\]>, ]/i)
|
179
|
+
if lft && rgt
|
180
|
+
tag = (lft[1] + rgt[1]).sub(/:+$/, '')
|
181
|
+
clip = api_map.clip(cursor)
|
182
|
+
clip.translate tag
|
183
|
+
else
|
184
|
+
[]
|
185
|
+
end
|
186
|
+
else
|
187
|
+
api_map.clip(cursor).define.map { |pin| pin.realize(api_map) }
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Get signature suggestions for the method at the specified file and
|
192
|
+
# location.
|
193
|
+
#
|
194
|
+
# @param filename [String] The file to analyze
|
195
|
+
# @param line [Integer] The zero-based line number
|
196
|
+
# @param column [Integer] The zero-based column number
|
197
|
+
# @return [Array<Solargraph::Pin::Base>]
|
198
|
+
# @todo Take filename/position instead of filename/line/column
|
199
|
+
def signatures_at filename, line, column
|
200
|
+
position = Position.new(line, column)
|
201
|
+
cursor = Source::Cursor.new(read(filename), position)
|
202
|
+
api_map.clip(cursor).signify
|
203
|
+
end
|
204
|
+
|
205
|
+
# @param filename [String]
|
206
|
+
# @param line [Integer]
|
207
|
+
# @param column [Integer]
|
208
|
+
# @param strip [Boolean] Strip special characters from variable names
|
209
|
+
# @return [Array<Solargraph::Range>]
|
210
|
+
# @todo Take a Location instead of filename/line/column
|
211
|
+
def references_from filename, line, column, strip: false
|
212
|
+
cursor = api_map.cursor_at(filename, Position.new(line, column))
|
213
|
+
clip = api_map.clip(cursor)
|
214
|
+
pins = clip.define
|
215
|
+
return [] if pins.empty?
|
216
|
+
result = []
|
217
|
+
pins.uniq.each do |pin|
|
218
|
+
(workspace.sources + (@current ? [@current] : [])).uniq(&:filename).each do |source|
|
219
|
+
found = source.references(pin.name)
|
220
|
+
found.select! do |loc|
|
221
|
+
referenced = definitions_at(loc.filename, loc.range.ending.line, loc.range.ending.character)
|
222
|
+
# HACK: The additional location comparison is necessary because
|
223
|
+
# Clip#define can return proxies for parameter pins
|
224
|
+
referenced.any? { |r| r == pin || r.location == pin.location }
|
225
|
+
end
|
226
|
+
# HACK: for language clients that exclude special characters from the start of variable names
|
227
|
+
if strip && match = cursor.word.match(/^[^a-z0-9_]+/i)
|
228
|
+
found.map! do |loc|
|
229
|
+
Solargraph::Location.new(loc.filename, Solargraph::Range.from_to(loc.range.start.line, loc.range.start.column + match[0].length, loc.range.ending.line, loc.range.ending.column))
|
230
|
+
end
|
231
|
+
end
|
232
|
+
result.concat(found.sort do |a, b|
|
233
|
+
a.range.start.line <=> b.range.start.line
|
234
|
+
end)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
result.uniq
|
238
|
+
end
|
239
|
+
|
240
|
+
# Get the pins at the specified location or nil if the pin does not exist.
|
241
|
+
#
|
242
|
+
# @param location [Location]
|
243
|
+
# @return [Array<Solargraph::Pin::Base>]
|
244
|
+
def locate_pins location
|
245
|
+
api_map.locate_pins(location).map { |pin| pin.realize(api_map) }
|
246
|
+
end
|
247
|
+
|
248
|
+
def locate_ref location
|
249
|
+
api_map.require_reference_at location
|
250
|
+
end
|
251
|
+
|
252
|
+
# Get an array of pins that match a path.
|
253
|
+
#
|
254
|
+
# @param path [String]
|
255
|
+
# @return [Array<Solargraph::Pin::Base>]
|
256
|
+
def get_path_pins path
|
257
|
+
api_map.get_path_suggestions(path)
|
258
|
+
end
|
259
|
+
|
260
|
+
# @param query [String]
|
261
|
+
# @return [Array<YARD::CodeObjects::Base>]
|
262
|
+
def document query
|
263
|
+
catalog
|
264
|
+
api_map.document query
|
265
|
+
end
|
266
|
+
|
267
|
+
# @param query [String]
|
268
|
+
# @return [Array<String>]
|
269
|
+
def search query
|
270
|
+
catalog
|
271
|
+
api_map.search query
|
272
|
+
end
|
273
|
+
|
274
|
+
# Get an array of all symbols in the workspace that match the query.
|
275
|
+
#
|
276
|
+
# @param query [String]
|
277
|
+
# @return [Array<Pin::Base>]
|
278
|
+
def query_symbols query
|
279
|
+
catalog
|
280
|
+
api_map.query_symbols query
|
281
|
+
end
|
282
|
+
|
283
|
+
# Get an array of document symbols.
|
284
|
+
#
|
285
|
+
# Document symbols are composed of namespace, method, and constant pins.
|
286
|
+
# The results of this query are appropriate for building the response to a
|
287
|
+
# textDocument/documentSymbol message in the language server protocol.
|
288
|
+
#
|
289
|
+
# @param filename [String]
|
290
|
+
# @return [Array<Solargraph::Pin::Base>]
|
291
|
+
def document_symbols filename
|
292
|
+
api_map.document_symbols(filename)
|
293
|
+
end
|
294
|
+
|
295
|
+
# @param path [String]
|
296
|
+
# @return [Array<Solargraph::Pin::Base>]
|
297
|
+
def path_pins path
|
298
|
+
catalog
|
299
|
+
api_map.get_path_suggestions(path)
|
300
|
+
end
|
301
|
+
|
302
|
+
# Get the current text of a file in the library.
|
303
|
+
#
|
304
|
+
# @param filename [String]
|
305
|
+
# @return [String]
|
306
|
+
def read_text filename
|
307
|
+
source = read(filename)
|
308
|
+
source.code
|
309
|
+
end
|
310
|
+
|
311
|
+
# Get diagnostics about a file.
|
312
|
+
#
|
313
|
+
# @param filename [String]
|
314
|
+
# @return [Array<Hash>]
|
315
|
+
def diagnose filename
|
316
|
+
# @todo Only open files get diagnosed. Determine whether anything or
|
317
|
+
# everything in the workspace should get diagnosed, or if there should
|
318
|
+
# be an option to do so.
|
319
|
+
#
|
320
|
+
return [] unless open?(filename)
|
321
|
+
catalog
|
322
|
+
result = []
|
323
|
+
source = read(filename)
|
324
|
+
repargs = {}
|
325
|
+
workspace.config.reporters.each do |line|
|
326
|
+
if line == 'all!'
|
327
|
+
Diagnostics.reporters.each do |reporter|
|
328
|
+
repargs[reporter] ||= []
|
329
|
+
end
|
330
|
+
else
|
331
|
+
args = line.split(':').map(&:strip)
|
332
|
+
name = args.shift
|
333
|
+
reporter = Diagnostics.reporter(name)
|
334
|
+
raise DiagnosticsError, "Diagnostics reporter #{name} does not exist" if reporter.nil?
|
335
|
+
repargs[reporter] ||= []
|
336
|
+
repargs[reporter].concat args
|
337
|
+
end
|
338
|
+
end
|
339
|
+
repargs.each_pair do |reporter, args|
|
340
|
+
result.concat reporter.new(*args.uniq).diagnose(source, api_map)
|
341
|
+
end
|
342
|
+
result
|
343
|
+
end
|
344
|
+
|
345
|
+
# Update the ApiMap from the library's workspace and open files.
|
346
|
+
#
|
347
|
+
# @return [void]
|
348
|
+
def catalog
|
349
|
+
@catalog_mutex.synchronize do
|
350
|
+
break if synchronized?
|
351
|
+
logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
|
352
|
+
api_map.catalog bench
|
353
|
+
@synchronized = true
|
354
|
+
logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)" if logger.info?
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
# Get an array of foldable ranges for the specified file.
|
359
|
+
#
|
360
|
+
# @deprecated The library should not need to handle folding ranges. The
|
361
|
+
# source itself has all the information it needs.
|
362
|
+
#
|
363
|
+
# @param filename [String]
|
364
|
+
# @return [Array<Range>]
|
365
|
+
def folding_ranges filename
|
366
|
+
read(filename).folding_ranges
|
367
|
+
end
|
368
|
+
|
369
|
+
# Create a library from a directory.
|
370
|
+
#
|
371
|
+
# @param directory [String] The path to be used for the workspace
|
372
|
+
# @param name [String, nil]
|
373
|
+
# @return [Solargraph::Library]
|
374
|
+
def self.load directory = '', name = nil
|
375
|
+
Solargraph::Library.new(Solargraph::Workspace.new(directory), name)
|
376
|
+
end
|
377
|
+
|
378
|
+
# Try to merge a source into the library's workspace. If the workspace is
|
379
|
+
# not configured to include the source, it gets ignored.
|
380
|
+
#
|
381
|
+
# @param source [Source]
|
382
|
+
# @return [Boolean] True if the source was merged into the workspace.
|
383
|
+
def merge source
|
384
|
+
result = false
|
385
|
+
mutex.synchronize do
|
386
|
+
result = workspace.merge(source)
|
387
|
+
@synchronized = !result if synchronized?
|
388
|
+
end
|
389
|
+
result
|
390
|
+
end
|
391
|
+
|
392
|
+
private
|
393
|
+
|
394
|
+
# @return [Mutex]
|
395
|
+
def mutex
|
396
|
+
@mutex ||= Mutex.new
|
397
|
+
end
|
398
|
+
|
399
|
+
# @return [ApiMap]
|
400
|
+
def api_map
|
401
|
+
@api_map ||= Solargraph::ApiMap.new
|
402
|
+
end
|
403
|
+
|
404
|
+
# @return [Bench]
|
405
|
+
def bench
|
406
|
+
Bench.new(
|
407
|
+
workspace: workspace,
|
408
|
+
opened: @current ? [@current] : []
|
409
|
+
)
|
410
|
+
end
|
411
|
+
|
412
|
+
# Get the source for an open file or create a new source if the file
|
413
|
+
# exists on disk. Sources created from disk are not added to the open
|
414
|
+
# workspace files, i.e., the version on disk remains the authoritative
|
415
|
+
# version.
|
416
|
+
#
|
417
|
+
# @raise [FileNotFoundError] if the file does not exist
|
418
|
+
# @param filename [String]
|
419
|
+
# @return [Solargraph::Source]
|
420
|
+
def read filename
|
421
|
+
return @current if @current && @current.filename == filename
|
422
|
+
raise FileNotFoundError, "File not found: #{filename}" unless workspace.has_file?(filename)
|
423
|
+
workspace.source(filename)
|
424
|
+
end
|
425
|
+
end
|
426
|
+
end
|