Class: ThemeCheck::LanguageServer::IOMessenger

Inherits:
Messenger
  • Object
show all
Defined in:
lib/theme_check/language_server/io_messenger.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(in_stream: STDIN, out_stream: STDOUT, err_stream: IOMessenger.err_stream) ⇒ IOMessenger

Returns a new instance of IOMessenger.



14
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
# File 'lib/theme_check/language_server/io_messenger.rb', line 14

def initialize(
  in_stream: STDIN,
  out_stream: STDOUT,
  err_stream: IOMessenger.err_stream
)
  validate!([in_stream, out_stream, err_stream])

  @in = in_stream
  @out = out_stream
  @err = err_stream

  # Because programming is fun,
  #
  # Ruby on Windows turns \n into \r\n. Which means that \r\n
  # gets turned into \r\r\n. Which means that the protocol
  # breaks on windows unless we turn STDOUT into binary mode.
  #
  # Hours wasted: 9.
  @out.binmode

  @out.sync = true # do not buffer
  @err.sync = true # do not buffer

  # Lock for writing, otherwise messages might be interspersed.
  @writer = Mutex.new
end

Class Method Details

.err_streamObject



6
7
8
9
10
11
12
# File 'lib/theme_check/language_server/io_messenger.rb', line 6

def self.err_stream
  if ThemeCheck.debug_log_file
    File.open(ThemeCheck.debug_log_file, "w")
  else
    STDERR
  end
end

Instance Method Details

#close_inputObject



69
70
71
# File 'lib/theme_check/language_server/io_messenger.rb', line 69

def close_input
  @in.close unless @in.closed?
end

#close_outputObject



73
74
75
76
# File 'lib/theme_check/language_server/io_messenger.rb', line 73

def close_output
  @err.close
  @out.close
end

#log(message) ⇒ Object



64
65
66
67
# File 'lib/theme_check/language_server/io_messenger.rb', line 64

def log(message)
  @err.puts(message)
  @err.flush
end

#read_messageObject



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/theme_check/language_server/io_messenger.rb', line 41

def read_message
  length = initial_line.match(/Content-Length: (\d+)/)[1].to_i
  content = ''
  length_to_read = 2 + length # 2 is the empty line length (\r\n)
  while content.length < length_to_read
    chunk = @in.read(length_to_read - content.length)
    raise DoneStreaming if chunk.nil?
    content += chunk
  end
  content.lstrip!
rescue IOError
  raise DoneStreaming
end

#send_message(message_body) ⇒ Object



55
56
57
58
59
60
61
62
# File 'lib/theme_check/language_server/io_messenger.rb', line 55

def send_message(message_body)
  @writer.synchronize do
    @out.write("Content-Length: #{message_body.bytesize}\r\n")
    @out.write("\r\n")
    @out.write(message_body)
    @out.flush
  end
end