solargraph 0.53.3 → 0.54.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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -0
  3. data/lib/solargraph/api_map/cache.rb +2 -12
  4. data/lib/solargraph/api_map/store.rb +11 -6
  5. data/lib/solargraph/api_map.rb +80 -26
  6. data/lib/solargraph/complex_type/type_methods.rb +62 -30
  7. data/lib/solargraph/complex_type/unique_type.rb +117 -66
  8. data/lib/solargraph/complex_type.rb +41 -25
  9. data/lib/solargraph/doc_map.rb +19 -3
  10. data/lib/solargraph/gem_pins.rb +9 -1
  11. data/lib/solargraph/language_server/host/dispatch.rb +8 -1
  12. data/lib/solargraph/language_server/host/sources.rb +1 -61
  13. data/lib/solargraph/language_server/host.rb +39 -68
  14. data/lib/solargraph/language_server/message/base.rb +1 -1
  15. data/lib/solargraph/language_server/message/initialize.rb +14 -0
  16. data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -0
  17. data/lib/solargraph/language_server/progress.rb +118 -0
  18. data/lib/solargraph/language_server.rb +1 -0
  19. data/lib/solargraph/library.rb +136 -96
  20. data/lib/solargraph/parser/node_processor/base.rb +3 -2
  21. data/lib/solargraph/parser/node_processor.rb +1 -0
  22. data/lib/solargraph/parser/parser_gem/class_methods.rb +3 -7
  23. data/lib/solargraph/parser/parser_gem/node_methods.rb +0 -4
  24. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +47 -0
  25. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +5 -3
  26. data/lib/solargraph/parser/parser_gem/node_processors.rb +2 -0
  27. data/lib/solargraph/pin/base_variable.rb +34 -5
  28. data/lib/solargraph/pin/block.rb +62 -7
  29. data/lib/solargraph/pin/delegated_method.rb +5 -1
  30. data/lib/solargraph/pin/documenting.rb +2 -0
  31. data/lib/solargraph/pin/method.rb +4 -2
  32. data/lib/solargraph/pin/parameter.rb +5 -28
  33. data/lib/solargraph/rbs_map/conversions.rb +12 -6
  34. data/lib/solargraph/rbs_map/core_fills.rb +4 -1
  35. data/lib/solargraph/rbs_map.rb +11 -3
  36. data/lib/solargraph/shell.rb +18 -13
  37. data/lib/solargraph/source/chain.rb +20 -0
  38. data/lib/solargraph/source/updater.rb +1 -0
  39. data/lib/solargraph/source.rb +0 -44
  40. data/lib/solargraph/source_map/clip.rb +1 -0
  41. data/lib/solargraph/source_map/mapper.rb +3 -2
  42. data/lib/solargraph/source_map.rb +10 -0
  43. data/lib/solargraph/type_checker.rb +44 -18
  44. data/lib/solargraph/version.rb +1 -1
  45. data/lib/solargraph/workspace/config.rb +2 -1
  46. data/lib/solargraph/workspace.rb +13 -0
  47. data/lib/solargraph/yard_map/mapper/to_method.rb +5 -2
  48. metadata +4 -3
  49. data/lib/solargraph/language_server/host/cataloger.rb +0 -57
@@ -12,7 +12,6 @@ module Solargraph
12
12
  #
13
13
  class Host
14
14
  autoload :Diagnoser, 'solargraph/language_server/host/diagnoser'
15
- autoload :Cataloger, 'solargraph/language_server/host/cataloger'
16
15
  autoload :Sources, 'solargraph/language_server/host/sources'
17
16
  autoload :Dispatch, 'solargraph/language_server/host/dispatch'
18
17
  autoload :MessageWorker, 'solargraph/language_server/host/message_worker'
@@ -43,8 +42,6 @@ module Solargraph
43
42
  return unless stopped?
44
43
  @stopped = false
45
44
  diagnoser.start
46
- cataloger.start
47
- sources.start
48
45
  message_worker.start
49
46
  end
50
47
 
@@ -155,6 +152,7 @@ module Solargraph
155
152
  def delete *uris
156
153
  filenames = uris.map { |uri| uri_to_file(uri) }
157
154
  libraries.each do |lib|
155
+ lib.delete_observer self
158
156
  lib.delete(*filenames)
159
157
  end
160
158
  uris.each do |uri|
@@ -253,7 +251,7 @@ module Solargraph
253
251
  # @return [void]
254
252
  def change params
255
253
  updater = generate_updater(params)
256
- sources.async_update params['textDocument']['uri'], updater
254
+ sources.update params['textDocument']['uri'], updater
257
255
  diagnoser.schedule params['textDocument']['uri']
258
256
  end
259
257
 
@@ -294,8 +292,9 @@ module Solargraph
294
292
  begin
295
293
  workspace = Solargraph::Workspace.new(path, nil, options)
296
294
  lib = Solargraph::Library.new(workspace, name)
295
+ lib.add_observer self
297
296
  libraries.push lib
298
- async_library_map lib
297
+ library_map lib
299
298
  rescue WorkspaceTooLargeError => e
300
299
  send_notification 'window/showMessage', {
301
300
  'type' => Solargraph::LanguageServer::MessageTypes::WARNING,
@@ -324,6 +323,7 @@ module Solargraph
324
323
  # @param lib [Library]
325
324
  libraries.delete_if do |lib|
326
325
  next false if lib.workspace.directory != directory
326
+ lib.delete_observer self
327
327
  true
328
328
  end
329
329
  end
@@ -458,9 +458,7 @@ module Solargraph
458
458
  return if @stopped
459
459
  @stopped = true
460
460
  message_worker.stop
461
- cataloger.stop
462
461
  diagnoser.stop
463
- sources.stop
464
462
  changed
465
463
  notify_observers
466
464
  end
@@ -493,6 +491,24 @@ module Solargraph
493
491
  end
494
492
  if params['data']['path']
495
493
  result.concat library.path_pins(params['data']['path'])
494
+ # @todo This exception is necessary because `Library#path_pins` does
495
+ # not perform a namespace method query, so the implicit `.new` pin
496
+ # might not exist.
497
+ if result.empty? && params['data']['path'] =~ /\.new$/
498
+ result.concat(library.path_pins(params['data']['path'].sub(/\.new$/, '#initialize')).map do |pin|
499
+ next pin unless pin.name == 'initialize'
500
+
501
+ Pin::Method.new(
502
+ name: 'new',
503
+ scope: :class,
504
+ location: pin.location,
505
+ parameters: pin.parameters,
506
+ return_type: ComplexType.try_parse(params['data']['path']),
507
+ comments: pin.comments,
508
+ closure: pin.closure
509
+ )
510
+ end)
511
+ end
496
512
  end
497
513
  # Selecting by both location and path can result in duplicate pins
498
514
  result.uniq { |p| [p.path, p.location] }
@@ -666,11 +682,15 @@ module Solargraph
666
682
  libraries.each(&:catalog)
667
683
  end
668
684
 
669
- # @return [Hash{String => BasicObject}]
685
+ # @return [Hash{String => Hash{String => Boolean}}]
670
686
  def client_capabilities
671
687
  @client_capabilities ||= {}
672
688
  end
673
689
 
690
+ def client_supports_progress?
691
+ client_capabilities['window'] && client_capabilities['window']['workDoneProgress']
692
+ end
693
+
674
694
  private
675
695
 
676
696
  # @return [MessageWorker]
@@ -683,11 +703,6 @@ module Solargraph
683
703
  @diagnoser ||= Diagnoser.new(self)
684
704
  end
685
705
 
686
- # @return [Cataloger]
687
- def cataloger
688
- @cataloger ||= Cataloger.new(self)
689
- end
690
-
691
706
  # A hash of client requests by ID. The host uses this to keep track of
692
707
  # pending responses.
693
708
  #
@@ -817,72 +832,28 @@ module Solargraph
817
832
  client_capabilities['rename'] && client_capabilities['rename']['prepareSupport']
818
833
  end
819
834
 
820
- def client_supports_progress?
821
- client_capabilities['window'] && client_capabilities['window']['workDoneProgress']
822
- end
823
-
824
835
  # @param library [Library]
825
836
  # @return [void]
826
- def async_library_map library
837
+ def library_map library
827
838
  return if library.mapped?
828
- Thread.new do
829
- if client_supports_progress?
830
- uuid = SecureRandom.uuid
831
- send_request 'window/workDoneProgress/create', {
832
- token: uuid
833
- } do |response|
834
- do_async_library_map library, response.nil? ? uuid : nil
835
- end
836
- else
837
- do_async_library_map library
838
- end
839
- end
839
+ Thread.new { sync_library_map library }
840
840
  end
841
841
 
842
842
  # @param library [Library]
843
843
  # @param uuid [String, nil]
844
844
  # @return [void]
845
- def do_async_library_map library, uuid = nil
845
+ def sync_library_map library
846
846
  total = library.workspace.sources.length
847
- if uuid
848
- send_notification '$/progress', {
849
- token: uuid,
850
- value: {
851
- kind: 'begin',
852
- title: "Mapping workspace",
853
- message: "0/#{total} files",
854
- cancellable: false,
855
- percentage: 0
856
- }
857
- }
858
- end
859
- pct = 0
860
- mod = 10
847
+ progress = Progress.new('Mapping workspace')
848
+ progress.begin "0/#{total} files", 0
849
+ progress.send self
861
850
  while library.next_map
862
- next unless uuid
863
- cur = ((library.source_map_hash.keys.length.to_f / total.to_f) * 100).to_i
864
- if cur > pct && cur % mod == 0
865
- pct = cur
866
- send_notification '$/progress', {
867
- token: uuid,
868
- value: {
869
- kind: 'report',
870
- cancellable: false,
871
- message: "#{library.source_map_hash.keys.length}/#{total} files",
872
- percentage: pct
873
- }
874
- }
875
- end
876
- end
877
- if uuid
878
- send_notification '$/progress', {
879
- token: uuid,
880
- value: {
881
- kind: 'end',
882
- message: 'Mapping complete'
883
- }
884
- }
851
+ pct = ((library.source_map_hash.keys.length.to_f / total) * 100).to_i
852
+ progress.report "#{library.source_map_hash.keys.length}/#{total} files", pct
853
+ progress.send self
885
854
  end
855
+ progress.finish 'done'
856
+ progress.send self
886
857
  end
887
858
  end
888
859
  end
@@ -16,7 +16,7 @@ module Solargraph
16
16
  # @return [String]
17
17
  attr_reader :method
18
18
 
19
- # @return [Hash]
19
+ # @return [Hash{String => Array, Hash, String, Integer}]
20
20
  attr_reader :params
21
21
 
22
22
  # @return [Hash, Array, nil]
@@ -47,6 +47,8 @@ module Solargraph
47
47
 
48
48
  private
49
49
 
50
+ # @todo '?' methods should type like RBS 'boolish' rather than a strict true or false
51
+ # @sg-ignore
50
52
  def support_workspace_folders?
51
53
  params['capabilities'] &&
52
54
  params['capabilities']['workspace'] &&
@@ -82,6 +84,7 @@ module Solargraph
82
84
  }
83
85
  end
84
86
 
87
+ # @return [Hash{Symbol => Hash{Symbol => String, Array<String>}}]
85
88
  def static_on_type_formatting
86
89
  {
87
90
  documentOnTypeFormattingProvider: {
@@ -91,6 +94,7 @@ module Solargraph
91
94
  }
92
95
  end
93
96
 
97
+ # @return [Hash{Symbol => Boolean}]
94
98
  def static_hover
95
99
  return {} unless host.options['hover']
96
100
  {
@@ -98,6 +102,7 @@ module Solargraph
98
102
  }
99
103
  end
100
104
 
105
+ # @return [Hash{Symbol => Boolean}]
101
106
  def static_document_formatting
102
107
  return {} unless host.options['formatting']
103
108
  {
@@ -105,6 +110,7 @@ module Solargraph
105
110
  }
106
111
  end
107
112
 
113
+ # @return [Hash{Symbol => Boolean}]
108
114
  def static_document_symbols
109
115
  return {} unless host.options['symbols']
110
116
  {
@@ -112,12 +118,14 @@ module Solargraph
112
118
  }
113
119
  end
114
120
 
121
+ # @return [Hash{Symbol => Boolean}]
115
122
  def static_workspace_symbols
116
123
  {
117
124
  workspaceSymbolProvider: true
118
125
  }
119
126
  end
120
127
 
128
+ # @return [Hash{Symbol => Boolean}]
121
129
  def static_definitions
122
130
  return {} unless host.options['definitions']
123
131
  {
@@ -125,6 +133,7 @@ module Solargraph
125
133
  }
126
134
  end
127
135
 
136
+ # @return [Hash{Symbol => Boolean}]
128
137
  def static_type_definitions
129
138
  return {} unless host.options['typeDefinitions']
130
139
  {
@@ -132,12 +141,15 @@ module Solargraph
132
141
  }
133
142
  end
134
143
 
144
+ # @return [Hash{Symbol => Hash{Symbol => Boolean}}]
135
145
  def static_rename
136
146
  {
137
147
  renameProvider: {prepareProvider: true}
138
148
  }
139
149
  end
140
150
 
151
+
152
+ # @return [Hash{Symbol => Boolean}]
141
153
  def static_references
142
154
  return {} unless host.options['references']
143
155
  {
@@ -145,6 +157,7 @@ module Solargraph
145
157
  }
146
158
  end
147
159
 
160
+ # @return [Hash{Symbol => Boolean}]
148
161
  def static_folding_range
149
162
  return {} unless host.options['folding']
150
163
  {
@@ -152,6 +165,7 @@ module Solargraph
152
165
  }
153
166
  end
154
167
 
168
+ # @return [Hash{Symbol => Boolean}]
155
169
  def static_highlights
156
170
  {
157
171
  documentHighlightProvider: true
@@ -70,6 +70,7 @@ module Solargraph
70
70
 
71
71
  def formatter_class(config)
72
72
  if self.class.const_defined?('BlankRubocopFormatter')
73
+ # @sg-ignore
73
74
  BlankRubocopFormatter
74
75
  else
75
76
  require_rubocop(config['version'])
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Solargraph
6
+ module LanguageServer
7
+ # Progress notification handling for language server hosts.
8
+ #
9
+ class Progress
10
+ WAITING = :waiting
11
+ CREATED = :created
12
+ FINISHED = :finished
13
+
14
+ # @return [String]
15
+ attr_reader :uuid
16
+
17
+ # @return [String]
18
+ attr_reader :title
19
+
20
+ # @return [String, nil]
21
+ attr_reader :kind
22
+
23
+ # @return [String, nil]
24
+ attr_reader :message
25
+
26
+ # @return [Integer]
27
+ attr_reader :percentage
28
+
29
+ # @return [Symbol]
30
+ attr_reader :status
31
+
32
+ # @param title [String]
33
+ def initialize title
34
+ @title = title
35
+ @uuid = SecureRandom.uuid
36
+ @percentage = 0
37
+ @status = WAITING
38
+ end
39
+
40
+ # @param message [String]
41
+ # @param percentage [Integer]
42
+ def begin message, percentage
43
+ @kind = 'begin'
44
+ @message = message
45
+ @percentage = percentage
46
+ end
47
+
48
+ # @param message [String]
49
+ # @param percentage [Integer]
50
+ def report message, percentage
51
+ @kind = 'report'
52
+ @message = message
53
+ @percentage = percentage
54
+ end
55
+
56
+ # @param message [String]
57
+ def finish message
58
+ @kind = 'end'
59
+ @message = message
60
+ @percentage = 100
61
+ true
62
+ end
63
+
64
+ # @param host [Solargraph::LanguageServer::Host]
65
+ def send host
66
+ return unless host.client_supports_progress? && !finished?
67
+
68
+ message = build
69
+
70
+ create(host) unless created?
71
+ host.send_notification '$/progress', message
72
+ @status = FINISHED if kind == 'end'
73
+ end
74
+
75
+ def created?
76
+ [CREATED, FINISHED].include?(status)
77
+ end
78
+
79
+ def finished?
80
+ status == FINISHED
81
+ end
82
+
83
+ private
84
+
85
+ # @param host [Solargraph::LanguageServer::Host]
86
+ # @return [void]
87
+ def create host
88
+ return if created?
89
+
90
+ host.send_request 'window/workDoneProgress/create', { token: uuid }
91
+ @status = CREATED
92
+ end
93
+
94
+ def build
95
+ {
96
+ token: uuid,
97
+ value: {
98
+ kind: kind,
99
+ cancellable: false
100
+ }.merge(build_value)
101
+ }
102
+ end
103
+
104
+ def build_value
105
+ case kind
106
+ when 'begin'
107
+ { title: title, message: message, percentage: percentage }
108
+ when 'report'
109
+ { message: message, percentage: percentage }
110
+ when 'end'
111
+ { message: message }
112
+ else
113
+ raise "Invalid progress kind #{kind}"
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -15,5 +15,6 @@ module Solargraph
15
15
  autoload :MessageTypes, 'solargraph/language_server/message_types'
16
16
  autoload :Request, 'solargraph/language_server/request'
17
17
  autoload :Transport, 'solargraph/language_server/transport'
18
+ autoload :Progress, 'solargraph/language_server/progress'
18
19
  end
19
20
  end