123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435 |
- local t = require('test.testutil')
- local n = require('test.functional.testnvim')()
- local t_lsp = require('test.functional.plugin.lsp.testutil')
- local clear = n.clear
- local exec_lua = n.exec_lua
- local eq = t.eq
- local neq = t.neq
- local create_server_definition = t_lsp.create_server_definition
- describe('vim.lsp.diagnostic', function()
- local fake_uri --- @type string
- local client_id --- @type integer
- local diagnostic_bufnr --- @type integer
- before_each(function()
- clear { env = {
- NVIM_LUA_NOTRACK = '1',
- VIMRUNTIME = os.getenv 'VIMRUNTIME',
- } }
- exec_lua(function()
- require('vim.lsp')
- _G.make_range = function(x1, y1, x2, y2)
- return { start = { line = x1, character = y1 }, ['end'] = { line = x2, character = y2 } }
- end
- _G.make_error = function(msg, x1, y1, x2, y2)
- return {
- range = _G.make_range(x1, y1, x2, y2),
- message = msg,
- severity = 1,
- }
- end
- _G.make_warning = function(msg, x1, y1, x2, y2)
- return {
- range = _G.make_range(x1, y1, x2, y2),
- message = msg,
- severity = 2,
- }
- end
- _G.make_information = function(msg, x1, y1, x2, y2)
- return {
- range = _G.make_range(x1, y1, x2, y2),
- message = msg,
- severity = 3,
- }
- end
- function _G.get_extmarks(bufnr, client_id0)
- local namespace = vim.lsp.diagnostic.get_namespace(client_id0)
- 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 = assert(vim.lsp.start({
- cmd_env = {
- NVIM_LUA_NOTRACK = '1',
- },
- cmd = {
- vim.v.progpath,
- '-es',
- '-u',
- 'NONE',
- '--headless',
- },
- offset_encoding = 'utf-16',
- }, { attach = false }))
- end)
- fake_uri = 'file:///fake/uri'
- exec_lua(function()
- 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)
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- end)
- end)
- after_each(function()
- clear()
- end)
- describe('vim.lsp.diagnostic.on_publish_diagnostics', function()
- it('correctly handles UTF-16 offsets', function()
- local line = 'All 💼 and no 🎉 makes Jack a dull 👦'
- local result = exec_lua(function()
- vim.api.nvim_buf_set_lines(diagnostic_bufnr, 0, -1, false, { line })
- vim.lsp.diagnostic.on_publish_diagnostics(nil, {
- uri = fake_uri,
- diagnostics = {
- _G.make_error('UTF-16 Diagnostic', 0, 7, 0, 8),
- },
- }, { client_id = client_id })
- local diags = vim.diagnostic.get(diagnostic_bufnr)
- vim.lsp.stop_client(client_id)
- vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })
- return diags
- end)
- eq(1, #result)
- eq(
- exec_lua(function()
- return vim.str_byteindex(line, 'utf-16', 7)
- end),
- result[1].col
- )
- eq(
- exec_lua(function()
- return vim.str_byteindex(line, 'utf-16', 8)
- end),
- result[1].end_col
- )
- end)
- it('does not create buffer on empty diagnostics', function()
- -- No buffer is created without diagnostics
- eq(
- -1,
- exec_lua(function()
- vim.lsp.diagnostic.on_publish_diagnostics(nil, {
- uri = 'file:///fake/uri2',
- diagnostics = {},
- }, { client_id = client_id })
- return vim.fn.bufnr(vim.uri_to_fname('file:///fake/uri2'))
- end)
- )
- -- Create buffer on diagnostics
- neq(
- -1,
- exec_lua(function()
- vim.lsp.diagnostic.on_publish_diagnostics(nil, {
- uri = 'file:///fake/uri2',
- diagnostics = {
- _G.make_error('Diagnostic', 0, 0, 0, 0),
- },
- }, { client_id = client_id })
- return vim.fn.bufnr(vim.uri_to_fname('file:///fake/uri2'))
- end)
- )
- eq(
- 1,
- exec_lua(function()
- return #vim.diagnostic.get(_G.bufnr)
- end)
- )
- -- Clear diagnostics after buffer was created
- neq(
- -1,
- exec_lua(function()
- vim.lsp.diagnostic.on_publish_diagnostics(nil, {
- uri = 'file:///fake/uri2',
- diagnostics = {},
- }, { client_id = client_id })
- return vim.fn.bufnr(vim.uri_to_fname('file:///fake/uri2'))
- end)
- )
- eq(
- 0,
- exec_lua(function()
- return #vim.diagnostic.get(_G.bufnr)
- end)
- )
- end)
- end)
- describe('vim.lsp.diagnostic.on_diagnostic', function()
- before_each(function()
- exec_lua(create_server_definition)
- exec_lua(function()
- _G.requests = 0
- _G.server = _G._create_server({
- capabilities = {
- diagnosticProvider = {},
- },
- handlers = {
- [vim.lsp.protocol.Methods.textDocument_diagnostic] = function()
- _G.requests = _G.requests + 1
- end,
- },
- })
- function _G.get_extmarks(bufnr, client_id0)
- local namespace = vim.lsp.diagnostic.get_namespace(client_id0, true)
- 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({ name = 'dummy', cmd = _G.server.cmd })
- end)
- end)
- it('adds diagnostics to vim.diagnostics', function()
- local diags = exec_lua(function()
- vim.lsp.diagnostic.on_diagnostic(nil, {
- kind = 'full',
- items = {
- _G.make_error('Pull Diagnostic', 4, 4, 4, 4),
- },
- }, {
- params = {
- textDocument = { uri = fake_uri },
- },
- uri = fake_uri,
- client_id = client_id,
- }, {})
- return vim.diagnostic.get(diagnostic_bufnr)
- end)
- eq(1, #diags)
- eq('Pull Diagnostic', diags[1].message)
- end)
- it('severity defaults to error if missing', function()
- ---@type vim.Diagnostic[]
- local diagnostics = exec_lua(function()
- vim.lsp.diagnostic.on_diagnostic(nil, {
- kind = 'full',
- items = {
- {
- range = _G.make_range(4, 4, 4, 4),
- message = 'bad!',
- },
- },
- }, {
- params = {
- textDocument = { uri = fake_uri },
- },
- uri = fake_uri,
- client_id = client_id,
- }, {})
- return vim.diagnostic.get(diagnostic_bufnr)
- end)
- eq(1, #diagnostics)
- eq(1, diagnostics[1].severity)
- end)
- it('clears diagnostics when client detaches', function()
- exec_lua(function()
- vim.lsp.diagnostic.on_diagnostic(nil, {
- kind = 'full',
- items = {
- _G.make_error('Pull Diagnostic', 4, 4, 4, 4),
- },
- }, {
- params = {
- textDocument = { uri = fake_uri },
- },
- uri = fake_uri,
- client_id = client_id,
- }, {})
- end)
- eq(
- 1,
- exec_lua(function()
- return #vim.diagnostic.get(diagnostic_bufnr)
- end)
- )
- exec_lua(function()
- vim.lsp.stop_client(client_id)
- end)
- eq(
- 0,
- exec_lua(function()
- return #vim.diagnostic.get(diagnostic_bufnr)
- end)
- )
- end)
- it('keeps diagnostics when one client detaches and others still are attached', function()
- local client_id2
- exec_lua(function()
- client_id2 = vim.lsp.start({ name = 'dummy2', cmd = _G.server.cmd })
- vim.lsp.diagnostic.on_diagnostic(nil, {
- kind = 'full',
- items = {
- _G.make_error('Pull Diagnostic', 4, 4, 4, 4),
- },
- }, {
- params = {
- textDocument = { uri = fake_uri },
- },
- uri = fake_uri,
- client_id = client_id,
- }, {})
- end)
- eq(
- 1,
- exec_lua(function()
- return #vim.diagnostic.get(diagnostic_bufnr)
- end)
- )
- exec_lua(function()
- vim.lsp.stop_client(client_id2)
- end)
- eq(
- 1,
- exec_lua(function()
- return #vim.diagnostic.get(diagnostic_bufnr)
- end)
- )
- end)
- it('handles server cancellation', function()
- eq(
- 1,
- exec_lua(function()
- vim.lsp.diagnostic.on_diagnostic({
- code = vim.lsp.protocol.ErrorCodes.ServerCancelled,
- -- Empty data defaults to retriggering request
- data = {},
- message = '',
- }, {}, {
- method = vim.lsp.protocol.Methods.textDocument_diagnostic,
- client_id = client_id,
- })
- return _G.requests
- end)
- )
- eq(
- 2,
- exec_lua(function()
- vim.lsp.diagnostic.on_diagnostic({
- code = vim.lsp.protocol.ErrorCodes.ServerCancelled,
- data = { retriggerRequest = true },
- message = '',
- }, {}, {
- method = vim.lsp.protocol.Methods.textDocument_diagnostic,
- client_id = client_id,
- })
- return _G.requests
- end)
- )
- eq(
- 2,
- exec_lua(function()
- vim.lsp.diagnostic.on_diagnostic({
- code = vim.lsp.protocol.ErrorCodes.ServerCancelled,
- data = { retriggerRequest = false },
- message = '',
- }, {}, {
- method = vim.lsp.protocol.Methods.textDocument_diagnostic,
- client_id = client_id,
- })
- return _G.requests
- end)
- )
- end)
- end)
- end)
|