ruby-lsp 0.4.5 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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 +1 -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.0
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