class RubyLanguageServer::IO

Public Class Methods

new(server, mutex) click to toggle source
# 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

Public Instance Methods

get_content(size, io = $stdin) click to toggle source
# 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) click to toggle source
# File lib/ruby_language_server/io.rb, line 92
def get_initial_request_line(io = $stdin)
  io.gets
end
get_length(string) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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'
    [id, response]
  else
    RubyLanguageServer.logger.warn "SERVER DOES NOT RESPOND TO #{method_name}"
    nil
  end
end
return_response(id, response, io = $stdout) click to toggle source
# 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.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) click to toggle source
# 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.info "send_notification body: #{body}"
  io.write "Content-Length: #{body.length + 0}\r\n"
  io.write "\r\n"
  io.write body
  io.flush
end