From 0aa8a9042856da2bcad5e3eb4f7d8d3314619e54 Mon Sep 17 00:00:00 2001 From: Joseph Johansen Date: Thu, 20 Feb 2025 12:40:48 +0000 Subject: [PATCH 1/2] Improve fault tolerance of addon delegation requests --- lib/ruby_lsp/ruby_lsp_rails/server.rb | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/ruby_lsp/ruby_lsp_rails/server.rb b/lib/ruby_lsp/ruby_lsp_rails/server.rb index a6b20171..872db540 100644 --- a/lib/ruby_lsp/ruby_lsp_rails/server.rb +++ b/lib/ruby_lsp/ruby_lsp_rails/server.rb @@ -158,6 +158,8 @@ def send_notification(message) class ServerAddon include Common + class MissingAddonError < StandardError; end + @server_addon_classes = [] @server_addons = {} @@ -171,7 +173,14 @@ def inherited(child) # Delegate `request` with `params` to the server add-on with the given `name` def delegate(name, request, params) - @server_addons[name]&.execute(request, params) + addon = @server_addons.fetch(name) do + checker = DidYouMean::SpellChecker.new(dictionary: @server_addons.keys) + suggestions = checker.correct(name) + msg = "No extension with name #{name}." + msg += " Did you mean: #{options.join(" / ")}" if suggestions.any? + raise ServerAddon::MissingAddonError, msg + end + addon.execute(request, params) end # Instantiate all server addons and store them in a hash for easy access after we have discovered the classes @@ -298,9 +307,13 @@ def execute(request, params) server_addon_name = params[:server_addon_name] request_name = params[:request_name] - # Do not wrap this in error handlers. Server add-ons need to have the flexibility to choose if they want to - # include a response or not as part of error handling, so a blanket approach is not appropriate. - ServerAddon.delegate(server_addon_name, request_name, params.except(:request_name, :server_addon_name)) + # Do not wrap this in additional error handlers. Server add-ons need to have the flexibility to choose if they want to + # include a response or not as part of their own error handling, so a blanket approach is not appropriate. + begin + ServerAddon.delegate(server_addon_name, request_name, params.except(:request_name, :server_addon_name)) + rescue ServerAddon::MissingAddonError => e + send_error_response(e.message) + end end end From 5fbd7474809154f2dc9c1bfea73f7e57f6216087 Mon Sep 17 00:00:00 2001 From: Joseph Johansen Date: Wed, 26 Feb 2025 12:20:35 +0000 Subject: [PATCH 2/2] Remove suggested corections --- lib/ruby_lsp/ruby_lsp_rails/server.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/ruby_lsp/ruby_lsp_rails/server.rb b/lib/ruby_lsp/ruby_lsp_rails/server.rb index 872db540..f4eb777a 100644 --- a/lib/ruby_lsp/ruby_lsp_rails/server.rb +++ b/lib/ruby_lsp/ruby_lsp_rails/server.rb @@ -174,11 +174,7 @@ def inherited(child) # Delegate `request` with `params` to the server add-on with the given `name` def delegate(name, request, params) addon = @server_addons.fetch(name) do - checker = DidYouMean::SpellChecker.new(dictionary: @server_addons.keys) - suggestions = checker.correct(name) - msg = "No extension with name #{name}." - msg += " Did you mean: #{options.join(" / ")}" if suggestions.any? - raise ServerAddon::MissingAddonError, msg + raise ServerAddon::MissingAddonError, "No extension with name #{name}" end addon.execute(request, params) end