solargraph 0.22.0 → 0.23.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 +4 -4
- data/lib/solargraph/api_map.rb +17 -2
- data/lib/solargraph/api_map/probe.rb +3 -0
- data/lib/solargraph/api_map/store.rb +21 -1
- data/lib/solargraph/diagnostics/require_not_found.rb +0 -2
- data/lib/solargraph/diagnostics/rubocop.rb +23 -11
- data/lib/solargraph/language_server/host.rb +79 -14
- data/lib/solargraph/language_server/message/initialize.rb +49 -44
- data/lib/solargraph/language_server/message/initialized.rb +11 -7
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +5 -3
- data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +16 -16
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +3 -2
- data/lib/solargraph/language_server/transport.rb +2 -1
- data/lib/solargraph/language_server/transport/socket.rb +0 -3
- data/lib/solargraph/language_server/transport/stdio.rb +66 -0
- data/lib/solargraph/pin/attribute.rb +1 -1
- data/lib/solargraph/pin/base.rb +5 -0
- data/lib/solargraph/pin/base_variable.rb +5 -0
- data/lib/solargraph/pin/constant.rb +5 -0
- data/lib/solargraph/pin/conversions.rb +26 -33
- data/lib/solargraph/pin/localized.rb +1 -1
- data/lib/solargraph/pin/method.rb +5 -0
- data/lib/solargraph/pin/namespace.rb +5 -0
- data/lib/solargraph/shell.rb +14 -0
- data/lib/solargraph/source/fragment.rb +12 -0
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +2 -4
- data/lib/solargraph/yard_map.rb +4 -0
- data/lib/solargraph/yard_map/cache.rb +8 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e4fd079cd97cdd7650d3040d3a9182451f280e8e89c1de91f82d2092dbef840
|
4
|
+
data.tar.gz: '0516619d1947a312eebb8b1caa535c4194bed4a308b4c68467af7d55c705119a'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b290e1ed7ecf9b59933abef586de329903c6c9f06d61b233dc71b817b75f7a4e4cae1f246803965779eac8b9eed1107e27263e63a039a282e2ede3da2f2260d
|
7
|
+
data.tar.gz: 7b29c6d72ce773d6ea9a55a5ae9d23398fbe1d4ef9ace42bab1b29723e8c61171bbae1c12900fd4e64f2e1b17193519b4eab202e39ab8428e3a24d691c8c17af
|
data/lib/solargraph/api_map.rb
CHANGED
@@ -46,10 +46,12 @@ module Solargraph
|
|
46
46
|
self.new(Solargraph::Workspace.new(directory))
|
47
47
|
end
|
48
48
|
|
49
|
+
# @return [Array<Solargraph::Pin::Base>]
|
49
50
|
def pins
|
50
51
|
store.pins
|
51
52
|
end
|
52
53
|
|
54
|
+
# @return [Array<String>]
|
53
55
|
def domains
|
54
56
|
@domains ||= []
|
55
57
|
end
|
@@ -244,6 +246,13 @@ module Solargraph
|
|
244
246
|
globals
|
245
247
|
end
|
246
248
|
|
249
|
+
# Get an array of methods available in a particular context.
|
250
|
+
#
|
251
|
+
# @param fqns [String] The fully qualified namespace to search for methods
|
252
|
+
# @param scope [Symbol] :class or :instance
|
253
|
+
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
254
|
+
# @param deep [Boolean] True to include superclasses, mixins, etc.
|
255
|
+
# @return [Array<Solargraph::Pin::Base>]
|
247
256
|
def get_methods fqns, scope: :instance, visibility: [:public], deep: true
|
248
257
|
result = []
|
249
258
|
skip = []
|
@@ -266,6 +275,10 @@ module Solargraph
|
|
266
275
|
result
|
267
276
|
end
|
268
277
|
|
278
|
+
# Get a set of available completions for the specified fragment. The
|
279
|
+
# resulting Completion object contains an array of pins and the range of
|
280
|
+
# text to replace in the source.
|
281
|
+
#
|
269
282
|
# @param fragment [Solargraph::Source::Fragment]
|
270
283
|
# @return [ApiMap::Completion]
|
271
284
|
def complete fragment
|
@@ -318,10 +331,12 @@ module Solargraph
|
|
318
331
|
Completion.new(filtered, fragment.whole_word_range)
|
319
332
|
end
|
320
333
|
|
334
|
+
# Get an array of pins that describe the symbol at the specified fragment.
|
335
|
+
#
|
321
336
|
# @param fragment [Solargraph::Source::Fragment]
|
322
337
|
# @return [Array<Solargraph::Pin::Base>]
|
323
338
|
def define fragment
|
324
|
-
return [] if fragment.string? or fragment.comment?
|
339
|
+
return [] if fragment.string? or fragment.comment? or fragment.literal?
|
325
340
|
if fragment.base_literal?
|
326
341
|
probe.infer_signature_pins fragment.whole_signature, Pin::ProxyMethod.new(fragment.base_literal), fragment.locals
|
327
342
|
else
|
@@ -421,11 +436,11 @@ module Solargraph
|
|
421
436
|
result
|
422
437
|
end
|
423
438
|
|
439
|
+
# @return [Solargraph::Pin::Base]
|
424
440
|
def locate_pin location
|
425
441
|
@sources.each do |source|
|
426
442
|
pin = source.locate_pin(location)
|
427
443
|
unless pin.nil?
|
428
|
-
# pin.resolve self
|
429
444
|
return pin
|
430
445
|
end
|
431
446
|
end
|
@@ -148,6 +148,9 @@ module Solargraph
|
|
148
148
|
pin
|
149
149
|
end
|
150
150
|
|
151
|
+
# @param pin [Solargraph::Pin::Base]
|
152
|
+
# @param locals [Array<Solargraph::Pin::Base>]
|
153
|
+
# @return [String]
|
151
154
|
def resolve_pin_type pin, locals
|
152
155
|
pin.return_type
|
153
156
|
return pin.return_type unless pin.return_type.nil?
|
@@ -3,12 +3,13 @@ require 'set'
|
|
3
3
|
module Solargraph
|
4
4
|
class ApiMap
|
5
5
|
class Store
|
6
|
-
# @param sources [Solargraph::Source]
|
6
|
+
# @param sources [Array<Solargraph::Source>]
|
7
7
|
def initialize sources
|
8
8
|
update *sources
|
9
9
|
index
|
10
10
|
end
|
11
11
|
|
12
|
+
# @return [Array<Solargraph::Pin::Base>]
|
12
13
|
def pins
|
13
14
|
@pins ||= []
|
14
15
|
end
|
@@ -31,6 +32,7 @@ module Solargraph
|
|
31
32
|
index
|
32
33
|
end
|
33
34
|
|
35
|
+
# @return [Array<Solargraph::Pin::Base>]
|
34
36
|
def get_constants fqns, visibility = [:public]
|
35
37
|
namespace_pins(fqns).select { |pin|
|
36
38
|
!pin.name.empty? and (pin.kind == Pin::NAMESPACE or pin.kind == Pin::CONSTANT) and visibility.include?(pin.visibility)
|
@@ -43,10 +45,13 @@ module Solargraph
|
|
43
45
|
}
|
44
46
|
end
|
45
47
|
|
48
|
+
# @return [Array<Solargraph::Pin::Base>]
|
46
49
|
def get_attrs fqns, scope
|
47
50
|
namespace_pins(fqns).select{ |pin| pin.kind == Pin::ATTRIBUTE and pin.scope == scope }
|
48
51
|
end
|
49
52
|
|
53
|
+
# @param fqns [String]
|
54
|
+
# @return [String]
|
50
55
|
def get_superclass fqns
|
51
56
|
fqns_pins(fqns).each do |pin|
|
52
57
|
return pin.superclass_reference.name unless pin.superclass_reference.nil?
|
@@ -54,6 +59,8 @@ module Solargraph
|
|
54
59
|
nil
|
55
60
|
end
|
56
61
|
|
62
|
+
# @param fqns [String]
|
63
|
+
# @return [Array<String>]
|
57
64
|
def get_includes fqns
|
58
65
|
result = []
|
59
66
|
fqns_pins(fqns).each do |pin|
|
@@ -62,6 +69,8 @@ module Solargraph
|
|
62
69
|
result
|
63
70
|
end
|
64
71
|
|
72
|
+
# @param fqns [String]
|
73
|
+
# @return [Array<String>]
|
65
74
|
def get_extends fqns
|
66
75
|
result = []
|
67
76
|
fqns_pins(fqns).each do |pin|
|
@@ -70,28 +79,39 @@ module Solargraph
|
|
70
79
|
result
|
71
80
|
end
|
72
81
|
|
82
|
+
# @param path [String]
|
83
|
+
# @return [Array<Solargraph::Pin::Base>]
|
73
84
|
def get_path_pins path
|
74
85
|
base = path.sub(/(#|\.|::)[a-z0-9_]*(\?|\!)?$/i, '')
|
75
86
|
base = '' if base == path
|
76
87
|
namespace_pins(base).select{ |pin| pin.path == path }
|
77
88
|
end
|
78
89
|
|
90
|
+
# @param fqns [String]
|
91
|
+
# @param scope [Symbol] :class or :instance
|
92
|
+
# @return [Array<Solargraph::Pin::Base>]
|
79
93
|
def get_instance_variables(fqns, scope = :instance)
|
80
94
|
namespace_pins(fqns).select{|pin| pin.kind == Pin::INSTANCE_VARIABLE and pin.scope == scope}
|
81
95
|
end
|
82
96
|
|
97
|
+
# @param fqns [String]
|
98
|
+
# @return [Array<Solargraph::Pin::Base>]
|
83
99
|
def get_class_variables(fqns)
|
84
100
|
namespace_pins(fqns).select{|pin| pin.kind == Pin::CLASS_VARIABLE}
|
85
101
|
end
|
86
102
|
|
103
|
+
# @return [Array<Solargraph::Pin::Base>]
|
87
104
|
def get_symbols
|
88
105
|
symbols.uniq(&:name)
|
89
106
|
end
|
90
107
|
|
108
|
+
# @param fqns [String]
|
109
|
+
# @return [Boolean]
|
91
110
|
def namespace_exists?(fqns)
|
92
111
|
fqns_pins(fqns).any?
|
93
112
|
end
|
94
113
|
|
114
|
+
# @return [Set<String>]
|
95
115
|
def namespaces
|
96
116
|
@namespaces ||= Set.new
|
97
117
|
end
|
@@ -3,8 +3,6 @@ module Solargraph
|
|
3
3
|
# RequireNotFound reports required paths that could not be resolved to
|
4
4
|
# either a file in the workspace or a gem.
|
5
5
|
#
|
6
|
-
# @todo Some stdlib paths can result in false positives.
|
7
|
-
#
|
8
6
|
class RequireNotFound < Base
|
9
7
|
def diagnose source, api_map
|
10
8
|
result = []
|
@@ -6,6 +6,15 @@ module Solargraph
|
|
6
6
|
# This reporter provides linting through RuboCop.
|
7
7
|
#
|
8
8
|
class Rubocop < Base
|
9
|
+
# Conversion of RuboCop severity names to LSP constants
|
10
|
+
SEVERITIES = {
|
11
|
+
'refactor' => 4,
|
12
|
+
'convention' => 3,
|
13
|
+
'warning' => 2,
|
14
|
+
'error' => 1,
|
15
|
+
'fatal' => 1
|
16
|
+
}
|
17
|
+
|
9
18
|
# The rubocop command
|
10
19
|
#
|
11
20
|
# @return [String]
|
@@ -23,11 +32,12 @@ module Solargraph
|
|
23
32
|
text = source.code
|
24
33
|
filename = source.filename
|
25
34
|
raise DiagnosticsError, 'No command specified' if command.nil? or command.empty?
|
26
|
-
cmd = "#{Shellwords.escape(command)} -f j
|
35
|
+
cmd = "#{Shellwords.escape(command)} -f j"
|
27
36
|
unless api_map.workspace.nil? or api_map.workspace.directory.nil?
|
28
37
|
rc = File.join(api_map.workspace.directory, '.rubocop.yml')
|
29
|
-
cmd += " -c #{Shellwords.escape(rc)}" if File.file?(rc)
|
38
|
+
cmd += " -c #{Shellwords.escape(fix_drive_letter(rc))}" if File.file?(rc)
|
30
39
|
end
|
40
|
+
cmd += " -s #{Shellwords.escape(fix_drive_letter(filename))}"
|
31
41
|
o, e, s = Open3.capture3(cmd, stdin_data: text)
|
32
42
|
STDERR.puts e unless e.empty?
|
33
43
|
raise DiagnosticsError, "Command '#{command}' is not available (gem exception)" if e.include?('Gem::Exception')
|
@@ -43,14 +53,6 @@ module Solargraph
|
|
43
53
|
private
|
44
54
|
|
45
55
|
def make_array resp
|
46
|
-
# Conversion of RuboCop severity names to LSP constants
|
47
|
-
severities = {
|
48
|
-
'refactor' => 4,
|
49
|
-
'convention' => 3,
|
50
|
-
'warning' => 2,
|
51
|
-
'error' => 1,
|
52
|
-
'fatal' => 1
|
53
|
-
}
|
54
56
|
diagnostics = []
|
55
57
|
resp['files'].each do |file|
|
56
58
|
file['offenses'].each do |off|
|
@@ -73,7 +75,7 @@ module Solargraph
|
|
73
75
|
}
|
74
76
|
},
|
75
77
|
# 1 = Error, 2 = Warning, 3 = Information, 4 = Hint
|
76
|
-
severity:
|
78
|
+
severity: SEVERITIES[off['severity']],
|
77
79
|
source: off['cop_name'],
|
78
80
|
message: off['message'].gsub(/^#{off['cop_name']}\:/, '')
|
79
81
|
}
|
@@ -82,6 +84,16 @@ module Solargraph
|
|
82
84
|
end
|
83
85
|
diagnostics
|
84
86
|
end
|
87
|
+
|
88
|
+
# RuboCop internally uses capitalized drive letters for Windows paths,
|
89
|
+
# so we need to convert the paths provided to the command.
|
90
|
+
#
|
91
|
+
# @param path [String]
|
92
|
+
# @return [String]
|
93
|
+
def fix_drive_letter path
|
94
|
+
return path unless path.match(/^[a-z]:/)
|
95
|
+
path[0].upcase + path[1..-1]
|
96
|
+
end
|
85
97
|
end
|
86
98
|
end
|
87
99
|
end
|
@@ -14,12 +14,15 @@ module Solargraph
|
|
14
14
|
@change_semaphore = Mutex.new
|
15
15
|
@cancel_semaphore = Mutex.new
|
16
16
|
@buffer_semaphore = Mutex.new
|
17
|
+
@register_semaphore = Mutex.new
|
17
18
|
@change_queue = []
|
18
19
|
@diagnostics_queue = []
|
19
20
|
@cancel = []
|
20
21
|
@buffer = ''
|
21
22
|
@stopped = false
|
22
23
|
@next_request_id = 0
|
24
|
+
@dynamic_capabilities = Set.new
|
25
|
+
@registered_capabilities = []
|
23
26
|
start_change_thread
|
24
27
|
start_diagnostics_thread
|
25
28
|
end
|
@@ -28,7 +31,8 @@ module Solargraph
|
|
28
31
|
#
|
29
32
|
# @param update [Hash]
|
30
33
|
def configure update
|
31
|
-
|
34
|
+
return if update.nil?
|
35
|
+
options.merge! update
|
32
36
|
end
|
33
37
|
|
34
38
|
# @return [Hash]
|
@@ -94,6 +98,11 @@ module Solargraph
|
|
94
98
|
@change_semaphore.synchronize do
|
95
99
|
filename = uri_to_file(uri)
|
96
100
|
library.delete filename
|
101
|
+
# Remove diagnostics for deleted files
|
102
|
+
send_notification "textDocument/publishDiagnostics", {
|
103
|
+
uri: uri,
|
104
|
+
diagnostics: []
|
105
|
+
}
|
97
106
|
end
|
98
107
|
end
|
99
108
|
|
@@ -235,27 +244,64 @@ module Solargraph
|
|
235
244
|
@next_request_id += 1
|
236
245
|
end
|
237
246
|
|
247
|
+
# Register the methods as capabilities with the client.
|
248
|
+
# This method will avoid duplicating registrations and ignore methods
|
249
|
+
# that were not flagged for dynamic registration by the client.
|
250
|
+
#
|
251
|
+
# @param methods [Array<String>] The methods to register
|
238
252
|
def register_capabilities methods
|
239
|
-
|
240
|
-
|
241
|
-
{
|
242
|
-
|
243
|
-
|
244
|
-
|
253
|
+
@register_semaphore.synchronize do
|
254
|
+
send_request 'client/registerCapability', {
|
255
|
+
registrations: methods.reject{|m| @dynamic_capabilities.include?(m) and @registered_capabilities.include?(m)}.map { |m|
|
256
|
+
@registered_capabilities.push m
|
257
|
+
{
|
258
|
+
id: m,
|
259
|
+
method: m,
|
260
|
+
registerOptions: dynamic_capability_options[m]
|
261
|
+
}
|
245
262
|
}
|
246
263
|
}
|
247
|
-
|
264
|
+
end
|
248
265
|
end
|
249
266
|
|
267
|
+
# Unregister the methods with the client.
|
268
|
+
# This method will avoid duplicating unregistrations and ignore methods
|
269
|
+
# that were not flagged for dynamic registration by the client.
|
270
|
+
#
|
271
|
+
# @param methods [Array<String>] The methods to unregister
|
250
272
|
def unregister_capabilities methods
|
251
|
-
|
252
|
-
|
253
|
-
{
|
254
|
-
|
255
|
-
|
273
|
+
@register_semaphore.synchronize do
|
274
|
+
send_request 'client/unregisterCapability', {
|
275
|
+
unregisterations: methods.select{|m| @registered_capabilities.include?(m)}.map{ |m|
|
276
|
+
@registered_capabilities.delete m
|
277
|
+
{
|
278
|
+
id: m,
|
279
|
+
method: m
|
280
|
+
}
|
256
281
|
}
|
257
282
|
}
|
258
|
-
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
# Flag a method as available for dynamic registration.
|
287
|
+
#
|
288
|
+
# @param method [String] The method name, e.g., 'textDocument/completion'
|
289
|
+
def allow_registration method
|
290
|
+
@register_semaphore.synchronize do
|
291
|
+
@dynamic_capabilities.add method
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
# True if the specified method has been registered.
|
296
|
+
#
|
297
|
+
# @param method [String] The method name, e.g., 'textDocument/completion'
|
298
|
+
# @return [Boolean]
|
299
|
+
def registered? method
|
300
|
+
result = nil
|
301
|
+
@register_semaphore.synchronize do
|
302
|
+
result = @registered_capabilities.include?(method)
|
303
|
+
end
|
304
|
+
result
|
259
305
|
end
|
260
306
|
|
261
307
|
# True if the specified file is in the process of changing.
|
@@ -380,6 +426,10 @@ module Solargraph
|
|
380
426
|
{
|
381
427
|
'completion' => true,
|
382
428
|
'hover' => true,
|
429
|
+
'symbols' => true,
|
430
|
+
'definitions' => true,
|
431
|
+
'rename' => true,
|
432
|
+
'references' => true,
|
383
433
|
'autoformat' => false,
|
384
434
|
'diagnostics' => false,
|
385
435
|
'formatting' => false
|
@@ -545,6 +595,21 @@ module Solargraph
|
|
545
595
|
# changeNotifications: true
|
546
596
|
# }
|
547
597
|
# }
|
598
|
+
'textDocument/definition' => {
|
599
|
+
definitionProvider: true
|
600
|
+
},
|
601
|
+
'textDocument/references' => {
|
602
|
+
referencesProvider: true
|
603
|
+
},
|
604
|
+
'textDocument/rename' => {
|
605
|
+
renameProvider: true
|
606
|
+
},
|
607
|
+
'textDocument/documentSymbol' => {
|
608
|
+
documentSymbolProvider: true
|
609
|
+
},
|
610
|
+
'workspace/workspaceSymbol' => {
|
611
|
+
workspaceSymbolProvider: true
|
612
|
+
}
|
548
613
|
}
|
549
614
|
end
|
550
615
|
end
|
@@ -8,24 +8,24 @@ module Solargraph
|
|
8
8
|
result = {
|
9
9
|
capabilities: {
|
10
10
|
textDocumentSync: 2, # @todo What should this be?
|
11
|
-
definitionProvider: true,
|
12
|
-
documentSymbolProvider: true,
|
13
|
-
workspaceSymbolProvider: true,
|
14
|
-
renameProvider: true,
|
15
11
|
workspace: {
|
16
12
|
workspaceFolders: {
|
17
13
|
supported: true,
|
18
14
|
changeNotifications: true
|
19
15
|
}
|
20
|
-
}
|
21
|
-
referencesProvider: true
|
16
|
+
}
|
22
17
|
}
|
23
18
|
}
|
24
|
-
result[:capabilities].merge! static_completion unless
|
25
|
-
result[:capabilities].merge! static_signature_help unless
|
26
|
-
result[:capabilities].merge! static_on_type_formatting unless
|
27
|
-
result[:capabilities].merge! static_hover unless
|
28
|
-
result[:capabilities].merge! static_document_formatting unless
|
19
|
+
result[:capabilities].merge! static_completion unless dynamic_registration_for?('textDocument', 'completion')
|
20
|
+
result[:capabilities].merge! static_signature_help unless dynamic_registration_for?('textDocument', 'signatureHelp')
|
21
|
+
# result[:capabilities].merge! static_on_type_formatting unless dynamic_registration_for?('textDocument', 'onTypeFormatting')
|
22
|
+
result[:capabilities].merge! static_hover unless dynamic_registration_for?('textDocument', 'hover')
|
23
|
+
result[:capabilities].merge! static_document_formatting unless dynamic_registration_for?('textDocument', 'formatting')
|
24
|
+
result[:capabilities].merge! static_document_symbols unless dynamic_registration_for?('textDocument', 'documentSymbol')
|
25
|
+
result[:capabilities].merge! static_definitions unless dynamic_registration_for?('textDocument', 'definition')
|
26
|
+
result[:capabilities].merge! static_rename unless dynamic_registration_for?('textDocument', 'rename')
|
27
|
+
result[:capabilities].merge! static_references unless dynamic_registration_for?('textDocument', 'references')
|
28
|
+
result[:capabilities].merge! static_workspace_symbols unless dynamic_registration_for?('workspace', 'symbol')
|
29
29
|
set_result result
|
30
30
|
end
|
31
31
|
|
@@ -40,13 +40,6 @@ module Solargraph
|
|
40
40
|
}
|
41
41
|
end
|
42
42
|
|
43
|
-
def dynamic_completion?
|
44
|
-
params['capabilities'] and
|
45
|
-
params['capabilities']['textDocument'] and
|
46
|
-
params['capabilities']['textDocument']['completion'] and
|
47
|
-
params['capabilities']['textDocument']['completion']['dynamicRegistration']
|
48
|
-
end
|
49
|
-
|
50
43
|
def static_signature_help
|
51
44
|
{
|
52
45
|
signatureHelpProvider: {
|
@@ -55,13 +48,6 @@ module Solargraph
|
|
55
48
|
}
|
56
49
|
end
|
57
50
|
|
58
|
-
def dynamic_signature_help?
|
59
|
-
params['capabilities'] and
|
60
|
-
params['capabilities']['textDocument'] and
|
61
|
-
params['capabilities']['textDocument']['signatureHelp'] and
|
62
|
-
params['capabilities']['textDocument']['signatureHelp']['dynamicRegistration']
|
63
|
-
end
|
64
|
-
|
65
51
|
def static_on_type_formatting
|
66
52
|
{
|
67
53
|
documentOnTypeFormattingProvider: {
|
@@ -71,37 +57,56 @@ module Solargraph
|
|
71
57
|
}
|
72
58
|
end
|
73
59
|
|
74
|
-
def dynamic_on_type_formatting?
|
75
|
-
params['capabilities'] and
|
76
|
-
params['capabilities']['textDocument'] and
|
77
|
-
params['capabilities']['textDocument']['onTypeFormatting'] and
|
78
|
-
params['capabilities']['textDocument']['onTypeFormatting']['dynamicRegistration']
|
79
|
-
end
|
80
|
-
|
81
60
|
def static_hover
|
82
61
|
{
|
83
62
|
hoverProvider: true
|
84
63
|
}
|
85
64
|
end
|
86
65
|
|
87
|
-
def dynamic_hover?
|
88
|
-
params['capabilities'] and
|
89
|
-
params['capabilities']['textDocument'] and
|
90
|
-
params['capabilities']['textDocument']['hover'] and
|
91
|
-
params['capabilities']['textDocument']['hover']['dynamicRegistration']
|
92
|
-
end
|
93
|
-
|
94
66
|
def static_document_formatting
|
95
67
|
{
|
96
68
|
documentFormattingProvider: true
|
97
69
|
}
|
98
70
|
end
|
99
71
|
|
100
|
-
def
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
72
|
+
def static_document_symbols
|
73
|
+
{
|
74
|
+
documentSymbolProvider: true
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
def static_workspace_symbols
|
79
|
+
{
|
80
|
+
workspaceSymbolProvider: true
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
def static_definitions
|
85
|
+
{
|
86
|
+
definitionProvider: true
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
def static_rename
|
91
|
+
{
|
92
|
+
renameProvider: true
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
def static_references
|
97
|
+
{
|
98
|
+
referencesProvider: true
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return [Boolean]
|
103
|
+
def dynamic_registration_for? section, capability
|
104
|
+
result = params['capabilities'] and
|
105
|
+
params['capabilities'][section] and
|
106
|
+
params['capabilities'][section][capability] and
|
107
|
+
params['capabilities'][section][capability]['dynamicRegistration']
|
108
|
+
host.allow_registration "#{section}/#{capability}" if result
|
109
|
+
result
|
105
110
|
end
|
106
111
|
end
|
107
112
|
end
|
@@ -3,13 +3,17 @@ module Solargraph
|
|
3
3
|
module Message
|
4
4
|
class Initialized < Base
|
5
5
|
def process
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
6
|
+
host.register_capabilities %w[
|
7
|
+
textDocument/completion
|
8
|
+
textDocument/hover
|
9
|
+
textDocument/signatureHelp
|
10
|
+
textDocument/formatting
|
11
|
+
textDocument/documentSymbol
|
12
|
+
textDocument/definition
|
13
|
+
textDocument/references
|
14
|
+
textDocument/rename
|
15
|
+
workspace/workspaceSymbol
|
16
|
+
]
|
13
17
|
end
|
14
18
|
end
|
15
19
|
end
|
@@ -4,14 +4,16 @@ class Solargraph::LanguageServer::Message::TextDocument::DocumentSymbol < Solarg
|
|
4
4
|
def process
|
5
5
|
pins = host.file_symbols params['textDocument']['uri']
|
6
6
|
info = pins.map do |pin|
|
7
|
-
{
|
8
|
-
name: pin.
|
9
|
-
|
7
|
+
result = {
|
8
|
+
name: pin.name,
|
9
|
+
containerName: pin.namespace,
|
10
|
+
kind: pin.symbol_kind,
|
10
11
|
location: {
|
11
12
|
uri: file_to_uri(pin.location.filename),
|
12
13
|
range: pin.location.range.to_hash
|
13
14
|
}
|
14
15
|
}
|
16
|
+
result
|
15
17
|
end
|
16
18
|
set_result info
|
17
19
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'uri'
|
2
|
+
require 'htmlentities'
|
2
3
|
|
3
4
|
module Solargraph::LanguageServer::Message::TextDocument
|
4
5
|
class Hover < Base
|
@@ -20,6 +21,7 @@ module Solargraph::LanguageServer::Message::TextDocument
|
|
20
21
|
if !this_path.nil? and this_path != last_path
|
21
22
|
parts.push link_documentation(this_path)
|
22
23
|
end
|
24
|
+
parts.push HTMLEntities.new.encode(pin.detail) unless pin.kind == Solargraph::Pin::NAMESPACE or pin.detail.nil?
|
23
25
|
parts.push pin.documentation unless pin.documentation.nil? or pin.documentation.empty?
|
24
26
|
contents.push parts.join("\n\n") unless parts.empty?
|
25
27
|
last_path = this_path unless this_path.nil?
|
@@ -4,24 +4,24 @@ module Solargraph::LanguageServer::Message::Workspace
|
|
4
4
|
class DidChangeConfiguration < Solargraph::LanguageServer::Message::Base
|
5
5
|
def process
|
6
6
|
update = params['settings']['solargraph']
|
7
|
+
host.configure update
|
8
|
+
register_from_options
|
9
|
+
end
|
7
10
|
|
8
|
-
|
9
|
-
meths.push 'textDocument/completion' if update.has_key?('completion') and update['completion'] and !host.options['completion']
|
10
|
-
meths.push 'textDocument/hover' if update.has_key?('hover') and update['hover'] and !host.options['hover']
|
11
|
-
meths.push 'textDocument/signatureHelp' if update.has_key?('hover') and update['hover'] and !host.options['hover']
|
12
|
-
meths.push 'textDocument/onTypeFormatting' if update.has_key?('autoformat') and update['autoformat'] and !host.options['autoformat']
|
13
|
-
meths.push "textDocument/formatting" if update.has_key?('formatting') and update['formatting'] and !host.options['formatting']
|
14
|
-
host.register_capabilities meths unless meths.empty?
|
15
|
-
|
16
|
-
meths = []
|
17
|
-
meths.push 'textDocument/completion' if update.has_key?('completion') and !update['completion'] and host.options['completion']
|
18
|
-
meths.push 'textDocument/hover' if update.has_key?('hover') and !update['hover'] and host.options['hover']
|
19
|
-
meths.push 'textDocument/signatureHelp' if update.has_key?('hover') and !update['hover'] and host.options['hover']
|
20
|
-
meths.push 'textDocument/onTypeFormatting' if update.has_key?('autoformat') and !update['autoformat'] and host.options['autoformat']
|
21
|
-
meths.push "textDocument/formatting" if update.has_key?('formatting') and !update['formatting'] and host.options['formatting']
|
22
|
-
host.unregister_capabilities meths unless meths.empty?
|
11
|
+
private
|
23
12
|
|
24
|
-
|
13
|
+
def register_from_options
|
14
|
+
y = []
|
15
|
+
n = []
|
16
|
+
(host.options['completion'] ? y : n).push('textDocument/completion')
|
17
|
+
(host.options['hover'] ? y : n).push('textDocument/hover', 'textDocument/signatureHelp')
|
18
|
+
(host.options['autoformat'] ? y : n).push('textDocument/onTypeFormatting')
|
19
|
+
(host.options['formatting'] ? y : n).push('textDocument/formatting')
|
20
|
+
(host.options['symbols'] ? y : n).push('textDocument/documentSymbol', 'workspace/workspaceSymbol')
|
21
|
+
(host.options['definitions'] ? y : n).push('textDocument/definition')
|
22
|
+
(host.options['references'] ? y : n).push('textDocument/references')
|
23
|
+
host.register_capabilities y
|
24
|
+
host.unregister_capabilities n
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -6,8 +6,9 @@ class Solargraph::LanguageServer::Message::Workspace::WorkspaceSymbol < Solargra
|
|
6
6
|
info = pins.map do |pin|
|
7
7
|
uri = file_to_uri(pin.location.filename)
|
8
8
|
{
|
9
|
-
name: pin.
|
10
|
-
|
9
|
+
name: pin.name,
|
10
|
+
containerName: pin.namespace,
|
11
|
+
kind: pin.symbol_kind,
|
11
12
|
location: {
|
12
13
|
uri: uri,
|
13
14
|
range: pin.location.range.to_hash
|
@@ -2,7 +2,8 @@ module Solargraph
|
|
2
2
|
module LanguageServer
|
3
3
|
module Transport
|
4
4
|
autoload :DataReader, 'solargraph/language_server/transport/data_reader'
|
5
|
-
autoload :Socket,
|
5
|
+
autoload :Socket, 'solargraph/language_server/transport/socket'
|
6
|
+
autoload :Stdio, 'solargraph/language_server/transport/stdio'
|
6
7
|
end
|
7
8
|
end
|
8
9
|
end
|
@@ -7,9 +7,6 @@ module Solargraph
|
|
7
7
|
#
|
8
8
|
module Socket
|
9
9
|
def post_init
|
10
|
-
@in_header = true
|
11
|
-
@content_length = 0
|
12
|
-
@buffer = ''
|
13
10
|
@host = Solargraph::LanguageServer::Host.new
|
14
11
|
@data_reader = Solargraph::LanguageServer::Transport::DataReader.new
|
15
12
|
@data_reader.set_message_handler do |message|
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module LanguageServer
|
5
|
+
module Transport
|
6
|
+
class Stdio
|
7
|
+
def initialize
|
8
|
+
# binmode is necessary to avoid EOL conversions
|
9
|
+
STDOUT.binmode
|
10
|
+
@host = Solargraph::LanguageServer::Host.new
|
11
|
+
@data_reader = Solargraph::LanguageServer::Transport::DataReader.new
|
12
|
+
@data_reader.set_message_handler do |message|
|
13
|
+
process message
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
start_reader
|
19
|
+
start_timers
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.run
|
23
|
+
std = Stdio.new
|
24
|
+
std.run
|
25
|
+
std
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def start_reader
|
31
|
+
Thread.new do
|
32
|
+
until @host.stopped?
|
33
|
+
char = STDIN.sysread(1)
|
34
|
+
break if char.nil?
|
35
|
+
@data_reader.receive char
|
36
|
+
STDIN.flush
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def send_data message
|
42
|
+
STDOUT.write message
|
43
|
+
STDOUT.flush
|
44
|
+
end
|
45
|
+
|
46
|
+
def process request
|
47
|
+
Thread.new do
|
48
|
+
message = @host.start(request)
|
49
|
+
message.send_response
|
50
|
+
tmp = @host.flush
|
51
|
+
send_data tmp unless tmp.empty?
|
52
|
+
GC.start unless request['method'] == 'textDocument/didChange'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def start_timers
|
57
|
+
EventMachine.add_periodic_timer 0.1 do
|
58
|
+
tmp = @host.flush
|
59
|
+
send_data tmp unless tmp.empty?
|
60
|
+
EventMachine.stop if @host.stopped?
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/solargraph/pin/base.rb
CHANGED
@@ -20,6 +20,11 @@ module Solargraph
|
|
20
20
|
Solargraph::LanguageServer::CompletionItemKinds::VARIABLE
|
21
21
|
end
|
22
22
|
|
23
|
+
# @return [Integer]
|
24
|
+
def symbol_kind
|
25
|
+
Solargraph::LanguageServer::SymbolKinds::VARIABLE
|
26
|
+
end
|
27
|
+
|
23
28
|
def return_type
|
24
29
|
if @return_type.nil?
|
25
30
|
if !docstring.nil?
|
@@ -4,10 +4,10 @@ module Solargraph
|
|
4
4
|
module Conversions
|
5
5
|
# @return [Hash]
|
6
6
|
def completion_item
|
7
|
-
{
|
7
|
+
@completion_item ||= {
|
8
8
|
label: name,
|
9
9
|
kind: completion_item_kind,
|
10
|
-
detail:
|
10
|
+
detail: detail,
|
11
11
|
data: {
|
12
12
|
path: path,
|
13
13
|
return_type: return_type,
|
@@ -18,50 +18,43 @@ module Solargraph
|
|
18
18
|
|
19
19
|
# @return [Hash]
|
20
20
|
def resolve_completion_item
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
# @todo Candidate for deprecation
|
31
|
-
# @param api_map [Solargraph::ApiMap]
|
32
|
-
def hover
|
33
|
-
info = ''
|
34
|
-
if self.kind_of?(Solargraph::Pin::BaseVariable)
|
35
|
-
info.concat link_documentation(return_type) unless return_type.nil?
|
36
|
-
else
|
37
|
-
info.concat link_documentation(path) unless path.nil?
|
21
|
+
if @resolve_completion_item.nil?
|
22
|
+
extra = {}
|
23
|
+
alldoc = ''
|
24
|
+
alldoc += link_documentation(path) unless path.nil?
|
25
|
+
alldoc += "\n\n" unless alldoc.empty?
|
26
|
+
alldoc += documentation unless documentation.nil?
|
27
|
+
extra[:documentation] = alldoc unless alldoc.empty?
|
28
|
+
@resolve_completion_item = completion_item.merge(extra)
|
38
29
|
end
|
39
|
-
|
40
|
-
info
|
30
|
+
@resolve_completion_item
|
41
31
|
end
|
42
32
|
|
43
33
|
# @return [Hash]
|
44
34
|
def signature_help
|
45
|
-
{
|
35
|
+
@signature_help ||= {
|
46
36
|
label: name + '(' + parameters.join(', ') + ')',
|
47
37
|
documentation: documentation
|
48
38
|
}
|
49
39
|
end
|
50
40
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
41
|
+
# @return [String]
|
42
|
+
def detail
|
43
|
+
if @detail.nil?
|
44
|
+
@detail = ''
|
45
|
+
@detail += "(#{parameters.join(', ')}) " unless kind != Pin::METHOD or parameters.empty?
|
46
|
+
@detail += "=> #{return_type}" unless return_type.nil?
|
47
|
+
@detail.strip!
|
48
|
+
end
|
49
|
+
return nil if @detail.empty?
|
50
|
+
@detail
|
59
51
|
end
|
60
52
|
|
53
|
+
private
|
54
|
+
|
61
55
|
def link_documentation path
|
62
|
-
|
63
|
-
|
64
|
-
end
|
56
|
+
@link_documentation ||= "[#{path}](solargraph:/document?query=#{URI.encode(path)})"
|
57
|
+
end
|
65
58
|
end
|
66
59
|
end
|
67
60
|
end
|
@@ -6,7 +6,7 @@ module Solargraph
|
|
6
6
|
# @return [Source::Range]
|
7
7
|
attr_reader :presence
|
8
8
|
|
9
|
-
# @param other [Pin::
|
9
|
+
# @param other [Pin::Base] The caller's block
|
10
10
|
# @param position [Source::Position] The caller's position
|
11
11
|
# @return [Boolean]
|
12
12
|
def visible_from?(other, position)
|
@@ -24,6 +24,11 @@ module Solargraph
|
|
24
24
|
Solargraph::LanguageServer::CompletionItemKinds::METHOD
|
25
25
|
end
|
26
26
|
|
27
|
+
# @return [Integer]
|
28
|
+
def symbol_kind
|
29
|
+
LanguageServer::SymbolKinds::METHOD
|
30
|
+
end
|
31
|
+
|
27
32
|
def return_type
|
28
33
|
if @return_type.nil? and !docstring.nil?
|
29
34
|
tag = docstring.tag(:return)
|
@@ -42,6 +42,11 @@ module Solargraph
|
|
42
42
|
(type == :class ? LanguageServer::CompletionItemKinds::CLASS : LanguageServer::CompletionItemKinds::MODULE)
|
43
43
|
end
|
44
44
|
|
45
|
+
# @return [Integer]
|
46
|
+
def symbol_kind
|
47
|
+
(type == :class ? LanguageServer::SymbolKinds::CLASS : LanguageServer::SymbolKinds::MODULE)
|
48
|
+
end
|
49
|
+
|
45
50
|
def path
|
46
51
|
@path ||= (namespace.empty? ? '' : "#{namespace}::") + name
|
47
52
|
end
|
data/lib/solargraph/shell.rb
CHANGED
@@ -35,6 +35,20 @@ module Solargraph
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
desc 'stdio', 'Run a Solargraph stdio server'
|
39
|
+
def stdio
|
40
|
+
EventMachine.run do
|
41
|
+
Signal.trap("INT") do
|
42
|
+
EventMachine.stop
|
43
|
+
end
|
44
|
+
Signal.trap("TERM") do
|
45
|
+
EventMachine.stop
|
46
|
+
end
|
47
|
+
Solargraph::LanguageServer::Transport::Stdio.run
|
48
|
+
STDERR.puts "Solargraph is listening on stdio PID=#{Process.pid}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
38
52
|
desc 'suggest', 'Get code suggestions for the provided input'
|
39
53
|
long_desc <<-LONGDESC
|
40
54
|
Analyze a Ruby file and output a list of code suggestions in JSON format.
|
@@ -227,6 +227,18 @@ module Solargraph
|
|
227
227
|
@base_literal
|
228
228
|
end
|
229
229
|
|
230
|
+
def literal?
|
231
|
+
!literal.nil?
|
232
|
+
end
|
233
|
+
|
234
|
+
def literal
|
235
|
+
if @literal.nil? and !@calculated_actual_literal
|
236
|
+
@calculated_actual_literal = true
|
237
|
+
pn = @source.node_at(line, column)
|
238
|
+
@literal = infer_literal_node_type(pn)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
230
242
|
private
|
231
243
|
|
232
244
|
# @return [Integer]
|
data/lib/solargraph/version.rb
CHANGED
@@ -88,9 +88,7 @@ module Solargraph
|
|
88
88
|
def process_globs globs
|
89
89
|
result = []
|
90
90
|
globs.each do |glob|
|
91
|
-
Dir[File.join workspace, glob].
|
92
|
-
result.push File.realdirpath(f).gsub(/\\/, '/')
|
93
|
-
end
|
91
|
+
result.concat Dir[File.join workspace, glob].map{ |f| f.gsub(/\\/, '/') }
|
94
92
|
end
|
95
93
|
result
|
96
94
|
end
|
@@ -98,7 +96,7 @@ module Solargraph
|
|
98
96
|
def process_exclusions globs
|
99
97
|
remainder = globs.select do |glob|
|
100
98
|
if glob_is_directory?(glob)
|
101
|
-
exdir = File.
|
99
|
+
exdir = File.join(workspace, glob_to_directory(glob))
|
102
100
|
included.delete_if { |file| file.start_with?(exdir) }
|
103
101
|
false
|
104
102
|
else
|
data/lib/solargraph/yard_map.rb
CHANGED
@@ -238,6 +238,8 @@ module Solargraph
|
|
238
238
|
end
|
239
239
|
|
240
240
|
def objects path, space = ''
|
241
|
+
cached = cache.get_objects(path, space)
|
242
|
+
return cached unless cached.nil?
|
241
243
|
result = []
|
242
244
|
yardocs.each { |y|
|
243
245
|
yard = load_yardoc(y)
|
@@ -251,6 +253,7 @@ module Solargraph
|
|
251
253
|
@stdlib_namespaces.each do |ns|
|
252
254
|
result.push Pin::YardObject.new(ns, object_location(ns)) if ns.path == path
|
253
255
|
end
|
256
|
+
cache.set_objects(path, space, result)
|
254
257
|
result
|
255
258
|
end
|
256
259
|
|
@@ -272,6 +275,7 @@ module Solargraph
|
|
272
275
|
|
273
276
|
private
|
274
277
|
|
278
|
+
# @return [Solargraph::YardMap::Cache]
|
275
279
|
def cache
|
276
280
|
@cache ||= Cache.new
|
277
281
|
end
|
@@ -4,6 +4,7 @@ module Solargraph
|
|
4
4
|
@constants = {}
|
5
5
|
@methods = {}
|
6
6
|
@instance_methods = {}
|
7
|
+
@objects = {}
|
7
8
|
end
|
8
9
|
|
9
10
|
def set_constants namespace, scope, suggestions
|
@@ -30,5 +31,12 @@ module Solargraph
|
|
30
31
|
@instance_methods[[namespace, scope, visibility]]
|
31
32
|
end
|
32
33
|
|
34
|
+
def set_objects path, space, pins
|
35
|
+
@objects[[path, space]] = pins
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_objects path, space
|
39
|
+
@objects[[path, space]]
|
40
|
+
end
|
33
41
|
end
|
34
42
|
end
|
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.23.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fred Snyder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-07-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|
@@ -295,6 +295,7 @@ files:
|
|
295
295
|
- lib/solargraph/language_server/transport.rb
|
296
296
|
- lib/solargraph/language_server/transport/data_reader.rb
|
297
297
|
- lib/solargraph/language_server/transport/socket.rb
|
298
|
+
- lib/solargraph/language_server/transport/stdio.rb
|
298
299
|
- lib/solargraph/language_server/uri_helpers.rb
|
299
300
|
- lib/solargraph/library.rb
|
300
301
|
- lib/solargraph/live_map.rb
|