Skip to content

Commit

Permalink
Check for pending migrations when watcher is fired
Browse files Browse the repository at this point in the history
  • Loading branch information
vinistock committed Nov 1, 2024
1 parent b26a4ca commit 32a4d5e
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 6 deletions.
98 changes: 92 additions & 6 deletions lib/ruby_lsp/ruby_lsp_rails/addon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,80 @@ def create_definition_listener(response_builder, uri, node_context, dispatcher)

sig { params(changes: T::Array[{ uri: String, type: Integer }]).void }
def workspace_did_change_watched_files(changes)
if changes.any? do |change|
change[:uri].end_with?("db/schema.rb") || change[:uri].end_with?("structure.sql")
end
if changes.any? { |c| c[:uri].end_with?("db/schema.rb") || c[:uri].end_with?("structure.sql") }
@rails_runner_client.trigger_reload
end

if changes.any? do |c|
%r{db(/|\\)migrate(/|\\).*\.rb}.match?(c[:uri]) && c[:type] != Constant::FileChangeType::CHANGED
end

offer_to_run_pending_migrations
end
end

sig { override.returns(String) }
def name
"Ruby LSP Rails"
end

sig { override.params(title: String).void }
def handle_window_show_message_response(title)
if title == "Run Migrations"

begin_progress("run-migrations", "Running Migrations")
response = @rails_runner_client.run_migrations

if response && @outgoing_queue
if response[:status] != 0
@outgoing_queue << Notification.window_show_message(
"Migrations failed to run\n\n#{response[:message]}",
type: Constant::MessageType::ERROR,
)
else
# Both log the message and show it as part of progress because sometimes running migrations is so fast you
# can't see the progress notification
@outgoing_queue << Notification.window_log_message(response[:message])
report_progress("run-migrations", message: response[:message])
end
end

end_progress("run-migrations")
end
end

private

sig { params(id: String, title: String, percentage: T.nilable(Integer), message: T.nilable(String)).void }
def begin_progress(id, title, percentage: nil, message: nil)
return unless @global_state&.client_capabilities&.supports_progress && @outgoing_queue

@outgoing_queue << Request.new(
id: "progress-request-#{id}",
method: "window/workDoneProgress/create",
params: Interface::WorkDoneProgressCreateParams.new(token: id),
)

@outgoing_queue << Notification.progress_begin(
id,
title,
percentage: percentage,
message: "#{percentage}% completed",
)
end

sig { params(id: String, percentage: T.nilable(Integer), message: T.nilable(String)).void }
def report_progress(id, percentage: nil, message: nil)
return unless @global_state&.client_capabilities&.supports_progress && @outgoing_queue

@outgoing_queue << Notification.progress_report(id, percentage: percentage, message: message)
end

sig { params(id: String).void }
def end_progress(id)
return unless @global_state&.client_capabilities&.supports_progress && @outgoing_queue

@outgoing_queue << Notification.progress_end(id)
end

sig { params(global_state: GlobalState, outgoing_queue: Thread::Queue).void }
Expand Down Expand Up @@ -152,9 +221,26 @@ def register_additional_file_watchers(global_state:, outgoing_queue:)
)
end

sig { override.returns(String) }
def name
"Ruby LSP Rails"
sig { void }
def offer_to_run_pending_migrations
return unless @outgoing_queue
return unless @global_state&.client_capabilities&.window_show_message_supports_extra_properties

migration_message = @rails_runner_client.pending_migrations
return unless migration_message

@outgoing_queue << Request.new(
id: "rails-pending-migrations",
method: "window/showMessageRequest",
params: {
type: Constant::MessageType::INFO,
message: migration_message,
actions: [
{ title: "Run Migrations", addon_name: name, method: "window/showMessageRequest" },
{ title: "Cancel", addon_name: name, method: "window/showMessageRequest" },
],
},
)
end
end
end
Expand Down
43 changes: 43 additions & 0 deletions test/ruby_lsp_rails/addon_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,49 @@ class AddonTest < ActiveSupport::TestCase
addon = Addon.new
addon.workspace_did_change_watched_files(changes)
end

test "handling window show message response to run migrations" do
RunnerClient.any_instance.expects(:run_migrations).once.returns({ message: "Ran migrations!", status: 0 })
outgoing_queue = Thread::Queue.new
global_state = GlobalState.new
global_state.apply_options({ capabilities: { window: { workDoneProgress: true } } })

addon = Addon.new
addon.activate(global_state, outgoing_queue)

# Wait until activation is done
Thread.new do
addon.rails_runner_client
end.join

addon.handle_window_show_message_response("Run Migrations")

progress_request = pop_message(outgoing_queue) { |message| message.is_a?(Request) }
assert_instance_of(Request, progress_request)

progress_begin = pop_message(outgoing_queue) do |message|
message.is_a?(Notification) && message.method == "$/progress"
end
assert_equal("begin", progress_begin.params.value.kind)

report_log = pop_message(outgoing_queue) do |message|
message.is_a?(Notification) && message.method == "window/logMessage"
end
assert_equal("Ran migrations!", report_log.params.message)

progress_report = pop_message(outgoing_queue) do |message|
message.is_a?(Notification) && message.method == "$/progress"
end
assert_equal("report", progress_report.params.value.kind)
assert_equal("Ran migrations!", progress_report.params.value.message)

progress_end = pop_message(outgoing_queue) do |message|
message.is_a?(Notification) && message.method == "$/progress"
end
assert_equal("end", progress_end.params.value.kind)
ensure
T.must(outgoing_queue).close
end
end
end
end
8 changes: 8 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,13 @@ def pop_log_notification(message_queue, type)
log = message_queue.pop until log.params.type == type
log
end

def pop_message(outgoing_queue, &block)
message = outgoing_queue.pop
return message if block.call(message)

message = outgoing_queue.pop until block.call(message)
message
end
end
end

0 comments on commit 32a4d5e

Please sign in to comment.