From 5be845537e154e25cdcb06ed061e7c3bc76cb893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Efe=20G=C3=B6kdemir?= Date: Sat, 7 Nov 2026 08:08:17 +0300 Subject: [PATCH] Fix pull diagnostic responses --- lib/ruby_lsp/server.rb | 13 ++++-- test/server_test.rb | 94 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 6 deletions(-) diff --git a/lib/ruby_lsp/server.rb b/lib/ruby_lsp/server.rb index c700fc6c55..a1dfce3bc1 100644 --- a/lib/ruby_lsp/server.rb +++ b/lib/ruby_lsp/server.rb @@ -892,7 +892,12 @@ def text_document_diagnostic(message) uri = message.dig(:params, :textDocument, :uri) path = uri.to_standardized_path unless path.nil? || path.start_with?(@global_state.workspace_path) - send_empty_response(message[:id]) + send_message( + Result.new( + id: message[:id], + response: Interface::FullDocumentDiagnosticReport.new(kind: "full", items: []), + ), + ) return end @@ -908,16 +913,17 @@ def text_document_diagnostic(message) send_message( Result.new( id: message[:id], - response: response && Interface::FullDocumentDiagnosticReport.new(kind: "full", items: response), + response: Interface::FullDocumentDiagnosticReport.new(kind: "full", items: response || []), ), ) rescue Requests::Request::InvalidFormatter => error + send_message(Error.new(id: message[:id], code: Constant::ErrorCodes::REQUEST_FAILED, message: error.message)) send_message(Notification.window_show_message( "Configuration error: #{error.message}", type: Constant::MessageType::ERROR, )) - send_empty_response(message[:id]) rescue StandardError, LoadError => error + send_message(Error.new(id: message[:id], code: Constant::ErrorCodes::REQUEST_FAILED, message: error.message)) send_message(Notification.window_show_message( "Error running diagnostics: #{error.message}", type: Constant::MessageType::ERROR, @@ -926,7 +932,6 @@ def text_document_diagnostic(message) "Diagnostics failed with\r\n: #{error.full_message}", type: Constant::MessageType::ERROR, )) - send_empty_response(message[:id]) end #: (Hash[Symbol, untyped] message) -> void diff --git a/test/server_test.rb b/test/server_test.rb index 1301c8b59c..93bf299b83 100644 --- a/test/server_test.rb +++ b/test/server_test.rb @@ -242,7 +242,7 @@ def test_applies_workspace_uri_to_indexing_configs_even_if_no_configs_are_specif assert_equal("/fake", index.configuration.instance_variable_get(:@workspace_path)) end - def test_returns_nil_diagnostics_and_formatting_for_files_outside_workspace + def test_returns_nil_formatting_and_empty_diagnostics_for_files_outside_workspace capture_subprocess_io do @server.process_message({ id: 1, @@ -275,7 +275,97 @@ def test_returns_nil_diagnostics_and_formatting_for_files_outside_workspace }) result = find_message(RubyLsp::Result, id: 3) - assert_nil(result.response) + assert_equal("full", result.response.kind) + assert_empty(result.response.items) + end + + def test_returns_empty_diagnostics_for_erb_and_rbs_documents + ["erb", "rbs"].each_with_index do |language_id, index| + uri = URI::Generic.from_path(path: File.join(Dir.pwd, "file.#{language_id}")) + @server.process_message({ + method: "textDocument/didOpen", + params: { + textDocument: { + uri: uri, + text: "", + version: 1, + languageId: language_id, + }, + }, + }) + + request_id = index + 1 + @server.process_message({ + id: request_id, + method: "textDocument/diagnostic", + params: { textDocument: { uri: uri } }, + }) + + report = find_message(RubyLsp::Result, id: request_id).response + assert_equal("full", report.kind) + assert_empty(report.items) + end + end + + def test_returns_error_when_diagnostics_fail + uri = URI::Generic.from_path(path: File.join(Dir.pwd, "file.rb")) + @server.process_message({ + method: "textDocument/didOpen", + params: { + textDocument: { + uri: uri, + text: "", + version: 1, + languageId: "ruby", + }, + }, + }) + RubyLsp::Requests::Diagnostics.any_instance.expects(:perform).raises(StandardError, "boom") + + capture_subprocess_io do + @server.process_message({ + id: 1, + method: "textDocument/diagnostic", + params: { textDocument: { uri: uri } }, + }) + end + + error = @server.pop_response + assert_instance_of(RubyLsp::Error, error) + assert_equal(RubyLsp::Constant::ErrorCodes::REQUEST_FAILED, error.code) + assert_equal("boom", error.message) + end + + def test_returns_error_when_diagnostics_fail_with_invalid_formatter + uri = URI::Generic.from_path(path: File.join(Dir.pwd, "file.rb")) + @server.process_message({ + method: "textDocument/didOpen", + params: { + textDocument: { + uri: uri, + text: "", + version: 1, + languageId: "ruby", + }, + }, + }) + RubyLsp::Requests::Diagnostics.any_instance.expects(:perform).raises( + RubyLsp::Requests::Request::InvalidFormatter, + "invalid formatter", + ) + + capture_subprocess_io do + @server.process_message({ + id: 1, + method: "textDocument/diagnostic", + params: { textDocument: { uri: uri } }, + }) + end + + error = @server.pop_response + assert_instance_of(RubyLsp::Error, error) + assert_equal(RubyLsp::Constant::ErrorCodes::REQUEST_FAILED, error.code) + assert_equal("invalid formatter", error.message) end def test_did_close_clears_diagnostics