diff --git a/lib/ruby_lsp/ruby_lsp_rails/addon.rb b/lib/ruby_lsp/ruby_lsp_rails/addon.rb index f4363c62..36a41b98 100644 --- a/lib/ruby_lsp/ruby_lsp_rails/addon.rb +++ b/lib/ruby_lsp/ruby_lsp_rails/addon.rb @@ -119,10 +119,13 @@ 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?(&routes) + @rails_runner_client.reload_routes end end @@ -141,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", + glob_pattern: "**/*structure.sql,**/*routes.rb,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" diff --git a/test/ruby_lsp_rails/server_test.rb b/test/ruby_lsp_rails/server_test.rb index 4120d921..99353ffa 100644 --- a/test/ruby_lsp_rails/server_test.rb +++ b/test/ruby_lsp_rails/server_test.rb @@ -176,10 +176,34 @@ def resolve_route_info(requirements) assert_equal("Hello\n", stderr) 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) + + 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" }) + + assert_nil(response[:result]) + ensure + File.write("test/dummy/config/routes.rb", old_routes) + end + 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