Class: PlatformosCheck::LanguageServer::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/platformos_check/language_server/server.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(messenger:, should_raise_errors: false, number_of_threads: 2) ⇒ Server

Returns a new instance of Server.



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
# File 'lib/platformos_check/language_server/server.rb', line 16

def initialize(
  messenger:,
  should_raise_errors: false,
  number_of_threads: 2
)
  # This is what does the IO
  @messenger = messenger

  # This is what you use to communicate with the language client
  @bridge = Bridge.new(@messenger)

  # The handler handles messages from the language client
  @handler = Handler.new(@bridge)

  # The queue holds the JSON RPC messages
  @queue = Queue.new

  # The JSON RPC thread pushes messages onto the queue
  @json_rpc_thread = nil

  # The handler threads read messages from the queue
  @number_of_threads = number_of_threads
  @handlers = []

  # The error queue holds blocks the main thread. When filled, we exit the program.
  @error = SizedQueue.new(number_of_threads)

  @should_raise_errors = should_raise_errors
end

Instance Attribute Details

#handlerObject (readonly)

Returns the value of attribute handler.



14
15
16
# File 'lib/platformos_check/language_server/server.rb', line 14

def handler
  @handler
end

#should_raise_errorsObject (readonly)

Returns the value of attribute should_raise_errors.



14
15
16
# File 'lib/platformos_check/language_server/server.rb', line 14

def should_raise_errors
  @should_raise_errors
end

Instance Method Details

#handle_messagesObject



103
104
105
106
107
108
109
110
111
112
113
# File 'lib/platformos_check/language_server/server.rb', line 103

def handle_messages
  loop do
    message = @queue.pop
    return if @queue.closed? && @queue.empty?

    handle_message(message)
  end
rescue Exception => e # rubocop:disable Lint/RescueException
  @bridge.log("rescuing #{e} in handler thread")
  @error << e
end

#listenObject



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/platformos_check/language_server/server.rb', line 46

def listen
  start_handler_threads
  start_json_rpc_thread
  err = @error.pop
  status_code = status_code_from_error(err)

  if status_code > 0
    # For a reason I can't comprehend, this hangs but prints
    # anyway. So it's wrapped in this ugly timeout...
    Timeout.timeout(1) do
      warn err.full_message
    end

    # Warn user of error, otherwise server might restart
    # without telling you.
    @bridge.send_notification("window/showMessage", {
                                type: 1,
                                message: "A platformos-check-language-server error has occurred, search OUTPUT logs for details."
                              })
  end

  cleanup(status_code)
rescue SignalException
  0
rescue StandardError
  2
end

#start_handler_threadsObject



95
96
97
98
99
100
101
# File 'lib/platformos_check/language_server/server.rb', line 95

def start_handler_threads
  @number_of_threads.times do
    @handlers << Thread.new do
      handle_messages
    end
  end
end

#start_json_rpc_threadObject



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/platformos_check/language_server/server.rb', line 74

def start_json_rpc_thread
  @json_rpc_thread = Thread.new do
    loop do
      message = @bridge.read_message
      if message[:method] == 'initialize'
        handle_message(message)
      elsif message.key?(:result)
        # Responses are handled on the main thread to prevent
        # a potential deadlock caused by all handlers waiting
        # for a responses.
        handle_response(message)
      else
        @queue << message
      end
    end
  rescue Exception => e # rubocop:disable Lint/RescueException
    @bridge.log("rescuing #{e.class} in jsonrpc thread")
    @error << e
  end
end

#status_code_from_error(e) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/platformos_check/language_server/server.rb', line 115

def status_code_from_error(e)
  raise e

# support ctrl+c and stuff
rescue SignalException, DoneStreaming
  0
rescue Exception => e # rubocop:disable Lint/RescueException
  raise e if should_raise_errors

  @bridge.log("Fatal #{e.class}")
  2
end