mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	Merge #34853 from ribru17/diag_related_docs
feat(lsp): diagnostic related documents support
This commit is contained in:
		| @@ -214,6 +214,8 @@ LSP | ||||
|   jump to the problematic location. | ||||
| • Support for `textDocument/linkedEditingRange`: |lsp-linked_editing_range| | ||||
|   https://microsoft.github.io/language-server-protocol/specification/#textDocument_linkedEditingRange | ||||
| • Support for related documents in pull diagnostics: | ||||
|   https://microsoft.github.io/language-server-protocol/specifications/specification-current/#relatedFullDocumentDiagnosticReport | ||||
|  | ||||
| LUA | ||||
|  | ||||
|   | ||||
| @@ -269,16 +269,36 @@ function M.on_diagnostic(error, result, ctx) | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   if result == nil or result.kind == 'unchanged' then | ||||
|   if result == nil then | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   local client_id = ctx.client_id | ||||
|   handle_diagnostics(ctx.params.textDocument.uri, client_id, result.items, true) | ||||
|  | ||||
|   local bufnr = assert(ctx.bufnr) | ||||
|   local bufstate = bufstates[bufnr] | ||||
|   bufstate.client_result_id[client_id] = result.resultId | ||||
|  | ||||
|   if result.kind == 'unchanged' then | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   handle_diagnostics(ctx.params.textDocument.uri, client_id, result.items, true) | ||||
|  | ||||
|   for uri, related_result in pairs(result.relatedDocuments or {}) do | ||||
|     if related_result.kind == 'full' then | ||||
|       handle_diagnostics(uri, client_id, related_result.items, true) | ||||
|     end | ||||
|  | ||||
|     local related_bufnr = vim.uri_to_bufnr(uri) | ||||
|     local related_bufstate = bufstates[related_bufnr] | ||||
|       -- Create a new bufstate if it doesn't exist for the related document. This will not enable | ||||
|       -- diagnostic pulling by itself, but will allow previous result IDs to be passed correctly the | ||||
|       -- next time this buffer's diagnostics are pulled. | ||||
|       or { pull_kind = 'document', client_result_id = {} } | ||||
|     bufstates[related_bufnr] = related_bufstate | ||||
|  | ||||
|     related_bufstate.client_result_id[client_id] = related_result.resultId | ||||
|   end | ||||
| end | ||||
|  | ||||
| --- Clear push diagnostics and diagnostic cache. | ||||
|   | ||||
| @@ -350,6 +350,7 @@ function protocol.make_client_capabilities() | ||||
|         }, | ||||
|         dataSupport = true, | ||||
|         relatedInformation = true, | ||||
|         relatedDocumentSupport = true, | ||||
|       }, | ||||
|       inlayHint = { | ||||
|         dynamicRegistration = true, | ||||
|   | ||||
| @@ -470,6 +470,7 @@ describe('vim.lsp.diagnostic', function() | ||||
|     end) | ||||
|  | ||||
|     it('requests with the `previousResultId`', function() | ||||
|       -- Full reports | ||||
|       eq( | ||||
|         'dummy_server', | ||||
|         exec_lua(function() | ||||
| @@ -497,6 +498,85 @@ describe('vim.lsp.diagnostic', function() | ||||
|           return _G.params.previousResultId | ||||
|         end) | ||||
|       ) | ||||
|  | ||||
|       -- Unchanged reports | ||||
|       eq( | ||||
|         'squidward', | ||||
|         exec_lua(function() | ||||
|           vim.lsp.diagnostic.on_diagnostic(nil, { | ||||
|             kind = 'unchanged', | ||||
|             resultId = 'squidward', | ||||
|           }, { | ||||
|             method = vim.lsp.protocol.Methods.textDocument_diagnostic, | ||||
|             params = { | ||||
|               textDocument = { uri = fake_uri }, | ||||
|             }, | ||||
|             client_id = client_id, | ||||
|             bufnr = diagnostic_bufnr, | ||||
|           }) | ||||
|           vim.api.nvim_exec_autocmds('LspNotify', { | ||||
|             buffer = diagnostic_bufnr, | ||||
|             data = { | ||||
|               method = vim.lsp.protocol.Methods.textDocument_didChange, | ||||
|               client_id = client_id, | ||||
|             }, | ||||
|           }) | ||||
|           return _G.params.previousResultId | ||||
|         end) | ||||
|       ) | ||||
|     end) | ||||
|  | ||||
|     it('handles relatedDocuments diagnostics', function() | ||||
|       local fake_uri_2 = 'file:///fake/uri2' | ||||
|       ---@type vim.Diagnostic[], vim.Diagnostic[], string? | ||||
|       local diagnostics, related_diagnostics, relatedPreviousResultId = exec_lua(function() | ||||
|         local second_buf = vim.uri_to_bufnr(fake_uri_2) | ||||
|         vim.fn.bufload(second_buf) | ||||
|  | ||||
|         -- Attach the client to both buffers. | ||||
|         vim.api.nvim_win_set_buf(0, second_buf) | ||||
|         vim.lsp.start({ name = 'dummy', cmd = _G.server.cmd }) | ||||
|  | ||||
|         vim.lsp.diagnostic.on_diagnostic(nil, { | ||||
|           kind = 'full', | ||||
|           relatedDocuments = { | ||||
|             [fake_uri_2] = { | ||||
|               kind = 'full', | ||||
|               resultId = 'spongebob', | ||||
|               items = { | ||||
|                 { | ||||
|                   range = _G.make_range(4, 4, 4, 4), | ||||
|                   message = 'related bad!', | ||||
|                 }, | ||||
|               }, | ||||
|             }, | ||||
|           }, | ||||
|           items = {}, | ||||
|         }, { | ||||
|           params = { | ||||
|             textDocument = { uri = fake_uri }, | ||||
|           }, | ||||
|           uri = fake_uri, | ||||
|           client_id = client_id, | ||||
|           bufnr = diagnostic_bufnr, | ||||
|         }, {}) | ||||
|  | ||||
|         vim.api.nvim_exec_autocmds('LspNotify', { | ||||
|           buffer = second_buf, | ||||
|           data = { | ||||
|             method = vim.lsp.protocol.Methods.textDocument_didChange, | ||||
|             client_id = client_id, | ||||
|           }, | ||||
|         }) | ||||
|  | ||||
|         return vim.diagnostic.get(diagnostic_bufnr), | ||||
|           vim.diagnostic.get(second_buf), | ||||
|           _G.params.previousResultId | ||||
|       end) | ||||
|       eq(0, #diagnostics) | ||||
|       eq(1, #related_diagnostics) | ||||
|       eq('related bad!', related_diagnostics[1].message) | ||||
|       eq('spongebob', relatedPreviousResultId) | ||||
|     end) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Justin M. Keyes
					Justin M. Keyes