ruby-lsp 0.4.5 → 0.5.1

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -86
  3. data/VERSION +1 -1
  4. data/lib/ruby_lsp/check_docs.rb +112 -0
  5. data/lib/ruby_lsp/document.rb +13 -2
  6. data/lib/ruby_lsp/event_emitter.rb +84 -18
  7. data/lib/ruby_lsp/executor.rb +126 -48
  8. data/lib/ruby_lsp/internal.rb +2 -0
  9. data/lib/ruby_lsp/listener.rb +6 -13
  10. data/lib/ruby_lsp/requests/base_request.rb +0 -5
  11. data/lib/ruby_lsp/requests/code_action_resolve.rb +1 -1
  12. data/lib/ruby_lsp/requests/code_actions.rb +1 -1
  13. data/lib/ruby_lsp/requests/code_lens.rb +82 -66
  14. data/lib/ruby_lsp/requests/diagnostics.rb +2 -2
  15. data/lib/ruby_lsp/requests/document_highlight.rb +1 -1
  16. data/lib/ruby_lsp/requests/document_link.rb +17 -15
  17. data/lib/ruby_lsp/requests/document_symbol.rb +51 -31
  18. data/lib/ruby_lsp/requests/folding_ranges.rb +1 -1
  19. data/lib/ruby_lsp/requests/formatting.rb +10 -11
  20. data/lib/ruby_lsp/requests/hover.rb +20 -20
  21. data/lib/ruby_lsp/requests/inlay_hints.rb +1 -1
  22. data/lib/ruby_lsp/requests/on_type_formatting.rb +1 -1
  23. data/lib/ruby_lsp/requests/path_completion.rb +21 -57
  24. data/lib/ruby_lsp/requests/selection_ranges.rb +1 -1
  25. data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -1
  26. data/lib/ruby_lsp/requests/support/common.rb +36 -0
  27. data/lib/ruby_lsp/requests/support/rubocop_diagnostics_runner.rb +0 -1
  28. data/lib/ruby_lsp/requests/support/rubocop_formatting_runner.rb +0 -1
  29. data/lib/ruby_lsp/requests/support/syntax_tree_formatting_runner.rb +5 -2
  30. data/lib/ruby_lsp/requests.rb +15 -15
  31. data/lib/ruby_lsp/server.rb +44 -20
  32. data/lib/ruby_lsp/store.rb +1 -1
  33. data/lib/ruby_lsp/utils.rb +2 -7
  34. metadata +3 -2
@@ -23,7 +23,32 @@ module RubyLsp
23
23
  @jobs = T.let({}, T::Hash[T.any(String, Integer), Job])
24
24
  @mutex = T.let(Mutex.new, Mutex)
25
25
  @worker = T.let(new_worker, Thread)
26
- @current_request_id = T.let(1, Integer)
26
+
27
+ # The messages queue includes requests and notifications to be sent to the client
28
+ @message_queue = T.let(Thread::Queue.new, Thread::Queue)
29
+
30
+ # Create a thread to watch the messages queue and send them to the client
31
+ @message_dispatcher = T.let(
32
+ Thread.new do
33
+ current_request_id = 1
34
+
35
+ loop do
36
+ message = @message_queue.pop
37
+ break if message.nil?
38
+
39
+ @mutex.synchronize do
40
+ case message
41
+ when Notification
42
+ @writer.write(method: message.message, params: message.params)
43
+ when Request
44
+ @writer.write(id: current_request_id, method: message.message, params: message.params)
45
+ current_request_id += 1
46
+ end
47
+ end
48
+ end
49
+ end,
50
+ Thread,
51
+ )
27
52
 
28
53
  Thread.main.priority = 1
29
54
  end
@@ -36,9 +61,8 @@ module RubyLsp
36
61
  # fall under the else branch which just pushes requests to the queue
37
62
  @reader.read do |request|
38
63
  case request[:method]
39
- when "initialize", "initialized", "textDocument/didOpen", "textDocument/didClose", "textDocument/didChange",
40
- "textDocument/formatting", "textDocument/onTypeFormatting", "codeAction/resolve"
41
- result = Executor.new(@store).execute(request)
64
+ when "initialize", "initialized", "textDocument/didOpen", "textDocument/didClose", "textDocument/didChange"
65
+ result = Executor.new(@store, @message_queue).execute(request)
42
66
  finalize_request(result, request)
43
67
  when "$/cancelRequest"
44
68
  # Cancel the job if it's still in the queue
@@ -46,6 +70,7 @@ module RubyLsp
46
70
  when "shutdown"
47
71
  warn("Shutting down Ruby LSP...")
48
72
 
73
+ @message_queue.close
49
74
  # Close the queue so that we can no longer receive items
50
75
  @job_queue.close
51
76
  # Clear any remaining jobs so that the thread can terminate
@@ -53,9 +78,10 @@ module RubyLsp
53
78
  @jobs.clear
54
79
  # Wait until the thread is finished
55
80
  @worker.join
81
+ @message_dispatcher.join
56
82
  @store.clear
57
83
 
58
- finalize_request(Result.new(response: nil, messages: []), request)
84
+ finalize_request(Result.new(response: nil), request)
59
85
  when "exit"
60
86
  # We return zero if shutdown has already been received or one otherwise as per the recommendation in the spec
61
87
  # https://microsoft.github.io/language-server-protocol/specification/#exit
@@ -66,8 +92,17 @@ module RubyLsp
66
92
  # Default case: push the request to the queue to be executed by the worker
67
93
  job = Job.new(request: request, cancelled: false)
68
94
 
69
- # Remember a handle to the job, so that we can cancel it
70
- @mutex.synchronize { @jobs[request[:id]] = job }
95
+ @mutex.synchronize do
96
+ # Remember a handle to the job, so that we can cancel it
97
+ @jobs[request[:id]] = job
98
+
99
+ # We must parse the document under a mutex lock or else we might switch threads and accept text edits in the
100
+ # source. Altering the source reference during parsing will put the parser in an invalid internal state,
101
+ # since it started parsing with one source but then it changed in the middle
102
+ uri = request.dig(:params, :textDocument, :uri)
103
+ @store.get(uri).parse if uri
104
+ end
105
+
71
106
  @job_queue << job
72
107
  end
73
108
  end
@@ -89,9 +124,9 @@ module RubyLsp
89
124
 
90
125
  result = if job.cancelled
91
126
  # We need to return nil to the client even if the request was cancelled
92
- Result.new(response: nil, messages: [])
127
+ Result.new(response: nil)
93
128
  else
94
- Executor.new(@store).execute(request)
129
+ Executor.new(@store, @message_queue).execute(request)
95
130
  end
96
131
 
97
132
  finalize_request(result, request)
@@ -119,17 +154,6 @@ module RubyLsp
119
154
  @writer.write(id: request[:id], result: response)
120
155
  end
121
156
 
122
- # If the response include any messages, go through them and publish each one
123
- result.messages.each do |n|
124
- case n
125
- when Notification
126
- @writer.write(method: n.message, params: n.params)
127
- when Request
128
- @writer.write(id: @current_request_id, method: n.message, params: n.params)
129
- @current_request_id += 1
130
- end
131
- end
132
-
133
157
  request_time = result.request_time
134
158
  if request_time
135
159
  @writer.write(method: "telemetry/event", params: telemetry_params(request, request_time, error))
@@ -61,7 +61,7 @@ module RubyLsp
61
61
  type_parameters(:T)
62
62
  .params(
63
63
  uri: String,
64
- request_name: Symbol,
64
+ request_name: String,
65
65
  block: T.proc.params(document: Document).returns(T.type_parameter(:T)),
66
66
  ).returns(T.type_parameter(:T))
67
67
  end
@@ -6,7 +6,7 @@ module RubyLsp
6
6
  VOID = T.let(Object.new.freeze, Object)
7
7
 
8
8
  # This freeze is not redundant since the interpolated string is mutable
9
- WORKSPACE_URI = T.let("file://#{Dir.pwd}".freeze, String) # rubocop:disable Style/RedundantFreeze
9
+ WORKSPACE_URI = T.let(URI("file://#{Dir.pwd}".freeze), URI::Generic) # rubocop:disable Style/RedundantFreeze
10
10
 
11
11
  # A notification to be sent to the client
12
12
  class Message
@@ -38,9 +38,6 @@ module RubyLsp
38
38
  sig { returns(T.untyped) }
39
39
  attr_reader :response
40
40
 
41
- sig { returns(T::Array[Message]) }
42
- attr_reader :messages
43
-
44
41
  sig { returns(T.nilable(Exception)) }
45
42
  attr_reader :error
46
43
 
@@ -50,14 +47,12 @@ module RubyLsp
50
47
  sig do
51
48
  params(
52
49
  response: T.untyped,
53
- messages: T::Array[Message],
54
50
  error: T.nilable(Exception),
55
51
  request_time: T.nilable(Float),
56
52
  ).void
57
53
  end
58
- def initialize(response:, messages:, error: nil, request_time: nil)
54
+ def initialize(response:, error: nil, request_time: nil)
59
55
  @response = response
60
- @messages = messages
61
56
  @error = error
62
57
  @request_time = request_time
63
58
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lsp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-21 00:00:00.000000000 Z
11
+ date: 2023-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: language_server-protocol
@@ -72,6 +72,7 @@ files:
72
72
  - exe/ruby-lsp
73
73
  - lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb
74
74
  - lib/ruby-lsp.rb
75
+ - lib/ruby_lsp/check_docs.rb
75
76
  - lib/ruby_lsp/document.rb
76
77
  - lib/ruby_lsp/event_emitter.rb
77
78
  - lib/ruby_lsp/executor.rb