Skip to content

Commit

Permalink
Start passing relevant capabilities to runtime server
Browse files Browse the repository at this point in the history
  • Loading branch information
vinistock committed Jan 28, 2025
1 parent 86ca9fa commit 4c8d1d1
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 14 deletions.
4 changes: 3 additions & 1 deletion lib/ruby_lsp/ruby_lsp_rails/addon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ def initialize
Thread.new do
@addon_mutex.synchronize do
# We need to ensure the Rails client is fully loaded before we activate the server addons
@client_mutex.synchronize { @rails_runner_client = RunnerClient.create_client(T.must(@outgoing_queue)) }
@client_mutex.synchronize do
@rails_runner_client = RunnerClient.create_client(T.must(@outgoing_queue), T.must(@global_state))
end
offer_to_run_pending_migrations
end
end
Expand Down
27 changes: 21 additions & 6 deletions lib/ruby_lsp/ruby_lsp_rails/runner_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ class RunnerClient
class << self
extend T::Sig

sig { params(outgoing_queue: Thread::Queue).returns(RunnerClient) }
def create_client(outgoing_queue)
sig { params(outgoing_queue: Thread::Queue, global_state: RubyLsp::GlobalState).returns(RunnerClient) }
def create_client(outgoing_queue, global_state)
if File.exist?("bin/rails")
new(outgoing_queue)
new(outgoing_queue, global_state)
else
unless outgoing_queue.closed?
outgoing_queue << RubyLsp::Notification.window_log_message(
Expand Down Expand Up @@ -51,8 +51,8 @@ class EmptyMessageError < MessageError; end
sig { returns(String) }
attr_reader :rails_root

sig { params(outgoing_queue: Thread::Queue).void }
def initialize(outgoing_queue)
sig { params(outgoing_queue: Thread::Queue, global_state: RubyLsp::GlobalState).void }
def initialize(outgoing_queue, global_state)
@outgoing_queue = T.let(outgoing_queue, Thread::Queue)
@mutex = T.let(Mutex.new, Mutex)
# Spring needs a Process session ID. It uses this ID to "attach" itself to the parent process, so that when the
Expand All @@ -71,7 +71,15 @@ def initialize(outgoing_queue)
log_message("Ruby LSP Rails booting server")

stdin, stdout, stderr, wait_thread = Bundler.with_original_env do
Open3.popen3("bundle", "exec", "rails", "runner", "#{__dir__}/server.rb", "start")
Open3.popen3(
"bundle",
"exec",
"rails",
"runner",
"#{__dir__}/server.rb",
"start",
server_relevant_capabilities(global_state),
)
end

@stdin = T.let(stdin, IO)
Expand Down Expand Up @@ -359,6 +367,13 @@ def read_notification

JSON.parse(raw_content, symbolize_names: true)
end

sig { params(global_state: GlobalState).returns(String) }
def server_relevant_capabilities(global_state)
{
supports_progress: global_state.client_capabilities.supports_progress,
}.to_json
end
end

class NullClient < RunnerClient
Expand Down
9 changes: 7 additions & 2 deletions lib/ruby_lsp/ruby_lsp_rails/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def execute(request, params)
class Server
include Common

def initialize(stdout: $stdout, stderr: $stderr, override_default_output_device: true)
def initialize(stdout: $stdout, stderr: $stderr, override_default_output_device: true, capabilities: {})
# Grab references to the original pipes so that we can change the default output device further down
@stdin = $stdin
@stdout = stdout
Expand All @@ -122,6 +122,9 @@ def initialize(stdout: $stdout, stderr: $stderr, override_default_output_device:
@stdout.binmode
@stderr.binmode

# A hash containing the capabilities of the editor that may be relevant for the runtime server
@capabilities = capabilities

# # Set the default output device to be $stderr. This means that using `puts` by itself will default to printing
# # to $stderr and only explicit `$stdout.puts` will go to $stdout. This reduces the chance that output coming
# # from the Rails app will be accidentally sent to the client
Expand Down Expand Up @@ -326,4 +329,6 @@ def clear_file_system_resolver_hooks
end
end

RubyLsp::Rails::Server.new.start if ARGV.first == "start"
if ARGV.first == "start"
RubyLsp::Rails::Server.new(capabilities: JSON.parse(ARGV[1], symbolize_names: true)).start
end
28 changes: 27 additions & 1 deletion test/ruby_lsp_rails/launch_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,34 @@ module Rails
class LaunchTest < ActiveSupport::TestCase
test "launching the client succeeds" do
outgoing_queue = Thread::Queue.new
global_state = GlobalState.new

client = RunnerClient.create_client(outgoing_queue)
client = RunnerClient.create_client(outgoing_queue, global_state)
refute_instance_of(NullClient, client)

first = pop_log_notification(outgoing_queue, Constant::MessageType::LOG)
assert_equal("Ruby LSP Rails booting server", first.params.message)

second = pop_log_notification(outgoing_queue, Constant::MessageType::LOG)
assert_match("Finished booting Ruby LSP Rails server", second.params.message)

client.shutdown
assert_predicate(client, :stopped?)
outgoing_queue.close
end

test "launching with client capabilities succeeds" do
outgoing_queue = Thread::Queue.new
global_state = GlobalState.new
global_state.apply_options({
capabilities: {
window: {
workDoneProgress: true,
},
},
})

client = RunnerClient.create_client(outgoing_queue, global_state)
refute_instance_of(NullClient, client)

first = pop_log_notification(outgoing_queue, Constant::MessageType::LOG)
Expand Down
9 changes: 5 additions & 4 deletions test/ruby_lsp_rails/runner_client_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ module Rails
class RunnerClientTest < ActiveSupport::TestCase
setup do
@outgoing_queue = Thread::Queue.new
@client = T.let(RunnerClient.new(@outgoing_queue), RunnerClient)
@global_state = GlobalState.new
@client = T.let(RunnerClient.new(@outgoing_queue, @global_state), RunnerClient)
end

teardown do
Expand Down Expand Up @@ -48,7 +49,7 @@ class RunnerClientTest < ActiveSupport::TestCase
FileUtils.mv("bin/rails", "bin/rails_backup")

outgoing_queue = Thread::Queue.new
client = RunnerClient.create_client(outgoing_queue)
client = RunnerClient.create_client(outgoing_queue, @global_state)

assert_instance_of(NullClient, client)
assert_nil(client.model("User"))
Expand All @@ -66,7 +67,7 @@ class RunnerClientTest < ActiveSupport::TestCase
FileUtils.mv("test/dummy/config/application.rb", "test/dummy/config/application.rb.bak")

outgoing_queue = Thread::Queue.new
client = RunnerClient.create_client(outgoing_queue)
client = RunnerClient.create_client(outgoing_queue, @global_state)

assert_instance_of(NullClient, client)
assert_nil(client.model("User"))
Expand All @@ -88,7 +89,7 @@ class RunnerClientTest < ActiveSupport::TestCase
File.write("test/dummy/config/application.rb", content + junk)

outgoing_queue = Thread::Queue.new
client = RunnerClient.create_client(outgoing_queue)
client = RunnerClient.create_client(outgoing_queue, @global_state)
response = client.model("User")

begin
Expand Down

0 comments on commit 4c8d1d1

Please sign in to comment.