solargraph 0.25.1 → 0.26.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.
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