solargraph 0.29.5 → 0.30.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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/solargraph.rb +1 -0
  3. data/lib/solargraph/api_map.rb +22 -13
  4. data/lib/solargraph/language_server/host.rb +121 -33
  5. data/lib/solargraph/language_server/host/cataloger.rb +5 -4
  6. data/lib/solargraph/language_server/message.rb +3 -0
  7. data/lib/solargraph/language_server/message/extended.rb +5 -4
  8. data/lib/solargraph/language_server/message/extended/document.rb +1 -1
  9. data/lib/solargraph/language_server/message/extended/environment.rb +20 -0
  10. data/lib/solargraph/language_server/message/extended/search.rb +1 -1
  11. data/lib/solargraph/language_server/message/initialize.rb +28 -4
  12. data/lib/solargraph/language_server/message/initialized.rb +1 -0
  13. data/lib/solargraph/language_server/message/text_document.rb +1 -0
  14. data/lib/solargraph/language_server/message/text_document/folding_range.rb +24 -0
  15. data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -0
  16. data/lib/solargraph/language_server/message/workspace.rb +4 -3
  17. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +1 -0
  18. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +3 -6
  19. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -0
  20. data/lib/solargraph/language_server/transport.rb +1 -2
  21. data/lib/solargraph/language_server/transport/{socket.rb → adapter.rb} +8 -10
  22. data/lib/solargraph/library.rb +29 -3
  23. data/lib/solargraph/logging.rb +25 -0
  24. data/lib/solargraph/page.rb +14 -4
  25. data/lib/solargraph/pin/documenting.rb +1 -1
  26. data/lib/solargraph/shell.rb +9 -10
  27. data/lib/solargraph/source.rb +59 -5
  28. data/lib/solargraph/source/encoding_fixes.rb +1 -1
  29. data/lib/solargraph/source_map/mapper.rb +14 -8
  30. data/lib/solargraph/version.rb +1 -1
  31. data/lib/solargraph/views/_method.erb +3 -0
  32. data/lib/solargraph/views/environment.erb +50 -0
  33. data/lib/solargraph/views/layout.erb +6 -0
  34. data/lib/solargraph/yard_map.rb +8 -8
  35. metadata +11 -13
  36. data/lib/solargraph/language_server/transport/stdio.rb +0 -63
@@ -12,8 +12,8 @@ module Solargraph
12
12
  # Notify the Cataloger that changes are pending.
13
13
  #
14
14
  # @return [void]
15
- def ping
16
- mutex.synchronize { pings.push nil }
15
+ def ping lib
16
+ mutex.synchronize { pings.push lib }
17
17
  end
18
18
 
19
19
  def synchronizing?
@@ -45,8 +45,9 @@ module Solargraph
45
45
  sleep 0.1
46
46
  next if pings.empty?
47
47
  mutex.synchronize do
48
- host.catalog
49
- pings.clear
48
+ lib = pings.shift
49
+ next if pings.include?(lib)
50
+ host.catalog lib
50
51
  end
51
52
  end
52
53
  end
@@ -70,8 +70,10 @@ module Solargraph
70
70
  register 'textDocument/documentSymbol', TextDocument::DocumentSymbol
71
71
  register 'textDocument/references', TextDocument::References
72
72
  register 'textDocument/rename', TextDocument::Rename
73
+ register 'textDocument/foldingRange', TextDocument::FoldingRange
73
74
  register 'workspace/didChangeWatchedFiles', Workspace::DidChangeWatchedFiles
74
75
  register 'workspace/didChangeConfiguration', Workspace::DidChangeConfiguration
76
+ register 'workspace/didChangeWorkspaceFolders', Workspace::DidChangeWorkspaceFolders
75
77
  register 'workspace/symbol', Workspace::WorkspaceSymbol
76
78
  register '$/cancelRequest', CancelRequest
77
79
  register '$/solargraph/document', Extended::Document
@@ -79,6 +81,7 @@ module Solargraph
79
81
  register '$/solargraph/checkGemVersion', Extended::CheckGemVersion
80
82
  register '$/solargraph/documentGems', Extended::DocumentGems
81
83
  register '$/solargraph/downloadCore', Extended::DownloadCore
84
+ register '$/solargraph/environment', Extended::Environment
82
85
  register 'shutdown', Shutdown
83
86
  register 'exit', ExitNotification
84
87
  end
@@ -7,11 +7,12 @@ module Solargraph
7
7
  # ignore them, as per the LSP specification.
8
8
  #
9
9
  module Extended
10
- autoload :Document, 'solargraph/language_server/message/extended/document'
11
- autoload :Search, 'solargraph/language_server/message/extended/search'
10
+ autoload :Document, 'solargraph/language_server/message/extended/document'
11
+ autoload :Search, 'solargraph/language_server/message/extended/search'
12
12
  autoload :CheckGemVersion, 'solargraph/language_server/message/extended/check_gem_version'
13
- autoload :DocumentGems, 'solargraph/language_server/message/extended/document_gems'
14
- autoload :DownloadCore, 'solargraph/language_server/message/extended/download_core'
13
+ autoload :DocumentGems, 'solargraph/language_server/message/extended/document_gems'
14
+ autoload :DownloadCore, 'solargraph/language_server/message/extended/download_core'
15
+ autoload :Environment, 'solargraph/language_server/message/extended/environment'
15
16
  end
16
17
  end
17
18
  end
@@ -6,7 +6,7 @@ module Solargraph
6
6
  def process
7
7
  objects = host.document(params['query'])
8
8
  page = Solargraph::Page.new(host.options['viewsPath'])
9
- content = page.render('document', locals: {objects: objects})
9
+ content = page.render('document', layout: true, locals: {objects: objects})
10
10
  set_result(
11
11
  content: content
12
12
  )
@@ -0,0 +1,20 @@
1
+ module Solargraph
2
+ module LanguageServer
3
+ module Message
4
+ module Extended
5
+ # Update YARD documentation for installed gems. If the `rebuild`
6
+ # parameter is true, rebuild existing yardocs.
7
+ #
8
+ class Environment < Base
9
+ def process
10
+ page = Solargraph::Page.new(host.options['viewsPath'])
11
+ content = page.render('environment', layout: true, locals: { config: host.options, folders: host.folders })
12
+ set_result(
13
+ content: content
14
+ )
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -6,7 +6,7 @@ module Solargraph
6
6
  def process
7
7
  results = host.search(params['query'])
8
8
  page = Solargraph::Page.new(host.options['viewsPath'])
9
- content = page.render('search', locals: {query: params['query'], results: results})
9
+ content = page.render('search', layout: true, locals: {query: params['query'], results: results})
10
10
  set_result(
11
11
  content: content
12
12
  )
@@ -4,7 +4,10 @@ module Solargraph
4
4
  class Initialize < Base
5
5
  def process
6
6
  host.configure params['initializationOptions']
7
- if params['rootUri']
7
+ if support_workspace_folders?
8
+ # @todo Prepare multiple folders
9
+ host.prepare_folders params['workspaceFolders']
10
+ elsif params['rootUri']
8
11
  host.prepare UriHelpers.uri_to_file(params['rootUri'])
9
12
  else
10
13
  host.prepare params['rootPath']
@@ -30,11 +33,18 @@ module Solargraph
30
33
  result[:capabilities].merge! static_rename unless dynamic_registration_for?('textDocument', 'rename')
31
34
  result[:capabilities].merge! static_references unless dynamic_registration_for?('textDocument', 'references')
32
35
  result[:capabilities].merge! static_workspace_symbols unless dynamic_registration_for?('workspace', 'symbol')
36
+ result[:capabilities].merge! static_folding_range unless dynamic_registration_for?('textDocument', 'foldingRange')
33
37
  set_result result
34
38
  end
35
39
 
36
40
  private
37
41
 
42
+ def support_workspace_folders?
43
+ params['capabilities'] &&
44
+ params['capabilities']['workspace'] &&
45
+ params['capabilities']['workspace']['workspaceFolders']
46
+ end
47
+
38
48
  def static_completion
39
49
  {
40
50
  completionProvider: {
@@ -103,11 +113,25 @@ module Solargraph
103
113
  }
104
114
  end
105
115
 
116
+ def static_references
117
+ {
118
+ referencesProvider: true
119
+ }
120
+ end
121
+
122
+ def static_folding_range
123
+ {
124
+ foldingRangeProvider: true
125
+ }
126
+ end
127
+
128
+ # @param section [String]
129
+ # @param capability [String]
106
130
  # @return [Boolean]
107
131
  def dynamic_registration_for? section, capability
108
- result = (params['capabilities'] and
109
- params['capabilities'][section] and
110
- params['capabilities'][section][capability] and
132
+ result = (params['capabilities'] &&
133
+ params['capabilities'][section] &&
134
+ params['capabilities'][section][capability] &&
111
135
  params['capabilities'][section][capability]['dynamicRegistration'])
112
136
  host.allow_registration("#{section}/#{capability}") if result
113
137
  result
@@ -12,6 +12,7 @@ module Solargraph
12
12
  textDocument/definition
13
13
  textDocument/references
14
14
  textDocument/rename
15
+ textDocument/foldingRange
15
16
  workspace/symbol
16
17
  ]
17
18
  end
@@ -17,6 +17,7 @@ module Solargraph
17
17
  autoload :Formatting, 'solargraph/language_server/message/text_document/formatting'
18
18
  autoload :References, 'solargraph/language_server/message/text_document/references'
19
19
  autoload :Rename, 'solargraph/language_server/message/text_document/rename'
20
+ autoload :FoldingRange, 'solargraph/language_server/message/text_document/folding_range'
20
21
  end
21
22
  end
22
23
  end
@@ -0,0 +1,24 @@
1
+ require 'open3'
2
+
3
+ module Solargraph
4
+ module LanguageServer
5
+ module Message
6
+ module TextDocument
7
+ class FoldingRange < Base
8
+ def process
9
+ result = host.folding_ranges(params['textDocument']['uri']).map do |range|
10
+ {
11
+ startLine: range.start.line,
12
+ startCharacter: 0,
13
+ endLine: range.ending.line - 1,
14
+ endCharacter: 0,
15
+ kind: 'region'
16
+ }
17
+ end
18
+ set_result result
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,4 +1,5 @@
1
1
  require 'open3'
2
+ require 'shellwords'
2
3
 
3
4
  module Solargraph
4
5
  module LanguageServer
@@ -2,9 +2,10 @@ module Solargraph
2
2
  module LanguageServer
3
3
  module Message
4
4
  module Workspace
5
- autoload :DidChangeWatchedFiles, 'solargraph/language_server/message/workspace/did_change_watched_files'
6
- autoload :WorkspaceSymbol, 'solargraph/language_server/message/workspace/workspace_symbol'
7
- autoload :DidChangeConfiguration, 'solargraph/language_server/message/workspace/did_change_configuration'
5
+ autoload :DidChangeWatchedFiles, 'solargraph/language_server/message/workspace/did_change_watched_files'
6
+ autoload :WorkspaceSymbol, 'solargraph/language_server/message/workspace/workspace_symbol'
7
+ autoload :DidChangeConfiguration, 'solargraph/language_server/message/workspace/did_change_configuration'
8
+ autoload :DidChangeWorkspaceFolders, 'solargraph/language_server/message/workspace/did_change_workspace_folders'
8
9
  end
9
10
  end
10
11
  end
@@ -20,6 +20,7 @@ module Solargraph::LanguageServer::Message::Workspace
20
20
  (host.options['symbols'] ? y : n).push('textDocument/documentSymbol', 'workspace/symbol')
21
21
  (host.options['definitions'] ? y : n).push('textDocument/definition')
22
22
  (host.options['references'] ? y : n).push('textDocument/references')
23
+ (host.options['folding'] ? y : n).push('textDocument/folding')
23
24
  host.register_capabilities y
24
25
  host.unregister_capabilities n
25
26
  end
@@ -11,14 +11,11 @@ module Solargraph::LanguageServer::Message::Workspace
11
11
  def process
12
12
  # @param change [Hash]
13
13
  params['changes'].each do |change|
14
+ # @todo Changes might need to be handled here even if the file is open
14
15
  if change['type'] == CREATED
15
- # It's only necessary to create the file from if the file isn't open
16
- # in the client
17
- host.create change['uri'] unless host.open?(change['uri'])
16
+ host.create change['uri'] #unless host.open?(change['uri'])
18
17
  elsif change['type'] == CHANGED
19
- # It's only necessary to update from here if the file isn't open in
20
- # the client
21
- host.create change['uri'] unless host.open?(change['uri'])
18
+ host.create change['uri'] #unless host.open?(change['uri'])
22
19
  elsif change['type'] == DELETED
23
20
  host.delete change['uri']
24
21
  else
@@ -0,0 +1,24 @@
1
+ require 'uri'
2
+
3
+ module Solargraph::LanguageServer::Message::Workspace
4
+ class DidChangeWorkspaceFolders < Solargraph::LanguageServer::Message::Base
5
+ def process
6
+ add_folders
7
+ remove_folders
8
+ end
9
+
10
+ private
11
+
12
+ def add_folders
13
+ return unless params['event'] && params['event']['added']
14
+ host.prepare_folders params['event']['added']
15
+ end
16
+
17
+ def remove_folders
18
+ return unless params['event'] && params['event']['removed']
19
+ params['event']['removed'].each do |folder|
20
+ host.remove_folders params['event']['removed']
21
+ end
22
+ end
23
+ end
24
+ end
@@ -4,9 +4,8 @@ module Solargraph
4
4
  # communication protocols for language servers.
5
5
  #
6
6
  module Transport
7
+ autoload :Adapter, 'solargraph/language_server/transport/adapter'
7
8
  autoload :DataReader, 'solargraph/language_server/transport/data_reader'
8
- autoload :Socket, 'solargraph/language_server/transport/socket'
9
- autoload :Stdio, 'solargraph/language_server/transport/stdio'
10
9
  end
11
10
  end
12
11
  end
@@ -1,12 +1,10 @@
1
- require 'thread'
2
-
3
1
  module Solargraph
4
2
  module LanguageServer
5
3
  module Transport
6
- # A module for running language servers in EventMachine.
4
+ # A common module for running language servers in Backport.
7
5
  #
8
- module Socket
9
- def post_init
6
+ module Adapter
7
+ def opening
10
8
  @host = Solargraph::LanguageServer::Host.new
11
9
  @data_reader = Solargraph::LanguageServer::Transport::DataReader.new
12
10
  @data_reader.set_message_handler do |message|
@@ -19,25 +17,25 @@ module Solargraph
19
17
  message = @host.start(request)
20
18
  message.send_response
21
19
  tmp = @host.flush
22
- send_data tmp unless tmp.empty?
20
+ write tmp unless tmp.empty?
23
21
  end
24
22
 
25
23
  # @param data [String]
26
- def receive_data data
24
+ def sending data
27
25
  @data_reader.receive data
28
26
  end
29
27
 
30
28
  private
31
29
 
32
30
  def start_timers
33
- EventMachine.add_periodic_timer 0.1 do
31
+ Backport.prepare_interval 0.1 do
34
32
  tmp = @host.flush
35
- send_data tmp unless tmp.empty?
33
+ write tmp unless tmp.empty?
36
34
  if @host.stopped?
37
35
  if @host.options['transport'] == 'external'
38
36
  @host = Solargraph::LanguageServer::Host.new
39
37
  else
40
- EventMachine.stop
38
+ Backport.stop
41
39
  end
42
40
  end
43
41
  end
@@ -2,12 +2,18 @@ module Solargraph
2
2
  # A Library handles coordination between a Workspace and an ApiMap.
3
3
  #
4
4
  class Library
5
+ include Logging
6
+
5
7
  # @return [Solargraph::Workspace]
6
8
  attr_reader :workspace
7
9
 
10
+ # @return [String, nil]
11
+ attr_reader :name
12
+
8
13
  # @param workspace [Solargraph::Workspace]
9
- def initialize workspace = Solargraph::Workspace.new
14
+ def initialize workspace = Solargraph::Workspace.new, name = nil
10
15
  @workspace = workspace
16
+ @name = name
11
17
  api_map.catalog bundle
12
18
  @synchronized = true
13
19
  end
@@ -37,6 +43,16 @@ module Solargraph
37
43
  end
38
44
  end
39
45
 
46
+ def open_from_disk filename
47
+ mutex.synchronize do
48
+ source = Solargraph::Source.load(filename)
49
+ workspace.merge source
50
+ open_file_hash[filename] = source
51
+ checkout filename
52
+ catalog
53
+ end
54
+ end
55
+
40
56
  # True if the specified file is currently open.
41
57
  #
42
58
  # @param filename [String]
@@ -318,16 +334,26 @@ module Solargraph
318
334
  #
319
335
  # @return [void]
320
336
  def catalog
337
+ logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
321
338
  api_map.catalog bundle
322
339
  @synchronized = true
323
340
  end
324
341
 
342
+ def folding_ranges filename
343
+ read(filename).folding_ranges
344
+ end
345
+
346
+ # @return [Array<Source>]
347
+ def open_sources
348
+ open_file_hash.values
349
+ end
350
+
325
351
  # Create a library from a directory.
326
352
  #
327
353
  # @param directory [String] The path to be used for the workspace
328
354
  # @return [Solargraph::Library]
329
- def self.load directory = ''
330
- Solargraph::Library.new(Solargraph::Workspace.new(directory))
355
+ def self.load directory = '', name = nil
356
+ Solargraph::Library.new(Solargraph::Workspace.new(directory), name)
331
357
  end
332
358
 
333
359
  private
@@ -0,0 +1,25 @@
1
+ require 'logger'
2
+
3
+ module Solargraph
4
+ module Logging
5
+ DEFAULT_LOG_LEVEL = Logger::WARN
6
+
7
+ LOG_LEVELS = {
8
+ 'warn' => Logger::WARN,
9
+ 'info' => Logger::INFO,
10
+ 'debug' => Logger::DEBUG
11
+ }
12
+
13
+ @@logger = Logger.new(STDERR, level: DEFAULT_LOG_LEVEL)
14
+ @@logger.formatter = proc do |severity, datetime, progname, msg|
15
+ "[#{severity}] #{msg}\n"
16
+ end
17
+
18
+ module_function
19
+
20
+ # @return [Logger]
21
+ def logger
22
+ @@logger
23
+ end
24
+ end
25
+ end
@@ -2,7 +2,7 @@ require 'ostruct'
2
2
  require 'tilt'
3
3
  require 'kramdown'
4
4
  require 'htmlentities'
5
- require 'reverse_markdown'
5
+ require 'cgi'
6
6
 
7
7
  module Solargraph
8
8
  class Page
@@ -39,14 +39,16 @@ module Solargraph
39
39
 
40
40
  def initialize directory = VIEWS_PATH
41
41
  directory = VIEWS_PATH if directory.nil? or !File.directory?(directory)
42
+ directories = [directory]
43
+ directories.push VIEWS_PATH if directory != VIEWS_PATH
42
44
  @render_method = proc { |template, layout: false, locals: {}|
43
45
  binder = Binder.new(locals, @render_method)
44
46
  if layout
45
- Tilt::ERBTemplate.new(File.join(directory, 'layout.erb')).render(binder) do
46
- Tilt::ERBTemplate.new(File.join(directory, "#{template}.erb")).render(binder)
47
+ Tilt::ERBTemplate.new(Page.select_template(directories, 'layout')).render(binder) do
48
+ Tilt::ERBTemplate.new(Page.select_template(directories, template)).render(binder)
47
49
  end
48
50
  else
49
- Tilt::ERBTemplate.new(File.join(directory, "#{template}.erb")).render(binder)
51
+ Tilt::ERBTemplate.new(Page.select_template(directories, template)).render(binder)
50
52
  end
51
53
  }
52
54
  end
@@ -54,5 +56,13 @@ module Solargraph
54
56
  def render template, layout: true, locals: {}
55
57
  @render_method.call(template, layout: layout, locals: locals)
56
58
  end
59
+
60
+ def self.select_template directories, name
61
+ directories.each do |dir|
62
+ path = File.join(dir, "#{name}.erb")
63
+ return path if File.file?(path)
64
+ end
65
+ raise FileNotFoundError, "Template not found: #{name}"
66
+ end
57
67
  end
58
68
  end