solargraph 0.22.0 → 0.23.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|