From 6161657b4276231837e2195e6ac5efa8e1a13cf4 Mon Sep 17 00:00:00 2001 From: Andy Waite <13400+andyw8@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:31:06 -0400 Subject: [PATCH 1/4] Reload routes when changed --- lib/ruby_lsp/ruby_lsp_rails/addon.rb | 6 +++++- lib/ruby_lsp/ruby_lsp_rails/runner_client.rb | 12 ++++++++++++ lib/ruby_lsp/ruby_lsp_rails/server.rb | 2 ++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/ruby_lsp/ruby_lsp_rails/addon.rb b/lib/ruby_lsp/ruby_lsp_rails/addon.rb index f4363c62..59000155 100644 --- a/lib/ruby_lsp/ruby_lsp_rails/addon.rb +++ b/lib/ruby_lsp/ruby_lsp_rails/addon.rb @@ -123,6 +123,10 @@ def workspace_did_change_watched_files(changes) change[:uri].end_with?("db/schema.rb") || change[:uri].end_with?("structure.sql") end @rails_runner_client.trigger_reload + elsif changes.any? do |change| + change[:uri].end_with?("routes.rb") # TODO: handle other patterns + end + @rails_runner_client.reload_routes end end @@ -141,7 +145,7 @@ def register_additional_file_watchers(global_state:, outgoing_queue:) register_options: Interface::DidChangeWatchedFilesRegistrationOptions.new( watchers: [ Interface::FileSystemWatcher.new( - glob_pattern: "**/*structure.sql", + glob_pattern: "**/*structure.sql,**/*routes.rb", kind: Constant::WatchKind::CREATE | Constant::WatchKind::CHANGE | Constant::WatchKind::DELETE, ), ], diff --git a/lib/ruby_lsp/ruby_lsp_rails/runner_client.rb b/lib/ruby_lsp/ruby_lsp_rails/runner_client.rb index 10706648..7535d702 100644 --- a/lib/ruby_lsp/ruby_lsp_rails/runner_client.rb +++ b/lib/ruby_lsp/ruby_lsp_rails/runner_client.rb @@ -225,6 +225,18 @@ def trigger_reload nil end + sig { void } + def reload_routes + log_message("Reloading Rails routes") + send_notification("reload_routes") + rescue IncompleteMessageError + log_message( + "Ruby LSP Rails failed to reload routes", + type: RubyLsp::Constant::MessageType::ERROR, + ) + nil + end + sig { void } def shutdown log_message("Ruby LSP Rails shutting down server") diff --git a/lib/ruby_lsp/ruby_lsp_rails/server.rb b/lib/ruby_lsp/ruby_lsp_rails/server.rb index 24675580..52a883fc 100644 --- a/lib/ruby_lsp/ruby_lsp_rails/server.rb +++ b/lib/ruby_lsp/ruby_lsp_rails/server.rb @@ -111,6 +111,8 @@ def execute(request, params) send_message(resolve_association_target(params)) when "reload" ::Rails.application.reloader.reload! + when "reload_routes" + ::Rails.application.routes_reloader.execute when "route_location" send_message(route_location(params.fetch(:name))) when "route_info" From 34356a218847d25c4634be8bff11e48ee1334702 Mon Sep 17 00:00:00 2001 From: Andy Waite <13400+andyw8@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:48:05 -0400 Subject: [PATCH 2/4] Add test (wip) --- test/ruby_lsp_rails/server_test.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/ruby_lsp_rails/server_test.rb b/test/ruby_lsp_rails/server_test.rb index 4120d921..e67de8e6 100644 --- a/test/ruby_lsp_rails/server_test.rb +++ b/test/ruby_lsp_rails/server_test.rb @@ -176,6 +176,28 @@ def resolve_route_info(requirements) assert_equal("Hello\n", stderr) end + test "reloads if routes files change" do + @server.execute("route_location", { name: "user_path" }) + location = response[:result][:location] + assert_match(%r{test/dummy/config/routes.rb:5$}, location) + + old_routes = File.read("test/dummy/config/routes.rb") + + File.write("test/dummy/config/routes.rb", <<~RUBY) + Rails.application.routes.draw do + end + RUBY + + @server.execute("reload_routes", {}) + + @server.execute("route_location", { name: "user_path" }) + + location = response[:result][:location] + assert_nil(location) + ensure + File.write("test/dummy/config/routes.rb", old_routes) + end + private def response From 95bd0ec66d9cf21e00699d65956a50e1c9be3def Mon Sep 17 00:00:00 2001 From: Andy Waite <13400+andyw8@users.noreply.github.com> Date: Thu, 31 Oct 2024 13:39:11 -0400 Subject: [PATCH 3/4] Support other patterns, and refactor --- lib/ruby_lsp/ruby_lsp_rails/addon.rb | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/ruby_lsp/ruby_lsp_rails/addon.rb b/lib/ruby_lsp/ruby_lsp_rails/addon.rb index 59000155..36a41b98 100644 --- a/lib/ruby_lsp/ruby_lsp_rails/addon.rb +++ b/lib/ruby_lsp/ruby_lsp_rails/addon.rb @@ -119,13 +119,12 @@ 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 + schema = lambda { |change| change[:uri].end_with?("db/schema.rb") || change[:uri].end_with?("structure.sql") } + routes = lambda { |change| change[:uri].end_with?("routes.rb") || change[:uri].match?("routes/**/*.rb") } + + if changes.any?(&schema) @rails_runner_client.trigger_reload - elsif changes.any? do |change| - change[:uri].end_with?("routes.rb") # TODO: handle other patterns - end + elsif changes.any?(&routes) @rails_runner_client.reload_routes end end @@ -145,7 +144,7 @@ def register_additional_file_watchers(global_state:, outgoing_queue:) register_options: Interface::DidChangeWatchedFilesRegistrationOptions.new( watchers: [ Interface::FileSystemWatcher.new( - glob_pattern: "**/*structure.sql,**/*routes.rb", + glob_pattern: "**/*structure.sql,**/*routes.rb,routes/**/*.rb", kind: Constant::WatchKind::CREATE | Constant::WatchKind::CHANGE | Constant::WatchKind::DELETE, ), ], From 8944ed62f52d303dacf89faae416205a566a5cfc Mon Sep 17 00:00:00 2001 From: Andy Waite <13400+andyw8@users.noreply.github.com> Date: Fri, 1 Nov 2024 13:44:56 -0400 Subject: [PATCH 4/4] Fix testing [skip ci] --- test/ruby_lsp_rails/server_test.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/test/ruby_lsp_rails/server_test.rb b/test/ruby_lsp_rails/server_test.rb index e67de8e6..99353ffa 100644 --- a/test/ruby_lsp_rails/server_test.rb +++ b/test/ruby_lsp_rails/server_test.rb @@ -177,12 +177,12 @@ def resolve_route_info(requirements) end test "reloads if routes files change" do + old_routes = File.read("test/dummy/config/routes.rb") + @server.execute("route_location", { name: "user_path" }) location = response[:result][:location] assert_match(%r{test/dummy/config/routes.rb:5$}, location) - old_routes = File.read("test/dummy/config/routes.rb") - File.write("test/dummy/config/routes.rb", <<~RUBY) Rails.application.routes.draw do end @@ -192,8 +192,7 @@ def resolve_route_info(requirements) @server.execute("route_location", { name: "user_path" }) - location = response[:result][:location] - assert_nil(location) + assert_nil(response[:result]) ensure File.write("test/dummy/config/routes.rb", old_routes) end @@ -201,7 +200,10 @@ def resolve_route_info(requirements) private def response - _headers, content = @stdout.string.split("\r\n\r\n") - JSON.parse(content, symbolize_names: true) + headers, content = @stdout.string.split("\r\n\r\n") + content_length = headers[/Content-Length: (\d+)/i, 1].to_i + # binding.break + # @stdout.string = "" + JSON.parse(content.first(content_length), symbolize_names: true) end end