solargraph 0.25.1 → 0.26.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/lib/solargraph.rb +18 -16
  3. data/lib/solargraph/api_map.rb +100 -161
  4. data/lib/solargraph/api_map/source_to_yard.rb +9 -9
  5. data/lib/solargraph/api_map/store.rb +50 -13
  6. data/lib/solargraph/basic_type.rb +33 -0
  7. data/lib/solargraph/basic_type_methods.rb +111 -0
  8. data/lib/solargraph/complex_type.rb +51 -89
  9. data/lib/solargraph/core_fills.rb +12 -8
  10. data/lib/solargraph/diagnostics/type_not_defined.rb +2 -2
  11. data/lib/solargraph/language_server.rb +3 -0
  12. data/lib/solargraph/language_server/completion_item_kinds.rb +2 -0
  13. data/lib/solargraph/language_server/error_codes.rb +2 -0
  14. data/lib/solargraph/language_server/host.rb +53 -6
  15. data/lib/solargraph/language_server/message.rb +13 -0
  16. data/lib/solargraph/language_server/message/text_document/definition.rb +4 -6
  17. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +2 -1
  18. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -1
  19. data/lib/solargraph/language_server/message_types.rb +2 -0
  20. data/lib/solargraph/language_server/request.rb +4 -0
  21. data/lib/solargraph/language_server/symbol_kinds.rb +28 -26
  22. data/lib/solargraph/language_server/transport.rb +3 -0
  23. data/lib/solargraph/language_server/uri_helpers.rb +2 -0
  24. data/lib/solargraph/library.rb +12 -7
  25. data/lib/solargraph/pin.rb +1 -1
  26. data/lib/solargraph/pin/attribute.rb +5 -5
  27. data/lib/solargraph/pin/base.rb +51 -16
  28. data/lib/solargraph/pin/base_variable.rb +25 -7
  29. data/lib/solargraph/pin/block.rb +18 -1
  30. data/lib/solargraph/pin/block_parameter.rb +42 -5
  31. data/lib/solargraph/pin/conversions.rb +4 -2
  32. data/lib/solargraph/pin/method.rb +6 -6
  33. data/lib/solargraph/pin/method_parameter.rb +6 -6
  34. data/lib/solargraph/pin/namespace.rb +7 -2
  35. data/lib/solargraph/pin/proxy_type.rb +39 -0
  36. data/lib/solargraph/pin/symbol.rb +20 -12
  37. data/lib/solargraph/pin/yard_pin/method.rb +2 -2
  38. data/lib/solargraph/source.rb +89 -38
  39. data/lib/solargraph/source/call_chainer.rb +273 -0
  40. data/lib/solargraph/source/chain.rb +104 -0
  41. data/lib/solargraph/source/chain/call.rb +72 -0
  42. data/lib/solargraph/source/chain/class_variable.rb +11 -0
  43. data/lib/solargraph/source/chain/constant.rb +17 -0
  44. data/lib/solargraph/source/chain/definition.rb +16 -0
  45. data/lib/solargraph/source/chain/global_variable.rb +11 -0
  46. data/lib/solargraph/source/chain/head.rb +20 -0
  47. data/lib/solargraph/source/chain/instance_variable.rb +11 -0
  48. data/lib/solargraph/source/chain/link.rb +33 -0
  49. data/lib/solargraph/source/chain/literal.rb +21 -0
  50. data/lib/solargraph/source/chain/variable.rb +11 -0
  51. data/lib/solargraph/source/change.rb +3 -1
  52. data/lib/solargraph/{api_map → source}/completion.rb +3 -1
  53. data/lib/solargraph/source/encoding_fixes.rb +21 -0
  54. data/lib/solargraph/source/fragment.rb +139 -284
  55. data/lib/solargraph/source/mapper.rb +27 -16
  56. data/lib/solargraph/source/node_chainer.rb +94 -0
  57. data/lib/solargraph/source/node_methods.rb +2 -2
  58. data/lib/solargraph/source/position.rb +4 -0
  59. data/lib/solargraph/source/range.rb +10 -2
  60. data/lib/solargraph/version.rb +1 -1
  61. data/lib/solargraph/yard_map.rb +13 -2
  62. metadata +20 -6
  63. data/lib/solargraph/api_map/probe.rb +0 -251
  64. data/lib/solargraph/api_map/type_methods.rb +0 -40
  65. data/lib/solargraph/pin/proxy_method.rb +0 -30
@@ -8,17 +8,21 @@ module Solargraph
8
8
  'then', 'true', 'undef', 'unless', 'until', 'when', 'while', 'yield'
9
9
  ].freeze
10
10
 
11
- METHODS_RETURNING_SELF = %w{
11
+ METHODS_RETURNING_SELF = %w[
12
+ Array#select Array#reject Array#keep_if Array#delete_if
13
+ Enumerable#select
12
14
  Object#clone Object#dup Object#freeze Object#taint Object#untaint
13
- }.freeze
15
+ ].freeze
14
16
 
15
- METHODS_RETURNING_SUBTYPES = %w{
16
- Array#[]
17
- }.freeze
17
+ METHODS_RETURNING_SUBTYPES = %w[
18
+ Array#[] Array#first Array#last
19
+ ].freeze
18
20
 
19
- METHODS_WITH_YIELDPARAM_SUBTYPES = %w{
20
- Array#each Hash#each_pair Array#map
21
- }.freeze
21
+ METHODS_WITH_YIELDPARAM_SUBTYPES = %w[
22
+ Array#each Array#map Array#any? Array#all?
23
+ Enumerable#each_entry Enumerable#map Enumerable#any? Enumerable#all?
24
+ Set#each
25
+ ].freeze
22
26
 
23
27
  CUSTOM_RETURN_TYPES = {
24
28
  'String#split' => 'Array<String>'
@@ -73,10 +73,10 @@ module Solargraph
73
73
  end
74
74
 
75
75
  def defined_return_type? pin, api_map
76
- return true unless pin.return_type.nil?
76
+ return true unless pin.return_complex_type.undefined?
77
77
  matches = api_map.get_method_stack(pin.namespace, pin.name, scope: pin.scope)
78
78
  matches.shift
79
- matches.any?{|m| !m.return_type.nil?}
79
+ matches.any?{|m| !m.return_complex_type.undefined?}
80
80
  end
81
81
 
82
82
  def defined_param_type? pin, param, api_map
@@ -3,6 +3,9 @@ require 'solargraph/language_server/completion_item_kinds'
3
3
  require 'solargraph/language_server/symbol_kinds'
4
4
 
5
5
  module Solargraph
6
+ # The LanguageServer namespace contains the classes and modules that compose
7
+ # concrete implementations of language servers.
8
+ #
6
9
  module LanguageServer
7
10
  autoload :Host, 'solargraph/language_server/host'
8
11
  autoload :Message, 'solargraph/language_server/message'
@@ -1,5 +1,7 @@
1
1
  module Solargraph
2
2
  module LanguageServer
3
+ # The CompletionItemKind constants for the language server protocol.
4
+ #
3
5
  module CompletionItemKinds
4
6
  TEXT = 1
5
7
  METHOD = 2
@@ -1,5 +1,7 @@
1
1
  module Solargraph
2
2
  module LanguageServer
3
+ # The ErrorCode constants for the language server protocol.
4
+ #
3
5
  module ErrorCodes
4
6
  PARSE_ERROR = -32700
5
7
  INVALID_REQUEST = -32600
@@ -136,7 +136,7 @@ module Solargraph
136
136
  def open? uri
137
137
  result = nil
138
138
  @change_semaphore.synchronize do
139
- result = library.open?(uri_to_file(uri))
139
+ result = unsafe_open?(uri)
140
140
  end
141
141
  result
142
142
  end
@@ -343,7 +343,7 @@ module Solargraph
343
343
  def locate_pin params
344
344
  pin = nil
345
345
  @change_semaphore.synchronize do
346
- pin = library.locate_pin(params['data']['location']) unless params['data']['location'].nil?
346
+ pin = library.locate_pin(params['data']['location']).first unless params['data']['location'].nil?
347
347
  # @todo Improve pin location
348
348
  if pin.nil? or pin.path != params['data']['path']
349
349
  pin = library.path_pins(params['data']['path']).first
@@ -352,6 +352,8 @@ module Solargraph
352
352
  pin
353
353
  end
354
354
 
355
+ # @param uri [String]
356
+ # @return [String]
355
357
  def read_text uri
356
358
  filename = uri_to_file(uri)
357
359
  text = nil
@@ -361,6 +363,10 @@ module Solargraph
361
363
  text
362
364
  end
363
365
 
366
+ # @param filename [String]
367
+ # @param line [Integer]
368
+ # @param column [Integer]
369
+ # @return [Solargraph::ApiMap::Completion]
364
370
  def completions_at filename, line, column
365
371
  result = nil
366
372
  @change_semaphore.synchronize do
@@ -369,6 +375,9 @@ module Solargraph
369
375
  result
370
376
  end
371
377
 
378
+ # @param filename [String]
379
+ # @param line [Integer]
380
+ # @param column [Integer]
372
381
  # @return [Array<Solargraph::Pin::Base>]
373
382
  def definitions_at filename, line, column
374
383
  result = []
@@ -378,6 +387,10 @@ module Solargraph
378
387
  result
379
388
  end
380
389
 
390
+ # @param filename [String]
391
+ # @param line [Integer]
392
+ # @param column [Integer]
393
+ # @return [Array<Solargraph::Pin::Base>]
381
394
  def signatures_at filename, line, column
382
395
  result = nil
383
396
  @change_semaphore.synchronize do
@@ -386,6 +399,10 @@ module Solargraph
386
399
  result
387
400
  end
388
401
 
402
+ # @param filename [String]
403
+ # @param line [Integer]
404
+ # @param column [Integer]
405
+ # @return [Array<Solargraph::Source::Range>]
389
406
  def references_from filename, line, column
390
407
  result = nil
391
408
  @change_semaphore.synchronize do
@@ -394,18 +411,24 @@ module Solargraph
394
411
  result
395
412
  end
396
413
 
414
+ # @param query [String]
415
+ # @return [Array<Solargraph::Pin::Base>]
397
416
  def query_symbols query
398
417
  result = nil
399
418
  @change_semaphore.synchronize { result = library.query_symbols(query) }
400
419
  result
401
420
  end
402
421
 
422
+ # @param query [String]
423
+ # @return [Array<String>]
403
424
  def search query
404
425
  result = nil
405
426
  @change_semaphore.synchronize { result = library.search(query) }
406
427
  result
407
428
  end
408
429
 
430
+ # @param query [String]
431
+ # @return [String]
409
432
  def document query
410
433
  result = nil
411
434
  @change_semaphore.synchronize { result = library.document(query) }
@@ -418,6 +441,10 @@ module Solargraph
418
441
  library.file_symbols(uri_to_file(uri))
419
442
  end
420
443
 
444
+ # Send a notification to the client.
445
+ #
446
+ # @param text [String]
447
+ # @param type [Integer] A MessageType constant
421
448
  def show_message text, type = LanguageServer::MessageTypes::INFO
422
449
  send_notification 'window/showMessage', {
423
450
  type: type,
@@ -425,6 +452,13 @@ module Solargraph
425
452
  }
426
453
  end
427
454
 
455
+ # Send a notification with optional responses.
456
+ #
457
+ # @param text [String]
458
+ # @param type [Integer] A MessageType constant
459
+ # @param actions [Array<String>] Response options for the client
460
+ # @param &block The block that processes the response
461
+ # @yieldparam [String] The action received from the client
428
462
  def show_message_request text, type, actions, &block
429
463
  send_request 'window/showMessageRequest', {
430
464
  type: type,
@@ -441,6 +475,7 @@ module Solargraph
441
475
  requests.keys
442
476
  end
443
477
 
478
+ # @return [Hash{String => Object}]
444
479
  def default_configuration
445
480
  {
446
481
  'completion' => true,
@@ -462,10 +497,16 @@ module Solargraph
462
497
  @library
463
498
  end
464
499
 
500
+ # @param file_uri [String]
501
+ # @return [Boolean]
465
502
  def unsafe_changing? file_uri
466
503
  @change_queue.any?{|change| change['textDocument']['uri'] == file_uri}
467
504
  end
468
505
 
506
+ def unsafe_open? uri
507
+ library.open?(uri_to_file(uri))
508
+ end
509
+
469
510
  def requests
470
511
  @requests ||= {}
471
512
  end
@@ -509,9 +550,13 @@ module Solargraph
509
550
  @diagnostics_queue.push change['textDocument']['uri']
510
551
  next true
511
552
  else
512
- # @todo Change is out of order. Save it for later
513
- STDERR.puts "Skipping out of order change to #{change['textDocument']['uri']}"
514
- next false
553
+ if unsafe_open?(change['textDocument']['uri'])
554
+ STDERR.puts "Skipping out of order change to #{change['textDocument']['uri']}"
555
+ next false
556
+ else
557
+ STDERR.puts "Deleting out of order change to closed file #{change['textDocument']['uri']}"
558
+ next true
559
+ end
515
560
  end
516
561
  end
517
562
  refreshable = changed and @change_queue.empty?
@@ -520,9 +565,11 @@ module Solargraph
520
565
  # Trying to get anything out of the error except its class
521
566
  # hangs the thread for some reason
522
567
  STDERR.puts "An error occurred in the change thread: #{e.class}"
568
+ STDERR.puts e.backtrace
569
+ @change_queue.clear
523
570
  end
524
571
  end
525
- sleep 0.1
572
+ sleep 0.01
526
573
  end
527
574
  end
528
575
  end
@@ -3,6 +3,9 @@ require 'uri'
3
3
 
4
4
  module Solargraph
5
5
  module LanguageServer
6
+ # The Message namespace contains classes that implement language server
7
+ # protocol methods.
8
+ #
6
9
  module Message
7
10
  autoload :Base, 'solargraph/language_server/message/base'
8
11
  autoload :Initialize, 'solargraph/language_server/message/initialize'
@@ -18,6 +21,15 @@ module Solargraph
18
21
  autoload :Workspace, 'solargraph/language_server/message/workspace'
19
22
 
20
23
  class << self
24
+ # Register a method name and message for handling by the language
25
+ # server.
26
+ #
27
+ # @example
28
+ # Message.register 'initialize', Solargraph::Message::Initialize
29
+ #
30
+ # @param path [String] The method name
31
+ # @param message_class [Class<Message::Base>] The message class
32
+ # @return [void]
21
33
  def register path, message_class
22
34
  method_map[path] = message_class
23
35
  end
@@ -36,6 +48,7 @@ module Solargraph
36
48
 
37
49
  private
38
50
 
51
+ # @return [Hash{String => Class<Message::Base>}]
39
52
  def method_map
40
53
  @method_map ||= {}
41
54
  end
@@ -12,12 +12,10 @@ module Solargraph::LanguageServer::Message::TextDocument
12
12
  col = params['position']['character']
13
13
  suggestions = host.definitions_at(filename, line, col)
14
14
  locations = suggestions.reject{|pin| pin.location.nil?}.map do |pin|
15
- unless pin.location.nil?
16
- {
17
- uri: file_to_uri(pin.location.filename),
18
- range: pin.location.range.to_hash
19
- }
20
- end
15
+ {
16
+ uri: file_to_uri(pin.location.filename),
17
+ range: pin.location.range.to_hash
18
+ }
21
19
  end
22
20
  set_result locations
23
21
  end
@@ -11,7 +11,8 @@ class Solargraph::LanguageServer::Message::TextDocument::DocumentSymbol < Solarg
11
11
  location: {
12
12
  uri: file_to_uri(pin.location.filename),
13
13
  range: pin.location.range.to_hash
14
- }
14
+ },
15
+ deprecated: pin.deprecated?
15
16
  }
16
17
  result
17
18
  end
@@ -12,7 +12,8 @@ class Solargraph::LanguageServer::Message::Workspace::WorkspaceSymbol < Solargra
12
12
  location: {
13
13
  uri: uri,
14
14
  range: pin.location.range.to_hash
15
- }
15
+ },
16
+ deprecated: pin.deprecated?
16
17
  }
17
18
  end
18
19
  set_result info
@@ -1,5 +1,7 @@
1
1
  module Solargraph
2
2
  module LanguageServer
3
+ # The MessageType constants from the language server specification.
4
+ #
3
5
  module MessageTypes
4
6
  ERROR = 1
5
7
  WARNING = 2
@@ -1,11 +1,15 @@
1
1
  module Solargraph
2
2
  module LanguageServer
3
3
  class Request
4
+ # @param id [Integer]
5
+ # @param &block The block that processes the client's response
4
6
  def initialize id, &block
5
7
  @id = id
6
8
  @block = block
7
9
  end
8
10
 
11
+ # @param result [Object]
12
+ # @return [void]
9
13
  def process result
10
14
  @block.call(result) unless @block.nil?
11
15
  end
@@ -1,32 +1,34 @@
1
1
  module Solargraph
2
2
  module LanguageServer
3
+ # The SymbolKind constants for the language server protocol.
4
+ #
3
5
  module SymbolKinds
4
- FILE = 1;
5
- MODULE = 2;
6
- NAMESPACE = 3;
7
- PACKAGE = 4;
8
- CLASS = 5;
9
- METHOD = 6;
10
- PROPERTY = 7;
11
- FIELD = 8;
12
- CONSTRUCTOR = 9;
13
- ENUM = 10;
14
- INTERFACE = 11;
15
- FUNCTION = 12;
16
- VARIABLE = 13;
17
- CONSTANT = 14;
18
- STRING = 15;
19
- NUMBER = 16;
20
- BOOLEAN = 17;
21
- ARRAY = 18;
22
- OBJECT = 19;
23
- KEY = 20;
24
- NULL = 21;
25
- ENUM_MEMBER = 22;
26
- STRUCT = 23;
27
- EVENT = 24;
28
- OPERATOR = 25;
29
- TYPE_PARAMETER = 26;
6
+ FILE = 1
7
+ MODULE = 2
8
+ NAMESPACE = 3
9
+ PACKAGE = 4
10
+ CLASS = 5
11
+ METHOD = 6
12
+ PROPERTY = 7
13
+ FIELD = 8
14
+ CONSTRUCTOR = 9
15
+ ENUM = 10
16
+ INTERFACE = 11
17
+ FUNCTION = 12
18
+ VARIABLE = 13
19
+ CONSTANT = 14
20
+ STRING = 15
21
+ NUMBER = 16
22
+ BOOLEAN = 17
23
+ ARRAY = 18
24
+ OBJECT = 19
25
+ KEY = 20
26
+ NULL = 21
27
+ ENUM_MEMBER = 22
28
+ STRUCT = 23
29
+ EVENT = 24
30
+ OPERATOR = 25
31
+ TYPE_PARAMETER = 26
30
32
  end
31
33
  end
32
34
  end
@@ -1,5 +1,8 @@
1
1
  module Solargraph
2
2
  module LanguageServer
3
+ # The Transport namespace contains concrete implementations of
4
+ # communication protocols for language servers.
5
+ #
3
6
  module Transport
4
7
  autoload :DataReader, 'solargraph/language_server/transport/data_reader'
5
8
  autoload :Socket, 'solargraph/language_server/transport/socket'
@@ -1,5 +1,7 @@
1
1
  module Solargraph
2
2
  module LanguageServer
3
+ # Methods to handle conversions between file URIs and paths.
4
+ #
3
5
  module UriHelpers
4
6
  module_function
5
7
 
@@ -114,7 +114,7 @@ module Solargraph
114
114
  source = read(filename)
115
115
  api_map.virtualize source
116
116
  fragment = source.fragment_at(line, column)
117
- api_map.complete(fragment)
117
+ fragment.complete(api_map)
118
118
  end
119
119
 
120
120
  # Get definition suggestions for the expression at the specified file and
@@ -128,7 +128,7 @@ module Solargraph
128
128
  source = read(filename)
129
129
  api_map.virtualize source
130
130
  fragment = source.fragment_at(line, column)
131
- api_map.define(fragment)
131
+ fragment.define(api_map)
132
132
  end
133
133
 
134
134
  # Get signature suggestions for the method at the specified file and
@@ -142,14 +142,18 @@ module Solargraph
142
142
  source = read(filename)
143
143
  api_map.virtualize source
144
144
  fragment = source.fragment_at(line, column)
145
- api_map.signify(fragment)
145
+ fragment.signify(api_map)
146
146
  end
147
147
 
148
+ # @param filename [String]
149
+ # @param line [Integer]
150
+ # @param column [Integer]
151
+ # @return [Array<Solargraph::Source::Range>]
148
152
  def references_from filename, line, column
149
153
  source = read(filename)
150
154
  api_map.virtualize source
151
155
  fragment = source.fragment_at(line, column)
152
- pins = api_map.define(fragment)
156
+ pins = fragment.define(api_map)
153
157
  return [] if pins.empty?
154
158
  result = []
155
159
  # @param pin [Solargraph::Pin::Base]
@@ -159,9 +163,10 @@ module Solargraph
159
163
  result.push mn_loc unless mn_loc.nil?
160
164
  end
161
165
  (workspace.sources + source_hash.values).uniq(&:filename).each do |source|
162
- found = source.references(pin.name).select do |loc|
163
- referenced = definitions_at(loc.filename, loc.range.ending.line, loc.range.ending.character).first
164
- !referenced.nil? and referenced.path == pin.path
166
+ found = source.references(pin.name)
167
+ found.select do |loc|
168
+ referenced = definitions_at(loc.filename, loc.range.ending.line, loc.range.ending.character)
169
+ referenced.any?{|r| r.path == pin.path}
165
170
  end
166
171
  result.concat found.sort{|a, b| a.range.start.line <=> b.range.start.line}
167
172
  end