diff options
Diffstat (limited to 'test/functional')
-rw-r--r-- | test/functional/plugin/lsp/diagnostic_spec.lua | 767 | ||||
-rw-r--r-- | test/functional/plugin/lsp/handler_spec.lua | 29 | ||||
-rw-r--r-- | test/functional/plugin/lsp_spec.lua | 95 |
3 files changed, 825 insertions, 66 deletions
diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua new file mode 100644 index 0000000000..0fb55da4bd --- /dev/null +++ b/test/functional/plugin/lsp/diagnostic_spec.lua @@ -0,0 +1,767 @@ +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local exec_lua = helpers.exec_lua +local eq = helpers.eq +local nvim = helpers.nvim + +describe('vim.lsp.diagnostic', function() + local fake_uri + + before_each(function() + clear() + + exec_lua [[ + require('vim.lsp') + + make_range = function(x1, y1, x2, y2) + return { start = { line = x1, character = y1 }, ['end'] = { line = x2, character = y2 } } + end + + make_error = function(msg, x1, y1, x2, y2) + return { + range = make_range(x1, y1, x2, y2), + message = msg, + severity = 1, + } + end + + make_warning = function(msg, x1, y1, x2, y2) + return { + range = make_range(x1, y1, x2, y2), + message = msg, + severity = 2, + } + end + + make_information = function(msg, x1, y1, x2, y2) + return { + range = make_range(x1, y1, x2, y2), + message = msg, + severity = 3, + } + end + + count_of_extmarks_for_client = function(bufnr, client_id) + return #vim.api.nvim_buf_get_extmarks( + bufnr, vim.lsp.diagnostic._get_diagnostic_namespace(client_id), 0, -1, {} + ) + end + ]] + + fake_uri = "file://fake/uri" + + exec_lua([[ + fake_uri = ... + diagnostic_bufnr = vim.uri_to_bufnr(fake_uri) + local lines = {"1st line of text", "2nd line of text", "wow", "cool", "more", "lines"} + vim.fn.bufload(diagnostic_bufnr) + vim.api.nvim_buf_set_lines(diagnostic_bufnr, 0, 1, false, lines) + return diagnostic_bufnr + ]], fake_uri) + end) + + after_each(function() + clear() + end) + + describe('vim.lsp.diagnostic', function() + describe('handle_publish_diagnostics', function() + it('should be able to save and count a single client error', function() + eq(1, exec_lua [[ + vim.lsp.diagnostic.save( + { + make_error('Diagnostic #1', 1, 1, 1, 1), + }, 0, 1 + ) + return vim.lsp.diagnostic.get_count(0, "Error", 1) + ]]) + end) + + it('should be able to save and count from two clients', function() + eq(2, exec_lua [[ + vim.lsp.diagnostic.save( + { + make_error('Diagnostic #1', 1, 1, 1, 1), + make_error('Diagnostic #2', 2, 1, 2, 1), + }, 0, 1 + ) + return vim.lsp.diagnostic.get_count(0, "Error", 1) + ]]) + end) + + it('should be able to save and count from multiple clients', function() + eq({1, 1, 2}, exec_lua [[ + vim.lsp.diagnostic.save( + { + make_error('Diagnostic From Server 1', 1, 1, 1, 1), + }, 0, 1 + ) + vim.lsp.diagnostic.save( + { + make_error('Diagnostic From Server 2', 1, 1, 1, 1), + }, 0, 2 + ) + return { + -- Server 1 + vim.lsp.diagnostic.get_count(0, "Error", 1), + -- Server 2 + vim.lsp.diagnostic.get_count(0, "Error", 2), + -- All servers + vim.lsp.diagnostic.get_count(0, "Error", nil), + } + ]]) + end) + + it('should be able to save and count from multiple clients with respect to severity', function() + eq({3, 0, 3}, exec_lua [[ + vim.lsp.diagnostic.save( + { + make_error('Diagnostic From Server 1:1', 1, 1, 1, 1), + make_error('Diagnostic From Server 1:2', 2, 2, 2, 2), + make_error('Diagnostic From Server 1:3', 2, 3, 3, 2), + }, 0, 1 + ) + vim.lsp.diagnostic.save( + { + make_warning('Warning From Server 2', 3, 3, 3, 3), + }, 0, 2 + ) + return { + -- Server 1 + vim.lsp.diagnostic.get_count(0, "Error", 1), + -- Server 2 + vim.lsp.diagnostic.get_count(0, "Error", 2), + -- All servers + vim.lsp.diagnostic.get_count(0, "Error", nil), + } + ]]) + end) + + it('should handle one server clearing highlights while the other still has highlights', function() + -- 1 Error (1) + -- 1 Warning (2) + -- 1 Warning (2) + 1 Warning (1) + -- 2 highlights and 2 underlines (since error) + -- 1 highlight + 1 underline + local all_highlights = {1, 1, 2, 4, 2} + eq(all_highlights, exec_lua [[ + local server_1_diags = { + make_error("Error 1", 1, 1, 1, 5), + make_warning("Warning on Server 1", 2, 1, 2, 5), + } + local server_2_diags = { + make_warning("Warning 1", 2, 1, 2, 5), + } + + vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, { uri = fake_uri, diagnostics = server_1_diags }, 1) + vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, { uri = fake_uri, diagnostics = server_2_diags }, 2) + return { + vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1), + vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2), + vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil), + count_of_extmarks_for_client(diagnostic_bufnr, 1), + count_of_extmarks_for_client(diagnostic_bufnr, 2), + } + ]]) + + -- Clear diagnostics from server 1, and make sure we have the right amount of stuff for client 2 + eq({1, 1, 2, 0, 2}, exec_lua [[ + vim.lsp.diagnostic.clear(diagnostic_bufnr, 1) + return { + vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1), + vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2), + vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil), + count_of_extmarks_for_client(diagnostic_bufnr, 1), + count_of_extmarks_for_client(diagnostic_bufnr, 2), + } + ]]) + + -- Show diagnostics from server 1 again + eq(all_highlights, exec_lua([[ + vim.lsp.diagnostic.display(nil, diagnostic_bufnr, 1) + return { + vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1), + vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2), + vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil), + count_of_extmarks_for_client(diagnostic_bufnr, 1), + count_of_extmarks_for_client(diagnostic_bufnr, 2), + } + ]])) + end) + + describe('get_next_diagnostic_pos', function() + it('can find the next pos with only one client', function() + eq({1, 1}, exec_lua [[ + vim.lsp.diagnostic.save( + { + make_error('Diagnostic #1', 1, 1, 1, 1), + }, diagnostic_bufnr, 1 + ) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + return vim.lsp.diagnostic.get_next_pos() + ]]) + end) + + it('can find next pos with two errors', function() + eq({4, 4}, exec_lua [[ + vim.lsp.diagnostic.save( + { + make_error('Diagnostic #1', 1, 1, 1, 1), + make_error('Diagnostic #2', 4, 4, 4, 4), + }, diagnostic_bufnr, 1 + ) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 1}) + return vim.lsp.diagnostic.get_next_pos { client_id = 1 } + ]]) + end) + + it('can cycle when position is past error', function() + eq({1, 1}, exec_lua [[ + vim.lsp.diagnostic.save( + { + make_error('Diagnostic #1', 1, 1, 1, 1), + }, diagnostic_bufnr, 1 + ) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 1}) + return vim.lsp.diagnostic.get_next_pos { client_id = 1 } + ]]) + end) + + it('will not cycle when wrap is off', function() + eq(false, exec_lua [[ + vim.lsp.diagnostic.save( + { + make_error('Diagnostic #1', 1, 1, 1, 1), + }, diagnostic_bufnr, 1 + ) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 1}) + return vim.lsp.diagnostic.get_next_pos { client_id = 1, wrap = false } + ]]) + end) + + it('can cycle even from the last line', function() + eq({4, 4}, exec_lua [[ + vim.lsp.diagnostic.save( + { + make_error('Diagnostic #2', 4, 4, 4, 4), + }, diagnostic_bufnr, 1 + ) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {vim.api.nvim_buf_line_count(0), 1}) + return vim.lsp.diagnostic.get_prev_pos { client_id = 1 } + ]]) + end) + end) + + describe('get_prev_diagnostic_pos', function() + it('can find the prev pos with only one client', function() + eq({1, 1}, exec_lua [[ + vim.lsp.diagnostic.save( + { + make_error('Diagnostic #1', 1, 1, 1, 1), + }, diagnostic_bufnr, 1 + ) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 1}) + return vim.lsp.diagnostic.get_prev_pos() + ]]) + end) + + it('can find prev pos with two errors', function() + eq({1, 1}, exec_lua [[ + vim.lsp.diagnostic.save( + { + make_error('Diagnostic #1', 1, 1, 1, 1), + make_error('Diagnostic #2', 4, 4, 4, 4), + }, diagnostic_bufnr, 1 + ) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 1}) + return vim.lsp.diagnostic.get_prev_pos { client_id = 1 } + ]]) + end) + + it('can cycle when position is past error', function() + eq({4, 4}, exec_lua [[ + vim.lsp.diagnostic.save( + { + make_error('Diagnostic #2', 4, 4, 4, 4), + }, diagnostic_bufnr, 1 + ) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 1}) + return vim.lsp.diagnostic.get_prev_pos { client_id = 1 } + ]]) + end) + + it('respects wrap parameter', function() + eq(false, exec_lua [[ + vim.lsp.diagnostic.save( + { + make_error('Diagnostic #2', 4, 4, 4, 4), + }, diagnostic_bufnr, 1 + ) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 1}) + return vim.lsp.diagnostic.get_prev_pos { client_id = 1, wrap = false} + ]]) + end) + end) + end) + end) + + describe("vim.lsp.diagnostic.get_line_diagnostics", function() + it('should return an empty table when no diagnostics are present', function() + eq({}, exec_lua [[return vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1)]]) + end) + + it('should return all diagnostics when no severity is supplied', function() + eq(2, exec_lua [[ + vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, { + uri = fake_uri, + diagnostics = { + make_error("Error 1", 1, 1, 1, 5), + make_warning("Warning on Server 1", 1, 1, 2, 5), + make_error("Error On Other Line", 2, 1, 1, 5), + } + }, 1) + + return #vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1) + ]]) + end) + + it('should return only requested diagnostics when severity_limit is supplied', function() + eq(2, exec_lua [[ + vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, { + uri = fake_uri, + diagnostics = { + make_error("Error 1", 1, 1, 1, 5), + make_warning("Warning on Server 1", 1, 1, 2, 5), + make_information("Ignored information", 1, 1, 2, 5), + make_error("Error On Other Line", 2, 1, 1, 5), + } + }, 1) + + return #vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1, { severity_limit = "Warning" }) + ]]) + end) + end) + + describe("vim.lsp.diagnostic.on_publish_diagnostics", function() + it('can use functions for config values', function() + exec_lua [[ + vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { + virtual_text = function() return true end, + })(nil, nil, { + uri = fake_uri, + diagnostics = { + make_error('Delayed Diagnostic', 4, 4, 4, 4), + } + }, 1 + ) + ]] + + eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) + eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) + + -- Now, don't enable virtual text. + -- We should have one less extmark displayed. + exec_lua [[ + vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { + virtual_text = function() return false end, + })(nil, nil, { + uri = fake_uri, + diagnostics = { + make_error('Delayed Diagnostic', 4, 4, 4, 4), + } + }, 1 + ) + ]] + + eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) + eq(1, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) + end) + + it('can perform updates after insert_leave', function() + exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]] + nvim("input", "o") + eq({mode='i', blocking=false}, nvim("get_mode")) + + -- Save the diagnostics + exec_lua [[ + vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { + update_in_insert = false, + })(nil, nil, { + uri = fake_uri, + diagnostics = { + make_error('Delayed Diagnostic', 4, 4, 4, 4), + } + }, 1 + ) + ]] + + -- No diagnostics displayed yet. + eq({mode='i', blocking=false}, nvim("get_mode")) + eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) + eq(0, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) + + nvim("input", "<esc>") + eq({mode='n', blocking=false}, nvim("get_mode")) + + eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) + eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) + end) + + it('does not perform updates when not needed', function() + exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]] + nvim("input", "o") + eq({mode='i', blocking=false}, nvim("get_mode")) + + -- Save the diagnostics + exec_lua [[ + PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { + update_in_insert = false, + virtual_text = true, + }) + + -- Count how many times we call display. + SetVirtualTextOriginal = vim.lsp.diagnostic.set_virtual_text + + DisplayCount = 0 + vim.lsp.diagnostic.set_virtual_text = function(...) + DisplayCount = DisplayCount + 1 + return SetVirtualTextOriginal(...) + end + + PublishDiagnostics(nil, nil, { + uri = fake_uri, + diagnostics = { + make_error('Delayed Diagnostic', 4, 4, 4, 4), + } + }, 1 + ) + ]] + + -- No diagnostics displayed yet. + eq({mode='i', blocking=false}, nvim("get_mode")) + eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) + eq(0, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) + eq(0, exec_lua [[return DisplayCount]]) + + nvim("input", "<esc>") + eq({mode='n', blocking=false}, nvim("get_mode")) + + eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) + eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) + eq(1, exec_lua [[return DisplayCount]]) + + -- Go in and out of insert mode one more time. + nvim("input", "o") + eq({mode='i', blocking=false}, nvim("get_mode")) + + nvim("input", "<esc>") + eq({mode='n', blocking=false}, nvim("get_mode")) + + -- Should not have set the virtual text again. + eq(1, exec_lua [[return DisplayCount]]) + end) + + it('never sets virtual text, in combination with insert leave', function() + exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]] + nvim("input", "o") + eq({mode='i', blocking=false}, nvim("get_mode")) + + -- Save the diagnostics + exec_lua [[ + PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { + update_in_insert = false, + virtual_text = false, + }) + + -- Count how many times we call display. + SetVirtualTextOriginal = vim.lsp.diagnostic.set_virtual_text + + DisplayCount = 0 + vim.lsp.diagnostic.set_virtual_text = function(...) + DisplayCount = DisplayCount + 1 + return SetVirtualTextOriginal(...) + end + + PublishDiagnostics(nil, nil, { + uri = fake_uri, + diagnostics = { + make_error('Delayed Diagnostic', 4, 4, 4, 4), + } + }, 1 + ) + ]] + + -- No diagnostics displayed yet. + eq({mode='i', blocking=false}, nvim("get_mode")) + eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) + eq(0, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) + eq(0, exec_lua [[return DisplayCount]]) + + nvim("input", "<esc>") + eq({mode='n', blocking=false}, nvim("get_mode")) + + eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) + eq(1, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) + eq(0, exec_lua [[return DisplayCount]]) + + -- Go in and out of insert mode one more time. + nvim("input", "o") + eq({mode='i', blocking=false}, nvim("get_mode")) + + nvim("input", "<esc>") + eq({mode='n', blocking=false}, nvim("get_mode")) + + -- Should not have set the virtual text still. + eq(0, exec_lua [[return DisplayCount]]) + end) + + it('can perform updates while in insert mode, if desired', function() + exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]] + nvim("input", "o") + eq({mode='i', blocking=false}, nvim("get_mode")) + + -- Save the diagnostics + exec_lua [[ + vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { + update_in_insert = true, + })(nil, nil, { + uri = fake_uri, + diagnostics = { + make_error('Delayed Diagnostic', 4, 4, 4, 4), + } + }, 1 + ) + ]] + + -- Diagnostics are displayed, because the user wanted them that way! + eq({mode='i', blocking=false}, nvim("get_mode")) + eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) + eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) + + nvim("input", "<esc>") + eq({mode='n', blocking=false}, nvim("get_mode")) + + eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]]) + eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]]) + end) + + it('allows configuring the virtual text via vim.lsp.with', function() + local expected_spacing = 10 + local extmarks = exec_lua([[ + PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { + virtual_text = { + spacing = ..., + }, + }) + + PublishDiagnostics(nil, nil, { + uri = fake_uri, + diagnostics = { + make_error('Delayed Diagnostic', 4, 4, 4, 4), + } + }, 1 + ) + + return vim.api.nvim_buf_get_extmarks( + diagnostic_bufnr, + vim.lsp.diagnostic._get_diagnostic_namespace(1), + 0, + -1, + { details = true } + ) + ]], expected_spacing) + + local virt_text = extmarks[1][4].virt_text + local spacing = virt_text[1][1] + + eq(expected_spacing, #spacing) + end) + + + it('allows configuring the virtual text via vim.lsp.with using a function', function() + local expected_spacing = 10 + local extmarks = exec_lua([[ + spacing = ... + + PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { + virtual_text = function() + return { + spacing = spacing, + } + end, + }) + + PublishDiagnostics(nil, nil, { + uri = fake_uri, + diagnostics = { + make_error('Delayed Diagnostic', 4, 4, 4, 4), + } + }, 1 + ) + + return vim.api.nvim_buf_get_extmarks( + diagnostic_bufnr, + vim.lsp.diagnostic._get_diagnostic_namespace(1), + 0, + -1, + { details = true } + ) + ]], expected_spacing) + + local virt_text = extmarks[1][4].virt_text + local spacing = virt_text[1][1] + + eq(expected_spacing, #spacing) + end) + end) + + describe('lsp.util.show_line_diagnostics', function() + it('creates floating window and returns popup bufnr and winnr if current line contains diagnostics', function() + -- Two lines: + -- Diagnostic: + -- 1. <msg> + eq(2, exec_lua [[ + local buffer = vim.api.nvim_create_buf(false, true) + vim.api.nvim_buf_set_lines(buffer, 0, -1, false, { + "testing"; + "123"; + }) + local diagnostics = { + { + range = { + start = { line = 0; character = 1; }; + ["end"] = { line = 0; character = 3; }; + }; + severity = vim.lsp.protocol.DiagnosticSeverity.Error; + message = "Syntax error"; + }, + } + vim.api.nvim_win_set_buf(0, buffer) + vim.lsp.diagnostic.save(diagnostics, buffer, 1) + local popup_bufnr, winnr = vim.lsp.diagnostic.show_line_diagnostics() + return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) + ]]) + end) + + it('creates floating window and returns popup bufnr and winnr without header, if requested', function() + -- One line (since no header): + -- 1. <msg> + eq(1, exec_lua [[ + local buffer = vim.api.nvim_create_buf(false, true) + vim.api.nvim_buf_set_lines(buffer, 0, -1, false, { + "testing"; + "123"; + }) + local diagnostics = { + { + range = { + start = { line = 0; character = 1; }; + ["end"] = { line = 0; character = 3; }; + }; + severity = vim.lsp.protocol.DiagnosticSeverity.Error; + message = "Syntax error"; + }, + } + vim.api.nvim_win_set_buf(0, buffer) + vim.lsp.diagnostic.save(diagnostics, buffer, 1) + local popup_bufnr, winnr = vim.lsp.diagnostic.show_line_diagnostics { show_header = false } + return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false) + ]]) + end) + end) + + describe('set_signs', function() + -- TODO(tjdevries): Find out why signs are not displayed when set from Lua...?? + pending('sets signs by default', function() + exec_lua [[ + PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { + update_in_insert = true, + signs = true, + }) + + local diagnostics = { + make_error('Delayed Diagnostic', 1, 1, 1, 2), + make_error('Delayed Diagnostic', 3, 3, 3, 3), + } + + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, { + uri = fake_uri, + diagnostics = diagnostics + }, 1 + ) + + vim.lsp.diagnostic.set_signs(diagnostics, diagnostic_bufnr, 1) + -- return vim.fn.sign_getplaced() + ]] + + nvim("input", "o") + nvim("input", "<esc>") + + -- TODO(tjdevries): Find a way to get the signs to display in the test... + eq(nil, exec_lua [[ + return im.fn.sign_getplaced()[1].signs + ]]) + end) + end) + + describe('set_loclist()', function() + it('sets diagnostics in lnum order', function() + local loc_list = exec_lua [[ + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + + vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, { + uri = fake_uri, + diagnostics = { + make_error('Farther Diagnostic', 4, 4, 4, 4), + make_error('Lower Diagnostic', 1, 1, 1, 1), + } + }, 1 + ) + + vim.lsp.diagnostic.set_loclist() + + return vim.fn.getloclist(0) + ]] + + assert(loc_list[1].lnum < loc_list[2].lnum) + end) + + it('sets diagnostics in lnum order, regardless of client', function() + local loc_list = exec_lua [[ + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + + vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, { + uri = fake_uri, + diagnostics = { + make_error('Lower Diagnostic', 1, 1, 1, 1), + } + }, 1 + ) + + vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, { + uri = fake_uri, + diagnostics = { + make_warning('Farther Diagnostic', 4, 4, 4, 4), + } + }, 2 + ) + + vim.lsp.diagnostic.set_loclist() + + return vim.fn.getloclist(0) + ]] + + assert(loc_list[1].lnum < loc_list[2].lnum) + end) + end) +end) diff --git a/test/functional/plugin/lsp/handler_spec.lua b/test/functional/plugin/lsp/handler_spec.lua new file mode 100644 index 0000000000..3086c23fe8 --- /dev/null +++ b/test/functional/plugin/lsp/handler_spec.lua @@ -0,0 +1,29 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local exec_lua = helpers.exec_lua +local pcall_err = helpers.pcall_err +local matches = helpers.matches + +describe('lsp-handlers', function() + describe('vim.lsp._with_extend', function() + it('should return a table with the default keys', function() + eq({hello = 'world' }, exec_lua [[ + return vim.lsp._with_extend('test', { hello = 'world' }) + ]]) + end) + + it('should override with config keys', function() + eq({hello = 'universe', other = true}, exec_lua [[ + return vim.lsp._with_extend('test', { other = true, hello = 'world' }, { hello = 'universe' }) + ]]) + end) + + it('should not allow invalid keys', function() + matches( + '.*Invalid option for `test`.*', + pcall_err(exec_lua, "return vim.lsp._with_extend('test', { hello = 'world' }, { invalid = true })") + ) + end) + end) +end) diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 00093f71d4..5b048f57e9 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -323,7 +323,7 @@ describe('LSP', function() test_name = "capabilities_for_client_supports_method"; on_setup = function() exec_lua([=[ - vim.lsp.callbacks['textDocument/hover'] = function(err, method) + vim.lsp.handlers['textDocument/hover'] = function(err, method) vim.lsp._last_lsp_callback = { err = err; method = method } end vim.lsp._unsupported_method = function(method) @@ -847,25 +847,28 @@ describe('LSP', function() end it('highlight groups', function() - eq({'LspDiagnosticsError', - 'LspDiagnosticsErrorFloating', - 'LspDiagnosticsErrorSign', - 'LspDiagnosticsHint', - 'LspDiagnosticsHintFloating', - 'LspDiagnosticsHintSign', - 'LspDiagnosticsInformation', - 'LspDiagnosticsInformationFloating', - 'LspDiagnosticsInformationSign', - 'LspDiagnosticsUnderline', - 'LspDiagnosticsUnderlineError', - 'LspDiagnosticsUnderlineHint', - 'LspDiagnosticsUnderlineInformation', - 'LspDiagnosticsUnderlineWarning', - 'LspDiagnosticsWarning', - 'LspDiagnosticsWarningFloating', - 'LspDiagnosticsWarningSign', - }, - exec_lua([[require'vim.lsp'; return vim.fn.getcompletion('Lsp', 'highlight')]])) + eq({ + 'LspDiagnosticsDefaultError', + 'LspDiagnosticsDefaultHint', + 'LspDiagnosticsDefaultInformation', + 'LspDiagnosticsDefaultWarning', + 'LspDiagnosticsFloatingError', + 'LspDiagnosticsFloatingHint', + 'LspDiagnosticsFloatingInformation', + 'LspDiagnosticsFloatingWarning', + 'LspDiagnosticsSignError', + 'LspDiagnosticsSignHint', + 'LspDiagnosticsSignInformation', + 'LspDiagnosticsSignWarning', + 'LspDiagnosticsUnderlineError', + 'LspDiagnosticsUnderlineHint', + 'LspDiagnosticsUnderlineInformation', + 'LspDiagnosticsUnderlineWarning', + 'LspDiagnosticsVirtualTextError', + 'LspDiagnosticsVirtualTextHint', + 'LspDiagnosticsVirtualTextInformation', + 'LspDiagnosticsVirtualTextWarning', + }, exec_lua([[require'vim.lsp'; return vim.fn.getcompletion('Lsp', 'highlight')]])) end) describe('apply_text_edits', function() @@ -1037,7 +1040,7 @@ describe('LSP', function() label = nil; edit = {}; } - return vim.lsp.callbacks['workspace/applyEdit'](nil, nil, apply_edit) + return vim.lsp.handlers['workspace/applyEdit'](nil, nil, apply_edit) ]]) end) end) @@ -1084,47 +1087,7 @@ describe('LSP', function() eq({}, exec_lua([[return vim.lsp.util.text_document_completion_list_to_complete_items(...)]], {}, prefix)) end) end) - describe('buf_diagnostics_save_positions', function() - it('stores the diagnostics in diagnostics_by_buf', function () - local diagnostics = { - { range = {}; message = "diag1" }, - { range = {}; message = "diag2" }, - } - exec_lua([[ - vim.lsp.util.buf_diagnostics_save_positions(...)]], 0, diagnostics) - eq(1, exec_lua [[ return #vim.lsp.util.diagnostics_by_buf ]]) - eq(diagnostics, exec_lua [[ - for _, diagnostics in pairs(vim.lsp.util.diagnostics_by_buf) do - return diagnostics - end - ]]) - end) - end) - describe('lsp.util.show_line_diagnostics', function() - it('creates floating window and returns popup bufnr and winnr if current line contains diagnostics', function() - eq(3, exec_lua [[ - local buffer = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_set_lines(buffer, 0, -1, false, { - "testing"; - "123"; - }) - local diagnostics = { - { - range = { - start = { line = 0; character = 1; }; - ["end"] = { line = 0; character = 3; }; - }; - severity = vim.lsp.protocol.DiagnosticSeverity.Error; - message = "Syntax error"; - }, - } - vim.api.nvim_win_set_buf(0, buffer) - vim.lsp.util.buf_diagnostics_save_positions(vim.fn.bufnr(buffer), diagnostics) - local popup_bufnr, winnr = vim.lsp.util.show_line_diagnostics() - return popup_bufnr - ]]) - end) - end) + describe('lsp.util.locations_to_items', function() it('Convert Location[] to items', function() local expected = { @@ -1556,7 +1519,7 @@ describe('LSP', function() describe('vim.lsp.buf.outgoing_calls', function() it('does nothing for an empty response', function() local qflist_count = exec_lua([=[ - require'vim.lsp.callbacks'['callHierarchy/outgoingCalls']() + require'vim.lsp.handlers'['callHierarchy/outgoingCalls']() return #vim.fn.getqflist() ]=]) eq(0, qflist_count) @@ -1602,7 +1565,7 @@ describe('LSP', function() uri = "file:///src/main.rs" } } } - local callback = require'vim.lsp.callbacks'['callHierarchy/outgoingCalls'] + local callback = require'vim.lsp.handlers'['callHierarchy/outgoingCalls'] callback(nil, nil, rust_analyzer_response) return vim.fn.getqflist() ]=]) @@ -1627,7 +1590,7 @@ describe('LSP', function() describe('vim.lsp.buf.incoming_calls', function() it('does nothing for an empty response', function() local qflist_count = exec_lua([=[ - require'vim.lsp.callbacks'['callHierarchy/incomingCalls']() + require'vim.lsp.handlers'['callHierarchy/incomingCalls']() return #vim.fn.getqflist() ]=]) eq(0, qflist_count) @@ -1674,7 +1637,7 @@ describe('LSP', function() } } } } - local callback = require'vim.lsp.callbacks'['callHierarchy/incomingCalls'] + local callback = require'vim.lsp.handlers'['callHierarchy/incomingCalls'] callback(nil, nil, rust_analyzer_response) return vim.fn.getqflist() ]=]) |