Class: RubyLanguageServer::IO

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_language_server/io.rb

Instance Method Summary collapse

Constructor Details

#initialize(server, mutex) ⇒ IO

Returns a new instance of IO.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/ruby_language_server/io.rb', line 7

def initialize(server, mutex)
  @server = server
  @mutex = mutex
  server.io = self
  loop do
    (id, response) = process_request($stdin)
    return_response(id, response, $stdout) unless id.nil?
  rescue SignalException => e
    RubyLanguageServer.logger.error "We received a signal.  Let's bail: #{e}"
    exit(true)
  rescue Exception => e
    RubyLanguageServer.logger.error "Something when horribly wrong: #{e}"
    backtrace = e.backtrace * "\n"
    RubyLanguageServer.logger.error "Backtrace:\n#{backtrace}"
  end
end

Instance Method Details

#get_content(size, io = $stdin) ⇒ Object



108
109
110
# File 'lib/ruby_language_server/io.rb', line 108

def get_content(size, io = $stdin)
  io.read(size)
end

#get_initial_request_line(io = $stdin) ⇒ Object



98
99
100
# File 'lib/ruby_language_server/io.rb', line 98

def get_initial_request_line(io = $stdin)
  io.gets
end

#get_length(string) ⇒ Object



102
103
104
105
106
# File 'lib/ruby_language_server/io.rb', line 102

def get_length(string)
  return 0 if string.nil?

  string.match(/Content-Length: (\d+)/)[1].to_i
end

#get_request(io = $stdin) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/ruby_language_server/io.rb', line 80

def get_request(io = $stdin)
  initial_line = get_initial_request_line(io)
  RubyLanguageServer.logger.debug "initial_line: #{initial_line}"
  length = get_length(initial_line)
  content = ''
  while content.length < length + 2
    begin
      content += get_content(length + 2, io) # Why + 2?  CRLF?
    rescue Exception => e
      RubyLanguageServer.logger.error e
      # We have almost certainly been disconnected from the server
      exit!(1)
    end
  end
  RubyLanguageServer.logger.debug "content.length: #{content.length}"
  content
end

#process_request(io = $stdin) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/ruby_language_server/io.rb', line 52

def process_request(io = $stdin)
  request_body = get_request(io)
  # RubyLanguageServer.logger.debug "request_body: #{request_body}"
  request_json = JSON.parse request_body
  id = request_json['id']
  method_name = request_json['method']
  params = request_json['params']
  method_name = "on_#{method_name.gsub(/[^\w]/, '_')}"
  if @server.respond_to? method_name
    response = ActiveRecord::Base.connection_pool.with_connection do
      retries = 3
      begin
        @server.send(method_name, params)
      rescue StandardError => e
        RubyLanguageServer.logger.warn("Error updating: #{e}\n#{e.backtrace * "\n"}")
        sleep 5
        retries -= 1
        retry unless retries <= 0
      end
    end
    exit(true) if response == 'EXIT'
    [id, response]
  else
    RubyLanguageServer.logger.warn "SERVER DOES NOT RESPOND TO #{method_name}"
    nil
  end
end

#return_response(id, response, io = $stdout) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/ruby_language_server/io.rb', line 24

def return_response(id, response, io = $stdout)
  full_response = {
    jsonrpc: '2.0',
    id:,
    result: response
  }
  response_body = JSON.unparse(full_response)
  RubyLanguageServer.logger.info "return_response body: #{response_body}"
  io.write "Content-Length: #{response_body.length + 0}\r\n"
  io.write "\r\n"
  io.write response_body
  io.flush
end

#send_notification(message, params, io = $stdout) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/ruby_language_server/io.rb', line 38

def send_notification(message, params, io = $stdout)
  full_response = {
    jsonrpc: '2.0',
    method: message,
    params:
  }
  body = JSON.unparse(full_response)
  RubyLanguageServer.logger.info "send_notification body: #{body}"
  io.write "Content-Length: #{body.length + 0}\r\n"
  io.write "\r\n"
  io.write body
  io.flush
end