diff options
Diffstat (limited to 'test/functional/plugin')
-rw-r--r-- | test/functional/plugin/health_spec.lua | 6 | ||||
-rw-r--r-- | test/functional/plugin/lsp/codelens_spec.lua | 27 | ||||
-rw-r--r-- | test/functional/plugin/lsp/diagnostic_spec.lua | 807 | ||||
-rw-r--r-- | test/functional/plugin/lsp_spec.lua | 205 |
4 files changed, 229 insertions, 816 deletions
diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua index b84e9d1533..b567b3e20c 100644 --- a/test/functional/plugin/health_spec.lua +++ b/test/functional/plugin/health_spec.lua @@ -134,7 +134,7 @@ describe('health.vim', function() command("checkhealth test_plug*") local buf_lines = helpers.curbuf('get_lines', 0, -1, true) -- avoid dealing with path separators - local received = table.concat(buf_lines, '\n', 1, #buf_lines - 2) + local received = table.concat(buf_lines, '\n', 1, #buf_lines - 5) local expected = helpers.dedent([[ test_plug: require("test_plug.health").check() @@ -175,10 +175,10 @@ describe('health.vim', function() it("gracefully handles broken lua healthcheck", function() command("checkhealth test_plug.submodule_failed") local buf_lines = helpers.curbuf('get_lines', 0, -1, true) - local received = table.concat(buf_lines, '\n', 1, #buf_lines - 2) + local received = table.concat(buf_lines, '\n', 1, #buf_lines - 5) -- avoid dealing with path separators local lua_err = "attempt to perform arithmetic on a nil value" - local last_line = buf_lines[#buf_lines - 1] + local last_line = buf_lines[#buf_lines - 4] assert(string.find(last_line, lua_err) ~= nil, "Lua error not present") local expected = global_helpers.dedent([[ diff --git a/test/functional/plugin/lsp/codelens_spec.lua b/test/functional/plugin/lsp/codelens_spec.lua index c8b75e65fc..ecc2f579b8 100644 --- a/test/functional/plugin/lsp/codelens_spec.lua +++ b/test/functional/plugin/lsp/codelens_spec.lua @@ -60,31 +60,4 @@ describe('vim.lsp.codelens', function() eq({[1] = {'Lens1', 'LspCodeLens'}}, virtual_text_chunks) end) - it('codelens uses client commands', function() - local fake_uri = "file:///fake/uri" - local cmd = exec_lua([[ - fake_uri = ... - local bufnr = vim.uri_to_bufnr(fake_uri) - vim.fn.bufload(bufnr) - vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'One line'}) - local lenses = { - { - range = { - start = { line = 0, character = 0, }, - ['end'] = { line = 0, character = 8 } - }, - command = { title = 'Lens1', command = 'Dummy' } - }, - } - vim.lsp.codelens.on_codelens(nil, lenses, {method='textDocument/codeLens', client_id=1, bufnr=bufnr}) - local cmd_called = nil - vim.lsp.commands['Dummy'] = function(command) - cmd_called = command - end - vim.api.nvim_set_current_buf(bufnr) - vim.lsp.codelens.run() - return cmd_called - ]], fake_uri) - eq({ command = 'Dummy', title = 'Lens1' }, cmd) - end) end) diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua index 243ad6bdb8..1269a2350c 100644 --- a/test/functional/plugin/lsp/diagnostic_spec.lua +++ b/test/functional/plugin/lsp/diagnostic_spec.lua @@ -3,7 +3,6 @@ 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 @@ -45,11 +44,32 @@ describe('vim.lsp.diagnostic', function() } end - count_of_extmarks_for_client = function(bufnr, client_id) - return #vim.api.nvim_buf_get_extmarks( - bufnr, vim.lsp.diagnostic.get_namespace(client_id), 0, -1, {} - ) + function get_extmarks(bufnr, client_id) + local namespace = vim.lsp.diagnostic.get_namespace(client_id) + local ns = vim.diagnostic.get_namespace(namespace) + local extmarks = {} + if ns.user_data.virt_text_ns then + for _, e in pairs(vim.api.nvim_buf_get_extmarks(bufnr, ns.user_data.virt_text_ns, 0, -1, {details=true})) do + table.insert(extmarks, e) + end + end + if ns.user_data.underline_ns then + for _, e in pairs(vim.api.nvim_buf_get_extmarks(bufnr, ns.user_data.underline_ns, 0, -1, {details=true})) do + table.insert(extmarks, e) + end + end + return extmarks end + + client_id = vim.lsp.start_client { + cmd_env = { + NVIM_LUA_NOTRACK = "1"; + }; + cmd = { + vim.v.progpath, '-es', '-u', 'NONE', '--headless' + }; + offset_encoding = "utf-16"; + } ]] fake_uri = "file:///fake/uri" @@ -69,366 +89,6 @@ describe('vim.lsp.diagnostic', function() end) describe('vim.lsp.diagnostic', function() - describe('handle_publish_diagnostics', function() - it('should be able to retrieve diagnostics from all buffers and clients', function() - local result = exec_lua [[ - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #1', 1, 1, 1, 1), - make_error('Diagnostic #2', 2, 1, 2, 1), - }, 1, 1 - ) - vim.lsp.diagnostic.save( - { - make_error('Diagnostic #3', 3, 1, 3, 1), - }, 2, 2 - ) - return vim.lsp.diagnostic.get_all() - ]] - eq(2, #result) - eq(2, #result[1]) - eq('Diagnostic #1', result[1][1].message) - end) - 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, { uri = fake_uri, diagnostics = server_1_diags }, {client_id=1}) - vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_2_diags }, {client_id=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.disable(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.enable(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) - - it('should not display diagnostics when disabled', function() - eq({0, 2}, 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, { uri = fake_uri, diagnostics = server_1_diags }, {client_id=1}) - vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_2_diags }, {client_id=2}) - - vim.lsp.diagnostic.disable(diagnostic_bufnr, 1) - - return { - count_of_extmarks_for_client(diagnostic_bufnr, 1), - count_of_extmarks_for_client(diagnostic_bufnr, 2), - } - ]]) - - eq({4, 0}, exec_lua [[ - vim.lsp.diagnostic.enable(diagnostic_bufnr, 1) - vim.lsp.diagnostic.disable(diagnostic_bufnr, 2) - - return { - count_of_extmarks_for_client(diagnostic_bufnr, 1), - count_of_extmarks_for_client(diagnostic_bufnr, 2), - } - ]]) - end) - - describe('reset', function() - it('diagnostic count is 0 and displayed diagnostics are 0 after call', 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, { uri = fake_uri, diagnostics = server_1_diags }, {client_id=1}) - vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_2_diags }, {client_id=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), - } - ]]) - - -- Reset diagnostics from server 1 - exec_lua([[ vim.lsp.diagnostic.reset(1, { [ diagnostic_bufnr ] = { [ 1 ] = true ; [ 2 ] = true } } )]]) - - -- Make sure we have the right diagnostic count - eq({0, 1, 1, 0, 2} , exec_lua [[ - local diagnostic_count = {} - vim.wait(100, function () diagnostic_count = { - 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 ) - return diagnostic_count - ]]) - - -- Reset diagnostics from server 2 - exec_lua([[ vim.lsp.diagnostic.reset(2, { [ diagnostic_bufnr ] = { [ 1 ] = true ; [ 2 ] = true } } )]]) - - -- Make sure we have the right diagnostic count - eq({0, 0, 0, 0, 0}, exec_lua [[ - local diagnostic_count = {} - vim.wait(100, function () diagnostic_count = { - 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 ) - return diagnostic_count - ]]) - - end) - 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) - it('maintains LSP information when translating diagnostics', function() local result = exec_lua [[ local diagnostics = { @@ -442,7 +102,7 @@ describe('vim.lsp.diagnostic', function() vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = diagnostics, - }, {client_id=1}) + }, {client_id=client_id}) return { vim.diagnostic.get(diagnostic_bufnr, {lnum=1})[1], @@ -456,246 +116,7 @@ describe('vim.lsp.diagnostic', function() 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, { - 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), - } - }, {client_id=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, { - 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), - } - }, {client_id=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, { - uri = fake_uri, - diagnostics = { - make_error('Delayed Diagnostic', 4, 4, 4, 4), - } - }, {client_id=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, { - uri = fake_uri, - diagnostics = { - make_error('Delayed Diagnostic', 4, 4, 4, 4), - } - }, {client_id=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, { - uri = fake_uri, - diagnostics = { - make_error('Delayed Diagnostic', 4, 4, 4, 4), - } - }, {client_id=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.diagnostic._set_virtual_text - - DisplayCount = 0 - vim.diagnostic._set_virtual_text = function(...) - DisplayCount = DisplayCount + 1 - return SetVirtualTextOriginal(...) - end - - PublishDiagnostics(nil, { - uri = fake_uri, - diagnostics = { - make_error('Delayed Diagnostic', 4, 4, 4, 4), - } - }, {client_id=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, { - uri = fake_uri, - diagnostics = { - make_error('Delayed Diagnostic', 4, 4, 4, 4), - } - }, {client_id=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, { - uri = fake_uri, - diagnostics = { - make_error('Delayed Diagnostic', 4, 4, 4, 4), - } - }, {client_id=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([[ @@ -710,16 +131,10 @@ describe('vim.lsp.diagnostic', function() diagnostics = { make_error('Delayed Diagnostic', 4, 4, 4, 4), } - }, {client_id=1} + }, {client_id=client_id} ) - return vim.api.nvim_buf_get_extmarks( - diagnostic_bufnr, - vim.lsp.diagnostic.get_namespace(1), - 0, - -1, - { details = true } - ) + return get_extmarks(diagnostic_bufnr, client_id) ]], expected_spacing) local virt_text = extmarks[1][4].virt_text @@ -728,7 +143,6 @@ describe('vim.lsp.diagnostic', function() 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([[ @@ -747,16 +161,10 @@ describe('vim.lsp.diagnostic', function() diagnostics = { make_error('Delayed Diagnostic', 4, 4, 4, 4), } - }, {client_id=1} + }, {client_id=client_id} ) - return vim.api.nvim_buf_get_extmarks( - diagnostic_bufnr, - vim.lsp.diagnostic.get_namespace(1), - 0, - -1, - { details = true } - ) + return get_extmarks(diagnostic_bufnr, client_id) ]], expected_spacing) local virt_text = extmarks[1][4].virt_text @@ -780,10 +188,10 @@ describe('vim.lsp.diagnostic', function() diagnostics = { make_warning('Delayed Diagnostic', 4, 4, 4, 4), } - }, {client_id=1} + }, {client_id=client_id} ) - return count_of_extmarks_for_client(diagnostic_bufnr, 1) + return #get_extmarks(diagnostic_bufnr, client_id) ]], severity_limit) end @@ -799,16 +207,6 @@ describe('vim.lsp.diagnostic', function() local line = "All 💼 and no 🎉 makes Jack a dull 👦" local result = exec_lua([[ local line = ... - local client_id = vim.lsp.start_client { - cmd_env = { - NVIM_LUA_NOTRACK = "1"; - }; - cmd = { - vim.v.progpath, '-es', '-u', 'NONE', '--headless' - }; - offset_encoding = "utf-16"; - } - vim.api.nvim_buf_set_lines(diagnostic_bufnr, 0, -1, false, {line}) vim.lsp.diagnostic.on_publish_diagnostics(nil, { @@ -829,145 +227,4 @@ describe('vim.lsp.diagnostic', function() eq(exec_lua([[return vim.str_byteindex(..., 8, true)]], line), result[1].end_col) 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, { - uri = fake_uri, - diagnostics = diagnostics - }, {client_id=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, { - uri = fake_uri, - diagnostics = { - make_error('Farther Diagnostic', 4, 4, 4, 4), - make_error('Lower Diagnostic', 1, 1, 1, 1), - } - }, {client_id=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, { - uri = fake_uri, - diagnostics = { - make_error('Lower Diagnostic', 1, 1, 1, 1), - } - }, {client_id=1} - ) - - vim.lsp.diagnostic.on_publish_diagnostics(nil, { - uri = fake_uri, - diagnostics = { - make_warning('Farther Diagnostic', 4, 4, 4, 4), - } - }, {client_id=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_spec.lua b/test/functional/plugin/lsp_spec.lua index ce50abb50d..c025e9f4ab 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -3,9 +3,11 @@ local helpers = require('test.functional.helpers')(after_each) local assert_log = helpers.assert_log local clear = helpers.clear local buf_lines = helpers.buf_lines +local command = helpers.command local dedent = helpers.dedent local exec_lua = helpers.exec_lua local eq = helpers.eq +local eval = helpers.eval local matches = helpers.matches local pcall_err = helpers.pcall_err local pesc = helpers.pesc @@ -272,7 +274,7 @@ describe('LSP', function() return end local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; + {NIL, {}, {method="shutdown", bufnr=1, client_id=1}}; {NIL, {}, {method="test", client_id=1}}; } test_rpc_server { @@ -486,7 +488,7 @@ describe('LSP', function() it('should forward ContentModified to callback', function() local expected_handlers = { {NIL, {}, {method="finish", client_id=1}}; - {{code = -32801}, NIL, {method = "error_code_test", client_id=1}}; + {{code = -32801}, NIL, {method = "error_code_test", bufnr=1, client_id=1}}; } local client test_rpc_server { @@ -509,6 +511,140 @@ describe('LSP', function() } end) + it('should track pending requests to the language server', function() + local expected_handlers = { + {NIL, {}, {method="finish", client_id=1}}; + {NIL, {}, {method="slow_request", bufnr=1, client_id=1}}; + } + local client + test_rpc_server { + test_name = "check_pending_request_tracked"; + on_init = function(_client) + client = _client + client.request("slow_request") + local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) + eq("slow_request", request.method) + eq("pending", request.type) + client.notify("release") + end; + on_exit = function(code, signal) + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, #expected_handlers, "did not call expected handler") + end; + on_handler = function(err, _, ctx) + eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler") + if ctx.method == 'slow_request' then + local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) + eq(NIL, request) + client.notify("finish") + end + if ctx.method == 'finish' then client.stop() end + end; + } + end) + + it('should track cancel requests to the language server', function() + local expected_handlers = { + {NIL, {}, {method="finish", client_id=1}}; + } + local client + test_rpc_server { + test_name = "check_cancel_request_tracked"; + on_init = function(_client) + client = _client + client.request("slow_request") + client.cancel_request(2) + local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) + eq("slow_request", request.method) + eq("cancel", request.type) + client.notify("release") + end; + on_exit = function(code, signal) + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, #expected_handlers, "did not call expected handler") + end; + on_handler = function(err, _, ctx) + eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler") + local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) + eq(NIL, request) + if ctx.method == 'finish' then client.stop() end + end; + } + end) + + it('should clear pending and cancel requests on reply', function() + local expected_handlers = { + {NIL, {}, {method="finish", client_id=1}}; + {NIL, {}, {method="slow_request", bufnr=1, client_id=1}}; + } + local client + test_rpc_server { + test_name = "check_tracked_requests_cleared"; + on_init = function(_client) + client = _client + client.request("slow_request") + local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) + eq("slow_request", request.method) + eq("pending", request.type) + client.cancel_request(2) + request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) + eq("slow_request", request.method) + eq("cancel", request.type) + client.notify("release") + end; + on_exit = function(code, signal) + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, #expected_handlers, "did not call expected handler") + end; + on_handler = function(err, _, ctx) + eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler") + if ctx.method == 'slow_request' then + local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) + eq(NIL, request) + client.notify("finish") + end + if ctx.method == 'finish' then client.stop() end + end; + } + end) + + it('should trigger LspRequest autocmd when requests table changes', function() + local expected_handlers = { + {NIL, {}, {method="finish", client_id=1}}; + {NIL, {}, {method="slow_request", bufnr=1, client_id=1}}; + } + local client + test_rpc_server { + test_name = "check_tracked_requests_cleared"; + on_init = function(_client) + command('let g:requests = 0') + command('autocmd User LspRequest let g:requests+=1') + client = _client + client.request("slow_request") + eq(1, eval('g:requests')) + client.cancel_request(2) + eq(2, eval('g:requests')) + client.notify("release") + end; + on_exit = function(code, signal) + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, #expected_handlers, "did not call expected handler") + eq(3, eval('g:requests')) + end; + on_handler = function(err, _, ctx) + eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler") + if ctx.method == 'slow_request' then + client.notify("finish") + end + if ctx.method == 'finish' then client.stop() end + end; + } + end) + it('should not send didOpen if the buffer closes before init', function() local expected_handlers = { {NIL, {}, {method="shutdown", client_id=1}}; @@ -790,7 +926,7 @@ describe('LSP', function() -- TODO(askhan) we don't support full for now, so we can disable these tests. pending('should check the body and didChange incremental normal mode editing', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; + {NIL, {}, {method="shutdown", bufnr=1, client_id=1}}; {NIL, {}, {method="finish", client_id=1}}; {NIL, {}, {method="start", client_id=1}}; } @@ -1017,15 +1153,9 @@ describe('LSP', function() end) it('should invalid cmd argument', function() - eq(dedent([[ - Error executing lua: .../lsp.lua:0: cmd: expected list, got nvim - stack traceback: - .../lsp.lua:0: in function <.../lsp.lua:0>]]), + eq('Error executing lua: .../lsp.lua:0: cmd: expected list, got nvim', pcall_err(_cmd_parts, 'nvim')) - eq(dedent([[ - Error executing lua: .../lsp.lua:0: cmd argument: expected string, got number - stack traceback: - .../lsp.lua:0: in function <.../lsp.lua:0>]]), + eq('Error executing lua: .../lsp.lua:0: cmd argument: expected string, got number', pcall_err(_cmd_parts, {'nvim', 1})) end) end) @@ -2395,4 +2525,57 @@ describe('LSP', function() ) end) end) + describe('vim.lsp.codelens', function() + it('uses client commands', function() + local client + local expected_handlers = { + {NIL, {}, {method="shutdown", client_id=1}}; + {NIL, {}, {method="start", client_id=1}}; + } + test_rpc_server { + test_name = 'clientside_commands', + on_init = function(client_) + client = client_ + end, + on_setup = function() + end, + on_exit = function(code, signal) + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) + end, + on_handler = function(err, result, ctx) + eq(table.remove(expected_handlers), {err, result, ctx}) + if ctx.method == 'start' then + local fake_uri = "file:///fake/uri" + local cmd = exec_lua([[ + fake_uri = ... + local bufnr = vim.uri_to_bufnr(fake_uri) + vim.fn.bufload(bufnr) + vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'One line'}) + local lenses = { + { + range = { + start = { line = 0, character = 0, }, + ['end'] = { line = 0, character = 8 } + }, + command = { title = 'Lens1', command = 'Dummy' } + }, + } + vim.lsp.codelens.on_codelens(nil, lenses, {method='textDocument/codeLens', client_id=1, bufnr=bufnr}) + local cmd_called = nil + vim.lsp.commands['Dummy'] = function(command) + cmd_called = command + end + vim.api.nvim_set_current_buf(bufnr) + vim.lsp.codelens.run() + return cmd_called + ]], fake_uri) + eq({ command = 'Dummy', title = 'Lens1' }, cmd) + elseif ctx.method == 'shutdown' then + client.stop() + end + end + } + end) + end) end) |