Class: RubyLsp::Server
- Inherits:
-
Object
- Object
- RubyLsp::Server
- Extended by:
- T::Sig
- Defined in:
- lib/ruby_lsp/server.rb
Overview
rubocop:enable RubyLsp/UseLanguageServerAliases
Instance Method Summary collapse
-
#initialize ⇒ Server
constructor
A new instance of Server.
- #start ⇒ Object
Constructor Details
permalink #initialize ⇒ Server
Returns a new instance of Server.
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/ruby_lsp/server.rb', line 15 def initialize @writer = T.let(Transport::Stdio::Writer.new, Transport::Stdio::Writer) @reader = T.let(Transport::Stdio::Reader.new, Transport::Stdio::Reader) @store = T.let(Store.new, Store) # The job queue is the actual list of requests we have to process @job_queue = T.let(Thread::Queue.new, Thread::Queue) # The jobs hash is just a way of keeping a handle to jobs based on the request ID, so we can cancel them @jobs = T.let({}, T::Hash[T.any(String, Integer), Job]) @mutex = T.let(Mutex.new, Mutex) @worker = T.let(new_worker, Thread) # The messages queue includes requests and notifications to be sent to the client @message_queue = T.let(Thread::Queue.new, Thread::Queue) # The executor is responsible for executing requests @executor = T.let(Executor.new(@store, @message_queue), Executor) # Create a thread to watch the messages queue and send them to the client @message_dispatcher = T.let( Thread.new do current_request_id = 1 loop do = @message_queue.pop break if .nil? @mutex.synchronize do case when Notification @writer.write(method: ., params: .params) when Request @writer.write(id: current_request_id, method: ., params: .params) current_request_id += 1 end end end end, Thread, ) Thread.main.priority = 1 end |
Instance Method Details
permalink #start ⇒ Object
[View source]
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/ruby_lsp/server.rb', line 60 def start warn("Starting Ruby LSP...") # Requests that have to be executed sequentially or in the main process are implemented here. All other requests # fall under the else branch which just pushes requests to the queue @reader.read do |request| case request[:method] when "initialize", "initialized", "textDocument/didOpen", "textDocument/didClose", "textDocument/didChange" result = @executor.execute(request) finalize_request(result, request) when "$/cancelRequest" # Cancel the job if it's still in the queue @mutex.synchronize { @jobs[request[:params][:id]]&.cancel } when "shutdown" warn("Shutting down Ruby LSP...") @message_queue.close # Close the queue so that we can no longer receive items @job_queue.close # Clear any remaining jobs so that the thread can terminate @job_queue.clear @jobs.clear # Wait until the thread is finished @worker.join @message_dispatcher.join @store.clear finalize_request(Result.new(response: nil), request) when "exit" # We return zero if shutdown has already been received or one otherwise as per the recommendation in the spec # https://microsoft.github.io/language-server-protocol/specification/#exit status = @store.empty? ? 0 : 1 warn("Shutdown complete with status #{status}") exit(status) else # Default case: push the request to the queue to be executed by the worker job = Job.new(request: request, cancelled: false) @mutex.synchronize do # Remember a handle to the job, so that we can cancel it @jobs[request[:id]] = job # We must parse the document under a mutex lock or else we might switch threads and accept text edits in the # source. Altering the source reference during parsing will put the parser in an invalid internal state, # since it started parsing with one source but then it changed in the middle uri = request.dig(:params, :textDocument, :uri) @store.get(uri).parse if uri end @job_queue << job end end end |