diff options
-rw-r--r-- | runtime/lua/vim/lsp/buf.lua | 15 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/default_callbacks.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 80 |
3 files changed, 77 insertions, 20 deletions
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 79d43fda4a..51295e5570 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -1,3 +1,4 @@ +local vim = vim local validate = vim.validate local api = vim.api local vfn = vim.fn @@ -330,5 +331,19 @@ function M.rename(new_name) end) end +function M.references(context) + validate { context = { context, 't', true } } + local params = util.make_position_params() + params.context = context or { + includeDeclaration = true; + } + params[vim.type_idx] = vim.types.dictionary + request('textDocument/references', params, function(_, _, result) + if not result then return end + util.set_qflist(result) + vim.api.nvim_command("copen") + end) +end + return M -- vim:sw=2 ts=2 et diff --git a/runtime/lua/vim/lsp/default_callbacks.lua b/runtime/lua/vim/lsp/default_callbacks.lua index d58280e0f2..2a891e7d1d 100644 --- a/runtime/lua/vim/lsp/default_callbacks.lua +++ b/runtime/lua/vim/lsp/default_callbacks.lua @@ -31,7 +31,7 @@ M['textDocument/publishDiagnostics'] = function(_, _, result) util.buf_diagnostics_save_positions(bufnr, result.diagnostics) util.buf_diagnostics_underline(bufnr, result.diagnostics) util.buf_diagnostics_virtual_text(bufnr, result.diagnostics) - -- util.buf_loclist(bufnr, result.diagnostics) + -- util.set_loclist(result.diagnostics) end local function log_message(_, _, result, client_id) diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 0c53494f02..2dfcdfc70c 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -1,4 +1,5 @@ local protocol = require 'vim.lsp.protocol' +local vim = vim local validate = vim.validate local api = vim.api @@ -573,30 +574,71 @@ do end end -function M.buf_loclist(bufnr, locations) - local targetwin - for _, winnr in ipairs(api.nvim_list_wins()) do - local winbuf = api.nvim_win_get_buf(winnr) - if winbuf == bufnr then - targetwin = winnr - break - end - end - if not targetwin then return end +local position_sort = sort_by_key(function(v) + return {v.line, v.character} +end) +-- Returns the items with the byte position calculated correctly and in sorted +-- order. +function M.locations_to_items(locations) local items = {} - local path = api.nvim_buf_get_name(bufnr) + local grouped = setmetatable({}, { + __index = function(t, k) + local v = {} + rawset(t, k, v) + return v + end; + }) for _, d in ipairs(locations) do - -- TODO: URL parsing here? local start = d.range.start - table.insert(items, { - filename = path, - lnum = start.line + 1, - col = start.character + 1, - text = d.message, - }) + local fname = assert(vim.uri_to_fname(d.uri)) + table.insert(grouped[fname], start) + end + local keys = vim.tbl_keys(grouped) + table.sort(keys) + -- TODO(ashkan) I wish we could do this lazily. + for _, fname in ipairs(keys) do + local rows = grouped[fname] + table.sort(rows, position_sort) + local i = 0 + for line in io.lines(fname) do + for _, pos in ipairs(rows) do + local row = pos.line + if i == row then + local col + if pos.character > #line then + col = #line + else + col = vim.str_byteindex(line, pos.character) + end + table.insert(items, { + filename = fname, + lnum = row + 1, + col = col + 1; + }) + end + end + i = i + 1 + end end - vim.fn.setloclist(targetwin, items, ' ', 'Language Server') + return items +end + +-- locations is Location[] +-- Only sets for the current window. +function M.set_loclist(locations) + vim.fn.setloclist(0, {}, ' ', { + title = 'Language Server'; + items = M.locations_to_items(locations); + }) +end + +-- locations is Location[] +function M.set_qflist(locations) + vim.fn.setqflist({}, ' ', { + title = 'Language Server'; + items = M.locations_to_items(locations); + }) end -- Remove empty lines from the beginning and end. |