From f058b3fc40d34315e561fb7934eacf9a77d9f135 Mon Sep 17 00:00:00 2001 From: ray-x Date: Thu, 9 Mar 2023 20:16:11 +1100 Subject: [PATCH] LSP type defination support --- README.md | 18 +++++++++++++++++- lua/navigator/definition.lua | 36 +++++++++++++++++++++++++++--------- lua/navigator/hover.lua | 13 +++++++++++++ lua/navigator/lazyloader.lua | 27 +++++++++++++++------------ 4 files changed, 72 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index d75d568..58aeffc 100644 --- a/README.md +++ b/README.md @@ -315,6 +315,21 @@ require'navigator'.setup({ update_in_insert = false, -- update diagnostic message in insert mode }, + hover = { + enable = true, + keymap = { + [''] = { + go = function() + local w = vim.fn.expand('') + vim.cmd('GoDoc ' .. w) + end, + default = function( + local w = vim.fn.expand('') + vim.lsp.buf.workspace_symbol(w) + end, + }, + }, + diagnostic_scrollbar_sign = {'▃', '▆', '█'}, -- experimental: diagnostic status in scroll bar area; set to false to disable the diagnostic sign, -- for other style, set to {'╍', 'ﮆ'} or {'-', '='} diagnostic_virtual_text = true, -- show virtual for diagnostic message @@ -449,9 +464,10 @@ In `playground` folder, there is a `init.lua` and source code for you to play wi | n | \gr | show reference and context | | i | \ | signature help | | n | \ | signature help | -| n | gW | workspace symbol | +| n | gW | workspace symbol fuzzy finder | | n | gD | declaration | | n | gd | definition | +| n | gt | type definition | | n | g0 | document symbol | | n | \ | go to definition (if multiple show listview) | | n | gp | definition preview (show Preview) | diff --git a/lua/navigator/definition.lua b/lua/navigator/definition.lua index 2b464b7..c72d58f 100644 --- a/lua/navigator/definition.lua +++ b/lua/navigator/definition.lua @@ -9,6 +9,12 @@ local TextView = require('guihua.textview') local definition_hdlr = function(err, locations, ctx, _) -- log(locations) if err ~= nil then + if tostring(err):find('no type definition') or tostring(err):find('invalid range') then + vim.notify('Definition: ' .. tostring(err), vim.log.levels.DEBUG) + return vim.lsp.buf.hover() -- this is a primitive type + elseif tostring(err):find('no identifier') then + return vim.notify('Definition: ' .. tostring(err), vim.log.levels.DEBUG) + end vim.notify('Defination: ' .. tostring(err) .. vim.inspect(ctx), vim.log.levels.WARN) return end @@ -25,13 +31,23 @@ local definition_hdlr = function(err, locations, ctx, _) locations = util.dedup(locations) log(locations) - log("found " .. #locations .. " locations") + log('found ' .. #locations .. ' locations') if vim.tbl_islist(locations) then if #locations > 1 then local items = locations_to_items(locations) gui.new_list_view({ items = items, api = 'Definition', title = 'Definition' }) else - vim.lsp.util.jump_to_location(locations[1], oe) + local loc = vim.lsp.util.make_position_params() + -- let check if the location is same as current + if + loc.textDocument.uri == locations[1].uri + and loc.position.line == locations[1].range.start.line + and loc.position.character == locations[1].range.start.character + then + vim.lsp.buf.type_definition() + else + vim.lsp.util.jump_to_location(locations[1], oe) + end end else vim.lsp.util.jump_to_location(locations, oe) @@ -43,9 +59,9 @@ local function get_symbol() return currentWord end -local function def_preview(timeout_ms) - assert(next(vim.lsp.get_active_clients({buffer = 0})), 'Must have a client running') - local method = 'textDocument/definition' +local function def_preview(timeout_ms, method) + assert(next(vim.lsp.get_active_clients({ buffer = 0 })), 'Must have a client running') + method = method or 'textDocument/definition' local params = vim.lsp.util.make_position_params() local result = vim.lsp.buf_request_sync(0, method, params, timeout_ms or 1000) @@ -118,7 +134,7 @@ local function def_preview(timeout_ms) end local width = 40 - local maxwidth = math.floor( vim.api.nvim_get_option('columns') * 0.8) + local maxwidth = math.floor(vim.api.nvim_get_option('columns') * 0.8) for _, value in pairs(definition) do -- log(key, value, width) width = math.max(width, #value + 4) @@ -152,7 +168,9 @@ local function def_preview(timeout_ms) -- TODO: -- https://github.com/oblitum/goyo.vim/blob/master/autoload/goyo.vim#L108-L135 end - +local function type_preview(timeout_ms) + return def_preview(timeout_ms, 'textDocument/typeDefinition') +end local def = function() local bufnr = vim.api.nvim_get_current_buf() @@ -165,11 +183,11 @@ local def = function() end) end -vim.lsp.handlers['textDocument/definition'] = definition_hdlr return { definition = def, definition_handler = definition_hdlr, definition_preview = def_preview, + type_definition_preview = type_preview, declaration_handler = definition_hdlr, - typeDefinition_handler = definition_hdlr, + type_definition_handler = definition_hdlr, } diff --git a/lua/navigator/hover.lua b/lua/navigator/hover.lua index d490ca8..cc86ec5 100644 --- a/lua/navigator/hover.lua +++ b/lua/navigator/hover.lua @@ -8,6 +8,8 @@ function M.handler(_, result, ctx, config) vim.notify('No information available') return end + local ft = vim.bo.ft + -- require('navigator.util').log(result) local markdown_lines = util.convert_input_to_markdown_lines(result.contents) markdown_lines = util.trim_empty_lines(markdown_lines) if vim.tbl_isempty(markdown_lines) then @@ -28,6 +30,17 @@ function M.handler(_, result, ctx, config) vim.api.nvim_buf_set_option(bufnr, 'modifiable', true) contents = lsp.util.stylize_markdown(bufnr, contents, opts) vim.api.nvim_buf_set_option(bufnr, 'modifiable', false) + if _NgConfigValues.lsp.hover.keymaps then + for key, v in pairs(_NgConfigValues.lsp.hover.keymaps) do + if v[ft] == nil or v[ft] == true then + local f = v.default or function() end + vim.keymap.set('n', key, f, { noremap = true, silent = true, buffer = bufnr }) + else + local f = v[ft] + vim.keymap.set('n', key, f, { noremap = true, silent = true, buffer = bufnr }) + end + end + end return bufnr, winnr end diff --git a/lua/navigator/lazyloader.lua b/lua/navigator/lazyloader.lua index ccf3b03..734ed1e 100644 --- a/lua/navigator/lazyloader.lua +++ b/lua/navigator/lazyloader.lua @@ -8,7 +8,7 @@ return { ['guihua.lua'] = 'ray-x/guihua.lua', } if pcall(require, 'lazy') then - require('lazy').load({plugins = {'nvim-lspconfig', 'guihua.lua'}}) + require('lazy').load({ plugins = { 'nvim-lspconfig', 'guihua.lua' } }) elseif vim.fn.empty(packer_plugins) == 0 then -- packer install -- packer installed loader = require('packer').loader @@ -24,20 +24,23 @@ return { vim.cmd(cmd) end end - end, load = function(plugin_name, path) local loader = nil - packer_plugins = packer_plugins or nil -- suppress warnings - -- packer only - if packer_plugins ~= nil then -- packer install - local lazy_plugins = {} - lazy_plugins[plugin_name] = path - loader = require('packer').loader - for plugin, _ in pairs(lazy_plugins) do - if packer_plugins[plugin] and packer_plugins[plugin].loaded == false then - -- log("loading ", plugin) - pcall(loader, plugin) + + if pcall(require, 'lazy') then + require('lazy').load({ plugins = { plugin_name } }) + else + packer_plugins = packer_plugins or nil -- suppress warnings + -- packer only + if packer_plugins ~= nil then -- packer install + local lazy_plugins = {} + lazy_plugins[plugin_name] = path + loader = require('packer').loader + for plugin, _ in pairs(lazy_plugins) do + if packer_plugins[plugin] and packer_plugins[plugin].loaded == false then + pcall(loader, plugin) + end end end end