solargraph 0.51.2 → 0.54.2
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 +4 -4
- data/.github/workflows/plugins.yml +40 -0
- data/.github/workflows/rspec.yml +1 -3
- data/.github/workflows/typecheck.yml +34 -0
- data/.yardopts +2 -2
- data/CHANGELOG.md +127 -5
- data/README.md +13 -16
- data/SPONSORS.md +1 -7
- data/lib/solargraph/api_map/cache.rb +50 -20
- data/lib/solargraph/api_map/source_to_yard.rb +17 -10
- data/lib/solargraph/api_map/store.rb +60 -15
- data/lib/solargraph/api_map.rb +282 -123
- data/lib/solargraph/bench.rb +3 -2
- data/lib/solargraph/cache.rb +29 -5
- data/lib/solargraph/complex_type/type_methods.rb +122 -39
- data/lib/solargraph/complex_type/unique_type.rb +310 -76
- data/lib/solargraph/complex_type.rb +166 -44
- data/lib/solargraph/convention.rb +0 -1
- data/lib/solargraph/converters/dd.rb +5 -0
- data/lib/solargraph/converters/dl.rb +3 -0
- data/lib/solargraph/converters/dt.rb +3 -0
- data/lib/solargraph/diagnostics/rubocop.rb +8 -7
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -0
- data/lib/solargraph/diagnostics/type_check.rb +1 -0
- data/lib/solargraph/diagnostics.rb +2 -2
- data/lib/solargraph/doc_map.rb +187 -0
- data/lib/solargraph/gem_pins.rb +72 -0
- data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
- data/lib/solargraph/language_server/host/dispatch.rb +22 -5
- data/lib/solargraph/language_server/host/message_worker.rb +49 -5
- data/lib/solargraph/language_server/host/sources.rb +8 -65
- data/lib/solargraph/language_server/host.rb +65 -84
- data/lib/solargraph/language_server/message/base.rb +19 -12
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
- data/lib/solargraph/language_server/message/initialize.rb +19 -2
- data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
- data/lib/solargraph/language_server/message/text_document/definition.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -0
- data/lib/solargraph/language_server/message/text_document/hover.rb +3 -1
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +3 -3
- data/lib/solargraph/language_server/message/text_document.rb +0 -1
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
- data/lib/solargraph/language_server/progress.rb +135 -0
- data/lib/solargraph/language_server/transport/adapter.rb +16 -1
- data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
- data/lib/solargraph/language_server.rb +1 -0
- data/lib/solargraph/library.rb +207 -111
- data/lib/solargraph/location.rb +15 -1
- data/lib/solargraph/page.rb +6 -0
- data/lib/solargraph/parser/comment_ripper.rb +4 -0
- data/lib/solargraph/parser/node_methods.rb +47 -7
- data/lib/solargraph/parser/node_processor/base.rb +11 -1
- data/lib/solargraph/parser/node_processor.rb +1 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -9
- data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +62 -43
- data/lib/solargraph/parser/parser_gem/node_methods.rb +495 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +57 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/def_node.rb +7 -20
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +4 -4
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +53 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sclass_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +8 -6
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/sym_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors.rb +56 -0
- data/lib/solargraph/parser/parser_gem.rb +12 -0
- data/lib/solargraph/parser/region.rb +1 -1
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +8 -12
- data/lib/solargraph/pin/base.rb +78 -10
- data/lib/solargraph/pin/base_variable.rb +40 -7
- data/lib/solargraph/pin/block.rb +69 -46
- data/lib/solargraph/pin/callable.rb +147 -0
- data/lib/solargraph/pin/closure.rb +23 -3
- data/lib/solargraph/pin/common.rb +6 -6
- data/lib/solargraph/pin/conversions.rb +36 -5
- data/lib/solargraph/pin/delegated_method.rb +6 -2
- data/lib/solargraph/pin/documenting.rb +25 -32
- data/lib/solargraph/pin/instance_variable.rb +6 -2
- data/lib/solargraph/pin/local_variable.rb +13 -1
- data/lib/solargraph/pin/method.rb +205 -32
- data/lib/solargraph/pin/namespace.rb +20 -7
- data/lib/solargraph/pin/parameter.rb +41 -36
- data/lib/solargraph/pin/proxy_type.rb +1 -1
- data/lib/solargraph/pin/reference/override.rb +2 -2
- data/lib/solargraph/pin/reference.rb +8 -0
- data/lib/solargraph/pin/search.rb +3 -3
- data/lib/solargraph/pin/signature.rb +8 -14
- data/lib/solargraph/pin.rb +4 -2
- data/lib/solargraph/range.rb +4 -6
- data/lib/solargraph/rbs_map/conversions.rb +326 -76
- data/lib/solargraph/rbs_map/core_fills.rb +16 -33
- data/lib/solargraph/rbs_map/core_map.rb +3 -13
- data/lib/solargraph/rbs_map/stdlib_map.rb +2 -8
- data/lib/solargraph/rbs_map.rb +32 -13
- data/lib/solargraph/shell.rb +95 -72
- data/lib/solargraph/source/chain/array.rb +33 -0
- data/lib/solargraph/source/chain/block_symbol.rb +13 -0
- data/lib/solargraph/source/chain/block_variable.rb +1 -1
- data/lib/solargraph/source/chain/call.rb +152 -69
- data/lib/solargraph/source/chain/constant.rb +15 -1
- data/lib/solargraph/source/chain/if.rb +23 -0
- data/lib/solargraph/source/chain/link.rb +17 -2
- data/lib/solargraph/source/chain/or.rb +2 -2
- data/lib/solargraph/source/chain/z_super.rb +3 -3
- data/lib/solargraph/source/chain.rb +85 -26
- data/lib/solargraph/source/change.rb +3 -0
- data/lib/solargraph/source/cursor.rb +16 -2
- data/lib/solargraph/source/source_chainer.rb +8 -5
- data/lib/solargraph/source/updater.rb +1 -0
- data/lib/solargraph/source.rb +120 -148
- data/lib/solargraph/source_map/clip.rb +16 -27
- data/lib/solargraph/source_map/data.rb +30 -0
- data/lib/solargraph/source_map/mapper.rb +15 -3
- data/lib/solargraph/source_map.rb +48 -24
- data/lib/solargraph/type_checker/checks.rb +10 -2
- data/lib/solargraph/type_checker/rules.rb +6 -1
- data/lib/solargraph/type_checker.rb +150 -39
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +3 -5
- data/lib/solargraph/workspace/config.rb +9 -6
- data/lib/solargraph/workspace.rb +30 -3
- data/lib/solargraph/yard_map/cache.rb +6 -0
- data/lib/solargraph/yard_map/helpers.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +16 -3
- data/lib/solargraph/yard_map/mapper.rb +1 -1
- data/lib/solargraph/yard_map/to_method.rb +11 -4
- data/lib/solargraph/yard_map.rb +1 -292
- data/lib/solargraph/yard_tags.rb +20 -0
- data/lib/solargraph/yardoc.rb +52 -0
- data/lib/solargraph.rb +6 -4
- data/solargraph.gemspec +7 -6
- metadata +71 -82
- data/lib/solargraph/api_map/bundler_methods.rb +0 -22
- data/lib/solargraph/documentor.rb +0 -76
- data/lib/solargraph/language_server/host/cataloger.rb +0 -56
- data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
- data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
- data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -50
- data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
- data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
- data/lib/solargraph/parser/legacy/node_processors.rb +0 -55
- data/lib/solargraph/parser/legacy.rb +0 -12
- data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -153
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
- data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -317
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
- data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -33
- data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
- data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
- data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
- data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
- data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
- data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -51
- data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -32
- data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
- data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -64
- data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
- data/lib/solargraph/parser/rubyvm.rb +0 -40
- data/lib/solargraph/rbs_map/core_signs.rb +0 -33
- data/lib/yard-solargraph.rb +0 -33
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rbs'
|
4
|
+
|
5
|
+
module Solargraph
|
6
|
+
# A utility for building gem pins from a combination of YARD and RBS
|
7
|
+
# documentation.
|
8
|
+
#
|
9
|
+
module GemPins
|
10
|
+
# Build an array of pins from a gem specification. The process starts with
|
11
|
+
# YARD, enhances the resulting pins with RBS definitions, and appends RBS
|
12
|
+
# pins that don't exist in the YARD mapping.
|
13
|
+
#
|
14
|
+
# @param gemspec [Gem::Specification]
|
15
|
+
# @return [Array<Pin::Base>]
|
16
|
+
def self.build(gemspec)
|
17
|
+
yard_pins = build_yard_pins(gemspec)
|
18
|
+
rbs_map = RbsMap.from_gemspec(gemspec)
|
19
|
+
combine yard_pins, rbs_map
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param yard_pins [Array<Pin::Base>]
|
23
|
+
# @param rbs_map [RbsMap]
|
24
|
+
# @return [Array<Pin::Base>]
|
25
|
+
def self.combine(yard_pins, rbs_map)
|
26
|
+
in_yard = Set.new
|
27
|
+
combined = yard_pins.map do |yard|
|
28
|
+
in_yard.add yard.path
|
29
|
+
next yard unless yard.is_a?(Pin::Method)
|
30
|
+
|
31
|
+
rbs = rbs_map.path_pin(yard.path, Pin::Method)
|
32
|
+
next yard unless rbs
|
33
|
+
|
34
|
+
# @sg-ignore
|
35
|
+
yard.class.new(
|
36
|
+
location: yard.location,
|
37
|
+
closure: yard.closure,
|
38
|
+
name: yard.name,
|
39
|
+
comments: yard.comments,
|
40
|
+
scope: yard.scope,
|
41
|
+
parameters: rbs.parameters,
|
42
|
+
generics: rbs.generics,
|
43
|
+
node: yard.node,
|
44
|
+
signatures: yard.signatures,
|
45
|
+
return_type: best_return_type(rbs.return_type, yard.return_type)
|
46
|
+
)
|
47
|
+
end
|
48
|
+
in_rbs = rbs_map.pins.reject { |pin| in_yard.include?(pin.path) }
|
49
|
+
combined + in_rbs
|
50
|
+
end
|
51
|
+
|
52
|
+
class << self
|
53
|
+
private
|
54
|
+
|
55
|
+
# @param gemspec [Gem::Specification]
|
56
|
+
# @return [Array<Pin::Base>]
|
57
|
+
def build_yard_pins(gemspec)
|
58
|
+
Yardoc.cache(gemspec) unless Yardoc.cached?(gemspec)
|
59
|
+
yardoc = Yardoc.load!(gemspec)
|
60
|
+
YardMap::Mapper.new(yardoc, gemspec).map
|
61
|
+
end
|
62
|
+
|
63
|
+
# Select the first defined type.
|
64
|
+
#
|
65
|
+
# @param choices [Array<ComplexType>]
|
66
|
+
# @return [ComplexType]
|
67
|
+
def best_return_type *choices
|
68
|
+
choices.find { |pin| pin.defined? } || choices.first || ComplexType::UNDEFINED
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -38,7 +38,7 @@ module Solargraph
|
|
38
38
|
|
39
39
|
# Start the diagnosis thread.
|
40
40
|
#
|
41
|
-
# @return [self]
|
41
|
+
# @return [self, nil]
|
42
42
|
def start
|
43
43
|
return unless @stopped
|
44
44
|
@stopped = false
|
@@ -81,7 +81,7 @@ module Solargraph
|
|
81
81
|
# @return [Mutex]
|
82
82
|
attr_reader :mutex
|
83
83
|
|
84
|
-
# @return [Array]
|
84
|
+
# @return [::Array]
|
85
85
|
attr_reader :queue
|
86
86
|
end
|
87
87
|
end
|
@@ -6,6 +6,12 @@ module Solargraph
|
|
6
6
|
# Methods for associating sources with libraries via URIs.
|
7
7
|
#
|
8
8
|
module Dispatch
|
9
|
+
# @abstract
|
10
|
+
# @return [Host::Diagnoser]
|
11
|
+
def diagnoser
|
12
|
+
raise NotImplementedError, 'Host::Dispatch requires a diagnoser method'
|
13
|
+
end
|
14
|
+
|
9
15
|
# @return [Sources]
|
10
16
|
def sources
|
11
17
|
@sources ||= begin
|
@@ -15,7 +21,7 @@ module Solargraph
|
|
15
21
|
end
|
16
22
|
end
|
17
23
|
|
18
|
-
# @return [Array<Library>]
|
24
|
+
# @return [::Array<Library>]
|
19
25
|
def libraries
|
20
26
|
@libraries ||= []
|
21
27
|
end
|
@@ -27,9 +33,9 @@ module Solargraph
|
|
27
33
|
# @return [void]
|
28
34
|
def update_libraries uri
|
29
35
|
src = sources.find(uri)
|
30
|
-
libraries.
|
31
|
-
|
32
|
-
|
36
|
+
using = libraries.select { |lib| lib.contain?(src.filename) }
|
37
|
+
using.push library_for(uri) if using.empty?
|
38
|
+
using.each { |lib| lib.merge src }
|
33
39
|
diagnoser.schedule uri
|
34
40
|
end
|
35
41
|
|
@@ -89,6 +95,10 @@ module Solargraph
|
|
89
95
|
nil
|
90
96
|
end
|
91
97
|
|
98
|
+
def options
|
99
|
+
@options ||= {}.freeze
|
100
|
+
end
|
101
|
+
|
92
102
|
# Get a generic library for the given URI and attach the corresponding
|
93
103
|
# source.
|
94
104
|
#
|
@@ -103,7 +113,14 @@ module Solargraph
|
|
103
113
|
|
104
114
|
# @return [Library]
|
105
115
|
def generic_library
|
106
|
-
@generic_library ||= Solargraph::Library.new
|
116
|
+
@generic_library ||= Solargraph::Library.new(Solargraph::Workspace.new('', nil, options), nil)
|
117
|
+
.tap { |lib| lib.add_observer self }
|
118
|
+
end
|
119
|
+
|
120
|
+
# @param library [Solargraph::Library]
|
121
|
+
# @return [void]
|
122
|
+
def update progress
|
123
|
+
progress&.send(self)
|
107
124
|
end
|
108
125
|
end
|
109
126
|
end
|
@@ -3,10 +3,15 @@
|
|
3
3
|
module Solargraph
|
4
4
|
module LanguageServer
|
5
5
|
class Host
|
6
|
-
# A serial worker Thread to handle
|
6
|
+
# A serial worker Thread to handle incoming messages.
|
7
7
|
#
|
8
|
-
# this make check pending message possible, and maybe cancelled to speedup process
|
9
8
|
class MessageWorker
|
9
|
+
UPDATE_METHODS = [
|
10
|
+
'textDocument/didOpen',
|
11
|
+
'textDocument/didChange',
|
12
|
+
'workspace/didChangeWatchedFiles'
|
13
|
+
].freeze
|
14
|
+
|
10
15
|
# @param host [Host]
|
11
16
|
def initialize(host)
|
12
17
|
@host = host
|
@@ -16,6 +21,7 @@ module Solargraph
|
|
16
21
|
end
|
17
22
|
|
18
23
|
# pending handle messages
|
24
|
+
# @return [Array<Hash>]
|
19
25
|
def messages
|
20
26
|
@messages ||= []
|
21
27
|
end
|
@@ -24,11 +30,12 @@ module Solargraph
|
|
24
30
|
@stopped
|
25
31
|
end
|
26
32
|
|
33
|
+
# @return [void]
|
27
34
|
def stop
|
28
35
|
@stopped = true
|
29
36
|
end
|
30
37
|
|
31
|
-
# @param message [Hash] The message
|
38
|
+
# @param message [Hash] The message to handle. Will be forwarded to Host#receive
|
32
39
|
# @return [void]
|
33
40
|
def queue(message)
|
34
41
|
@mutex.synchronize do
|
@@ -37,6 +44,7 @@ module Solargraph
|
|
37
44
|
end
|
38
45
|
end
|
39
46
|
|
47
|
+
# @return [void]
|
40
48
|
def start
|
41
49
|
return unless @stopped
|
42
50
|
@stopped = false
|
@@ -45,13 +53,49 @@ module Solargraph
|
|
45
53
|
end
|
46
54
|
end
|
47
55
|
|
56
|
+
# @return [void]
|
48
57
|
def tick
|
49
58
|
message = @mutex.synchronize do
|
50
59
|
@resource.wait(@mutex) if messages.empty?
|
51
|
-
|
60
|
+
next_message
|
52
61
|
end
|
53
62
|
handler = @host.receive(message)
|
54
|
-
handler
|
63
|
+
handler&.send_response
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def next_message
|
69
|
+
cancel_message || next_priority
|
70
|
+
end
|
71
|
+
|
72
|
+
def cancel_message
|
73
|
+
# Handle cancellations first
|
74
|
+
idx = messages.find_index { |msg| msg['method'] == '$/cancelRequest' }
|
75
|
+
return unless idx
|
76
|
+
|
77
|
+
msg = messages[idx]
|
78
|
+
messages.delete_at idx
|
79
|
+
msg
|
80
|
+
end
|
81
|
+
|
82
|
+
def next_priority
|
83
|
+
# Prioritize updates and version-dependent messages for performance
|
84
|
+
idx = messages.find_index do |msg|
|
85
|
+
UPDATE_METHODS.include?(msg['method']) || version_dependent?(msg)
|
86
|
+
end
|
87
|
+
return messages.shift unless idx
|
88
|
+
|
89
|
+
msg = messages[idx]
|
90
|
+
messages.delete_at idx
|
91
|
+
msg
|
92
|
+
end
|
93
|
+
|
94
|
+
# True if the message requires a previous update to have executed in
|
95
|
+
# order to work correctly.
|
96
|
+
#
|
97
|
+
def version_dependent? msg
|
98
|
+
msg['textDocument'] && msg['position']
|
55
99
|
end
|
56
100
|
end
|
57
101
|
end
|
@@ -11,53 +11,10 @@ module Solargraph
|
|
11
11
|
include Observable
|
12
12
|
include UriHelpers
|
13
13
|
|
14
|
-
|
15
|
-
@mutex = Mutex.new
|
16
|
-
@stopped = true
|
17
|
-
@has_uri = ConditionVariable.new
|
18
|
-
end
|
19
|
-
|
20
|
-
def stopped?
|
21
|
-
@stopped
|
22
|
-
end
|
23
|
-
|
24
|
-
# @return [void]
|
25
|
-
def start
|
26
|
-
return unless @stopped
|
27
|
-
@stopped = false
|
28
|
-
Thread.new do
|
29
|
-
tick until stopped?
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# @return [void]
|
34
|
-
def tick
|
35
|
-
uri = mutex.synchronize { next_uri }
|
36
|
-
|
37
|
-
return if queue.include?(uri)
|
38
|
-
mutex.synchronize do
|
39
|
-
nxt = open_source_hash[uri].finish_synchronize
|
40
|
-
open_source_hash[uri] = nxt
|
41
|
-
changed
|
42
|
-
notify_observers uri
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
14
|
+
# @param uri [String]
|
46
15
|
# @return [void]
|
47
16
|
def add_uri(uri)
|
48
17
|
queue.push(uri)
|
49
|
-
@has_uri.signal
|
50
|
-
end
|
51
|
-
|
52
|
-
# @return [String]
|
53
|
-
def next_uri
|
54
|
-
@has_uri.wait(mutex) if queue.empty?
|
55
|
-
queue.shift
|
56
|
-
end
|
57
|
-
|
58
|
-
# @return [void]
|
59
|
-
def stop
|
60
|
-
@stopped = true
|
61
18
|
end
|
62
19
|
|
63
20
|
# Open a source.
|
@@ -72,6 +29,8 @@ module Solargraph
|
|
72
29
|
open_source_hash[uri] = source
|
73
30
|
end
|
74
31
|
|
32
|
+
# @param uri [String]
|
33
|
+
# @return [void]
|
75
34
|
def open_from_disk uri
|
76
35
|
source = Solargraph::Source.load(UriHelpers.uri_to_file(uri))
|
77
36
|
open_source_hash[uri] = source
|
@@ -81,25 +40,12 @@ module Solargraph
|
|
81
40
|
#
|
82
41
|
# @raise [FileNotFoundError] if the URI does not match an open source.
|
83
42
|
#
|
84
|
-
# @param uri [String]
|
85
|
-
# @param updater [Source::Updater]
|
86
|
-
# @return [Source]
|
87
|
-
def update uri, updater
|
88
|
-
src = find(uri)
|
89
|
-
mutex.synchronize { open_source_hash[uri] = src.synchronize(updater) }
|
90
|
-
changed
|
91
|
-
notify_observers uri
|
92
|
-
end
|
93
|
-
|
94
43
|
# @param uri [String]
|
95
44
|
# @param updater [Source::Updater]
|
96
45
|
# @return [void]
|
97
|
-
def
|
46
|
+
def update uri, updater
|
98
47
|
src = find(uri)
|
99
|
-
|
100
|
-
open_source_hash[uri] = src.start_synchronize(updater)
|
101
|
-
add_uri(uri)
|
102
|
-
end
|
48
|
+
open_source_hash[uri] = src.synchronize(updater)
|
103
49
|
changed
|
104
50
|
notify_observers uri
|
105
51
|
end
|
@@ -109,7 +55,7 @@ module Solargraph
|
|
109
55
|
# @raise [FileNotFoundError] if the URI does not match an open source.
|
110
56
|
#
|
111
57
|
# @param uri [String]
|
112
|
-
# @return [Source]
|
58
|
+
# @return [Solargraph::Source]
|
113
59
|
def find uri
|
114
60
|
open_source_hash[uri] || raise(Solargraph::FileNotFoundError, "Host could not find #{uri}")
|
115
61
|
end
|
@@ -136,17 +82,14 @@ module Solargraph
|
|
136
82
|
|
137
83
|
private
|
138
84
|
|
139
|
-
# @return [Hash]
|
85
|
+
# @return [Hash{String => Solargraph::Source}]
|
140
86
|
def open_source_hash
|
141
87
|
@open_source_hash ||= {}
|
142
88
|
end
|
143
89
|
|
144
|
-
# @return [Mutex]
|
145
|
-
attr_reader :mutex
|
146
|
-
|
147
90
|
# An array of source URIs that are waiting to finish synchronizing.
|
148
91
|
#
|
149
|
-
# @return [Array<String>]
|
92
|
+
# @return [::Array<String>]
|
150
93
|
def queue
|
151
94
|
@queue ||= []
|
152
95
|
end
|
@@ -3,7 +3,6 @@
|
|
3
3
|
require 'diff/lcs'
|
4
4
|
require 'observer'
|
5
5
|
require 'securerandom'
|
6
|
-
require 'set'
|
7
6
|
|
8
7
|
module Solargraph
|
9
8
|
module LanguageServer
|
@@ -13,7 +12,6 @@ module Solargraph
|
|
13
12
|
#
|
14
13
|
class Host
|
15
14
|
autoload :Diagnoser, 'solargraph/language_server/host/diagnoser'
|
16
|
-
autoload :Cataloger, 'solargraph/language_server/host/cataloger'
|
17
15
|
autoload :Sources, 'solargraph/language_server/host/sources'
|
18
16
|
autoload :Dispatch, 'solargraph/language_server/host/dispatch'
|
19
17
|
autoload :MessageWorker, 'solargraph/language_server/host/message_worker'
|
@@ -26,10 +24,8 @@ module Solargraph
|
|
26
24
|
attr_writer :client_capabilities
|
27
25
|
|
28
26
|
def initialize
|
29
|
-
@cancel_semaphore = Mutex.new
|
30
27
|
@buffer_semaphore = Mutex.new
|
31
28
|
@request_mutex = Mutex.new
|
32
|
-
@cancel = []
|
33
29
|
@buffer = String.new
|
34
30
|
@stopped = true
|
35
31
|
@next_request_id = 1
|
@@ -44,8 +40,6 @@ module Solargraph
|
|
44
40
|
return unless stopped?
|
45
41
|
@stopped = false
|
46
42
|
diagnoser.start
|
47
|
-
cataloger.start
|
48
|
-
sources.start
|
49
43
|
message_worker.start
|
50
44
|
end
|
51
45
|
|
@@ -59,7 +53,7 @@ module Solargraph
|
|
59
53
|
logger.level = LOG_LEVELS[options['logLevel']] || DEFAULT_LOG_LEVEL
|
60
54
|
end
|
61
55
|
|
62
|
-
# @return [Hash]
|
56
|
+
# @return [Hash{String => [Boolean, String]}]
|
63
57
|
def options
|
64
58
|
@options ||= default_configuration
|
65
59
|
end
|
@@ -69,7 +63,7 @@ module Solargraph
|
|
69
63
|
# @param id [Integer]
|
70
64
|
# @return [void]
|
71
65
|
def cancel id
|
72
|
-
|
66
|
+
cancelled.push id
|
73
67
|
end
|
74
68
|
|
75
69
|
# True if the host received a request to cancel the method with the
|
@@ -78,9 +72,7 @@ module Solargraph
|
|
78
72
|
# @param id [Integer]
|
79
73
|
# @return [Boolean]
|
80
74
|
def cancel? id
|
81
|
-
|
82
|
-
@cancel_semaphore.synchronize { result = @cancel.include? id }
|
83
|
-
result
|
75
|
+
cancelled.include? id
|
84
76
|
end
|
85
77
|
|
86
78
|
# Delete the specified ID from the list of cancelled IDs if it exists.
|
@@ -88,7 +80,7 @@ module Solargraph
|
|
88
80
|
# @param id [Integer]
|
89
81
|
# @return [void]
|
90
82
|
def clear id
|
91
|
-
|
83
|
+
cancelled.delete id
|
92
84
|
end
|
93
85
|
|
94
86
|
# Called by adapter, to handle the request
|
@@ -101,15 +93,15 @@ module Solargraph
|
|
101
93
|
# Start processing a request from the client. After the message is
|
102
94
|
# processed, caller is responsible for sending the response.
|
103
95
|
#
|
104
|
-
# @param request [Hash] The contents of the message.
|
105
|
-
# @return [Solargraph::LanguageServer::Message::Base] The message handler.
|
96
|
+
# @param request [Hash{String => unspecified}] The contents of the message.
|
97
|
+
# @return [Solargraph::LanguageServer::Message::Base, nil] The message handler.
|
106
98
|
def receive request
|
107
99
|
if request['method']
|
108
|
-
logger.info "
|
100
|
+
logger.info "Host received ##{request['id']} #{request['method']}"
|
109
101
|
logger.debug request
|
110
102
|
message = Message.select(request['method']).new(self, request)
|
111
103
|
begin
|
112
|
-
message.process
|
104
|
+
message.process unless cancel?(request['id'])
|
113
105
|
rescue StandardError => e
|
114
106
|
logger.warn "Error processing request: [#{e.class}] #{e.message}"
|
115
107
|
logger.warn e.backtrace.join("\n")
|
@@ -127,6 +119,7 @@ module Solargraph
|
|
127
119
|
else
|
128
120
|
logger.warn "Invalid message received."
|
129
121
|
logger.debug request
|
122
|
+
nil
|
130
123
|
end
|
131
124
|
end
|
132
125
|
|
@@ -155,6 +148,7 @@ module Solargraph
|
|
155
148
|
def delete *uris
|
156
149
|
filenames = uris.map { |uri| uri_to_file(uri) }
|
157
150
|
libraries.each do |lib|
|
151
|
+
lib.delete_observer self
|
158
152
|
lib.delete(*filenames)
|
159
153
|
end
|
160
154
|
uris.each do |uri|
|
@@ -253,7 +247,7 @@ module Solargraph
|
|
253
247
|
# @return [void]
|
254
248
|
def change params
|
255
249
|
updater = generate_updater(params)
|
256
|
-
sources.
|
250
|
+
sources.update params['textDocument']['uri'], updater
|
257
251
|
diagnoser.schedule params['textDocument']['uri']
|
258
252
|
end
|
259
253
|
|
@@ -292,9 +286,11 @@ module Solargraph
|
|
292
286
|
path = ''
|
293
287
|
path = normalize_separators(directory) unless directory.nil?
|
294
288
|
begin
|
295
|
-
|
289
|
+
workspace = Solargraph::Workspace.new(path, nil, options)
|
290
|
+
lib = Solargraph::Library.new(workspace, name)
|
291
|
+
lib.add_observer self
|
296
292
|
libraries.push lib
|
297
|
-
|
293
|
+
library_map lib
|
298
294
|
rescue WorkspaceTooLargeError => e
|
299
295
|
send_notification 'window/showMessage', {
|
300
296
|
'type' => Solargraph::LanguageServer::MessageTypes::WARNING,
|
@@ -323,6 +319,7 @@ module Solargraph
|
|
323
319
|
# @param lib [Library]
|
324
320
|
libraries.delete_if do |lib|
|
325
321
|
next false if lib.workspace.directory != directory
|
322
|
+
lib.delete_observer self
|
326
323
|
true
|
327
324
|
end
|
328
325
|
end
|
@@ -380,7 +377,6 @@ module Solargraph
|
|
380
377
|
envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
|
381
378
|
queue envelope
|
382
379
|
@next_request_id += 1
|
383
|
-
logger.info "Server sent #{method}"
|
384
380
|
logger.debug params
|
385
381
|
end
|
386
382
|
end
|
@@ -457,9 +453,7 @@ module Solargraph
|
|
457
453
|
return if @stopped
|
458
454
|
@stopped = true
|
459
455
|
message_worker.stop
|
460
|
-
cataloger.stop
|
461
456
|
diagnoser.stop
|
462
|
-
sources.stop
|
463
457
|
changed
|
464
458
|
notify_observers
|
465
459
|
end
|
@@ -492,6 +486,24 @@ module Solargraph
|
|
492
486
|
end
|
493
487
|
if params['data']['path']
|
494
488
|
result.concat library.path_pins(params['data']['path'])
|
489
|
+
# @todo This exception is necessary because `Library#path_pins` does
|
490
|
+
# not perform a namespace method query, so the implicit `.new` pin
|
491
|
+
# might not exist.
|
492
|
+
if result.empty? && params['data']['path'] =~ /\.new$/
|
493
|
+
result.concat(library.path_pins(params['data']['path'].sub(/\.new$/, '#initialize')).map do |pin|
|
494
|
+
next pin unless pin.name == 'initialize'
|
495
|
+
|
496
|
+
Pin::Method.new(
|
497
|
+
name: 'new',
|
498
|
+
scope: :class,
|
499
|
+
location: pin.location,
|
500
|
+
parameters: pin.parameters,
|
501
|
+
return_type: ComplexType.try_parse(params['data']['path']),
|
502
|
+
comments: pin.comments,
|
503
|
+
closure: pin.closure
|
504
|
+
)
|
505
|
+
end)
|
506
|
+
end
|
495
507
|
end
|
496
508
|
# Selecting by both location and path can result in duplicate pins
|
497
509
|
result.uniq { |p| [p.path, p.location] }
|
@@ -505,6 +517,8 @@ module Solargraph
|
|
505
517
|
library.read_text(filename)
|
506
518
|
end
|
507
519
|
|
520
|
+
# @param uri [String]
|
521
|
+
# @return [Hash]
|
508
522
|
def formatter_config uri
|
509
523
|
library = library_for(uri)
|
510
524
|
library.workspace.config.formatter
|
@@ -632,7 +646,7 @@ module Solargraph
|
|
632
646
|
requests.keys
|
633
647
|
end
|
634
648
|
|
635
|
-
# @return [Hash{String =>
|
649
|
+
# @return [Hash{String => [Boolean,String]}]
|
636
650
|
def default_configuration
|
637
651
|
{
|
638
652
|
'completion' => true,
|
@@ -663,12 +677,22 @@ module Solargraph
|
|
663
677
|
libraries.each(&:catalog)
|
664
678
|
end
|
665
679
|
|
680
|
+
# @return [Hash{String => Hash{String => Boolean}}]
|
666
681
|
def client_capabilities
|
667
682
|
@client_capabilities ||= {}
|
668
683
|
end
|
669
684
|
|
685
|
+
def client_supports_progress?
|
686
|
+
client_capabilities['window'] && client_capabilities['window']['workDoneProgress']
|
687
|
+
end
|
688
|
+
|
670
689
|
private
|
671
690
|
|
691
|
+
# @return [Array<Integer>]
|
692
|
+
def cancelled
|
693
|
+
@cancelled ||= []
|
694
|
+
end
|
695
|
+
|
672
696
|
# @return [MessageWorker]
|
673
697
|
def message_worker
|
674
698
|
@message_worker ||= MessageWorker.new(self)
|
@@ -679,15 +703,10 @@ module Solargraph
|
|
679
703
|
@diagnoser ||= Diagnoser.new(self)
|
680
704
|
end
|
681
705
|
|
682
|
-
# @return [Cataloger]
|
683
|
-
def cataloger
|
684
|
-
@cataloger ||= Cataloger.new(self)
|
685
|
-
end
|
686
|
-
|
687
706
|
# A hash of client requests by ID. The host uses this to keep track of
|
688
707
|
# pending responses.
|
689
708
|
#
|
690
|
-
# @return [Hash{Integer =>
|
709
|
+
# @return [Hash{Integer => Solargraph::LanguageServer::Host}]
|
691
710
|
def requests
|
692
711
|
@requests ||= {}
|
693
712
|
end
|
@@ -779,6 +798,9 @@ module Solargraph
|
|
779
798
|
'textDocument/definition' => {
|
780
799
|
definitionProvider: true
|
781
800
|
},
|
801
|
+
'textDocument/typeDefinition' => {
|
802
|
+
typeDefinitionProvider: true
|
803
|
+
},
|
782
804
|
'textDocument/references' => {
|
783
805
|
referencesProvider: true
|
784
806
|
},
|
@@ -810,69 +832,28 @@ module Solargraph
|
|
810
832
|
client_capabilities['rename'] && client_capabilities['rename']['prepareSupport']
|
811
833
|
end
|
812
834
|
|
813
|
-
def client_supports_progress?
|
814
|
-
client_capabilities['window'] && client_capabilities['window']['workDoneProgress']
|
815
|
-
end
|
816
|
-
|
817
835
|
# @param library [Library]
|
818
836
|
# @return [void]
|
819
|
-
def
|
837
|
+
def library_map library
|
820
838
|
return if library.mapped?
|
821
|
-
Thread.new
|
822
|
-
if client_supports_progress?
|
823
|
-
uuid = SecureRandom.uuid
|
824
|
-
send_request 'window/workDoneProgress/create', {
|
825
|
-
token: uuid
|
826
|
-
} do |response|
|
827
|
-
do_async_library_map library, response.nil? ? uuid : nil
|
828
|
-
end
|
829
|
-
else
|
830
|
-
do_async_library_map library
|
831
|
-
end
|
832
|
-
end
|
839
|
+
Thread.new { sync_library_map library }
|
833
840
|
end
|
834
841
|
|
835
|
-
|
842
|
+
# @param library [Library]
|
843
|
+
# @param uuid [String, nil]
|
844
|
+
# @return [void]
|
845
|
+
def sync_library_map library
|
836
846
|
total = library.workspace.sources.length
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
value: {
|
841
|
-
kind: 'begin',
|
842
|
-
title: "Mapping workspace",
|
843
|
-
message: "0/#{total} files",
|
844
|
-
cancellable: false,
|
845
|
-
percentage: 0
|
846
|
-
}
|
847
|
-
}
|
848
|
-
end
|
849
|
-
pct = 0
|
850
|
-
mod = 10
|
847
|
+
progress = Progress.new('Mapping workspace')
|
848
|
+
progress.begin "0/#{total} files", 0
|
849
|
+
progress.send self
|
851
850
|
while library.next_map
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
pct = cur
|
856
|
-
send_notification '$/progress', {
|
857
|
-
token: uuid,
|
858
|
-
value: {
|
859
|
-
kind: 'report',
|
860
|
-
cancellable: false,
|
861
|
-
message: "#{library.source_map_hash.keys.length}/#{total} files",
|
862
|
-
percentage: pct
|
863
|
-
}
|
864
|
-
}
|
865
|
-
end
|
866
|
-
end
|
867
|
-
if uuid
|
868
|
-
send_notification '$/progress', {
|
869
|
-
token: uuid,
|
870
|
-
value: {
|
871
|
-
kind: 'end',
|
872
|
-
message: 'Mapping complete'
|
873
|
-
}
|
874
|
-
}
|
851
|
+
pct = ((library.source_map_hash.keys.length.to_f / total) * 100).to_i
|
852
|
+
progress.report "#{library.source_map_hash.keys.length}/#{total} files", pct
|
853
|
+
progress.send self
|
875
854
|
end
|
855
|
+
progress.finish 'done'
|
856
|
+
progress.send self
|
876
857
|
end
|
877
858
|
end
|
878
859
|
end
|