diff --git a/lib/ruby_lsp/ruby_lsp_rails/runner_client.rb b/lib/ruby_lsp/ruby_lsp_rails/runner_client.rb index 8478e798..b8dce414 100644 --- a/lib/ruby_lsp/ruby_lsp_rails/runner_client.rb +++ b/lib/ruby_lsp/ruby_lsp_rails/runner_client.rb @@ -12,7 +12,15 @@ class << self sig { returns(RunnerClient) } def create_client - new + if File.exist?("bin/rails") + new + else + $stderr.puts(<<~MSG) + Ruby LSP Rails failed to locate bin/rails in the current directory: #{Dir.pwd}" + MSG + $stderr.puts("Server dependent features will not be available") + NullClient.new + end rescue Errno::ENOENT, StandardError => e # rubocop:disable Lint/ShadowedException $stderr.puts("Ruby LSP Rails failed to initialize server: #{e.message}\n#{e.backtrace&.join("\n")}") $stderr.puts("Server dependent features will not be available") diff --git a/test/ruby_lsp_rails/runner_client_test.rb b/test/ruby_lsp_rails/runner_client_test.rb index 92f96717..ac582b02 100644 --- a/test/ruby_lsp_rails/runner_client_test.rb +++ b/test/ruby_lsp_rails/runner_client_test.rb @@ -39,10 +39,32 @@ class RunnerClientTest < ActiveSupport::TestCase assert_nil @client.model("ApplicationRecord") # ApplicationRecord is abstract end + test "falls back to null client when bin/rails is not found" do + FileUtils.mv("bin/rails", "bin/rails_backup") + + assert_output("", %r{Ruby LSP Rails failed to locate bin/rails in the current directory}) do + client = RunnerClient.create_client + + assert_instance_of(NullClient, client) + assert_nil(client.model("User")) + assert_predicate(client, :stopped?) + end + ensure + FileUtils.mv("bin/rails_backup", "bin/rails") + end + test "failing to spawn server creates a null client" do FileUtils.mv("bin/rails", "bin/rails_backup") + File.open("bin/rails", "w") do |f| + f.write("foo") + end + File.chmod(0o755, "bin/rails") - assert_output("", %r{No such file or directory - bin/rails}) do + # The error message is slightly different on Ubuntu, so we need to allow for that + assert_output( + "", + %r{Ruby LSP Rails failed to initialize server: bin/rails: (line )?1: foo:( command)? not found}, + ) do client = RunnerClient.create_client assert_instance_of(NullClient, client)