solargraph 0.42.3 → 0.43.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/CHANGELOG.md +23 -0
- data/README.md +2 -1
- data/SPONSORS.md +0 -1
- data/lib/solargraph/api_map/store.rb +17 -17
- data/lib/solargraph/api_map.rb +1 -1
- data/lib/solargraph/complex_type/type_methods.rb +6 -3
- data/lib/solargraph/complex_type.rb +4 -0
- data/lib/solargraph/language_server/host/dispatch.rb +2 -3
- data/lib/solargraph/language_server/host/message_worker.rb +59 -0
- data/lib/solargraph/language_server/host.rb +47 -34
- data/lib/solargraph/language_server/message/base.rb +6 -2
- data/lib/solargraph/language_server/message/text_document/completion.rb +2 -0
- data/lib/solargraph/language_server/transport/adapter.rb +1 -2
- data/lib/solargraph/library.rb +8 -4
- data/lib/solargraph/parser/comment_ripper.rb +1 -1
- data/lib/solargraph/parser/legacy/class_methods.rb +25 -0
- data/lib/solargraph/parser/legacy/node_chainer.rb +14 -1
- data/lib/solargraph/parser/legacy/node_methods.rb +9 -2
- data/lib/solargraph/parser/node_processor/base.rb +0 -3
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +22 -1
- data/lib/solargraph/parser/rubyvm/node_methods.rb +5 -0
- data/lib/solargraph/pin/base.rb +1 -1
- data/lib/solargraph/pin/namespace.rb +8 -2
- data/lib/solargraph/source/chain/hash.rb +28 -0
- data/lib/solargraph/source/chain.rb +1 -4
- data/lib/solargraph/source.rb +0 -12
- data/lib/solargraph/source_map/clip.rb +1 -1
- data/lib/solargraph/source_map/mapper.rb +2 -0
- data/lib/solargraph/type_checker.rb +11 -4
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/_method.erb +1 -1
- data/lib/solargraph/workspace.rb +1 -1
- data/lib/solargraph/yard_map.rb +7 -7
- data/lib/solargraph.rb +1 -0
- data/lib/yard-solargraph.rb +3 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e671eddad2fe717ad573954a63154bd89adbc12c9899c3f8762bf38a93160657
|
4
|
+
data.tar.gz: 2224d1457b9e8f7279bfa89b2777fe3d60a0a2283de4047930bebb79034a1ac4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76ffe1331d8020eed92c39d2c4886ce7d01e4143a8b8264ac1bf4011335fabfd32a48f16a7099f889fed2e7c485e2e9cbf09714f677cd6e9396381032522f67a
|
7
|
+
data.tar.gz: 9c6da25c26ed209af38be4a0bc8d7a6ce826fb3012bce650089e982f829f4c8b14807ed0f7d1ecdeacd9b737bedd9d682440a9701a864313a83e60182771ade0
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,26 @@
|
|
1
|
+
## 0.43.2 - September 23, 2021
|
2
|
+
- Synchronize server requests (#461)
|
3
|
+
|
4
|
+
## 0.43.1 - September 20, 2021
|
5
|
+
- Complete nested namespaces in open gates
|
6
|
+
- SourceMap::Mapper reports filename for encoding errors (#474)
|
7
|
+
- Handle request on a specific thread, and cancel completion when there has newer completion request (#459)
|
8
|
+
- Fix namespace links generated by views/_method.erb (#472)
|
9
|
+
- Source handles long squiggly heredocs (#460)
|
10
|
+
|
11
|
+
## 0.43.0 - July 25, 2021
|
12
|
+
- Correct arity checks when restarg precedes arg (#418)
|
13
|
+
- Improve the performance of catalog by 4 times (#457)
|
14
|
+
- Type checker validates duck type variables and params (#453)
|
15
|
+
- Kernel#raise exception type checker
|
16
|
+
- Pin::Base#inspect includes path
|
17
|
+
- Fix arity with combined restargs and kwrestargs (#396)
|
18
|
+
|
19
|
+
## 0.42.4 - July 11, 2021
|
20
|
+
- Yardoc cache handling
|
21
|
+
- Fix required_paths when gemspec is used (#451)
|
22
|
+
- fix: yard stdout may break language client (#454)
|
23
|
+
|
1
24
|
## 0.42.3 - June 14, 2021
|
2
25
|
- Require 'pathname' for Library
|
3
26
|
|
data/README.md
CHANGED
@@ -34,7 +34,8 @@ Plug-ins and extensions are available for the following editors:
|
|
34
34
|
* GitHub: https://github.com/autozimu/LanguageClient-neovim
|
35
35
|
|
36
36
|
* **Emacs**
|
37
|
-
* GitHub: https://github.com/
|
37
|
+
* GitHub: `eglot.el`, https://github.com/joaotavora/eglot
|
38
|
+
* GitHub: `lsp-mode.el`, https://github.com/emacs-lsp/lsp-mode
|
38
39
|
|
39
40
|
* **Eclipse**
|
40
41
|
* Plugin: https://marketplace.eclipse.org/content/ruby-solargraph
|
data/SPONSORS.md
CHANGED
@@ -5,10 +5,10 @@ require 'set'
|
|
5
5
|
module Solargraph
|
6
6
|
class ApiMap
|
7
7
|
class Store
|
8
|
-
# @return [
|
8
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
9
9
|
attr_reader :pins
|
10
10
|
|
11
|
-
# @param pins [
|
11
|
+
# @param pins [Enumerable<Solargraph::Pin::Base>]
|
12
12
|
def initialize pins = []
|
13
13
|
@pins = pins
|
14
14
|
index
|
@@ -16,7 +16,7 @@ module Solargraph
|
|
16
16
|
|
17
17
|
# @param fqns [String]
|
18
18
|
# @param visibility [Array<Symbol>]
|
19
|
-
# @return [
|
19
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
20
20
|
def get_constants fqns, visibility = [:public]
|
21
21
|
namespace_children(fqns).select { |pin|
|
22
22
|
!pin.name.empty? && (pin.is_a?(Pin::Namespace) || pin.is_a?(Pin::Constant)) && visibility.include?(pin.visibility)
|
@@ -26,7 +26,7 @@ module Solargraph
|
|
26
26
|
# @param fqns [String]
|
27
27
|
# @param scope [Symbol]
|
28
28
|
# @param visibility [Array<Symbol>]
|
29
|
-
# @return [
|
29
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
30
30
|
def get_methods fqns, scope: :instance, visibility: [:public]
|
31
31
|
namespace_children(fqns).select do |pin|
|
32
32
|
pin.is_a?(Pin::Method) && pin.scope == scope && visibility.include?(pin.visibility)
|
@@ -61,14 +61,14 @@ module Solargraph
|
|
61
61
|
end
|
62
62
|
|
63
63
|
# @param path [String]
|
64
|
-
# @return [
|
64
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
65
65
|
def get_path_pins path
|
66
66
|
path_pin_hash[path] || []
|
67
67
|
end
|
68
68
|
|
69
69
|
# @param fqns [String]
|
70
70
|
# @param scope [Symbol] :class or :instance
|
71
|
-
# @return [
|
71
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
72
72
|
def get_instance_variables(fqns, scope = :instance)
|
73
73
|
all_instance_variables.select { |pin|
|
74
74
|
pin.binder.namespace == fqns && pin.binder.scope == scope
|
@@ -76,12 +76,12 @@ module Solargraph
|
|
76
76
|
end
|
77
77
|
|
78
78
|
# @param fqns [String]
|
79
|
-
# @return [
|
79
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
80
80
|
def get_class_variables(fqns)
|
81
81
|
namespace_children(fqns).select{|pin| pin.is_a?(Pin::ClassVariable)}
|
82
82
|
end
|
83
83
|
|
84
|
-
# @return [
|
84
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
85
85
|
def get_symbols
|
86
86
|
symbols.uniq(&:name)
|
87
87
|
end
|
@@ -97,12 +97,12 @@ module Solargraph
|
|
97
97
|
@namespaces ||= Set.new
|
98
98
|
end
|
99
99
|
|
100
|
-
# @return [
|
100
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
101
101
|
def namespace_pins
|
102
102
|
pins_by_class(Solargraph::Pin::Namespace)
|
103
103
|
end
|
104
104
|
|
105
|
-
# @return [
|
105
|
+
# @return [Enumerable<Solargraph::Pin::Method>]
|
106
106
|
def method_pins
|
107
107
|
pins_by_class(Solargraph::Pin::Method)
|
108
108
|
end
|
@@ -131,7 +131,7 @@ module Solargraph
|
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
|
-
# @return [
|
134
|
+
# @return [Enumerable<Pin::Block>]
|
135
135
|
def block_pins
|
136
136
|
pins_by_class(Pin::Block)
|
137
137
|
end
|
@@ -142,9 +142,9 @@ module Solargraph
|
|
142
142
|
end
|
143
143
|
|
144
144
|
# @param klass [Class]
|
145
|
-
# @return [
|
145
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
146
146
|
def pins_by_class klass
|
147
|
-
@pin_select_cache[klass] ||= @pin_class_hash.
|
147
|
+
@pin_select_cache[klass] ||= @pin_class_hash.each_with_object(Set.new) { |(key, o), n| n.merge(o) if key <= klass }
|
148
148
|
end
|
149
149
|
|
150
150
|
private
|
@@ -171,7 +171,7 @@ module Solargraph
|
|
171
171
|
end
|
172
172
|
end
|
173
173
|
|
174
|
-
# @return [
|
174
|
+
# @return [Enumerable<Solargraph::Pin::Symbol>]
|
175
175
|
def symbols
|
176
176
|
pins_by_class(Pin::Symbol)
|
177
177
|
end
|
@@ -193,7 +193,7 @@ module Solargraph
|
|
193
193
|
end
|
194
194
|
|
195
195
|
# @param name [String]
|
196
|
-
# @return [
|
196
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
197
197
|
def namespace_children name
|
198
198
|
namespace_map[name] || []
|
199
199
|
end
|
@@ -216,8 +216,8 @@ module Solargraph
|
|
216
216
|
set = pins.to_set
|
217
217
|
@pin_class_hash = set.classify(&:class).transform_values(&:to_a)
|
218
218
|
@pin_select_cache = {}
|
219
|
-
@namespace_map = set.classify(&:namespace)
|
220
|
-
@path_pin_hash = set.classify(&:path)
|
219
|
+
@namespace_map = set.classify(&:namespace)
|
220
|
+
@path_pin_hash = set.classify(&:path)
|
221
221
|
@namespaces = @path_pin_hash.keys.compact.to_set
|
222
222
|
pins_by_class(Pin::Reference::Include).each do |pin|
|
223
223
|
include_references[pin.namespace] ||= []
|
data/lib/solargraph/api_map.rb
CHANGED
@@ -138,7 +138,7 @@ module Solargraph
|
|
138
138
|
|
139
139
|
# An array of pins based on Ruby keywords (`if`, `end`, etc.).
|
140
140
|
#
|
141
|
-
# @return [
|
141
|
+
# @return [Enumerable<Solargraph::Pin::Keyword>]
|
142
142
|
def keyword_pins
|
143
143
|
store.pins_by_class(Pin::Keyword)
|
144
144
|
end
|
@@ -72,9 +72,12 @@ module Solargraph
|
|
72
72
|
|
73
73
|
# @return [String]
|
74
74
|
def namespace
|
75
|
-
|
76
|
-
@namespace ||=
|
77
|
-
|
75
|
+
# if priority higher than ||=, old implements cause unnecessary check
|
76
|
+
@namespace ||= lambda do
|
77
|
+
return 'Object' if duck_type?
|
78
|
+
return 'NilClass' if nil_type?
|
79
|
+
return (name == 'Class' || name == 'Module') && !subtypes.empty? ? subtypes.first.name : name
|
80
|
+
end.call
|
78
81
|
end
|
79
82
|
|
80
83
|
# @return [Symbol] :class or :instance
|
@@ -51,6 +51,10 @@ module Solargraph
|
|
51
51
|
def select &block
|
52
52
|
@items.select &block
|
53
53
|
end
|
54
|
+
def namespace
|
55
|
+
# cache this attr for high frequency call
|
56
|
+
@namespace ||= method_missing(:namespace).to_s
|
57
|
+
end
|
54
58
|
|
55
59
|
def method_missing name, *args, &block
|
56
60
|
return if @items.first.nil?
|
@@ -41,7 +41,8 @@ module Solargraph
|
|
41
41
|
result = explicit_library_for(uri) ||
|
42
42
|
implicit_library_for(uri) ||
|
43
43
|
generic_library_for(uri)
|
44
|
-
|
44
|
+
# previous library for already call attach. avoid call twice
|
45
|
+
# result.attach sources.find(uri) if sources.include?(uri)
|
45
46
|
result
|
46
47
|
end
|
47
48
|
|
@@ -82,7 +83,6 @@ module Solargraph
|
|
82
83
|
libraries.each do |lib|
|
83
84
|
if filename.start_with?(lib.workspace.directory)
|
84
85
|
lib.attach sources.find(uri)
|
85
|
-
lib.catalog
|
86
86
|
return lib
|
87
87
|
end
|
88
88
|
end
|
@@ -98,7 +98,6 @@ module Solargraph
|
|
98
98
|
# @return [Library]
|
99
99
|
def generic_library_for uri
|
100
100
|
generic_library.attach sources.find(uri)
|
101
|
-
generic_library.catalog
|
102
101
|
generic_library
|
103
102
|
end
|
104
103
|
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module LanguageServer
|
5
|
+
class Host
|
6
|
+
# A serial worker Thread to handle message.
|
7
|
+
#
|
8
|
+
# this make check pending message possible, and maybe cancelled to speedup process
|
9
|
+
class MessageWorker
|
10
|
+
# @param host [Host]
|
11
|
+
def initialize(host)
|
12
|
+
@host = host
|
13
|
+
@mutex = Mutex.new
|
14
|
+
@resource = ConditionVariable.new
|
15
|
+
@stopped = true
|
16
|
+
end
|
17
|
+
|
18
|
+
# pending handle messages
|
19
|
+
def messages
|
20
|
+
@messages ||= []
|
21
|
+
end
|
22
|
+
|
23
|
+
def stopped?
|
24
|
+
@stopped
|
25
|
+
end
|
26
|
+
|
27
|
+
def stop
|
28
|
+
@stopped = true
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param message [Hash] The message should be handle. will pass back to Host#receive
|
32
|
+
# @return [void]
|
33
|
+
def queue(message)
|
34
|
+
@mutex.synchronize do
|
35
|
+
messages.push(message)
|
36
|
+
@resource.signal
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def start
|
41
|
+
return unless @stopped
|
42
|
+
@stopped = false
|
43
|
+
Thread.new do
|
44
|
+
tick until stopped?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def tick
|
49
|
+
message = @mutex.synchronize do
|
50
|
+
@resource.wait(@mutex) if messages.empty?
|
51
|
+
messages.shift
|
52
|
+
end
|
53
|
+
handler = @host.receive(message)
|
54
|
+
handler && handler.send_response
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -12,10 +12,12 @@ module Solargraph
|
|
12
12
|
# safety for multi-threaded transports.
|
13
13
|
#
|
14
14
|
class Host
|
15
|
-
autoload :Diagnoser,
|
16
|
-
autoload :Cataloger,
|
17
|
-
autoload :Sources,
|
18
|
-
autoload :Dispatch,
|
15
|
+
autoload :Diagnoser, 'solargraph/language_server/host/diagnoser'
|
16
|
+
autoload :Cataloger, 'solargraph/language_server/host/cataloger'
|
17
|
+
autoload :Sources, 'solargraph/language_server/host/sources'
|
18
|
+
autoload :Dispatch, 'solargraph/language_server/host/dispatch'
|
19
|
+
autoload :MessageWorker, 'solargraph/language_server/host/message_worker'
|
20
|
+
|
19
21
|
|
20
22
|
include UriHelpers
|
21
23
|
include Logging
|
@@ -27,7 +29,7 @@ module Solargraph
|
|
27
29
|
def initialize
|
28
30
|
@cancel_semaphore = Mutex.new
|
29
31
|
@buffer_semaphore = Mutex.new
|
30
|
-
@
|
32
|
+
@request_mutex = Mutex.new
|
31
33
|
@cancel = []
|
32
34
|
@buffer = String.new
|
33
35
|
@stopped = true
|
@@ -45,6 +47,7 @@ module Solargraph
|
|
45
47
|
diagnoser.start
|
46
48
|
cataloger.start
|
47
49
|
sources.start
|
50
|
+
message_worker.start
|
48
51
|
end
|
49
52
|
|
50
53
|
# Update the configuration options with the provided hash.
|
@@ -89,8 +92,15 @@ module Solargraph
|
|
89
92
|
@cancel_semaphore.synchronize { @cancel.delete id }
|
90
93
|
end
|
91
94
|
|
95
|
+
# Called by adapter, to handle the request
|
96
|
+
# @param request [Hash]
|
97
|
+
# @return [void]
|
98
|
+
def process request
|
99
|
+
message_worker.queue(request)
|
100
|
+
end
|
101
|
+
|
92
102
|
# Start processing a request from the client. After the message is
|
93
|
-
# processed,
|
103
|
+
# processed, caller is responsible for sending the response.
|
94
104
|
#
|
95
105
|
# @param request [Hash] The contents of the message.
|
96
106
|
# @return [Solargraph::LanguageServer::Message::Base] The message handler.
|
@@ -355,19 +365,21 @@ module Solargraph
|
|
355
365
|
# @yieldparam [Hash] The result sent by the client
|
356
366
|
# @return [void]
|
357
367
|
def send_request method, params, &block
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
368
|
+
@request_mutex.synchronize do
|
369
|
+
message = {
|
370
|
+
jsonrpc: "2.0",
|
371
|
+
method: method,
|
372
|
+
params: params,
|
373
|
+
id: @next_request_id
|
374
|
+
}
|
375
|
+
json = message.to_json
|
376
|
+
requests[@next_request_id] = Request.new(@next_request_id, &block)
|
377
|
+
envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
|
378
|
+
queue envelope
|
379
|
+
@next_request_id += 1
|
380
|
+
logger.info "Server sent #{method}"
|
381
|
+
logger.debug params
|
382
|
+
end
|
371
383
|
end
|
372
384
|
|
373
385
|
# Register the methods as capabilities with the client.
|
@@ -378,20 +390,16 @@ module Solargraph
|
|
378
390
|
# @return [void]
|
379
391
|
def register_capabilities methods
|
380
392
|
logger.debug "Registering capabilities: #{methods}"
|
381
|
-
registrations = methods.select{|m| can_register?(m) and !registered?(m)}.map
|
393
|
+
registrations = methods.select { |m| can_register?(m) and !registered?(m) }.map do |m|
|
382
394
|
@registered_capabilities.add m
|
383
395
|
{
|
384
396
|
id: m,
|
385
397
|
method: m,
|
386
398
|
registerOptions: dynamic_capability_options[m]
|
387
399
|
}
|
388
|
-
}
|
389
|
-
return if registrations.empty?
|
390
|
-
@register_semaphore.synchronize do
|
391
|
-
send_request 'client/registerCapability', {
|
392
|
-
registrations: registrations
|
393
|
-
}
|
394
400
|
end
|
401
|
+
return if registrations.empty?
|
402
|
+
send_request 'client/registerCapability', { registrations: registrations }
|
395
403
|
end
|
396
404
|
|
397
405
|
# Unregister the methods with the client.
|
@@ -410,11 +418,7 @@ module Solargraph
|
|
410
418
|
}
|
411
419
|
}
|
412
420
|
return if unregisterations.empty?
|
413
|
-
|
414
|
-
send_request 'client/unregisterCapability', {
|
415
|
-
unregisterations: unregisterations
|
416
|
-
}
|
417
|
-
end
|
421
|
+
send_request 'client/unregisterCapability', { unregisterations: unregisterations }
|
418
422
|
end
|
419
423
|
|
420
424
|
# Flag a method as available for dynamic registration.
|
@@ -422,9 +426,7 @@ module Solargraph
|
|
422
426
|
# @param method [String] The method name, e.g., 'textDocument/completion'
|
423
427
|
# @return [void]
|
424
428
|
def allow_registration method
|
425
|
-
@
|
426
|
-
@dynamic_capabilities.add method
|
427
|
-
end
|
429
|
+
@dynamic_capabilities.add method
|
428
430
|
end
|
429
431
|
|
430
432
|
# True if the specified LSP method can be dynamically registered.
|
@@ -451,6 +453,7 @@ module Solargraph
|
|
451
453
|
def stop
|
452
454
|
return if @stopped
|
453
455
|
@stopped = true
|
456
|
+
message_worker.stop
|
454
457
|
cataloger.stop
|
455
458
|
diagnoser.stop
|
456
459
|
sources.stop
|
@@ -513,6 +516,11 @@ module Solargraph
|
|
513
516
|
library.completions_at uri_to_file(uri), line, column
|
514
517
|
end
|
515
518
|
|
519
|
+
# @return [Bool] if has pending completion request
|
520
|
+
def has_pending_completions?
|
521
|
+
message_worker.messages.reverse_each.any? { |req| req['method'] == 'textDocument/completion' }
|
522
|
+
end
|
523
|
+
|
516
524
|
# @param uri [String]
|
517
525
|
# @param line [Integer]
|
518
526
|
# @param column [Integer]
|
@@ -646,6 +654,11 @@ module Solargraph
|
|
646
654
|
|
647
655
|
private
|
648
656
|
|
657
|
+
# @return [MessageWorker]
|
658
|
+
def message_worker
|
659
|
+
@message_worker ||= MessageWorker.new(self)
|
660
|
+
end
|
661
|
+
|
649
662
|
# @return [Diagnoser]
|
650
663
|
def diagnoser
|
651
664
|
@diagnoser ||= Diagnoser.new(self)
|
@@ -62,10 +62,14 @@ module Solargraph
|
|
62
62
|
def send_response
|
63
63
|
return if id.nil?
|
64
64
|
if host.cancel?(id)
|
65
|
+
# https://microsoft.github.io/language-server-protocol/specifications/specification-current/#cancelRequest
|
66
|
+
# cancel should send response RequestCancelled
|
65
67
|
Solargraph::Logging.logger.info "Cancelled response to #{method}"
|
66
|
-
|
68
|
+
set_result nil
|
69
|
+
set_error ErrorCodes::REQUEST_CANCELLED, "cancelled by client"
|
70
|
+
else
|
71
|
+
Solargraph::Logging.logger.info "Sending response to #{method}"
|
67
72
|
end
|
68
|
-
Solargraph::Logging.logger.info "Sending response to #{method}"
|
69
73
|
response = {
|
70
74
|
jsonrpc: "2.0",
|
71
75
|
id: id,
|
@@ -6,6 +6,8 @@ module Solargraph
|
|
6
6
|
module TextDocument
|
7
7
|
class Completion < Base
|
8
8
|
def process
|
9
|
+
return set_error(ErrorCodes::REQUEST_CANCELLED, "cancelled by so many request") if host.has_pending_completions?
|
10
|
+
|
9
11
|
line = params['position']['line']
|
10
12
|
col = params['position']['character']
|
11
13
|
begin
|
data/lib/solargraph/library.rb
CHANGED
@@ -56,7 +56,7 @@ module Solargraph
|
|
56
56
|
end
|
57
57
|
@current = source
|
58
58
|
maybe_map @current
|
59
|
-
|
59
|
+
catalog_inlock
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -351,7 +351,7 @@ module Solargraph
|
|
351
351
|
else
|
352
352
|
args = line.split(':').map(&:strip)
|
353
353
|
name = args.shift
|
354
|
-
|
354
|
+
reporter = Diagnostics.reporter(name)
|
355
355
|
raise DiagnosticsError, "Diagnostics reporter #{name} does not exist" if reporter.nil?
|
356
356
|
repargs[reporter] ||= []
|
357
357
|
repargs[reporter].concat args
|
@@ -368,12 +368,16 @@ module Solargraph
|
|
368
368
|
# @return [void]
|
369
369
|
def catalog
|
370
370
|
mutex.synchronize do
|
371
|
-
|
371
|
+
catalog_inlock
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
private def catalog_inlock
|
376
|
+
return if synchronized?
|
372
377
|
logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
|
373
378
|
api_map.catalog bench
|
374
379
|
@synchronized = true
|
375
380
|
logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)" if logger.info?
|
376
|
-
end
|
377
381
|
end
|
378
382
|
|
379
383
|
def bench
|
@@ -103,6 +103,31 @@ module Solargraph
|
|
103
103
|
en = Position.new(node.loc.last_line, node.loc.last_column)
|
104
104
|
Range.new(st, en)
|
105
105
|
end
|
106
|
+
|
107
|
+
def string_ranges node
|
108
|
+
return [] unless is_ast_node?(node)
|
109
|
+
result = []
|
110
|
+
if node.type == :str
|
111
|
+
result.push Range.from_node(node)
|
112
|
+
elsif node.type == :dstr
|
113
|
+
here = Range.from_node(node)
|
114
|
+
there = Range.from_node(node.children[1])
|
115
|
+
result.push Range.new(here.start, there.start)
|
116
|
+
end
|
117
|
+
node.children.each do |child|
|
118
|
+
result.concat string_ranges(child)
|
119
|
+
end
|
120
|
+
if node.type == :dstr && node.children.last.nil?
|
121
|
+
# result.push Range.new(result.last.ending, result.last.ending)
|
122
|
+
last = node.children[-2]
|
123
|
+
unless last.nil?
|
124
|
+
rng = Range.from_node(last)
|
125
|
+
pos = Position.new(rng.ending.line, rng.ending.column - 1)
|
126
|
+
result.push Range.new(pos, pos)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
result
|
130
|
+
end
|
106
131
|
end
|
107
132
|
end
|
108
133
|
end
|
@@ -102,13 +102,26 @@ module Solargraph
|
|
102
102
|
result.concat generate_links(n.children[0])
|
103
103
|
elsif n.type == :block_pass
|
104
104
|
result.push Chain::BlockVariable.new("&#{n.children[0].children[0].to_s}")
|
105
|
+
elsif n.type == :hash
|
106
|
+
result.push Chain::Hash.new('::Hash', hash_is_splatted?(n))
|
105
107
|
else
|
106
108
|
lit = infer_literal_node_type(n)
|
107
|
-
|
109
|
+
# if lit == '::Hash'
|
110
|
+
# result.push Chain::Hash.new(lit, hash_is_splatted?(n))
|
111
|
+
# else
|
112
|
+
result.push (lit ? Chain::Literal.new(lit) : Chain::Link.new)
|
113
|
+
# end
|
108
114
|
end
|
109
115
|
result
|
110
116
|
end
|
111
117
|
|
118
|
+
def hash_is_splatted? node
|
119
|
+
return false unless Parser.is_ast_node?(node) && node.type == :hash
|
120
|
+
return false unless Parser.is_ast_node?(node.children.last) && node.children.last.type == :kwsplat
|
121
|
+
return false if Parser.is_ast_node?(node.children.last.children[0]) && node.children.last.children[0].type == :hash
|
122
|
+
true
|
123
|
+
end
|
124
|
+
|
112
125
|
def block_passed? node
|
113
126
|
node.children.last.is_a?(::Parser::AST::Node) && node.children.last.type == :block_pass
|
114
127
|
end
|
@@ -97,8 +97,10 @@ module Solargraph
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def convert_hash node
|
100
|
-
return {} unless Parser.is_ast_node?(node)
|
101
|
-
return convert_hash(node.children[0]
|
100
|
+
return {} unless Parser.is_ast_node?(node)
|
101
|
+
return convert_hash(node.children[0]) if node.type == :kwsplat
|
102
|
+
return convert_hash(node.children[0]) if Parser.is_ast_node?(node.children[0]) && node.children[0].type == :kwsplat
|
103
|
+
return {} unless node.type == :hash
|
102
104
|
result = {}
|
103
105
|
node.children.each do |pair|
|
104
106
|
result[pair.children[0].children[0]] = Solargraph::Parser.chain(pair.children[1])
|
@@ -124,9 +126,14 @@ module Solargraph
|
|
124
126
|
end
|
125
127
|
|
126
128
|
def splatted_call? node
|
129
|
+
return false unless Parser.is_ast_node?(node)
|
127
130
|
Parser.is_ast_node?(node.children[0]) && node.children[0].type == :kwsplat && node.children[0].children[0].type != :hash
|
128
131
|
end
|
129
132
|
|
133
|
+
def any_splatted_call?(nodes)
|
134
|
+
nodes.any? { |n| splatted_call?(n) }
|
135
|
+
end
|
136
|
+
|
130
137
|
# @todo Temporarily here for testing. Move to Solargraph::Parser.
|
131
138
|
def call_nodes_from node
|
132
139
|
return [] unless node.is_a?(::Parser::AST::Node)
|
@@ -97,13 +97,31 @@ module Solargraph
|
|
97
97
|
result.concat generate_links(n.children[0])
|
98
98
|
elsif n.type == :BLOCK_PASS
|
99
99
|
result.push Chain::BlockVariable.new("&#{n.children[1].children[0].to_s}")
|
100
|
+
elsif n.type == :HASH
|
101
|
+
result.push Chain::Hash.new('::Hash', hash_is_splatted?(n))
|
100
102
|
else
|
101
103
|
lit = infer_literal_node_type(n)
|
102
|
-
|
104
|
+
if lit
|
105
|
+
if lit == '::Hash'
|
106
|
+
result.push Chain::Hash.new(lit, hash_is_splatted?(n))
|
107
|
+
else
|
108
|
+
result.push Chain::Literal.new(lit)
|
109
|
+
end
|
110
|
+
else
|
111
|
+
result.push Chain::Link.new
|
112
|
+
end
|
113
|
+
# result.push (lit ? Chain::Literal.new(lit) : Chain::Link.new)
|
103
114
|
end
|
104
115
|
result
|
105
116
|
end
|
106
117
|
|
118
|
+
def hash_is_splatted? node
|
119
|
+
return false unless Parser.is_ast_node?(node.children[0]) && node.children[0].type == :LIST
|
120
|
+
list = node.children[0].children
|
121
|
+
eol = list.rindex(&:nil?)
|
122
|
+
eol && Parser.is_ast_node?(list[eol + 1])
|
123
|
+
end
|
124
|
+
|
107
125
|
def block_passed? node
|
108
126
|
node.children.last.is_a?(RubyVM::AbstractSyntaxTree::Node) && node.children.last.type == :BLOCK_PASS
|
109
127
|
end
|
@@ -114,6 +132,9 @@ module Solargraph
|
|
114
132
|
node.children[0..-2].map { |c| NodeChainer.chain(c) }
|
115
133
|
elsif node.type == :SPLAT
|
116
134
|
[NodeChainer.chain(node)]
|
135
|
+
elsif node.type == :ARGSPUSH
|
136
|
+
result = node_to_argchains(node.children[0])
|
137
|
+
result.push NodeChainer.chain(node.children[1]) if Parser.is_ast_node?(node.children[1])
|
117
138
|
elsif node.type == :ARGSCAT
|
118
139
|
result = node.children[0].children[0..-2].map { |c| NodeChainer.chain(c) }
|
119
140
|
result.push NodeChainer.chain(node.children[1])
|
@@ -117,9 +117,14 @@ module Solargraph
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def splatted_call? node
|
120
|
+
return false unless Parser.is_ast_node?(node)
|
120
121
|
splatted_node?(node) && node.children[0].children[1].type != :HASH
|
121
122
|
end
|
122
123
|
|
124
|
+
def any_splatted_call?(nodes)
|
125
|
+
nodes.any? { |n| splatted_call?(n) }
|
126
|
+
end
|
127
|
+
|
123
128
|
def node? node
|
124
129
|
node.is_a?(RubyVM::AbstractSyntaxTree::Node)
|
125
130
|
end
|
data/lib/solargraph/pin/base.rb
CHANGED
@@ -22,12 +22,18 @@ module Solargraph
|
|
22
22
|
@closure = Solargraph::Pin::ROOT_PIN
|
23
23
|
end
|
24
24
|
@open_gates = gates
|
25
|
-
if @
|
25
|
+
if @name.include?('::')
|
26
26
|
# In this case, a chained namespace was opened (e.g., Foo::Bar)
|
27
27
|
# but Foo does not exist.
|
28
28
|
parts = @name.split('::')
|
29
29
|
@name = parts.pop
|
30
|
-
|
30
|
+
closure_name = if [Solargraph::Pin::ROOT_PIN, nil].include?(closure)
|
31
|
+
''
|
32
|
+
else
|
33
|
+
closure.full_context.namespace + '::'
|
34
|
+
end
|
35
|
+
closure_name += parts.join('::')
|
36
|
+
@closure = Pin::Namespace.new(name: closure_name, gates: [parts.join('::')])
|
31
37
|
@context = nil
|
32
38
|
end
|
33
39
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
class Source
|
5
|
+
class Chain
|
6
|
+
class Hash < Literal
|
7
|
+
# @param type [String]
|
8
|
+
# @param splatted [Boolean]
|
9
|
+
def initialize type, splatted = false
|
10
|
+
super(type)
|
11
|
+
@splatted = splatted
|
12
|
+
end
|
13
|
+
|
14
|
+
def word
|
15
|
+
@word ||= "<#{@type}>"
|
16
|
+
end
|
17
|
+
|
18
|
+
def resolve api_map, name_pin, locals
|
19
|
+
[Pin::ProxyType.anonymous(@complex_type)]
|
20
|
+
end
|
21
|
+
|
22
|
+
def splatted?
|
23
|
+
@splatted
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -21,6 +21,7 @@ module Solargraph
|
|
21
21
|
autoload :Or, 'solargraph/source/chain/or'
|
22
22
|
autoload :BlockVariable, 'solargraph/source/chain/block_variable'
|
23
23
|
autoload :ZSuper, 'solargraph/source/chain/z_super'
|
24
|
+
autoload :Hash, 'solargraph/source/chain/hash'
|
24
25
|
|
25
26
|
@@inference_stack = []
|
26
27
|
@@inference_depth = 0
|
@@ -61,10 +62,6 @@ module Solargraph
|
|
61
62
|
working_pin = name_pin
|
62
63
|
links[0..-2].each do |link|
|
63
64
|
pins = link.resolve(api_map, working_pin, locals)
|
64
|
-
# Locals are only used when resolving the first link
|
65
|
-
# @todo There's a problem here. Call links need to resolve arguments
|
66
|
-
# that might refer to local variables.
|
67
|
-
# locals = []
|
68
65
|
type = infer_first_defined(pins, working_pin, api_map)
|
69
66
|
return [] if type.undefined?
|
70
67
|
working_pin = Pin::ProxyType.anonymous(type)
|
data/lib/solargraph/source.rb
CHANGED
@@ -6,19 +6,15 @@ module Solargraph
|
|
6
6
|
# A Ruby file that has been parsed into an AST.
|
7
7
|
#
|
8
8
|
class Source
|
9
|
-
# autoload :FlawedBuilder, 'solargraph/source/flawed_builder'
|
10
9
|
autoload :Updater, 'solargraph/source/updater'
|
11
10
|
autoload :Change, 'solargraph/source/change'
|
12
11
|
autoload :Mapper, 'solargraph/source/mapper'
|
13
|
-
# autoload :NodeMethods, 'solargraph/source/node_methods'
|
14
12
|
autoload :EncodingFixes, 'solargraph/source/encoding_fixes'
|
15
13
|
autoload :Cursor, 'solargraph/source/cursor'
|
16
14
|
autoload :Chain, 'solargraph/source/chain'
|
17
15
|
autoload :SourceChainer, 'solargraph/source/source_chainer'
|
18
|
-
# autoload :NodeChainer, 'solargraph/source/node_chainer'
|
19
16
|
|
20
17
|
include EncodingFixes
|
21
|
-
# include NodeMethods
|
22
18
|
|
23
19
|
# @return [String]
|
24
20
|
attr_reader :filename
|
@@ -50,17 +46,9 @@ module Solargraph
|
|
50
46
|
@node, @comments = Solargraph::Parser.parse_with_comments(@code, filename)
|
51
47
|
@parsed = true
|
52
48
|
rescue Parser::SyntaxError, EncodingError => e
|
53
|
-
# @todo 100% whitespace results in a nil node, so there's no reason to parse it.
|
54
|
-
# We still need to determine whether the resulting node should be nil or a dummy
|
55
|
-
# node with a location that encompasses the range.
|
56
|
-
# @node, @comments = Source.parse_with_comments(@code.gsub(/[^\s]/, ' '), filename)
|
57
49
|
@node = nil
|
58
50
|
@comments = {}
|
59
51
|
@parsed = false
|
60
|
-
# rescue Exception => e
|
61
|
-
# Solargraph.logger.warn "[#{e.class}] #{e.message}"
|
62
|
-
# Solargraph.logger.warn e.backtrace.join("\n")
|
63
|
-
# raise "Error parsing #{filename || '(source)'}: [#{e.class}] #{e.message}"
|
64
52
|
ensure
|
65
53
|
@code.freeze
|
66
54
|
end
|
@@ -213,7 +213,7 @@ module Solargraph
|
|
213
213
|
result.concat api_map.get_methods(block.binder.namespace, scope: block.binder.scope, visibility: [:public, :private, :protected])
|
214
214
|
result.concat api_map.get_methods('Kernel')
|
215
215
|
# result.concat ApiMap.keywords
|
216
|
-
result.concat api_map.keyword_pins
|
216
|
+
result.concat api_map.keyword_pins.to_a
|
217
217
|
result.concat yielded_self_pins
|
218
218
|
end
|
219
219
|
end
|
@@ -204,6 +204,8 @@ module Solargraph
|
|
204
204
|
com_pos = Position.new(line + 1 - comments.lines.length, 0)
|
205
205
|
process_comment(src_pos, com_pos, comments)
|
206
206
|
end
|
207
|
+
rescue StandardError => e
|
208
|
+
raise e.class, "Error processing comment directives in #{@filename}: #{e.message}"
|
207
209
|
end
|
208
210
|
end
|
209
211
|
end
|
@@ -148,6 +148,7 @@ module Solargraph
|
|
148
148
|
all_variables.each do |pin|
|
149
149
|
if pin.return_type.defined?
|
150
150
|
declared = pin.typify(api_map)
|
151
|
+
next if declared.duck_type?
|
151
152
|
if declared.defined?
|
152
153
|
if rules.validate_tags?
|
153
154
|
inferred = pin.probe(api_map)
|
@@ -416,7 +417,7 @@ module Solargraph
|
|
416
417
|
end
|
417
418
|
settled_kwargs = 0
|
418
419
|
unless unchecked.empty?
|
419
|
-
if
|
420
|
+
if any_splatted_call?(unchecked.map(&:node))
|
420
421
|
settled_kwargs = pin.parameters.count(&:keyword?)
|
421
422
|
else
|
422
423
|
kwargs = convert_hash(unchecked.last.node)
|
@@ -431,6 +432,7 @@ module Solargraph
|
|
431
432
|
kwargs.delete param.name.to_sym
|
432
433
|
settled_kwargs += 1
|
433
434
|
elsif param.decl == :kwarg
|
435
|
+
return [] if arguments.last.links.last.is_a?(Solargraph::Source::Chain::Hash) && arguments.last.links.last.splatted?
|
434
436
|
return [Problem.new(location, "Missing keyword argument #{param.name} to #{pin.path}")]
|
435
437
|
end
|
436
438
|
end
|
@@ -450,12 +452,17 @@ module Solargraph
|
|
450
452
|
if unchecked.length == req + opt + 1 && unchecked.last.links.last.is_a?(Source::Chain::BlockVariable)
|
451
453
|
return []
|
452
454
|
end
|
453
|
-
if req + add_params + 1 == unchecked.length &&
|
455
|
+
if req + add_params + 1 == unchecked.length && any_splatted_call?(unchecked.map(&:node)) && (pin.parameters.map(&:decl) & [:kwarg, :kwoptarg, :kwrestarg]).any?
|
454
456
|
return []
|
455
457
|
end
|
458
|
+
return [] if arguments.length - req == pin.parameters.select { |p| [:optarg, :kwoptarg].include?(p.decl) }.length
|
456
459
|
return [Problem.new(location, "Too many arguments to #{pin.path}")]
|
457
|
-
elsif unchecked.length < req - settled_kwargs && (arguments.empty? || !arguments.last.splat?)
|
458
|
-
|
460
|
+
elsif unchecked.length < req - settled_kwargs && (arguments.empty? || (!arguments.last.splat? && !arguments.last.links.last.is_a?(Solargraph::Source::Chain::Hash)))
|
461
|
+
# HACK: Kernel#raise signature is incorrect in Ruby 2.7 core docs.
|
462
|
+
# See https://github.com/castwide/solargraph/issues/418
|
463
|
+
unless arguments.empty? && pin.path == 'Kernel#raise'
|
464
|
+
return [Problem.new(location, "Not enough arguments to #{pin.path}")]
|
465
|
+
end
|
459
466
|
end
|
460
467
|
[]
|
461
468
|
end
|
data/lib/solargraph/version.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
Namespace:
|
3
3
|
</h2>
|
4
4
|
<p>
|
5
|
-
<a href="
|
5
|
+
<a href="solargraph:/document?query=<%= CGI.escape object.namespace.path %>"><%= object.namespace %></a>
|
6
6
|
</p>
|
7
7
|
<h2>
|
8
8
|
Overview:
|
data/lib/solargraph/workspace.rb
CHANGED
data/lib/solargraph/yard_map.rb
CHANGED
@@ -288,9 +288,6 @@ module Solargraph
|
|
288
288
|
# @return [Array<Pin::Base>]
|
289
289
|
def process_yardoc y, spec = nil
|
290
290
|
return [] if y.nil?
|
291
|
-
size = Dir.glob(File.join(y, '**', '*'))
|
292
|
-
.map{ |f| File.size(f) }
|
293
|
-
.inject(:+)
|
294
291
|
if spec
|
295
292
|
ser = File.join(CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}.ser")
|
296
293
|
if File.file?(ser)
|
@@ -299,19 +296,24 @@ module Solargraph
|
|
299
296
|
dump = file.read
|
300
297
|
file.close
|
301
298
|
begin
|
302
|
-
|
299
|
+
result = Marshal.load(dump)
|
300
|
+
return result unless result.nil? || result.empty?
|
301
|
+
Solargraph.logger.warn "Empty cache for #{spec.name} #{spec.version}. Reloading"
|
303
302
|
rescue StandardError => e
|
304
303
|
Solargraph.logger.warn "Error loading pin cache: [#{e.class}] #{e.message}"
|
305
304
|
File.unlink ser
|
306
305
|
end
|
307
306
|
end
|
308
307
|
end
|
308
|
+
size = Dir.glob(File.join(y, '**', '*'))
|
309
|
+
.map{ |f| File.size(f) }
|
310
|
+
.inject(:+)
|
309
311
|
if !size.nil? && size > 20_000_000
|
310
312
|
Solargraph::Logging.logger.warn "Yardoc at #{y} is too large to process (#{size} bytes)"
|
311
313
|
return []
|
312
314
|
end
|
315
|
+
Solargraph.logger.info "Loading #{spec.name} #{spec.version} from #{y}"
|
313
316
|
load_yardoc y
|
314
|
-
Solargraph.logger.info "Loading #{spec.name} #{spec.version} from yardoc"
|
315
317
|
result = Mapper.new(YARD::Registry.all, spec).map
|
316
318
|
if spec
|
317
319
|
ser = File.join(CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}.ser")
|
@@ -435,5 +437,3 @@ module Solargraph
|
|
435
437
|
end
|
436
438
|
|
437
439
|
Solargraph::YardMap::CoreDocs.require_minimum
|
438
|
-
# Change YARD log IO to avoid sending unexpected messages to STDOUT
|
439
|
-
YARD::Logger.instance.io = File.new(File::NULL, 'w')
|
data/lib/solargraph.rb
CHANGED
@@ -57,6 +57,7 @@ module Solargraph
|
|
57
57
|
# A helper method that runs Bundler.with_unbundled_env or falls back to
|
58
58
|
# Bundler.with_clean_env for earlier versions of Bundler.
|
59
59
|
#
|
60
|
+
# @return [void]
|
60
61
|
def self.with_clean_env &block
|
61
62
|
meth = if Bundler.respond_to?(:with_unbundled_env)
|
62
63
|
:with_unbundled_env
|
data/lib/yard-solargraph.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'yard'
|
4
4
|
|
5
|
+
# Change YARD log IO to avoid sending unexpected messages to STDOUT
|
6
|
+
YARD::Logger.instance.io = File.new(File::NULL, 'w')
|
7
|
+
|
5
8
|
module Solargraph
|
6
9
|
# A placeholder for the @!domain directive. It doesn't need to do anything
|
7
10
|
# for yardocs. It's only used for Solargraph API maps.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solargraph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.43.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fred Snyder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backport
|
@@ -350,6 +350,7 @@ files:
|
|
350
350
|
- lib/solargraph/language_server/host/cataloger.rb
|
351
351
|
- lib/solargraph/language_server/host/diagnoser.rb
|
352
352
|
- lib/solargraph/language_server/host/dispatch.rb
|
353
|
+
- lib/solargraph/language_server/host/message_worker.rb
|
353
354
|
- lib/solargraph/language_server/host/sources.rb
|
354
355
|
- lib/solargraph/language_server/message.rb
|
355
356
|
- lib/solargraph/language_server/message/base.rb
|
@@ -502,6 +503,7 @@ files:
|
|
502
503
|
- lib/solargraph/source/chain/class_variable.rb
|
503
504
|
- lib/solargraph/source/chain/constant.rb
|
504
505
|
- lib/solargraph/source/chain/global_variable.rb
|
506
|
+
- lib/solargraph/source/chain/hash.rb
|
505
507
|
- lib/solargraph/source/chain/head.rb
|
506
508
|
- lib/solargraph/source/chain/instance_variable.rb
|
507
509
|
- lib/solargraph/source/chain/link.rb
|