Skip to content

Commit 572da64

Browse files
committed
More attempts
1 parent 9495bc4 commit 572da64

File tree

4 files changed

+74
-60
lines changed

4 files changed

+74
-60
lines changed

lib/ruby_lsp/ruby_lsp_rails/addon.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,13 @@ def rails_runner_client
4646
@addon_mutex.synchronize { @rails_runner_client }
4747
end
4848

49-
sig { override.params(global_state: GlobalState, message_queue: Thread::Queue).void }
50-
def activate(global_state, message_queue)
49+
sig { override.params(global_state: GlobalState, outgoing_queue: Thread::Queue).void }
50+
def activate(global_state, outgoing_queue)
5151
@global_state = global_state
52-
@message_queue = message_queue
52+
@message_queue = outgoing_queue
5353
@message_queue << Notification.window_log_message("Activating Ruby LSP Rails add-on v#{VERSION}")
5454

55-
register_additional_file_watchers(global_state: global_state, message_queue: message_queue)
55+
register_additional_file_watchers(global_state: global_state, outgoing_queue: outgoing_queue)
5656
@global_state.index.register_enhancement(IndexingEnhancement.new)
5757

5858
# Start booting the real client in a background thread. Until this completes, the client will be a NullClient
@@ -126,11 +126,11 @@ def workspace_did_change_watched_files(changes)
126126
end
127127
end
128128

129-
sig { params(global_state: GlobalState, message_queue: Thread::Queue).void }
130-
def register_additional_file_watchers(global_state:, message_queue:)
129+
sig { params(global_state: GlobalState, outgoing_queue: Thread::Queue).void }
130+
def register_additional_file_watchers(global_state:, outgoing_queue:)
131131
return unless global_state.supports_watching_files
132132

133-
message_queue << Request.new(
133+
outgoing_queue << Request.new(
134134
id: "ruby-lsp-rails-file-watcher",
135135
method: "client/registerCapability",
136136
params: Interface::RegistrationParams.new(

lib/ruby_lsp/ruby_lsp_rails/runner_client.rb

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

13-
sig { params(message_queue: Thread::Queue).returns(RunnerClient) }
14-
def create_client(message_queue)
13+
sig { params(outgoing_queue: Thread::Queue).returns(RunnerClient) }
14+
def create_client(outgoing_queue)
1515
if File.exist?("bin/rails")
16-
new(message_queue)
16+
new(outgoing_queue)
1717
else
18-
message_queue << RubyLsp::Notification.window_log_message(
18+
unless outgoing_queue.closed?
19+
outgoing_queue << RubyLsp::Notification.window_log_message(
20+
<<~MESSAGE.chomp,
21+
Ruby LSP Rails failed to locate bin/rails in the current directory: #{Dir.pwd}
22+
Server dependent features will not be available
23+
MESSAGE
24+
type: RubyLsp::Constant::MessageType::WARNING,
25+
)
26+
end
27+
28+
NullClient.new
29+
end
30+
rescue Errno::ENOENT, StandardError => e # rubocop:disable Lint/ShadowedException
31+
unless outgoing_queue.closed?
32+
outgoing_queue << RubyLsp::Notification.window_log_message(
1933
<<~MESSAGE.chomp,
20-
Ruby LSP Rails failed to locate bin/rails in the current directory: #{Dir.pwd}
34+
Ruby LSP Rails failed to initialize server: #{e.full_message}
2135
Server dependent features will not be available
2236
MESSAGE
23-
type: RubyLsp::Constant::MessageType::WARNING,
37+
type: Constant::MessageType::ERROR,
2438
)
25-
NullClient.new
2639
end
27-
rescue Errno::ENOENT, StandardError => e # rubocop:disable Lint/ShadowedException
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-
)
40+
3541
NullClient.new
3642
end
3743
end
@@ -47,9 +53,9 @@ class EmptyMessageError < StandardError; end
4753
sig { returns(String) }
4854
attr_reader :rails_root
4955

50-
sig { params(message_queue: Thread::Queue).void }
51-
def initialize(message_queue)
52-
@message_queue = T.let(message_queue, Thread::Queue)
56+
sig { params(outgoing_queue: Thread::Queue).void }
57+
def initialize(outgoing_queue)
58+
@outgoing_queue = T.let(outgoing_queue, Thread::Queue)
5359
@mutex = T.let(Mutex.new, Mutex)
5460
# Spring needs a Process session ID. It uses this ID to "attach" itself to the parent process, so that when the
5561
# parent ends, the spring process ends as well. If this is not set, Spring will throw an error while trying to
@@ -78,19 +84,19 @@ def initialize(message_queue)
7884
@stdout.binmode
7985
@stderr.binmode
8086

81-
@message_queue << RubyLsp::Notification.window_log_message("Ruby LSP Rails booting server")
87+
log_message("Ruby LSP Rails booting server")
8288
count = 0
8389

8490
begin
8591
count += 1
8692
initialize_response = T.must(read_response)
8793
@rails_root = T.let(initialize_response[:root], String)
8894
rescue EmptyMessageError
89-
@message_queue << RubyLsp::Notification.window_log_message("Ruby LSP Rails is retrying initialize (#{count})")
95+
log_message("Ruby LSP Rails is retrying initialize (#{count})")
9096
retry if count < MAX_RETRIES
9197
end
9298

93-
@message_queue << RubyLsp::Notification.window_log_message("Finished booting Ruby LSP Rails server")
99+
log_message("Finished booting Ruby LSP Rails server")
94100

95101
unless ENV["RAILS_ENV"] == "test"
96102
at_exit do
@@ -108,7 +114,7 @@ def initialize(message_queue)
108114
def register_server_addon(server_addon_path)
109115
send_notification("server_addon/register", server_addon_path: server_addon_path)
110116
rescue IncompleteMessageError
111-
@message_queue << RubyLsp::Notification.window_log_message(
117+
log_message(
112118
"Ruby LSP Rails failed to register server addon #{server_addon_path}",
113119
type: RubyLsp::Constant::MessageType::ERROR,
114120
)
@@ -119,7 +125,7 @@ def register_server_addon(server_addon_path)
119125
def model(name)
120126
make_request("model", name: name)
121127
rescue IncompleteMessageError
122-
@message_queue << RubyLsp::Notification.window_log_message(
128+
log_message(
123129
"Ruby LSP Rails failed to get model information: #{@stderr.read}",
124130
type: RubyLsp::Constant::MessageType::ERROR,
125131
)
@@ -139,7 +145,7 @@ def association_target_location(model_name:, association_name:)
139145
association_name: association_name,
140146
)
141147
rescue => e
142-
@message_queue << RubyLsp::Notification.window_log_message(
148+
log_message(
143149
"Ruby LSP Rails failed with #{e.message}: #{@stderr.read}",
144150
type: RubyLsp::Constant::MessageType::ERROR,
145151
)
@@ -150,7 +156,7 @@ def association_target_location(model_name:, association_name:)
150156
def route_location(name)
151157
make_request("route_location", name: name)
152158
rescue IncompleteMessageError
153-
@message_queue << RubyLsp::Notification.window_log_message(
159+
log_message(
154160
"Ruby LSP Rails failed to get route location: #{@stderr.read}",
155161
type: RubyLsp::Constant::MessageType::ERROR,
156162
)
@@ -161,7 +167,7 @@ def route_location(name)
161167
def route(controller:, action:)
162168
make_request("route_info", controller: controller, action: action)
163169
rescue IncompleteMessageError
164-
@message_queue << RubyLsp::Notification.window_log_message(
170+
log_message(
165171
"Ruby LSP Rails failed to get route information: #{@stderr.read}",
166172
type: RubyLsp::Constant::MessageType::ERROR,
167173
)
@@ -170,10 +176,10 @@ def route(controller:, action:)
170176

171177
sig { void }
172178
def trigger_reload
173-
@message_queue << RubyLsp::Notification.window_log_message("Reloading Rails application")
179+
log_message("Reloading Rails application")
174180
send_notification("reload")
175181
rescue IncompleteMessageError
176-
@message_queue << RubyLsp::Notification.window_log_message(
182+
log_message(
177183
"Ruby LSP Rails failed to trigger reload",
178184
type: RubyLsp::Constant::MessageType::ERROR,
179185
)
@@ -182,7 +188,7 @@ def trigger_reload
182188

183189
sig { void }
184190
def shutdown
185-
@message_queue << RubyLsp::Notification.window_log_message("Ruby LSP Rails shutting down server")
191+
log_message("Ruby LSP Rails shutting down server")
186192
send_message("shutdown")
187193
sleep(0.5) # give the server a bit of time to shutdown
188194
[@stdin, @stdout, @stderr].each(&:close)
@@ -241,7 +247,7 @@ def read_response
241247
response = JSON.parse(T.must(raw_response), symbolize_names: true)
242248

243249
if response[:error]
244-
@message_queue << RubyLsp::Notification.window_log_message(
250+
log_message(
245251
"Ruby LSP Rails error: #{response[:error]}",
246252
type: RubyLsp::Constant::MessageType::ERROR,
247253
)
@@ -259,6 +265,13 @@ def force_kill
259265
# Windows does not support the `TERM` signal, so we're forced to use `KILL` here
260266
Process.kill(T.must(Signal.list["KILL"]), @wait_thread.pid)
261267
end
268+
269+
sig { params(message: ::String, type: ::Integer).void }
270+
def log_message(message, type: RubyLsp::Constant::MessageType::LOG)
271+
return if @outgoing_queue.closed?
272+
273+
@outgoing_queue << RubyLsp::Notification.window_log_message(message, type: type)
274+
end
262275
end
263276

264277
class NullClient < RunnerClient

test/ruby_lsp_rails/addon_test.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ def with_addon(&block)
6868
addon.activate(RubyLsp::GlobalState.new, message_queue)
6969
thread.join
7070
ensure
71+
T.must(addon).deactivate
7172
T.must(message_queue).close
7273
end
7374
end

test/ruby_lsp_rails/runner_client_test.rb

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,9 @@
77
module RubyLsp
88
module Rails
99
class RunnerClientTest < ActiveSupport::TestCase
10-
setup do
11-
@message_queue = Thread::Queue.new
12-
@client = T.let(RunnerClient.new(@message_queue), RunnerClient)
13-
end
14-
15-
teardown do
16-
@client.shutdown
17-
18-
# On Windows, the server process sometimes takes a lot longer to shutdown and may end up getting force killed,
19-
# which makes this assertion flaky
20-
assert_predicate(@client, :stopped?) unless Gem.win_platform?
21-
@message_queue.close
22-
end
23-
24-
# These are integration tests which start the server. For the more fine-grained tests, see `server_test.rb`.
25-
2610
test "#model returns information for the requested model" do
11+
message_queue = Thread::Queue.new
12+
client = T.let(RunnerClient.new(message_queue), RunnerClient)
2713
# These columns are from the schema in the dummy app: test/dummy/db/schema.rb
2814
columns = [
2915
["id", "integer"],
@@ -34,13 +20,23 @@ class RunnerClientTest < ActiveSupport::TestCase
3420
["updated_at", "datetime"],
3521
["country_id", "integer"],
3622
]
37-
response = T.must(@client.model("User"))
23+
response = T.must(client.model("User"))
3824
assert_equal(columns, response.fetch(:columns))
3925
assert_match(%r{db/schema\.rb$}, response.fetch(:schema_file))
26+
ensure
27+
T.must(client).shutdown
28+
assert_predicate(client, :stopped?) unless Gem.win_platform?
29+
T.must(message_queue).close
4030
end
4131

4232
test "returns nil if the request returns a nil response" do
43-
assert_nil @client.model("ApplicationRecord") # ApplicationRecord is abstract
33+
message_queue = Thread::Queue.new
34+
client = T.let(RunnerClient.new(message_queue), RunnerClient)
35+
assert_nil(client.model("ApplicationRecord")) # ApplicationRecord is abstract
36+
ensure
37+
T.must(client).shutdown
38+
assert_predicate(client, :stopped?) unless Gem.win_platform?
39+
T.must(message_queue).close
4440
end
4541

4642
test "falls back to null client when bin/rails is not found" do
@@ -58,6 +54,8 @@ class RunnerClientTest < ActiveSupport::TestCase
5854
assert_instance_of(RubyLsp::Notification, log)
5955
assert_match("Ruby LSP Rails failed to locate bin/rails in the current directory", log.params.message)
6056
ensure
57+
T.must(client).shutdown
58+
assert_predicate(client, :stopped?) unless Gem.win_platform?
6159
T.must(message_queue).close
6260
FileUtils.mv("bin/rails_backup", "bin/rails")
6361
end
@@ -76,6 +74,8 @@ class RunnerClientTest < ActiveSupport::TestCase
7674
assert_instance_of(RubyLsp::Notification, log)
7775
assert_match("Ruby LSP Rails failed to initialize server", log.params.message)
7876
ensure
77+
T.must(client).shutdown
78+
assert_predicate(client, :stopped?) unless Gem.win_platform?
7979
T.must(message_queue).close
8080
FileUtils.mv("test/dummy/config/application.rb.bak", "test/dummy/config/application.rb")
8181
end
@@ -87,13 +87,13 @@ class RunnerClientTest < ActiveSupport::TestCase
8787
junk = %{\nputs "1\r\n\r\nhello"}
8888
File.write("test/dummy/config/application.rb", content + junk)
8989

90-
capture_subprocess_io do
91-
client = RunnerClient.create_client(message_queue)
90+
client = RunnerClient.create_client(message_queue)
9291

93-
response = T.must(client.model("User"))
94-
assert(response.key?(:columns))
95-
end
92+
response = T.must(client.model("User"))
93+
assert(response.key?(:columns))
9694
ensure
95+
T.must(client).shutdown
96+
assert_predicate(client, :stopped?) unless Gem.win_platform?
9797
T.must(message_queue).close
9898
FileUtils.mv("test/dummy/config/application.rb.bak", "test/dummy/config/application.rb")
9999
end

0 commit comments

Comments
 (0)