solargraph 0.30.2 → 0.31.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/solargraph.rb +7 -0
  3. data/lib/solargraph/api_map.rb +31 -38
  4. data/lib/solargraph/api_map/store.rb +7 -1
  5. data/lib/solargraph/diagnostics/require_not_found.rb +2 -1
  6. data/lib/solargraph/language_server/host.rb +34 -83
  7. data/lib/solargraph/language_server/host/cataloger.rb +17 -7
  8. data/lib/solargraph/language_server/host/diagnoser.rb +19 -10
  9. data/lib/solargraph/language_server/host/dispatch.rb +110 -0
  10. data/lib/solargraph/language_server/host/sources.rb +100 -1
  11. data/lib/solargraph/language_server/message/base.rb +15 -11
  12. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
  13. data/lib/solargraph/language_server/message/initialize.rb +32 -27
  14. data/lib/solargraph/language_server/message/text_document/completion.rb +1 -8
  15. data/lib/solargraph/language_server/transport/adapter.rb +26 -15
  16. data/lib/solargraph/language_server/transport/data_reader.rb +2 -2
  17. data/lib/solargraph/library.rb +30 -58
  18. data/lib/solargraph/live_map.rb +1 -1
  19. data/lib/solargraph/pin.rb +1 -0
  20. data/lib/solargraph/pin/base.rb +1 -1
  21. data/lib/solargraph/pin/base_method.rb +1 -1
  22. data/lib/solargraph/pin/method.rb +1 -1
  23. data/lib/solargraph/pin/method_alias.rb +15 -4
  24. data/lib/solargraph/plugin/process.rb +1 -1
  25. data/lib/solargraph/position.rb +1 -2
  26. data/lib/solargraph/server_methods.rb +1 -0
  27. data/lib/solargraph/shell.rb +0 -28
  28. data/lib/solargraph/source.rb +116 -20
  29. data/lib/solargraph/source/encoding_fixes.rb +1 -1
  30. data/lib/solargraph/source/source_chainer.rb +16 -8
  31. data/lib/solargraph/source_map.rb +11 -2
  32. data/lib/solargraph/source_map/clip.rb +1 -1
  33. data/lib/solargraph/source_map/mapper.rb +8 -5
  34. data/lib/solargraph/version.rb +1 -1
  35. data/lib/solargraph/views/environment.erb +3 -0
  36. data/lib/solargraph/workspace.rb +17 -14
  37. data/lib/solargraph/workspace/config.rb +1 -1
  38. data/lib/solargraph/yard_map.rb +6 -5
  39. data/lib/solargraph/yard_map/core_docs.rb +68 -18
  40. data/lib/solargraph/yard_map/core_gen.rb +47 -0
  41. data/lib/yard-coregen.rb +16 -0
  42. data/lib/yard-solargraph.rb +10 -1
  43. metadata +21 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61453319a056f4779bf21c852bb34b5f797207c19ff9266d422d25c724934bc1
4
- data.tar.gz: 405c13271fce7df56c5daae95b95430f5933a66728d3e2f6fff11762d4f392d0
3
+ metadata.gz: 7e808b8b4e3550a64f5737991858a16cfb43c1d4d839fa0be4c7018d9740783f
4
+ data.tar.gz: 7a90449ea2b30e07234f89bfb468eaf0e33e28711799b15064a9ae9dbcf83bc3
5
5
  SHA512:
6
- metadata.gz: 5dcd832eff27b926dd8d244feff2edc37398f0004fa62dd002f07981e325d6f5a88f7c93bc1ad91d1f0ce34954790afc0410ed9581936d5ad57a465f99cc2372
7
- data.tar.gz: 246cb5bbb21a7134532512c0321e86633d21adcf4eebd24de3d33427ab3da39663dafba488b8e0a304abd252c874408513ced6370cdc8e88cde18187f1242b79
6
+ metadata.gz: d87b8b907a0c33376f138381ad1b70c8c49be1ce504aec7e098bcac84030f53c9c469ea87b3b0e2fdaebe04bc51cf0b338ac3074fa1064be47f87e60c82499c4
7
+ data.tar.gz: 5888e2114dfea0da7dd3681d800400f7393cb63804f8d4f043aac2f74b0bf9bce1f986f34ae9d85bcc9753e49f5c773ad7ec3791257fbe372f632f3deb81ee04
@@ -40,6 +40,13 @@ module Solargraph
40
40
  YARDOC_PATH = File.realpath(File.join(dir, '..', 'yardoc'))
41
41
  YARD_EXTENSION_FILE = File.join(dir, 'yard-solargraph.rb')
42
42
  VIEWS_PATH = File.join(dir, 'solargraph', 'views')
43
+
44
+ # A convenience method for Solargraph::Logging.logger.
45
+ #
46
+ # @return [Logger]
47
+ def self.logger
48
+ Solargraph::Logging.logger
49
+ end
43
50
  end
44
51
 
45
52
  Solargraph::YardMap::CoreDocs.require_minimum
@@ -11,7 +11,7 @@ module Solargraph
11
11
  autoload :SourceToYard, 'solargraph/api_map/source_to_yard'
12
12
  autoload :Store, 'solargraph/api_map/store'
13
13
 
14
- include Solargraph::ApiMap::SourceToYard
14
+ include SourceToYard
15
15
 
16
16
  # Get a LiveMap associated with the current workspace.
17
17
  #
@@ -40,7 +40,7 @@ module Solargraph
40
40
  @store = Store.new(pins + YardMap.new.pins)
41
41
  @unresolved_requires = []
42
42
  }
43
- resolve_method_aliases
43
+ # resolve_method_aliases
44
44
  self
45
45
  end
46
46
 
@@ -66,9 +66,13 @@ module Solargraph
66
66
  # Bundle always needs to be merged if it adds or removes sources
67
67
  merged = (bundle.sources.length == source_map_hash.values.length)
68
68
  bundle.sources.each do |source|
69
- if source_map_hash.has_key?(source.filename)
70
- if source_map_hash[source.filename].code == source.code
69
+ if source_map_hash.key?(source.filename)
70
+ if source_map_hash[source.filename].code == source.code && source_map_hash[source.filename].source.synchronized? && source.synchronized?
71
71
  new_map_hash[source.filename] = source_map_hash[source.filename]
72
+ elsif !source.synchronized?
73
+ new_map_hash[source.filename] = source_map_hash[source.filename]
74
+ # @todo Smelly instance variable access
75
+ new_map_hash[source.filename].instance_variable_set(:@source, source)
72
76
  else
73
77
  map = Solargraph::SourceMap.map(source)
74
78
  if source_map_hash[source.filename].try_merge!(map)
@@ -114,7 +118,7 @@ module Solargraph
114
118
  @store = new_store
115
119
  @unresolved_requires = yard_map.unresolved_requires
116
120
  }
117
- resolve_method_aliases
121
+ # resolve_method_aliases
118
122
  self
119
123
  end
120
124
 
@@ -142,8 +146,7 @@ module Solargraph
142
146
  # @param directory [String]
143
147
  # @return [ApiMap]
144
148
  def self.load directory
145
- # @todo How should this work?
146
- api_map = self.new #(Solargraph::Workspace.new(directory))
149
+ api_map = self.new
147
150
  workspace = Solargraph::Workspace.new(directory)
148
151
  api_map.catalog Bundle.new(workspace: workspace)
149
152
  api_map
@@ -220,13 +223,11 @@ module Solargraph
220
223
  return qualify(context) if namespace == 'self'
221
224
  cached = cache.get_qualified_namespace(namespace, context)
222
225
  return cached.clone unless cached.nil?
223
- # result = inner_qualify(namespace, context, [])
224
- # result = result[2..-1] if !result.nil? && result.start_with?('::')
225
- if namespace.start_with?('::')
226
- result = inner_qualify(namespace[2..-1], '', [])
227
- else
228
- result = inner_qualify(namespace, context, [])
229
- end
226
+ result = if namespace.start_with?('::')
227
+ inner_qualify(namespace[2..-1], '', [])
228
+ else
229
+ inner_qualify(namespace, context, [])
230
+ end
230
231
  cache.set_qualified_namespace(namespace, context, result)
231
232
  result
232
233
  end
@@ -296,8 +297,9 @@ module Solargraph
296
297
  # exist = result.map(&:name)
297
298
  # result.concat live.reject{|p| exist.include?(p.name)}
298
299
  # end
299
- cache.set_methods(fqns, scope, visibility, deep, result)
300
- result
300
+ resolved = resolve_method_aliases(result)
301
+ cache.set_methods(fqns, scope, visibility, deep, resolved)
302
+ resolved
301
303
  end
302
304
 
303
305
  # Get an array of method pins for a complex type.
@@ -371,7 +373,7 @@ module Solargraph
371
373
  # lp = live_map.get_path_pin(path)
372
374
  # result.push lp unless lp.nil?
373
375
  # end
374
- result
376
+ resolve_method_aliases(result)
375
377
  end
376
378
 
377
379
  # Get an array of pins that match the specified path.
@@ -461,6 +463,7 @@ module Solargraph
461
463
 
462
464
  private
463
465
 
466
+ # @return [YardMap]
464
467
  def yard_map
465
468
  @yard_map ||= YardMap.new
466
469
  end
@@ -469,23 +472,17 @@ module Solargraph
469
472
  #
470
473
  # @return [Hash{String => SourceMap}]
471
474
  def source_map_hash
472
- @mutex.synchronize {
473
- @source_map_hash
474
- }
475
+ @mutex.synchronize { @source_map_hash }
475
476
  end
476
477
 
477
478
  # @return [ApiMap::Store]
478
479
  def store
479
- @mutex.synchronize {
480
- @store
481
- }
480
+ @mutex.synchronize { @store }
482
481
  end
483
482
 
484
483
  # @return [Solargraph::ApiMap::Cache]
485
484
  def cache
486
- @mutex.synchronize {
487
- @cache
488
- }
485
+ @mutex.synchronize { @cache }
489
486
  end
490
487
 
491
488
  # @param fqns [String] A fully qualified namespace
@@ -558,7 +555,7 @@ module Solargraph
558
555
  # @return [void]
559
556
  def require_extensions
560
557
  Gem::Specification.all_names.select{|n| n.match(/^solargraph\-[a-z0-9_\-]*?\-ext\-[0-9\.]*$/)}.each do |n|
561
- STDERR.puts "Loading extension #{n}"
558
+ Solargraph::Logging.logger.info "Loading extension #{n}"
562
559
  require n.match(/^(solargraph\-[a-z0-9_\-]*?\-ext)\-[0-9\.]*$/)[1]
563
560
  end
564
561
  end
@@ -583,9 +580,8 @@ module Solargraph
583
580
  return inner_qualify(root, '', skip)
584
581
  end
585
582
  else
586
- if (root == '')
583
+ if root == ''
587
584
  return name if store.namespace_exists?(name)
588
- # @todo What to do about the @namespace_includes stuff above?
589
585
  else
590
586
  roots = root.to_s.split('::')
591
587
  while roots.length > 0
@@ -642,18 +638,15 @@ module Solargraph
642
638
  false
643
639
  end
644
640
 
645
- # @return [void]
646
- def resolve_method_aliases
647
- aliased = false
648
- result = pins.map do |pin|
649
- next pin unless pin.is_a?(Pin::MethodAlias)
650
- origin = get_method_stack(pin.namespace, pin.original, scope: pin.scope).select{|pin| pin.class == Pin::Method}.first
641
+ # @param pins [Array<Pin::Base>]
642
+ # @return [Array<Pin::Base>]
643
+ def resolve_method_aliases pins
644
+ pins.map do |pin|
645
+ next pin unless pin.kind == Pin::METHOD_ALIAS
646
+ origin = get_method_stack(pin.namespace, pin.original, scope: pin.scope).select{|pin| pin.is_a?(Pin::BaseMethod)}.first
651
647
  next pin if origin.nil?
652
- aliased = true
653
648
  Pin::Method.new(pin.location, pin.namespace, pin.name, origin.comments, origin.scope, origin.visibility, origin.parameters)
654
649
  end
655
- return nil unless aliased
656
- @mutex.synchronize { @store = Store.new(result) }
657
650
  end
658
651
  end
659
652
  end
@@ -26,8 +26,9 @@ module Solargraph
26
26
  # @param visibility [Array<Symbol>]
27
27
  # @return [Array<Solargraph::Pin::Base>]
28
28
  def get_methods fqns, scope: :instance, visibility: [:public]
29
+ kinds = [Pin::METHOD, Pin::ATTRIBUTE]
29
30
  namespace_children(fqns).select{ |pin|
30
- [Pin::METHOD, Pin::ATTRIBUTE].include?(pin.kind) && pin.scope == scope && visibility.include?(pin.visibility)
31
+ kinds.include?(pin.kind) && pin.scope == scope && visibility.include?(pin.visibility)
31
32
  }
32
33
  end
33
34
 
@@ -120,6 +121,11 @@ module Solargraph
120
121
  end
121
122
  end
122
123
 
124
+ def inspect
125
+ # Avoid insane dumps in specs
126
+ to_s
127
+ end
128
+
123
129
  private
124
130
 
125
131
  # @param fqns [String]
@@ -5,9 +5,10 @@ module Solargraph
5
5
  #
6
6
  class RequireNotFound < Base
7
7
  def diagnose source, api_map
8
+ return [] unless source.parsed? && source.synchronized?
8
9
  result = []
9
10
  refs = {}
10
- map = Solargraph::SourceMap.map(source)
11
+ map = api_map.source_map(source.filename)
11
12
  map.requires.each do |ref|
12
13
  refs[ref.name] = ref
13
14
  end
@@ -11,9 +11,11 @@ module Solargraph
11
11
  autoload :Diagnoser, 'solargraph/language_server/host/diagnoser'
12
12
  autoload :Cataloger, 'solargraph/language_server/host/cataloger'
13
13
  autoload :Sources, 'solargraph/language_server/host/sources'
14
+ autoload :Dispatch, 'solargraph/language_server/host/dispatch'
14
15
 
15
- include Solargraph::LanguageServer::UriHelpers
16
+ include UriHelpers
16
17
  include Logging
18
+ include Dispatch
17
19
 
18
20
  def initialize
19
21
  @cancel_semaphore = Mutex.new
@@ -21,12 +23,23 @@ module Solargraph
21
23
  @register_semaphore = Mutex.new
22
24
  @cancel = []
23
25
  @buffer = ''
24
- @stopped = false
26
+ @stopped = true
25
27
  @next_request_id = 0
26
28
  @dynamic_capabilities = Set.new
27
29
  @registered_capabilities = Set.new
28
30
  end
29
31
 
32
+ # Start asynchronous process handling.
33
+ #
34
+ # @return [void]
35
+ def start
36
+ return unless stopped?
37
+ @stopped = false
38
+ diagnoser.start
39
+ cataloger.start
40
+ sources.start
41
+ end
42
+
30
43
  # Update the configuration options with the provided hash.
31
44
  #
32
45
  # @param update [Hash]
@@ -62,6 +75,7 @@ module Solargraph
62
75
  # Delete the specified ID from the list of cancelled IDs if it exists.
63
76
  #
64
77
  # @param id [Integer]
78
+ # @return [void]
65
79
  def clear id
66
80
  @cancel_semaphore.synchronize { @cancel.delete id }
67
81
  end
@@ -71,7 +85,7 @@ module Solargraph
71
85
  #
72
86
  # @param request [Hash] The contents of the message.
73
87
  # @return [Solargraph::LanguageServer::Message::Base] The message handler.
74
- def start request
88
+ def receive request
75
89
  if request['method']
76
90
  logger.info "Server received #{request['method']}"
77
91
  logger.debug request
@@ -79,8 +93,8 @@ module Solargraph
79
93
  begin
80
94
  message.process
81
95
  rescue Exception => e
82
- STDERR.puts e.message
83
- STDERR.puts e.backtrace
96
+ logger.warn "Error processing request: [#{e.class}] #{e.message}"
97
+ logger.warn e.backtrace
84
98
  message.set_error Solargraph::LanguageServer::ErrorCodes::INTERNAL_ERROR, "[#{e.class}] #{e.message}"
85
99
  end
86
100
  message
@@ -89,7 +103,8 @@ module Solargraph
89
103
  requests[request['id']].process(request['result'])
90
104
  requests.delete request['id']
91
105
  else
92
- STDERR.puts "Invalid message received."
106
+ logger.warn "Invalid message received."
107
+ logger.debug request
93
108
  end
94
109
  end
95
110
 
@@ -112,11 +127,13 @@ module Solargraph
112
127
  # Delete the specified file from the library.
113
128
  #
114
129
  # @param uri [String] The file uri.
130
+ # @return [void]
115
131
  def delete uri
116
132
  sources.close uri
117
133
  filename = uri_to_file(uri)
118
134
  libraries.each do |lib|
119
- lib.delete filename
135
+ # lib.delete filename
136
+ lib.detach filename
120
137
  end
121
138
  send_notification "textDocument/publishDiagnostics", {
122
139
  uri: uri,
@@ -129,6 +146,7 @@ module Solargraph
129
146
  # @param uri [String] The file uri.
130
147
  # @param text [String] The contents of the file.
131
148
  # @param version [Integer] A version number.
149
+ # @return [void]
132
150
  def open uri, text, version
133
151
  src = sources.open(uri, text, version)
134
152
  libraries.each do |lib|
@@ -167,6 +185,7 @@ module Solargraph
167
185
  if sources.include?(uri)
168
186
  logger.info "Diagnosing #{uri}"
169
187
  library = library_for(uri)
188
+ library.catalog
170
189
  begin
171
190
  results = library.diagnose uri_to_file(uri)
172
191
  send_notification "textDocument/publishDiagnostics", {
@@ -196,11 +215,7 @@ module Solargraph
196
215
  # @return [void]
197
216
  def change params
198
217
  updater = generate_updater(params)
199
- src = sources.update(params['textDocument']['uri'], updater)
200
- libraries.each do |lib|
201
- lib.merge src
202
- end
203
- diagnoser.schedule params['textDocument']['uri']
218
+ sources.async_update params['textDocument']['uri'], updater
204
219
  end
205
220
 
206
221
  # Queue a message to be sent to the client.
@@ -238,16 +253,13 @@ module Solargraph
238
253
  path = normalize_separators(directory) unless directory.nil?
239
254
  begin
240
255
  lib = Solargraph::Library.load(path, name)
256
+ libraries.push lib
241
257
  rescue WorkspaceTooLargeError => e
242
258
  send_notification 'window/showMessage', {
243
259
  'type' => Solargraph::LanguageServer::MessageTypes::WARNING,
244
260
  'message' => e.message
245
261
  }
246
- lib = Solargraph::Library.new('', name)
247
262
  end
248
- libraries.push lib
249
- diagnoser.start
250
- cataloger.start
251
263
  end
252
264
 
253
265
  # Prepare multiple folders.
@@ -400,9 +412,11 @@ module Solargraph
400
412
 
401
413
  # @return [void]
402
414
  def stop
415
+ return if @stopped
403
416
  @stopped = true
404
417
  cataloger.stop
405
418
  diagnoser.stop
419
+ sources.stop
406
420
  end
407
421
 
408
422
  def stopped?
@@ -576,80 +590,17 @@ module Solargraph
576
590
  }
577
591
  end
578
592
 
579
- # Catalog the library.
580
- #
581
- # @return [void]
582
- def catalog lib
583
- lib.catalog
584
- end
585
-
586
593
  # @param uri [String]
587
594
  # @return [Array<Range>]
588
595
  def folding_ranges uri
589
- library = library_for(uri)
590
- file = uri_to_file(uri)
591
- library.folding_ranges(file)
596
+ # library = library_for(uri)
597
+ # file = uri_to_file(uri)
598
+ # library.folding_ranges(file)
599
+ sources.find(uri).folding_ranges
592
600
  end
593
601
 
594
602
  private
595
603
 
596
- # @return [Array<Library>]
597
- def libraries
598
- @libraries ||= []
599
- end
600
-
601
- # @return [Sources]
602
- def sources
603
- @sources ||= Sources.new
604
- end
605
-
606
- # @param uri [String]
607
- # @return [Library]
608
- def library_for uri
609
- explicit_library_for(uri) ||
610
- implicit_library_for(uri) ||
611
- generic_library_for(uri)
612
- end
613
-
614
- # @param uri [String]
615
- # @return [Library, nil]
616
- def explicit_library_for uri
617
- filename = uri_to_file(uri)
618
- libraries.each do |lib|
619
- if lib.contain?(filename) #|| lib.open?(filename)
620
- lib.attach sources.find(uri) if sources.include?(uri)
621
- return lib
622
- end
623
- end
624
- nil
625
- end
626
-
627
- # @param uri [String]
628
- # @return [Library, nil]
629
- def implicit_library_for uri
630
- filename = uri_to_file(uri)
631
- libraries.each do |lib|
632
- # return lib if filename.start_with?(lib.workspace.directory)
633
- if lib.open?(filename) || filename.start_with?(lib.workspace.directory)
634
- lib.attach sources.find(uri)
635
- return lib
636
- end
637
- end
638
- nil
639
- end
640
-
641
- # @param uri [String]
642
- # @return [Library]
643
- def generic_library_for uri
644
- generic_library.attach sources.find(uri)
645
- generic_library
646
- end
647
-
648
- # @return [Library]
649
- def generic_library
650
- @generic_library ||= Solargraph::Library.new
651
- end
652
-
653
604
  # @return [Diagnoser]
654
605
  def diagnoser
655
606
  @diagnoser ||= Diagnoser.new(self)