Skip to content

Commit 6bd59f5

Browse files
authored
Ensure output printed during boot doesn't break LSP when starting (#310)
Co-authored-by: Andy Waite <[email protected]>
1 parent e21b791 commit 6bd59f5

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

lib/ruby_lsp/ruby_lsp_rails/runner_client.rb

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ def create_client
3030

3131
class InitializationError < StandardError; end
3232
class IncompleteMessageError < StandardError; end
33+
class EmptyMessageError < StandardError; end
34+
35+
MAX_RETRIES = 5
3336

3437
extend T::Sig
3538

@@ -59,7 +62,16 @@ def initialize
5962
@stdout.binmode # for Windows compatibility
6063

6164
$stderr.puts("Ruby LSP Rails booting server")
62-
read_response
65+
count = 0
66+
67+
begin
68+
count += 1
69+
read_response
70+
rescue EmptyMessageError
71+
$stderr.puts("Ruby LSP Rails is retrying initialize (#{count})")
72+
retry if count < MAX_RETRIES
73+
end
74+
6375
$stderr.puts("Finished booting Ruby LSP Rails server")
6476

6577
unless ENV["RAILS_ENV"] == "test"
@@ -134,7 +146,10 @@ def read_response
134146
headers = @stdout.gets("\r\n\r\n")
135147
raise IncompleteMessageError unless headers
136148

137-
raw_response = @stdout.read(headers[/Content-Length: (\d+)/i, 1].to_i)
149+
content_length = headers[/Content-Length: (\d+)/i, 1].to_i
150+
raise EmptyMessageError if content_length.zero?
151+
152+
raw_response = @stdout.read(content_length)
138153
response = JSON.parse(T.must(raw_response), symbolize_names: true)
139154

140155
if response[:error]

test/ruby_lsp_rails/runner_client_test.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,22 @@ class RunnerClientTest < ActiveSupport::TestCase
7474
ensure
7575
FileUtils.mv("bin/rails_backup", "bin/rails")
7676
end
77+
78+
test "is resilient to extra output being printed during boot" do
79+
content = File.read("test/dummy/config/application.rb")
80+
FileUtils.mv("test/dummy/config/application.rb", "test/dummy/config/application.rb.bak")
81+
junk = %{\nputs "1\r\n\r\nhello"}
82+
File.write("test/dummy/config/application.rb", content + junk)
83+
84+
capture_subprocess_io do
85+
client = RunnerClient.create_client
86+
87+
response = T.must(client.model("User"))
88+
assert(response.key?(:columns))
89+
end
90+
ensure
91+
FileUtils.mv("test/dummy/config/application.rb.bak", "test/dummy/config/application.rb")
92+
end
7793
end
7894
end
7995
end

0 commit comments

Comments
 (0)