solargraph 0.21.1 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/solargraph.rb +0 -1
  3. data/lib/solargraph/api_map.rb +40 -23
  4. data/lib/solargraph/api_map/completion.rb +3 -0
  5. data/lib/solargraph/api_map/probe.rb +16 -19
  6. data/lib/solargraph/api_map/store.rb +6 -2
  7. data/lib/solargraph/diagnostics/rubocop.rb +6 -0
  8. data/lib/solargraph/language_server/host.rb +9 -1
  9. data/lib/solargraph/language_server/message.rb +3 -0
  10. data/lib/solargraph/language_server/message/extended.rb +1 -0
  11. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
  12. data/lib/solargraph/language_server/message/extended/download_core.rb +25 -0
  13. data/lib/solargraph/language_server/message/initialize.rb +3 -1
  14. data/lib/solargraph/language_server/message/text_document.rb +13 -11
  15. data/lib/solargraph/language_server/message/text_document/definition.rb +1 -1
  16. data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
  17. data/lib/solargraph/language_server/message/text_document/references.rb +14 -0
  18. data/lib/solargraph/language_server/message/text_document/rename.rb +17 -0
  19. data/lib/solargraph/language_server/uri_helpers.rb +2 -0
  20. data/lib/solargraph/library.rb +37 -0
  21. data/lib/solargraph/live_map.rb +8 -2
  22. data/lib/solargraph/live_map/cache.rb +7 -0
  23. data/lib/solargraph/pin.rb +1 -0
  24. data/lib/solargraph/pin/attribute.rb +5 -1
  25. data/lib/solargraph/pin/namespace.rb +0 -2
  26. data/lib/solargraph/pin/proxy_method.rb +31 -0
  27. data/lib/solargraph/plugin/process.rb +1 -1
  28. data/lib/solargraph/plugin/runtime.rb +0 -1
  29. data/lib/solargraph/shell.rb +0 -1
  30. data/lib/solargraph/source.rb +31 -1
  31. data/lib/solargraph/source/fragment.rb +12 -15
  32. data/lib/solargraph/source/location.rb +3 -0
  33. data/lib/solargraph/source/mapper.rb +20 -10
  34. data/lib/solargraph/source/node_methods.rb +111 -0
  35. data/lib/solargraph/version.rb +1 -1
  36. data/lib/solargraph/workspace.rb +7 -1
  37. data/lib/solargraph/workspace/config.rb +6 -2
  38. data/lib/solargraph/yard_map.rb +12 -1
  39. metadata +25 -7
  40. data/lib/solargraph/node_methods.rb +0 -101
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f93d18c2483c24a81693e662698b7d67e86086211608d6f50a0128b95cc817b6
4
- data.tar.gz: f0346ff1adf21faebba30306cc2e682cf99d83bcedf66ebfca3029dad4031025
3
+ metadata.gz: c647321bb57cb5ba859e1762032855324aa967e78a562c0e259508e5c24c22ee
4
+ data.tar.gz: 057c1a4298f9c4574c0773425cce496216ab60e22165871487d6d77e13733745
5
5
  SHA512:
6
- metadata.gz: d87a287c2608cbd7af255684a790ab079b85821a2abf3a6051212b36a156bf3662310bf5e9e7d3857ad89338b81628e94eb270dc74db258c6cb2ff2f4f0bc852
7
- data.tar.gz: ad9ae29c4d354588e383fb68926175bad72e419a2ef736f7e9f7069c701d3b94bc5ab784768be4dd1823ef1ac65201bea9e971ea554c6918f2f23d9fd1c42b92
6
+ metadata.gz: ae8cb69f92e2f3ad78959bd8767b78dda5a7d4baa861fa59680be191b7c92944f0df15ff12ccad2ed4a93231afcc55db53bd40cf9b42473387491f4d168f1cef
7
+ data.tar.gz: 8d02f2a10b1a71579a0b48e9dae4268689cc0ec642c137b1adedf6fc99749ae5a1b04f46b4d9b30448d3316a71b65dfdf79b5066c0af499e2181fcc5a107201f
data/lib/solargraph.rb CHANGED
@@ -20,7 +20,6 @@ module Solargraph
20
20
  autoload :Shell, 'solargraph/shell'
21
21
  autoload :Source, 'solargraph/source'
22
22
  autoload :ApiMap, 'solargraph/api_map'
23
- autoload :NodeMethods, 'solargraph/node_methods'
24
23
  autoload :YardMap, 'solargraph/yard_map'
25
24
  autoload :Pin, 'solargraph/pin'
26
25
  autoload :LiveMap, 'solargraph/live_map'
@@ -20,6 +20,14 @@ module Solargraph
20
20
  # @return [Solargraph::Workspace]
21
21
  attr_reader :workspace
22
22
 
23
+ # @return [ApiMap::Store]
24
+ attr_reader :store
25
+
26
+ # Get a LiveMap associated with the current workspace.
27
+ #
28
+ # @return [Solargraph::LiveMap]
29
+ attr_reader :live_map
30
+
23
31
  # @param workspace [Solargraph::Workspace]
24
32
  def initialize workspace = Solargraph::Workspace.new(nil)
25
33
  @workspace = workspace
@@ -28,7 +36,7 @@ module Solargraph
28
36
  @yard_stale = true
29
37
  # process_maps
30
38
  @sources = workspace.sources
31
- yard_map
39
+ refresh_store_and_maps
32
40
  end
33
41
 
34
42
  # Create an ApiMap with a workspace in the specified directory.
@@ -38,11 +46,6 @@ module Solargraph
38
46
  self.new(Solargraph::Workspace.new(directory))
39
47
  end
40
48
 
41
- # @return [ApiMap::Store]
42
- def store
43
- @store ||= ApiMap::Store.new(@sources)
44
- end
45
-
46
49
  def pins
47
50
  store.pins
48
51
  end
@@ -68,19 +71,12 @@ module Solargraph
68
71
  # @return [Solargraph::YardMap]
69
72
  def yard_map
70
73
  # refresh
71
- if @yard_map.nil? || @yard_map.required.to_set != required.to_set
74
+ if @yard_map.required.to_set != required.to_set
72
75
  @yard_map = Solargraph::YardMap.new(required: required, workspace: workspace)
73
76
  end
74
77
  @yard_map
75
78
  end
76
79
 
77
- # Get a LiveMap associated with the current workspace.
78
- #
79
- # @return [Solargraph::LiveMap]
80
- def live_map
81
- @live_map ||= Solargraph::LiveMap.new(self)
82
- end
83
-
84
80
  # Declare a virtual source that will be included in the map regardless of
85
81
  # whether it's in the workspace.
86
82
  #
@@ -231,7 +227,7 @@ module Solargraph
231
227
  # @param namespace [String] A fully qualified namespace
232
228
  # @return [Array<Solargraph::Pin::ClassVariable>]
233
229
  def get_class_variable_pins(namespace)
234
- prefer_non_nil_variables(@cvar_pins[namespace] || [])
230
+ prefer_non_nil_variables(store.get_class_variables(namespace))
235
231
  end
236
232
 
237
233
  # @return [Array<Solargraph::Pin::Base>]
@@ -262,6 +258,11 @@ module Solargraph
262
258
  else
263
259
  result.concat inner_get_methods(fqns, scope, visibility, deep, skip)
264
260
  end
261
+ live = live_map.get_methods(fqns, '', scope.to_s, visibility.include?(:private))
262
+ unless live.empty?
263
+ exist = result.map(&:name)
264
+ result.concat live.reject{|p| exist.include?(p.name)}
265
+ end
265
266
  result
266
267
  end
267
268
 
@@ -295,7 +296,7 @@ module Solargraph
295
296
  if fragment.base.empty?
296
297
  result.concat get_methods(pin.path)
297
298
  else
298
- type = probe.infer_signature_type(fragment.base, pin, fragment.locals)
299
+ type = probe.infer_signature_type("#{pin.path}.new.#{fragment.base}", pin, fragment.locals)
299
300
  unless type.nil?
300
301
  namespace, scope = extract_namespace_and_scope(type)
301
302
  result.concat get_methods(namespace, scope: scope)
@@ -321,7 +322,11 @@ module Solargraph
321
322
  # @return [Array<Solargraph::Pin::Base>]
322
323
  def define fragment
323
324
  return [] if fragment.string? or fragment.comment?
324
- probe.infer_signature_pins fragment.whole_signature, fragment.named_path, fragment.locals
325
+ if fragment.base_literal?
326
+ probe.infer_signature_pins fragment.whole_signature, Pin::ProxyMethod.new(fragment.base_literal), fragment.locals
327
+ else
328
+ probe.infer_signature_pins fragment.whole_signature, fragment.named_path, fragment.locals
329
+ end
325
330
  end
326
331
 
327
332
  # Infer a return type from a fragment. This method will attempt to resolve
@@ -345,9 +350,13 @@ module Solargraph
345
350
  def signify fragment
346
351
  return [] unless fragment.argument?
347
352
  return [] if fragment.recipient.whole_signature.nil? or fragment.recipient.whole_signature.empty?
348
- probe.infer_signature_pins(
349
- fragment.recipient.whole_signature, fragment.named_path, fragment.locals
350
- ).select{ |pin| pin.kind == Pin::METHOD }
353
+ result = []
354
+ if fragment.recipient.base_literal?
355
+ result.concat probe.infer_signature_pins(fragment.recipient.whole_signature, Pin::ProxyMethod.new(fragment.recipient.base_literal), fragment.locals)
356
+ else
357
+ result.concat probe.infer_signature_pins(fragment.recipient.whole_signature, fragment.named_path, fragment.locals)
358
+ end
359
+ result.select{ |pin| pin.kind == Pin::METHOD }
351
360
  end
352
361
 
353
362
  # Get an array of all suggestions that match the specified path.
@@ -359,6 +368,10 @@ module Solargraph
359
368
  result = []
360
369
  result.concat store.get_path_pins(path)
361
370
  result.concat yard_map.objects(path)
371
+ if result.empty?
372
+ lp = live_map.get_path_pin(path)
373
+ result.push lp unless lp.nil?
374
+ end
362
375
  result
363
376
  end
364
377
 
@@ -426,6 +439,12 @@ module Solargraph
426
439
 
427
440
  private
428
441
 
442
+ def refresh_store_and_maps
443
+ @store = ApiMap::Store.new(@sources)
444
+ @live_map = Solargraph::LiveMap.new(self)
445
+ @yard_map = Solargraph::YardMap.new(required: required, workspace: workspace)
446
+ end
447
+
429
448
  def process_virtual
430
449
  unless @virtual_source.nil?
431
450
  map_source @virtual_source
@@ -451,9 +470,7 @@ module Solargraph
451
470
  return [] if skip.include?(reqstr)
452
471
  skip.push reqstr
453
472
  result = []
454
- if scope == :instance
455
- result.concat store.get_attrs(fqns)
456
- end
473
+ result.concat store.get_attrs(fqns, scope)
457
474
  result.concat store.get_methods(fqns, scope: scope, visibility: visibility)
458
475
  if deep
459
476
  sc = store.get_superclass(fqns)
@@ -1,5 +1,8 @@
1
1
  module Solargraph
2
2
  class ApiMap
3
+ # The result of a completion request containing the pins that describe
4
+ # completion options and the range to be replaced.
5
+ #
3
6
  class Completion
4
7
  # @return [Array<Solargraph::Pin::Base>]
5
8
  attr_reader :pins
@@ -1,16 +1,6 @@
1
1
  module Solargraph
2
2
  class ApiMap
3
3
  class Probe
4
- class VirtualPin
5
- attr_reader :return_type
6
- def initialize return_type
7
- @return_type = return_type
8
- end
9
- def namespace
10
- @namespace ||= TypeMethods.extract_namespace(@return_type)
11
- end
12
- end
13
-
14
4
  include TypeMethods
15
5
 
16
6
  # @return [Solargraph::ApiMap]
@@ -29,8 +19,8 @@ module Solargraph
29
19
  return infer_word_pins(base, context_pin, locals) if rest.nil?
30
20
  pins = infer_word_pins(base, context_pin, locals).map do |pin|
31
21
  next pin unless pin.return_type.nil?
32
- type = resolve_pin_type(pin)
33
- VirtualPin.new(type)
22
+ type = resolve_pin_type(pin, locals - [pin])
23
+ Pin::ProxyMethod.new(type)
34
24
  end
35
25
  return [] if pins.empty?
36
26
  rest = rest.split('.')
@@ -58,7 +48,7 @@ module Solargraph
58
48
  def infer_signature_type signature, context_pin, locals
59
49
  pins = infer_signature_pins(signature, context_pin, locals)
60
50
  pins.each do |pin|
61
- type = resolve_pin_type(pin)
51
+ type = resolve_pin_type(pin, locals - [pin])
62
52
  return qualify(type, pin.named_context) unless type.nil?
63
53
  end
64
54
  nil
@@ -75,9 +65,16 @@ module Solargraph
75
65
  namespace, scope = extract_namespace_and_scope_from_pin(context_pin)
76
66
  return api_map.pins.select{|pin| word_matches_context?(word, namespace, scope, pin)} if variable_name?(word)
77
67
  result = []
78
- result.concat api_map.get_path_suggestions(word)
68
+ cparts = namespace.split('::')
69
+ until cparts.empty?
70
+ break unless result.empty?
71
+ cur = cparts.join('::')
72
+ result.concat api_map.get_path_suggestions("#{cur}::#{word}")
73
+ cparts.pop
74
+ end
75
+ result.concat api_map.get_path_suggestions(word) if result.empty?
79
76
  result.concat api_map.get_methods(namespace, scope: scope, visibility: [:public, :private, :protected]).select{|pin| pin.name == word} unless word.include?('::')
80
- result.concat api_map.get_constants('', namespace).select{|pin| pin.name == word}
77
+ result.concat api_map.get_constants('', namespace).select{|pin| pin.name == word} if result.empty?
81
78
  result
82
79
  end
83
80
 
@@ -151,11 +148,11 @@ module Solargraph
151
148
  pin
152
149
  end
153
150
 
154
- def resolve_pin_type pin
151
+ def resolve_pin_type pin, locals
155
152
  pin.return_type
156
153
  return pin.return_type unless pin.return_type.nil?
157
154
  return resolve_block_parameter(pin) if pin.kind == Pin::BLOCK_PARAMETER
158
- return resolve_variable(pin) if pin.variable?
155
+ return resolve_variable(pin, locals) if pin.variable?
159
156
  nil
160
157
  end
161
158
 
@@ -184,10 +181,10 @@ module Solargraph
184
181
  nil
185
182
  end
186
183
 
187
- def resolve_variable(pin)
184
+ def resolve_variable(pin, locals)
188
185
  return nil if pin.nil_assignment?
189
186
  # @todo Do we need the locals here?
190
- return infer_signature_type(pin.signature, pin.context, [])
187
+ return infer_signature_type(pin.signature, pin.context, locals)
191
188
  end
192
189
 
193
190
  def get_subtypes type
@@ -43,8 +43,8 @@ module Solargraph
43
43
  }
44
44
  end
45
45
 
46
- def get_attrs fqns
47
- namespace_pins(fqns).select{ |pin| pin.kind == Pin::ATTRIBUTE }
46
+ def get_attrs fqns, scope
47
+ namespace_pins(fqns).select{ |pin| pin.kind == Pin::ATTRIBUTE and pin.scope == scope }
48
48
  end
49
49
 
50
50
  def get_superclass fqns
@@ -80,6 +80,10 @@ module Solargraph
80
80
  namespace_pins(fqns).select{|pin| pin.kind == Pin::INSTANCE_VARIABLE and pin.scope == scope}
81
81
  end
82
82
 
83
+ def get_class_variables(fqns)
84
+ namespace_pins(fqns).select{|pin| pin.kind == Pin::CLASS_VARIABLE}
85
+ end
86
+
83
87
  def get_symbols
84
88
  symbols.uniq(&:name)
85
89
  end
@@ -15,6 +15,8 @@ module Solargraph
15
15
  @command = command
16
16
  end
17
17
 
18
+ # @param source [Solargraph::Source]
19
+ # @param api_map [Solargraph::ApiMap]
18
20
  # @return [Array<Hash>]
19
21
  def diagnose source, api_map
20
22
  begin
@@ -22,6 +24,10 @@ module Solargraph
22
24
  filename = source.filename
23
25
  raise DiagnosticsError, 'No command specified' if command.nil? or command.empty?
24
26
  cmd = "#{Shellwords.escape(command)} -f j -s #{Shellwords.escape(filename)}"
27
+ unless api_map.workspace.nil? or api_map.workspace.directory.nil?
28
+ rc = File.join(api_map.workspace.directory, '.rubocop.yml')
29
+ cmd += " -c #{Shellwords.escape(rc)}" if File.file?(rc)
30
+ end
25
31
  o, e, s = Open3.capture3(cmd, stdin_data: text)
26
32
  STDERR.puts e unless e.empty?
27
33
  raise DiagnosticsError, "Command '#{command}' is not available (gem exception)" if e.include?('Gem::Exception')
@@ -323,6 +323,14 @@ module Solargraph
323
323
  result
324
324
  end
325
325
 
326
+ def references_from filename, line, column
327
+ result = nil
328
+ @change_semaphore.synchronize do
329
+ result = library.references_from(filename, line, column)
330
+ end
331
+ result
332
+ end
333
+
326
334
  def query_symbols query
327
335
  result = nil
328
336
  @change_semaphore.synchronize { result = library.query_symbols(query) }
@@ -446,7 +454,7 @@ module Solargraph
446
454
  Thread.new do
447
455
  diagnoser = Diagnostics::Rubocop.new
448
456
  until stopped?
449
- sleep 1
457
+ sleep 0.1
450
458
  if !options['diagnostics']
451
459
  @change_semaphore.synchronize { @diagnostics_queue.clear }
452
460
  next
@@ -56,6 +56,8 @@ module Solargraph
56
56
  register 'textDocument/formatting', TextDocument::Formatting
57
57
  register 'textDocument/onTypeFormatting', TextDocument::OnTypeFormatting
58
58
  register 'textDocument/documentSymbol', TextDocument::DocumentSymbol
59
+ register 'textDocument/references', TextDocument::References
60
+ register 'textDocument/rename', TextDocument::Rename
59
61
  register 'workspace/didChangeWatchedFiles', Workspace::DidChangeWatchedFiles
60
62
  register 'workspace/didChangeConfiguration', Workspace::DidChangeConfiguration
61
63
  register 'workspace/symbol', Workspace::WorkspaceSymbol
@@ -64,6 +66,7 @@ module Solargraph
64
66
  register '$/solargraph/search', Extended::Search
65
67
  register '$/solargraph/checkGemVersion', Extended::CheckGemVersion
66
68
  register '$/solargraph/documentGems', Extended::DocumentGems
69
+ register '$/solargraph/downloadCore', Extended::DownloadCore
67
70
  register 'shutdown', Shutdown
68
71
  register 'exit', ExitNotification
69
72
  end
@@ -11,6 +11,7 @@ module Solargraph
11
11
  autoload :Search, 'solargraph/language_server/message/extended/search'
12
12
  autoload :CheckGemVersion, 'solargraph/language_server/message/extended/check_gem_version'
13
13
  autoload :DocumentGems, 'solargraph/language_server/message/extended/document_gems'
14
+ autoload :DownloadCore, 'solargraph/language_server/message/extended/download_core'
14
15
  end
15
16
  end
16
17
  end
@@ -11,7 +11,7 @@ module Solargraph
11
11
  class CheckGemVersion < Base
12
12
  def process
13
13
  o, s = Open3.capture2("gem search solargraph")
14
- match = o.match(/solargraph \([0-9\.]*?\)/)
14
+ match = o.match(/solargraph \(([\d]*\.[\d]*\.[\d]*)\)/)
15
15
  # @todo Error if no match or status code != 0
16
16
  available = Gem::Version.new(match[1])
17
17
  current = Gem::Version.new(Solargraph::VERSION)
@@ -0,0 +1,25 @@
1
+ require 'open3'
2
+
3
+ module Solargraph
4
+ module LanguageServer
5
+ module Message
6
+ module Extended
7
+ # Update core Ruby documentation.
8
+ #
9
+ class DownloadCore < Base
10
+ def process
11
+ cmd = "solargraph download-core"
12
+ o, s = Open3.capture2(cmd)
13
+ if s != 0
14
+ host.show_message "An error occurred while downloading documentation.", LanguageServer::MessageTypes::ERROR
15
+ else
16
+ ver = o.match(/[\d]*\.[\d]*\.[\d]*/)[0]
17
+ host.show_message "Downloaded documentation for Ruby #{ver}.", LanguageServer::MessageTypes::INFO
18
+ # @todo YardMap should be refreshed
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -11,12 +11,14 @@ module Solargraph
11
11
  definitionProvider: true,
12
12
  documentSymbolProvider: true,
13
13
  workspaceSymbolProvider: true,
14
+ renameProvider: true,
14
15
  workspace: {
15
16
  workspaceFolders: {
16
17
  supported: true,
17
18
  changeNotifications: true
18
19
  }
19
- }
20
+ },
21
+ referencesProvider: true
20
22
  }
21
23
  }
22
24
  result[:capabilities].merge! static_completion unless dynamic_completion?
@@ -2,19 +2,21 @@ module Solargraph
2
2
  module LanguageServer
3
3
  module Message
4
4
  module TextDocument
5
- autoload :Base, 'solargraph/language_server/message/text_document/base'
6
- autoload :Completion, 'solargraph/language_server/message/text_document/completion'
7
- autoload :DidOpen, 'solargraph/language_server/message/text_document/did_open'
8
- autoload :DidChange, 'solargraph/language_server/message/text_document/did_change'
9
- autoload :DidClose, 'solargraph/language_server/message/text_document/did_close'
10
- autoload :DidSave, 'solargraph/language_server/message/text_document/did_save'
11
- autoload :Hover, 'solargraph/language_server/message/text_document/hover'
12
- autoload :SignatureHelp, 'solargraph/language_server/message/text_document/signature_help'
5
+ autoload :Base, 'solargraph/language_server/message/text_document/base'
6
+ autoload :Completion, 'solargraph/language_server/message/text_document/completion'
7
+ autoload :DidOpen, 'solargraph/language_server/message/text_document/did_open'
8
+ autoload :DidChange, 'solargraph/language_server/message/text_document/did_change'
9
+ autoload :DidClose, 'solargraph/language_server/message/text_document/did_close'
10
+ autoload :DidSave, 'solargraph/language_server/message/text_document/did_save'
11
+ autoload :Hover, 'solargraph/language_server/message/text_document/hover'
12
+ autoload :SignatureHelp, 'solargraph/language_server/message/text_document/signature_help'
13
13
  autoload :DiagnosticsQueue, 'solargraph/language_server/message/text_document/diagnostics_queue'
14
14
  autoload :OnTypeFormatting, 'solargraph/language_server/message/text_document/on_type_formatting'
15
- autoload :Definition, 'solargraph/language_server/message/text_document/definition'
16
- autoload :DocumentSymbol, 'solargraph/language_server/message/text_document/document_symbol'
17
- autoload :Formatting, 'solargraph/language_server/message/text_document/formatting'
15
+ autoload :Definition, 'solargraph/language_server/message/text_document/definition'
16
+ autoload :DocumentSymbol, 'solargraph/language_server/message/text_document/document_symbol'
17
+ autoload :Formatting, 'solargraph/language_server/message/text_document/formatting'
18
+ autoload :References, 'solargraph/language_server/message/text_document/references'
19
+ autoload :Rename, 'solargraph/language_server/message/text_document/rename'
18
20
  end
19
21
  end
20
22
  end
@@ -11,7 +11,7 @@ module Solargraph::LanguageServer::Message::TextDocument
11
11
  line = params['position']['line']
12
12
  col = params['position']['character']
13
13
  suggestions = host.definitions_at(filename, line, col)
14
- locations = suggestions.map do |pin|
14
+ locations = suggestions.reject{|pin| pin.location.nil?}.map do |pin|
15
15
  unless pin.location.nil?
16
16
  {
17
17
  uri: file_to_uri(pin.location.filename),