Skip to content

Commit

Permalink
Load DSL compilers and extensions ahead of time in add-on mode
Browse files Browse the repository at this point in the history
  • Loading branch information
vinistock committed Jan 14, 2025
1 parent d90ca33 commit b298065
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 19 deletions.
5 changes: 5 additions & 0 deletions lib/ruby_lsp/tapioca/addon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ def activate(global_state, outgoing_queue)
@rails_runner_client = addon.rails_runner_client
@outgoing_queue << Notification.window_log_message("Activating Tapioca add-on v#{version}")
@rails_runner_client.register_server_addon(File.expand_path("server_addon.rb", __dir__))
@rails_runner_client.delegate_notification(
server_addon_name: "Tapioca",
request_name: "load_compilers_and_extensions",
workspace_path: @global_state.workspace_path,
)
rescue IncompatibleApiError
# The requested version for the Rails add-on no longer matches. We need to upgrade and fix the breaking
# changes
Expand Down
9 changes: 9 additions & 0 deletions lib/ruby_lsp/tapioca/server_addon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ def name

def execute(request, params)
case request
when "load_compilers_and_extensions"
# Load DSL extensions and compilers ahead of time, so that we don't have to pay the price of invoking
# `Gem.find_files` on every execution, which is quite expensive
::Tapioca::Loaders::Dsl.new(
tapioca_path: ::Tapioca::TAPIOCA_DIR,
eager_load: false,
app_root: params[:workspace_path],
halt_upon_load_error: false,
).load_dsl_extensions_and_compilers
when "dsl"
fork do
dsl(params)
Expand Down
4 changes: 3 additions & 1 deletion lib/tapioca/commands/abstract_dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,14 @@ def pipeline

sig { void }
def load_application
# Loaded ahead of time when using the add-on to avoid reloading multiple times
return if @lsp_addon

Loaders::Dsl.load_application(
tapioca_path: @tapioca_path,
eager_load: @requested_constants.empty? && @requested_paths.empty?,
app_root: @app_root,
halt_upon_load_error: @halt_upon_load_error,
lsp_addon: @lsp_addon,
)
end

Expand Down
13 changes: 3 additions & 10 deletions lib/tapioca/loaders/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,20 @@ class << self
eager_load: T::Boolean,
app_root: String,
halt_upon_load_error: T::Boolean,
lsp_addon: T::Boolean,
).void
end
def load_application(
tapioca_path:,
eager_load: true,
app_root: ".",
halt_upon_load_error: true,
lsp_addon: false
halt_upon_load_error: true
)
loader = new(
new(
tapioca_path: tapioca_path,
eager_load: eager_load,
app_root: app_root,
halt_upon_load_error: halt_upon_load_error,
)
if lsp_addon
loader.load_dsl_extensions_and_compilers
else
loader.load
end
).load
end
end

Expand Down
24 changes: 16 additions & 8 deletions spec/tapioca/addon_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,31 @@ class AddonSpec < Minitest::HooksSpec
def initialize(*args)
super(*T.unsafe(args))
@outgoing_queue = Thread::Queue.new
@client = T.let(nil, T.nilable(RubyLsp::Rails::RunnerClient))
FileUtils.chdir("spec/dummy") do
@client = RubyLsp::Rails::RunnerClient.new(@outgoing_queue)
end
@client = T.let(
FileUtils.chdir("spec/dummy") do
RubyLsp::Rails::RunnerClient.new(@outgoing_queue)
end,
RubyLsp::Rails::RunnerClient,
)

addon_path = File.expand_path("lib/ruby_lsp/tapioca/server_addon.rb")
@client.register_server_addon(File.expand_path(addon_path))
@client.delegate_notification(
server_addon_name: "Tapioca",
request_name: "load_compilers_and_extensions",
workspace_path: Dir.pwd,
)
end

after(:all) do
T.must(@client).shutdown
@client.shutdown

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

it "generates DSL RBIs for a given constant" do
addon_path = File.expand_path("lib/ruby_lsp/tapioca/server_addon.rb")
T.must(@client).register_server_addon(File.expand_path(addon_path))
T.must(@client).delegate_notification(
@client.delegate_notification(
server_addon_name: "Tapioca",
request_name: "dsl",
constants: ["NotifyUserJob"],
Expand Down

0 comments on commit b298065

Please sign in to comment.