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



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

def get_content(size, io = STDIN)
  io.read(size)
end

#get_initial_request_line(io = STDIN) ⇒ Object



92
93
94
# File 'lib/ruby_language_server/io.rb', line 92

def get_initial_request_line(io = STDIN)
  io.gets
end

#get_length(string) ⇒ Object



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

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

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

#get_request(io = STDIN) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/ruby_language_server/io.rb', line 74

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
# 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
    RubyLanguageServer.logger.debug 'Locking io'
    response = @mutex.synchronize do
      @server.send(method_name, params)
    end
    RubyLanguageServer.logger.debug 'UNLocking io'
    exit(true) if response == 'EXIT'
    return id, response
  else
    RubyLanguageServer.logger.warn "SERVER DOES NOT RESPOND TO #{method_name}"
    return 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: id,
    result: response
  }
  response_body = JSON.unparse(full_response)
  # RubyLanguageServer.logger.debug "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: params
  }
  body = JSON.unparse(full_response)
  # RubyLanguageServer.logger.debug "body: #{body}"
  io.write "Content-Length: #{body.length + 0}\r\n"
  io.write "\r\n"
  io.write body
  io.flush
end