solargraph 0.20.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/lib/solargraph.rb +2 -3
  3. data/lib/solargraph/api_map.rb +6 -6
  4. data/lib/solargraph/api_map/source_to_yard.rb +1 -1
  5. data/lib/solargraph/language_server/host.rb +69 -10
  6. data/lib/solargraph/language_server/message.rb +1 -2
  7. data/lib/solargraph/language_server/message/initialize.rb +83 -15
  8. data/lib/solargraph/language_server/message/initialized.rb +7 -0
  9. data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -1
  10. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +20 -19
  11. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +19 -1
  12. data/lib/solargraph/language_server/request.rb +1 -1
  13. data/lib/solargraph/language_server/transport.rb +1 -0
  14. data/lib/solargraph/language_server/transport/data_reader.rb +66 -0
  15. data/lib/solargraph/language_server/transport/socket.rb +8 -32
  16. data/lib/solargraph/library.rb +11 -6
  17. data/lib/solargraph/page.rb +1 -1
  18. data/lib/solargraph/pin/base.rb +8 -7
  19. data/lib/solargraph/pin/method_parameter.rb +2 -15
  20. data/lib/solargraph/pin/yard_object.rb +1 -1
  21. data/lib/solargraph/plugin/runtime.rb +0 -2
  22. data/lib/solargraph/shell.rb +0 -24
  23. data/lib/solargraph/source.rb +5 -169
  24. data/lib/solargraph/source/mapper.rb +8 -3
  25. data/lib/solargraph/version.rb +1 -1
  26. data/lib/solargraph/workspace.rb +3 -3
  27. data/lib/solargraph/workspace/config.rb +7 -9
  28. data/lib/solargraph/yard_map.rb +9 -48
  29. metadata +17 -74
  30. data/lib/solargraph/server.rb +0 -212
  31. data/lib/solargraph/suggestion.rb +0 -178
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e1a1a75c9706d5d54ca2359b21bf336b9980bce
4
- data.tar.gz: 618ae6ec9b01ddd2ee7656a34c787cc6b26bfc0b
3
+ metadata.gz: 04dd49e264774d545fbdf1a7f52d0b7227ff3f11
4
+ data.tar.gz: cb617a8800b2eec8688c46fc89cf4ee79445dd50
5
5
  SHA512:
6
- metadata.gz: 7ab817f132710bdb79f93773937cb8280dd764b07e7bd29f4b33064e097690a192afc219f6bbcf69b00d3ca1257cb8a6e90db91c9c8ee3109fa522f6ea054474
7
- data.tar.gz: ccb208a618f8c891c6bfd102e45bd65a31307abc87bb51cd738ed64582eb0e1a45adbc4ba7e7248de64b5cc6760dfa68370eb6f883c63a18c340a2657e38a4b3
6
+ metadata.gz: db20a5e3053060171bf9077c1ce572de8428193b4d562c7d939c9a7003074de64f41ffe879100b7f7a31bb42f625a32e69ad7755afc68b8c31d2cc64d15be353
7
+ data.tar.gz: bb9a311819e91501145c05fc2045178a791933fb6f9598e6265f68efe301664cbb6bfa50170928989d1fd8543a726cd36e0079b2f650c2ded36f9ad3a66c92c6
@@ -1,7 +1,6 @@
1
1
  require 'solargraph/version'
2
2
  require 'rubygems/package'
3
3
  require 'yard-solargraph'
4
- require 'sinatra'
5
4
 
6
5
  module Solargraph
7
6
  class InvalidOffsetError < RangeError; end
@@ -11,6 +10,8 @@ module Solargraph
11
10
 
12
11
  class WorkspaceTooLargeError < RuntimeError
13
12
  attr_reader :size
13
+
14
+ # @param size [Integer] The number of files included in the workspace
14
15
  def initialize size
15
16
  @size = size
16
17
  end
@@ -20,8 +21,6 @@ module Solargraph
20
21
  autoload :Source, 'solargraph/source'
21
22
  autoload :ApiMap, 'solargraph/api_map'
22
23
  autoload :NodeMethods, 'solargraph/node_methods'
23
- autoload :Suggestion, 'solargraph/suggestion'
24
- autoload :Server, 'solargraph/server'
25
24
  autoload :YardMap, 'solargraph/yard_map'
26
25
  autoload :Pin, 'solargraph/pin'
27
26
  autoload :LiveMap, 'solargraph/live_map'
@@ -57,6 +57,7 @@ module Solargraph
57
57
  @sources.each do |s|
58
58
  result.concat s.required.map(&:name)
59
59
  end
60
+ result.concat workspace.config.required
60
61
  result.uniq
61
62
  end
62
63
 
@@ -341,7 +342,9 @@ module Solargraph
341
342
  def signify fragment
342
343
  return [] unless fragment.argument?
343
344
  return [] if fragment.recipient.whole_signature.nil? or fragment.recipient.whole_signature.empty?
344
- probe.infer_signature_pins fragment.recipient.whole_signature, fragment.named_path, fragment.locals
345
+ probe.infer_signature_pins(
346
+ fragment.recipient.whole_signature, fragment.named_path, fragment.locals
347
+ ).select{ |pin| pin.kind == Pin::METHOD }
345
348
  end
346
349
 
347
350
  # Get an array of all suggestions that match the specified path.
@@ -471,11 +474,8 @@ module Solargraph
471
474
  end
472
475
  result.concat yard_map.get_methods(fqns, '', visibility: visibility)
473
476
  type = get_namespace_type(fqns)
474
- if type == :class
475
- result.concat inner_get_methods('Class', :instance, [:public], deep, skip)
476
- else
477
- result.concat inner_get_methods('Module', :instance, [:public], deep, skip)
478
- end
477
+ result.concat inner_get_methods('Class', :instance, fqns == '' ? [:public] : visibility, deep, skip) if type == :class
478
+ result.concat inner_get_methods('Module', :instance, fqns == '' ? [:public] : visibility, deep, skip)
479
479
  end
480
480
  end
481
481
  result
@@ -19,7 +19,7 @@ module Solargraph
19
19
  sources.each do |s|
20
20
  s.namespace_pins.each do |pin|
21
21
  next if pin.path.empty?
22
- if pin.kind == Solargraph::Suggestion::CLASS
22
+ if pin.type == :class
23
23
  code_object_map[pin.path] ||= YARD::CodeObjects::ClassObject.new(root_code_object, pin.path)
24
24
  else
25
25
  code_object_map[pin.path] ||= YARD::CodeObjects::ModuleObject.new(root_code_object, pin.path)
@@ -33,7 +33,7 @@ module Solargraph
33
33
 
34
34
  # @return [Hash]
35
35
  def options
36
- @options ||= {}
36
+ @options ||= default_configuration
37
37
  end
38
38
 
39
39
  def cancel id
@@ -54,7 +54,7 @@ module Solargraph
54
54
  # processed, the transport is responsible for sending the response.
55
55
  #
56
56
  # @param request [Hash] The contents of the message.
57
- # @return [Solargraph::LanguageServer::Message] The message handler.
57
+ # @return [Solargraph::LanguageServer::Message::Base] The message handler.
58
58
  def start request
59
59
  if request['method']
60
60
  message = Message.select(request['method']).new(self, request)
@@ -214,10 +214,12 @@ module Solargraph
214
214
  end
215
215
 
216
216
  # Send a request to the client and execute the provided block to process
217
- # the response.
217
+ # the response. If an ID is not provided, the host will use an auto-
218
+ # incrementing integer.
218
219
  #
219
220
  # @param method [String] The message method
220
221
  # @param params [Hash] The method parameters
222
+ # @param id [String] An optional ID
221
223
  # @yieldparam [Hash] The result sent by the client
222
224
  def send_request method, params, &block
223
225
  message = {
@@ -233,6 +235,29 @@ module Solargraph
233
235
  @next_request_id += 1
234
236
  end
235
237
 
238
+ def register_capabilities methods
239
+ send_request 'client/registerCapability', {
240
+ registrations: methods.map { |m|
241
+ {
242
+ id: m,
243
+ method: m,
244
+ registerOptions: dynamic_capability_options[m]
245
+ }
246
+ }
247
+ }
248
+ end
249
+
250
+ def unregister_capabilities methods
251
+ send_request 'client/unregisterCapability', {
252
+ unregisterations: methods.map { |m|
253
+ {
254
+ id: m,
255
+ method: m
256
+ }
257
+ }
258
+ }
259
+ end
260
+
236
261
  # True if the specified file is in the process of changing.
237
262
  #
238
263
  # @return [Boolean]
@@ -343,6 +368,16 @@ module Solargraph
343
368
  requests.keys
344
369
  end
345
370
 
371
+ def default_configuration
372
+ {
373
+ 'completion' => true,
374
+ 'hover' => true,
375
+ 'autoformat' => false,
376
+ 'diagnostics' => false,
377
+ 'formatting' => false
378
+ }
379
+ end
380
+
346
381
  private
347
382
 
348
383
  # @return [Solargraph::Library]
@@ -412,13 +447,13 @@ module Solargraph
412
447
  diagnoser = Diagnostics::Rubocop.new
413
448
  until stopped?
414
449
  sleep 1
415
- if options['diagnostics'] != 'rubocop'
450
+ if !options['diagnostics']
416
451
  @change_semaphore.synchronize { @diagnostics_queue.clear }
417
452
  next
418
453
  end
419
454
  begin
420
- # Diagnosis is broken into two parts to reduce the amount of times it runs while
421
- # a document is changing
455
+ # Diagnosis is broken into two parts to reduce the number of
456
+ # times it runs while a document is changing
422
457
  current = nil
423
458
  already_changing = nil
424
459
  @change_semaphore.synchronize do
@@ -429,13 +464,9 @@ module Solargraph
429
464
  end
430
465
  next if current.nil? or already_changing
431
466
  filename = uri_to_file(current)
432
- # text = library.read_text(filename)
433
- # results = diagnoser.diagnose text, filename
434
- # results.concat library.diagnose(filename)
435
467
  results = library.diagnose(filename)
436
468
  @change_semaphore.synchronize do
437
469
  already_changing = (unsafe_changing?(current) or @diagnostics_queue.include?(current))
438
- # publish_diagnostics current, resp unless already_changing
439
470
  unless already_changing
440
471
  send_notification "textDocument/publishDiagnostics", {
441
472
  uri: current,
@@ -480,6 +511,34 @@ module Solargraph
480
511
  changes
481
512
  )
482
513
  end
514
+
515
+ def dynamic_capability_options
516
+ @dynamic_capability_options ||= {
517
+ # textDocumentSync: 2, # @todo What should this be?
518
+ 'textDocument/completion' => {
519
+ resolveProvider: true,
520
+ triggerCharacters: ['.', ':', '@']
521
+ },
522
+ # hoverProvider: true,
523
+ # definitionProvider: true,
524
+ 'textDocument/signatureHelp' => {
525
+ triggerCharacters: ['(', ',']
526
+ },
527
+ # documentFormattingProvider: true,
528
+ 'textDocument/onTypeFormatting' => {
529
+ firstTriggerCharacter: '{',
530
+ moreTriggerCharacter: ['(']
531
+ },
532
+ # documentSymbolProvider: true,
533
+ # workspaceSymbolProvider: true,
534
+ # workspace: {
535
+ # workspaceFolders: {
536
+ # supported: true,
537
+ # changeNotifications: true
538
+ # }
539
+ # }
540
+ }
541
+ end
483
542
  end
484
543
  end
485
544
  end
@@ -24,14 +24,13 @@ module Solargraph
24
24
  end
25
25
 
26
26
  # @param path [String]
27
- # @return [Solargraph::LanguageServer::Message::Base]
27
+ # @return [Class<Solargraph::LanguageServer::Message::Base>]
28
28
  def select path
29
29
  if method_map.has_key?(path)
30
30
  method_map[path]
31
31
  elsif path.start_with?('$/')
32
32
  MethodNotImplemented
33
33
  else
34
- STDERR.puts "Method not found: #{path}"
35
34
  MethodNotFound
36
35
  end
37
36
  end
@@ -5,23 +5,10 @@ module Solargraph
5
5
  def process
6
6
  host.configure params['initializationOptions']
7
7
  host.prepare params['rootPath']
8
- set_result(
8
+ result = {
9
9
  capabilities: {
10
10
  textDocumentSync: 2, # @todo What should this be?
11
- completionProvider: {
12
- resolveProvider: true,
13
- triggerCharacters: ['.', ':', '@']
14
- },
15
- hoverProvider: true,
16
11
  definitionProvider: true,
17
- signatureHelpProvider: {
18
- triggerCharacters: ['(', ',']
19
- },
20
- documentFormattingProvider: true,
21
- documentOnTypeFormattingProvider: {
22
- firstTriggerCharacter: '{',
23
- moreTriggerCharacter: ['(']
24
- },
25
12
  documentSymbolProvider: true,
26
13
  workspaceSymbolProvider: true,
27
14
  workspace: {
@@ -31,7 +18,88 @@ module Solargraph
31
18
  }
32
19
  }
33
20
  }
34
- )
21
+ }
22
+ result[:capabilities].merge! static_completion unless dynamic_completion?
23
+ result[:capabilities].merge! static_signature_help unless dynamic_signature_help?
24
+ result[:capabilities].merge! static_on_type_formatting unless dynamic_on_type_formatting?
25
+ result[:capabilities].merge! static_hover unless dynamic_hover?
26
+ result[:capabilities].merge! static_document_formatting unless dynamic_document_formatting?
27
+ set_result result
28
+ end
29
+
30
+ private
31
+
32
+ def static_completion
33
+ {
34
+ completionProvider: {
35
+ resolveProvider: true,
36
+ triggerCharacters: ['.', ':', '@']
37
+ }
38
+ }
39
+ end
40
+
41
+ def dynamic_completion?
42
+ params['capabilities'] and
43
+ params['capabilities']['textDocument'] and
44
+ params['capabilities']['textDocument']['completion'] and
45
+ params['capabilities']['textDocument']['completion']['dynamicRegistration']
46
+ end
47
+
48
+ def static_signature_help
49
+ {
50
+ signatureHelpProvider: {
51
+ triggerCharacters: ['(', ',']
52
+ }
53
+ }
54
+ end
55
+
56
+ def dynamic_signature_help?
57
+ params['capabilities'] and
58
+ params['capabilities']['textDocument'] and
59
+ params['capabilities']['textDocument']['signatureHelp'] and
60
+ params['capabilities']['textDocument']['signatureHelp']['dynamicRegistration']
61
+ end
62
+
63
+ def static_on_type_formatting
64
+ {
65
+ documentOnTypeFormattingProvider: {
66
+ firstTriggerCharacter: '{',
67
+ moreTriggerCharacter: ['(']
68
+ }
69
+ }
70
+ end
71
+
72
+ def dynamic_on_type_formatting?
73
+ params['capabilities'] and
74
+ params['capabilities']['textDocument'] and
75
+ params['capabilities']['textDocument']['onTypeFormatting'] and
76
+ params['capabilities']['textDocument']['onTypeFormatting']['dynamicRegistration']
77
+ end
78
+
79
+ def static_hover
80
+ {
81
+ hoverProvider: true
82
+ }
83
+ end
84
+
85
+ def dynamic_hover?
86
+ params['capabilities'] and
87
+ params['capabilities']['textDocument'] and
88
+ params['capabilities']['textDocument']['hover'] and
89
+ params['capabilities']['textDocument']['hover']['dynamicRegistration']
90
+ end
91
+
92
+ def static_document_formatting
93
+ {
94
+ documentFormattingProvider: true
95
+ }
96
+ end
97
+
98
+ def dynamic_document_formatting?
99
+ params['capabilities'] and
100
+ params['capabilities']['textDocument'] and
101
+ params['capabilities']['textDocument']['hover'] and
102
+ params['capabilities']['textDocument']['hover']['dynamicRegistration']
35
103
  end
36
104
  end
37
105
  end
@@ -3,6 +3,13 @@ module Solargraph
3
3
  module Message
4
4
  class Initialized < Base
5
5
  def process
6
+ meths = []
7
+ meths.push 'textDocument/completion' if host.options['completion']
8
+ meths.push 'textDocument/hover' if host.options['hover']
9
+ meths.push 'textDocument/signatureHelp' if host.options['hover']
10
+ meths.push 'textDocument/onTypeFormatting' if host.options['autoformat']
11
+ meths.push 'textDocument/formatting' if host.options['formatting']
12
+ host.register_capabilities meths unless meths.empty?
6
13
  end
7
14
  end
8
15
  end
@@ -7,10 +7,13 @@ module Solargraph
7
7
  class Formatting < Base
8
8
  def process
9
9
  filename = uri_to_file(params['textDocument']['uri'])
10
+ filename = 'tmp.rb' if filename.nil? or filename.empty?
10
11
  original = host.read_text(params['textDocument']['uri'])
11
12
  cmd = "rubocop -a -f fi -s #{Shellwords.escape(filename)}"
12
13
  o, e, s = Open3.capture3(cmd, stdin_data: original)
13
- formatted = o.lines[2..-1].join
14
+ lines = o.lines
15
+ index = lines.index{|l| l.start_with?('====================')}
16
+ formatted = lines[index+1..-1].join
14
17
  set_result(
15
18
  [
16
19
  {
@@ -4,25 +4,26 @@ module Solargraph
4
4
  module TextDocument
5
5
  class OnTypeFormatting < Base
6
6
  def process
7
- src = host.send(:library).checkout(uri_to_file(params['textDocument']['uri']))
8
- fragment = src.fragment_at(params['position']['line'], params['position']['character'] - 1)
9
- offset = fragment.send(:offset)
10
- if fragment.string? and params['ch'] == '{' and src.code[offset-1,2] == '#{'
11
- set_result(
12
- [
13
- {
14
- range: {
15
- start: params['position'],
16
- end: params['position']
17
- },
18
- newText: '}'
19
- }
20
- ]
21
- )
22
- else
23
- # @todo Is `nil` or `[]` more appropriate here?
24
- set_result nil
25
- end
7
+ # @todo Temporarily disabled due to conflicts with VSCode formatting on type
8
+ # src = host.send(:library).checkout(uri_to_file(params['textDocument']['uri']))
9
+ # fragment = src.fragment_at(params['position']['line'], params['position']['character'] - 1)
10
+ # offset = fragment.send(:offset)
11
+ # if fragment.string? and params['ch'] == '{' and src.code[offset - 1, 2] == '#{'
12
+ # set_result(
13
+ # [
14
+ # {
15
+ # range: {
16
+ # start: params['position'],
17
+ # end: params['position']
18
+ # },
19
+ # newText: '}'
20
+ # }
21
+ # ]
22
+ # )
23
+ # else
24
+ # # @todo Is `nil` or `[]` more appropriate here?
25
+ # set_result nil
26
+ # end
26
27
  end
27
28
  end
28
29
  end
@@ -3,7 +3,25 @@ require 'uri'
3
3
  module Solargraph::LanguageServer::Message::Workspace
4
4
  class DidChangeConfiguration < Solargraph::LanguageServer::Message::Base
5
5
  def process
6
- host.configure params['settings']['solargraph']
6
+ update = params['settings']['solargraph']
7
+
8
+ meths = []
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?
23
+
24
+ host.configure update
7
25
  end
8
26
  end
9
27
  end