Skip to content

Commit 7f44e98

Browse files
committed
Use log trace instead of printing to stderr
1 parent c5043be commit 7f44e98

File tree

9 files changed

+161
-63
lines changed

9 files changed

+161
-63
lines changed

lib/ruby_lsp/ruby_lsp_rails/addon.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ def initialize
2828
# the real client is initialized, features that depend on it will not be blocked by using the NullClient
2929
@rails_runner_client = T.let(NullClient.new, RunnerClient)
3030
@global_state = T.let(nil, T.nilable(GlobalState))
31+
@message_queue = T.let(nil, T.nilable(Thread::Queue))
3132
@addon_mutex = T.let(Mutex.new, Mutex)
3233
@client_mutex = T.let(Mutex.new, Mutex)
3334
@client_mutex.lock
3435

3536
Thread.new do
3637
@addon_mutex.synchronize do
3738
# We need to ensure the Rails client is fully loaded before we activate the server addons
38-
@client_mutex.synchronize { @rails_runner_client = RunnerClient.create_client }
39+
@client_mutex.synchronize { @rails_runner_client = RunnerClient.create_client(T.must(@message_queue)) }
3940
end
4041
end
4142
end
@@ -48,7 +49,9 @@ def rails_runner_client
4849
sig { override.params(global_state: GlobalState, message_queue: Thread::Queue).void }
4950
def activate(global_state, message_queue)
5051
@global_state = global_state
51-
$stderr.puts("Activating Ruby LSP Rails add-on v#{version}")
52+
@message_queue = message_queue
53+
@message_queue << Notification.window_log_message("Activating Ruby LSP Rails add-on v#{VERSION}")
54+
5255
register_additional_file_watchers(global_state: global_state, message_queue: message_queue)
5356
@global_state.index.register_enhancement(IndexingEnhancement.new)
5457

lib/ruby_lsp/ruby_lsp_rails/runner_client.rb

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,28 @@ class RunnerClient
1010
class << self
1111
extend T::Sig
1212

13-
sig { returns(RunnerClient) }
14-
def create_client
13+
sig { params(message_queue: Thread::Queue).returns(RunnerClient) }
14+
def create_client(message_queue)
1515
if File.exist?("bin/rails")
16-
new
16+
new(message_queue)
1717
else
18-
$stderr.puts(<<~MSG)
19-
Ruby LSP Rails failed to locate bin/rails in the current directory: #{Dir.pwd}"
20-
MSG
21-
$stderr.puts("Server dependent features will not be available")
18+
message_queue << RubyLsp::Notification.window_log_message(
19+
<<~MESSAGE.chomp,
20+
Ruby LSP Rails failed to locate bin/rails in the current directory: #{Dir.pwd}
21+
Server dependent features will not be available
22+
MESSAGE
23+
type: RubyLsp::Constant::MessageType::WARNING,
24+
)
2225
NullClient.new
2326
end
2427
rescue Errno::ENOENT, StandardError => e # rubocop:disable Lint/ShadowedException
25-
$stderr.puts("Ruby LSP Rails failed to initialize server: #{e.message}\n#{e.backtrace&.join("\n")}")
26-
$stderr.puts("Server dependent features will not be available")
28+
message_queue << RubyLsp::Notification.window_log_message(
29+
<<~MESSAGE.chomp,
30+
Ruby LSP Rails failed to initialize server: #{e.full_message}
31+
Server dependent features will not be available
32+
MESSAGE
33+
type: Constant::MessageType::ERROR,
34+
)
2735
NullClient.new
2836
end
2937
end
@@ -39,8 +47,9 @@ class EmptyMessageError < StandardError; end
3947
sig { returns(String) }
4048
attr_reader :rails_root
4149

42-
sig { void }
43-
def initialize
50+
sig { params(message_queue: Thread::Queue).void }
51+
def initialize(message_queue)
52+
@message_queue = T.let(message_queue, Thread::Queue)
4453
@mutex = T.let(Mutex.new, Mutex)
4554
# Spring needs a Process session ID. It uses this ID to "attach" itself to the parent process, so that when the
4655
# parent ends, the spring process ends as well. If this is not set, Spring will throw an error while trying to
@@ -69,24 +78,23 @@ def initialize
6978
@stdout.binmode
7079
@stderr.binmode
7180

72-
$stderr.puts("Ruby LSP Rails booting server")
81+
@message_queue << RubyLsp::Notification.window_log_message("Ruby LSP Rails booting server")
7382
count = 0
7483

7584
begin
7685
count += 1
7786
initialize_response = T.must(read_response)
7887
@rails_root = T.let(initialize_response[:root], String)
7988
rescue EmptyMessageError
80-
$stderr.puts("Ruby LSP Rails is retrying initialize (#{count})")
89+
@message_queue << RubyLsp::Notification.window_log_message("Ruby LSP Rails is retrying initialize (#{count})")
8190
retry if count < MAX_RETRIES
8291
end
8392

84-
$stderr.puts("Finished booting Ruby LSP Rails server")
93+
@message_queue << RubyLsp::Notification.window_log_message("Finished booting Ruby LSP Rails server")
8594

8695
unless ENV["RAILS_ENV"] == "test"
8796
at_exit do
8897
if @wait_thread.alive?
89-
$stderr.puts("Ruby LSP Rails is force killing the server")
9098
sleep(0.5) # give the server a bit of time if we already issued a shutdown notification
9199
force_kill
92100
end
@@ -100,15 +108,21 @@ def initialize
100108
def register_server_addon(server_addon_path)
101109
send_notification("server_addon/register", server_addon_path: server_addon_path)
102110
rescue IncompleteMessageError
103-
$stderr.puts("Ruby LSP Rails failed to register server addon #{server_addon_path}")
111+
@message_queue << RubyLsp::Notification.window_log_message(
112+
"Ruby LSP Rails failed to register server addon #{server_addon_path}",
113+
type: RubyLsp::Constant::MessageType::ERROR,
114+
)
104115
nil
105116
end
106117

107118
sig { params(name: String).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
108119
def model(name)
109120
make_request("model", name: name)
110121
rescue IncompleteMessageError
111-
$stderr.puts("Ruby LSP Rails failed to get model information: #{@stderr.read}")
122+
@message_queue << RubyLsp::Notification.window_log_message(
123+
"Ruby LSP Rails failed to get model information: #{@stderr.read}",
124+
type: RubyLsp::Constant::MessageType::ERROR,
125+
)
112126
nil
113127
end
114128

@@ -125,37 +139,50 @@ def association_target_location(model_name:, association_name:)
125139
association_name: association_name,
126140
)
127141
rescue => e
128-
$stderr.puts("Ruby LSP Rails failed with #{e.message}: #{@stderr.read}")
142+
@message_queue << RubyLsp::Notification.window_log_message(
143+
"Ruby LSP Rails failed with #{e.message}: #{@stderr.read}",
144+
type: RubyLsp::Constant::MessageType::ERROR,
145+
)
146+
nil
129147
end
130148

131149
sig { params(name: String).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
132150
def route_location(name)
133151
make_request("route_location", name: name)
134152
rescue IncompleteMessageError
135-
$stderr.puts("Ruby LSP Rails failed to get route location: #{@stderr.read}")
153+
@message_queue << RubyLsp::Notification.window_log_message(
154+
"Ruby LSP Rails failed to get route location: #{@stderr.read}",
155+
type: RubyLsp::Constant::MessageType::ERROR,
156+
)
136157
nil
137158
end
138159

139160
sig { params(controller: String, action: String).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
140161
def route(controller:, action:)
141162
make_request("route_info", controller: controller, action: action)
142163
rescue IncompleteMessageError
143-
$stderr.puts("Ruby LSP Rails failed to get route information: #{@stderr.read}")
164+
@message_queue << RubyLsp::Notification.window_log_message(
165+
"Ruby LSP Rails failed to get route information: #{@stderr.read}",
166+
type: RubyLsp::Constant::MessageType::ERROR,
167+
)
144168
nil
145169
end
146170

147171
sig { void }
148172
def trigger_reload
149-
$stderr.puts("Reloading Rails application")
173+
@message_queue << RubyLsp::Notification.window_log_message("Reloading Rails application")
150174
send_notification("reload")
151175
rescue IncompleteMessageError
152-
$stderr.puts("Ruby LSP Rails failed to trigger reload")
176+
@message_queue << RubyLsp::Notification.window_log_message(
177+
"Ruby LSP Rails failed to trigger reload",
178+
type: RubyLsp::Constant::MessageType::ERROR,
179+
)
153180
nil
154181
end
155182

156183
sig { void }
157184
def shutdown
158-
$stderr.puts("Ruby LSP Rails shutting down server")
185+
@message_queue << RubyLsp::Notification.window_log_message("Ruby LSP Rails shutting down server")
159186
send_message("shutdown")
160187
sleep(0.5) # give the server a bit of time to shutdown
161188
[@stdin, @stdout, @stderr].each(&:close)
@@ -214,7 +241,10 @@ def read_response
214241
response = JSON.parse(T.must(raw_response), symbolize_names: true)
215242

216243
if response[:error]
217-
$stderr.puts("Ruby LSP Rails error: " + response[:error])
244+
@message_queue << RubyLsp::Notification.window_log_message(
245+
"Ruby LSP Rails error: #{response[:error]}",
246+
type: RubyLsp::Constant::MessageType::ERROR,
247+
)
218248
return
219249
end
220250

test/ruby_lsp_rails/addon_test.rb

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ module RubyLsp
77
module Rails
88
class AddonTest < ActiveSupport::TestCase
99
test "name returns add-on name" do
10-
addon = Addon.new
11-
assert_equal("Ruby LSP Rails", addon.name)
10+
with_addon do |addon|
11+
assert_equal("Ruby LSP Rails", addon.name)
12+
end
1213
end
1314

1415
test "sends reload notification if db/schema.rb is changed" do
@@ -19,9 +20,10 @@ class AddonTest < ActiveSupport::TestCase
1920
},
2021
]
2122

22-
RunnerClient.any_instance.expects(:send_notification).with("reload").once
23-
addon = Addon.new
24-
addon.workspace_did_change_watched_files(changes)
23+
with_addon do |addon, client|
24+
client.expects(:trigger_reload).once
25+
addon.workspace_did_change_watched_files(changes)
26+
end
2527
end
2628

2729
test "sends reload notification if a *structure.sql file is changed" do
@@ -32,9 +34,10 @@ class AddonTest < ActiveSupport::TestCase
3234
},
3335
]
3436

35-
RunnerClient.any_instance.expects(:send_notification).with("reload").once
36-
addon = Addon.new
37-
addon.workspace_did_change_watched_files(changes)
37+
with_addon do |addon, client|
38+
client.expects(:trigger_reload).once
39+
addon.workspace_did_change_watched_files(changes)
40+
end
3841
end
3942

4043
test "does not send reload notification if schema is not changed" do
@@ -45,9 +48,27 @@ class AddonTest < ActiveSupport::TestCase
4548
},
4649
]
4750

48-
RunnerClient.any_instance.expects(:send_notification).never
51+
with_addon do |addon, client|
52+
client.expects(:trigger_reload).never
53+
addon.workspace_did_change_watched_files(changes)
54+
end
55+
end
56+
57+
private
58+
59+
def with_addon(&block)
60+
message_queue = Thread::Queue.new
4961
addon = Addon.new
50-
addon.workspace_did_change_watched_files(changes)
62+
63+
thread = Thread.new do
64+
client = addon.rails_runner_client
65+
block&.call(addon, client)
66+
end
67+
68+
addon.activate(RubyLsp::GlobalState.new, message_queue)
69+
thread.join
70+
ensure
71+
T.must(message_queue).close
5172
end
5273
end
5374
end

test/ruby_lsp_rails/code_lens_test.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -402,17 +402,15 @@ def index
402402

403403
def generate_code_lens_for_source(source, file: "/fake.rb")
404404
with_server(source, URI(file)) do |server, uri|
405-
sleep(0.1) while RubyLsp::Addon.addons.first.instance_variable_get(:@rails_runner_client).is_a?(NullClient)
405+
wait_for_rails_addon_activation
406406

407407
server.process_message(
408408
id: 1,
409409
method: "textDocument/codeLens",
410410
params: { textDocument: { uri: uri }, position: { line: 0, character: 0 } },
411411
)
412412

413-
result = server.pop_response
414-
415-
assert_instance_of(RubyLsp::Result, result)
413+
result = pop_result(server)
416414
result.response
417415
end
418416
end

test/ruby_lsp_rails/definition_test.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,16 +225,15 @@ def baz; end
225225

226226
def generate_definitions_for_source(source, position)
227227
with_server(source) do |server, uri|
228-
sleep(0.1) while RubyLsp::Addon.addons.first.instance_variable_get(:@rails_runner_client).is_a?(NullClient)
228+
wait_for_rails_addon_activation
229229

230230
server.process_message(
231231
id: 1,
232232
method: "textDocument/definition",
233233
params: { textDocument: { uri: uri }, position: position },
234234
)
235235

236-
result = server.pop_response
237-
assert_instance_of(RubyLsp::Result, result)
236+
result = pop_result(server)
238237
result.response
239238
end
240239
end

test/ruby_lsp_rails/document_symbol_test.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,13 +431,16 @@ class FooModel < ApplicationRecord
431431

432432
def generate_document_symbols_for_source(source)
433433
with_server(source) do |server, uri|
434+
wait_for_rails_addon_activation
435+
434436
server.process_message(
435437
id: 1,
436438
method: "textDocument/documentSymbol",
437439
params: { textDocument: { uri: uri }, position: { line: 0, character: 0 } },
438440
)
439441

440-
server.pop_response.response
442+
result = pop_result(server)
443+
result.response
441444
end
442445
end
443446
end

test/ruby_lsp_rails/hover_test.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,16 @@ class User < ApplicationRecord
188188

189189
def hover_on_source(source, position)
190190
with_server(source, stub_no_typechecker: true) do |server, uri|
191+
wait_for_rails_addon_activation
192+
191193
server.process_message(
192194
id: 1,
193195
method: "textDocument/hover",
194196
params: { textDocument: { uri: uri }, position: position },
195197
)
196198

197-
server.pop_response.response
199+
result = pop_result(server)
200+
result.response
198201
end
199202
end
200203
end

0 commit comments

Comments
 (0)